diff --git a/.github/workflows/autochangelog.yml b/.github/workflows/autochangelog.yml
index d0ab3fe4f66..dced49689a2 100644
--- a/.github/workflows/autochangelog.yml
+++ b/.github/workflows/autochangelog.yml
@@ -11,7 +11,7 @@ env:
jobs:
autochangelog:
name: Autochangelog
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
if: github.event.pull_request.merged == true
steps:
- uses: /actions/checkout@v3
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 19bf8f27893..52d707d9646 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -8,39 +8,66 @@ env:
BASENAME: "vorestation"
jobs:
- file_tests:
+
+ run_linters:
name: Run Linters
- runs-on: ubuntu-22.04 # YW EDIT: 20.04 to 22.04
+ runs-on: ubuntu-22.04
+
steps:
- uses: actions/checkout@v4
- - name: Ensure +x on CI directory
- run: |
- chmod -R +x ./tools/ci
- - name: Install Tools
- run: |
- bash tools/ci/install_build_deps.sh
+ # Caches
- name: Restore Yarn cache
- if: "${{ contains(github.event.pull_request.labels.*.name, 'Type: TGUI Bundle') }}"
uses: actions/cache@v4
with:
path: tgui/.yarn/cache
- key: ${{ runner.os }}-yarn-${{ secrets.CACHE_PURGE_KEY }}-${{ hashFiles('tgui/yarn.lock') }}
+ key: ${{ runner.os }}-yarn-${{ hashFiles('tgui/yarn.lock') }}
restore-keys: |
- ${{ runner.os }}-build-${{ secrets.CACHE_PURGE_KEY }}-
- ${{ runner.os }}-build-
- ${{ runner.os }}-
- - name: Run Tests
+ ${{ runner.os }}-yarn-
+ - name: Restore Node cache
+ uses: actions/cache@v4
+ with:
+ path: ~/.nvm
+ key: ${{ runner.os }}-node-${{ hashFiles('dependencies.sh') }}
+ restore-keys: |
+ ${{ runner.os }}-node-
+ - name: Restore Bootstrap cache
+ uses: actions/cache@v4
+ with:
+ path: tools/bootstrap/.cache
+ key: ${{ runner.os }}-bootstrap-${{ hashFiles('tools/requirements.txt') }}
+ restore-keys: |
+ ${{ runner.os }}-bootstrap-
+ - name: Restore Rust cache
+ uses: actions/cache@v4
+ with:
+ path: ~/.cargo
+ key: ${{ runner.os }}-rust-${{ hashFiles('tools/ci/ci_dependencies.sh')}}
+ restore-keys: |
+ ${{ runner.os }}-rust-
+ - name: Restore Cutter cache
+ uses: actions/cache@v4
+ with:
+ path: tools/icon_cutter/cache
+ key: ${{ runner.os }}-cutter-${{ hashFiles('dependencies.sh') }}
+ # End Caches
+ - name: Install Tools
run: |
- tools/ci/validate_files.sh
- tools/ci/build_tgui.sh
+ pip3 install setuptools
+ bash tools/ci/install_node.sh
+ bash tools/ci/install_ripgrep.sh
+ tools/bootstrap/python -c ''
+ - name: Run Grep Checks
+ run: tools/ci/validate_files.sh
+ - name: Run TGUI Checks
+ run: tools/build/build --ci lint tgui-test
dreamchecker:
name: DreamChecker
- runs-on: ubuntu-22.04 # YW EDIT: 20.04 to 22.04
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- - name: Cache SpacemanDMM
+ - name: Restore SpacemanDMM Cache
uses: actions/cache@v4
with:
path: ~/SpacemanDMM
@@ -63,24 +90,22 @@ jobs:
outputFile: output-annotations.txt
unit_tests:
- # YW EDIT start
- #strategy:
- # matrix:
- # map: ['tether', 'stellar_delight', 'groundbase']
+ strategy:
+ matrix:
+ map: ['USE_MAP_CRYOGAIA'] # YW EDIT Cryogaia
# name: Integration Tests (${{ matrix.map }})
- # YW EDIT: end
name: Integration Tests
- # needs: ['file_tests', 'dreamchecker']
- runs-on: ubuntu-22.04 # YW EDIT: 20.04 to 22.04
+ # needs: ['run_linters', 'dreamchecker']
+ runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Ensure +x on CI directory
run: |
chmod -R +x ./tools/ci
- - name: Setup Cache
+ - name: Restore BYOND Cache
uses: actions/cache@v4
with:
- path: $HOME/BYOND
+ path: $HOME/byond
key: ${{ runner.os }}-byond
- name: Install RUST_G Dependencies
run: |
@@ -88,47 +113,46 @@ jobs:
sudo apt update || true
sudo apt install zlib1g-dev:i386 libssl-dev:i386
ldd librust_g.so
+ ldd libbapi_dmm_reader.so
+ ldd libverdigris.so
- name: Unit Tests
run: |
tools/ci/install_byond.sh
tools/ci/compile_and_run.sh
env:
- TEST_DEFINE: "UNIT_TEST"
- TEST_FILE: "code/_unit_tests.dm"
- # YW EDIT: start
- #MAP: ${{ matrix.map }}
- #REPLACE: true
- # YW EDIT: end
+ EXTRA_ARGS: "-DUNIT_TEST -D${{ matrix.map }}"
RUN: "1"
- - name: Compile POIs
+
+ extra_map_tests:
+ name: Map Tests
+ runs-on: ubuntu-22.04
+ steps:
+ - uses: actions/checkout@v4
+ - name: Ensure +x on CI directory
run: |
- tools/ci/install_byond.sh
- tools/ci/compile_and_run.sh
+ chmod -R +x ./tools/ci
+ - name: Restore BYOND Cache
+ uses: actions/cache@v4
+ with:
+ path: $HOME/byond
+ key: ${{ runner.os }}-byond
+ - name: Install BYOND
+ run: tools/ci/install_byond.sh
+ - name: Compile POIs
+ run: tools/ci/compile_and_run.sh
env:
- TEST_DEFINE: "MAP_TEST"
- TEST_FILE: "code/_map_tests.dm"
- # YW EDIT: start
- #MAP: ${{ matrix.map }}
- #REPLACE: false
- # YW EDIT: end
+ EXTRA_ARGS: "-DMAP_TEST"
RUN: "0"
- name: Compile away missions
- run: |
- tools/ci/install_byond.sh
- tools/ci/compile_and_run.sh
+ run: tools/ci/compile_and_run.sh
env:
- TEST_DEFINE: "AWAY_MISSION_TEST"
- TEST_FILE: "code/_away_mission_tests.dm"
- # YW EDIT: start
- #MAP: ${{ matrix.map }}
- #REPLACE: false
- # YW EDIT: end
+ EXTRA_ARGS: "-DAWAY_MISSION_TEST -DUSE_MAP_CRYOGAIA" # YW EDIT CRYOGAIA # Only Tether has support for all away missions
RUN: "0"
tests_successful:
name: Integration Tests
- needs: ['file_tests', 'dreamchecker', 'unit_tests']
- runs-on: ubuntu-22.04 # YW EDIT: 20.04 to 22.04
+ needs: ['run_linters', 'dreamchecker', 'unit_tests', 'extra_map_tests']
+ runs-on: ubuntu-22.04
steps:
- name: Report Success
run: |
diff --git a/.github/workflows/render_nanomaps.yml b/.github/workflows/render_nanomaps.yml
index 767eefe400a..ec05c188cbb 100644
--- a/.github/workflows/render_nanomaps.yml
+++ b/.github/workflows/render_nanomaps.yml
@@ -19,7 +19,7 @@ jobs:
pull-requests: write # to create pull requests (repo-sync/pull-request)
name: 'Generate NanoMaps'
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
steps:
- name: Clone
uses: actions/checkout@v4
diff --git a/.gitignore b/.gitignore
index 0cda0875f25..28f0cda51c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@ cfg/
#Ignore everything in datafolder and subdirectories
/data/**/*
/tmp/**/*
+/cache/**/*
#Visual studio stuff
*.vscode/*
@@ -30,5 +31,12 @@ cfg/
temp.dmi
node_modules/
package-lock.json
-# YW ADDITION: start
-# YW ADDITION: end
+
+# CBT Things
+.cache
+
+#These get built by some automatic process
+tgui/public/tgui.bundle.css
+tgui/public/tgui.bundle.js
+#ignore tracy dll
+prof.dll
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 00000000000..2789c260b7c
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+v20.13.0
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 24779e223e7..80b1d58f759 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -4,13 +4,59 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
- {
- "type": "byond",
- "request": "launch",
- "name": "Launch DreamDaemon",
- "preLaunchTask": "dm: build - ${command:CurrentDME}",
- "dmb": "${workspaceFolder}/${command:CurrentDMB}",
- "dreamDaemon": true
- }
+ {
+ "type": "byond",
+ "request": "launch",
+ "name": "Launch DreamSeeker",
+ "preLaunchTask": "Build All",
+ "dmb": "${workspaceFolder}/${command:CurrentDMB}"
+ },
+ {
+ "type": "byond",
+ "request": "launch",
+ "name": "Launch DreamSeeker (low memory mode)",
+ "preLaunchTask": "Build All (low memory mode)",
+ "dmb": "${workspaceFolder}/${command:CurrentDMB}"
+ },
+ {
+ "type": "byond",
+ "request": "launch",
+ "name": "Launch DreamDaemon",
+ "preLaunchTask": "Build All",
+ "dmb": "${workspaceFolder}/${command:CurrentDMB}",
+ "dreamDaemon": true
+ },
+ {
+ "type": "byond",
+ "request": "launch",
+ "name": "Launch DreamDaemon (low memory mode)",
+ "preLaunchTask": "Build All (low memory mode)",
+ "dmb": "${workspaceFolder}/${command:CurrentDMB}",
+ "dreamDaemon": true
+ },
+ {
+ "name": "Debug External Libraries",
+ "type": "cppvsdbg",
+ "request": "launch",
+ "program": "${command:dreammaker.returnDreamDaemonPath}",
+ "cwd": "${workspaceRoot}",
+ "args": [
+ "${command:dreammaker.getFilenameDmb}",
+ "-trusted"
+ ],
+ "preLaunchTask": "Build All"
+ },
+ {
+ "name": "Debug External Libraries (low memory mode)",
+ "type": "cppvsdbg",
+ "request": "launch",
+ "program": "${command:dreammaker.returnDreamDaemonPath}",
+ "cwd": "${workspaceRoot}",
+ "args": [
+ "${command:dreammaker.getFilenameDmb}",
+ "-trusted"
+ ],
+ "preLaunchTask": "Build All (low memory mode)"
+ }
]
-}
\ No newline at end of file
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 2b0aed0e814..e101d591657 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,6 +1,149 @@
{
"version": "2.0.0",
"tasks": [
+ {
+ "type": "process",
+ "command": "tools/build/build",
+ "windows": {
+ "command": ".\\tools\\build\\build.bat"
+ },
+ "options": {
+ "env": {
+ "DM_EXE": "${config:dreammaker.byondPath}"
+ }
+ },
+ "problemMatcher": [
+ "$dreammaker",
+ "$tsc",
+ "$eslint-stylish"
+ ],
+ "group": {
+ "kind": "build",
+ "isDefault": true
+ },
+ "dependsOn": "dm: reparse",
+ "label": "Build All"
+ },
+ {
+ "type": "process",
+ "command": "tools/build/build",
+ "args": ["-DLOWMEMORYMODE"],
+ "windows": {
+ "command": ".\\tools\\build\\build.bat",
+ "args": ["-DLOWMEMORYMODE"]
+ },
+ "options": {
+ "env": {
+ "DM_EXE": "${config:dreammaker.byondPath}"
+ }
+ },
+ "problemMatcher": [
+ "$dreammaker",
+ "$tsc",
+ "$eslint-stylish"
+ ],
+ "group": {
+ "kind": "build"
+ },
+ "dependsOn": "dm: reparse",
+ "label": "Build All (low memory mode)"
+ },
+ {
+ "type": "process",
+ "command": "tools/build/build",
+ "args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_TETHER"],
+ "windows": {
+ "command": ".\\tools\\build\\build.bat",
+ "args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_TETHER"]
+ },
+ "options": {
+ "env": {
+ "DM_EXE": "${config:dreammaker.byondPath}"
+ }
+ },
+ "problemMatcher": [
+ "$dreammaker",
+ "$tsc",
+ "$eslint-stylish"
+ ],
+ "group": {
+ "kind": "build"
+ },
+ "dependsOn": "dm: reparse",
+ "label": "Build All (Force Tether)"
+ },
+ {
+ "type": "process",
+ "command": "tools/build/build",
+ "args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_STELLARDELIGHT"],
+ "windows": {
+ "command": ".\\tools\\build\\build.bat",
+ "args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_STELLARDELIGHT"]
+ },
+ "options": {
+ "env": {
+ "DM_EXE": "${config:dreammaker.byondPath}"
+ }
+ },
+ "problemMatcher": [
+ "$dreammaker",
+ "$tsc",
+ "$eslint-stylish"
+ ],
+ "group": {
+ "kind": "build"
+ },
+ "dependsOn": "dm: reparse",
+ "label": "Build All (Force Stellar Delight)"
+ },
+ {
+ "type": "process",
+ "command": "tools/build/build",
+ "args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_GROUNDBASE"],
+ "windows": {
+ "command": ".\\tools\\build\\build.bat",
+ "args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_GROUNDBASE"]
+ },
+ "options": {
+ "env": {
+ "DM_EXE": "${config:dreammaker.byondPath}"
+ }
+ },
+ "problemMatcher": [
+ "$dreammaker",
+ "$tsc",
+ "$eslint-stylish"
+ ],
+ "group": {
+ "kind": "build"
+ },
+ "dependsOn": "dm: reparse",
+ "label": "Build All (Force Groundbase)"
+ },
+ {
+ "type": "process",
+ "command": "tools/build/build",
+ "args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_MINITEST"],
+ "windows": {
+ "command": ".\\tools\\build\\build.bat",
+ "args": ["-DLOWMEMORYMODE", "-DCITESTING", "-DUSE_MAP_MINITEST"]
+ },
+ "options": {
+ "env": {
+ "DM_EXE": "${config:dreammaker.byondPath}"
+ }
+ },
+ "problemMatcher": [
+ "$dreammaker",
+ "$tsc",
+ "$eslint-stylish"
+ ],
+ "group": {
+ "kind": "build"
+ },
+ "dependsOn": "dm: reparse",
+ "label": "Build All (Force Minitest)"
+ },
{
"type": "dreammaker",
"dme": "vorestation.dme",
@@ -10,11 +153,16 @@
"group": "build",
"label": "dm: build - vorestation.dme"
},
+ {
+ "command": "${command:dreammaker.reparse}",
+ "group": "build",
+ "label": "dm: reparse"
+ },
{
"type": "shell",
- "command": "tgui/bin/tgui",
+ "command": "bin/tgui-build",
"windows": {
- "command": ".\\tgui\\bin\\tgui.bat"
+ "command": ".\\bin\\tgui-build.cmd"
},
"problemMatcher": [
"$tsc",
@@ -25,43 +173,55 @@
},
{
"type": "shell",
- "command": "yarn build",
- "options": {
- "cwd": "tgui/packages/tgfont/",
+ "command": "bin/tgui-dev",
+ "windows": {
+ "command": ".\\bin\\tgui-dev.cmd"
},
+ "problemMatcher": [
+ "$tsc",
+ "$eslint-stylish"
+ ],
"group": "build",
- "problemMatcher": [],
- "label": "tgui: build tgfont",
- "detail": "node mkdist.cjs && fantasticon --config config.cjs"
+ "label": "tgui: dev server"
},
{
"type": "shell",
- "command": "tgui/bin/tgui",
+ "command": "bin/tgui-bench",
"windows": {
- "command": ".\\tgui\\bin\\tgui-prettybuild.bat"
+ "command": ".\\bin\\tgui-bench.cmd"
},
"problemMatcher": [
"$tsc",
"$eslint-stylish"
],
"group": "build",
- "label": "tgui: prettybuild"
+ "label": "tgui: bench"
},
{
"type": "shell",
- "command": "bin/tgui --dev",
+ "command": "bin/tgui-sonar",
"windows": {
- "command": ".\\bin\\tgui.bat --dev"
+ "command": ".\\bin\\tgui-sonar.cmd"
},
"problemMatcher": [
"$tsc",
"$eslint-stylish"
],
- "options": {
- "cwd": ".\\tgui\\",
+ "group": "build",
+ "label": "tgui: sonar"
+ },
+ {
+ "type": "shell",
+ "command": "bin/tgfont",
+ "windows": {
+ "command": ".\\bin\\tgfont.cmd"
},
+ "problemMatcher": [
+ "$tsc",
+ "$eslint-stylish"
+ ],
"group": "build",
- "label": "tgui: dev server"
+ "label": "tgui: rebuild tgfont"
}
]
}
diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md
index 60f2305a8c3..abaf97a0b98 100644
--- a/ATTRIBUTIONS.md
+++ b/ATTRIBUTIONS.md
@@ -73,3 +73,16 @@
**Creator:** Poojawa (https://github.com/VOREStation/VOREStation/pull/6052)
**License:** [General License](sound/vore/sunesound/LICENSE.txt)
**Notes:** Permission to use assets also given in writing. All files under this folder is NOT licensed under CC3. Seek separate permission before copying/using.
+
+**File:** `icons/rogue-star/loafs_64x32.dmi`and `icons/rogue-star/tails_64x32_rs.dmi`
+**Title:** Rogue Star Tails
+**Icon-States:** `flagtail`, derivs by VerySoft, `bnytr`, derivs by Verysoft, `chonksqrl`, derivs by Verysoft
+**Creator:** VerySoft (https://github.com/TS-Rogue-Star/Rogue-Star/pull/435)
+**URL:** [Website](https://rogue-star.net/)
+**License:** Permission granting in writing for use by Virgo and Chomp with proper attribution
+
+**File:** `icons/mob/turkey.dmi`
+**Title:** Turkey
+**Creator:** VerySoft (https://github.com/TS-Rogue-Star/Rogue-Star/pull/669)
+**URL:** [Website](https://rogue-star.net/)
+**License:** Permission granted in writing for use by Virgo and Chomp with proper attribution
diff --git a/README.md b/README.md
index 1ff396a057d..36ed02c5379 100644
--- a/README.md
+++ b/README.md
@@ -55,11 +55,11 @@ This will take a while to download, but it provides an easier method for updatin
First-time installation should be fairly straightforward. First, you'll need BYOND installed. You can get it from [here](http://www.byond.com/).
-This is a sourcecode-only release, so the next step is to compile the server files. Open vorestation.dme by double-clicking it, open the Build menu, and click compile. This'll take a little while, and if everything's done right you'll get a message like this:
+**The quick way**. Find `bin/server.cmd` in this folder and double click it to automatically build and host the server on port 1337.
- saving vorestation.dmb (DEBUG mode)
+**The long way**. Find `bin/build.cmd` in this folder, and double click it to initiate the build. It consists of multiple steps and might take around 1-5 minutes to compile. If it closes, it means it has finished its job. You can then [setup the server](.github/guides/RUNNING_A_SERVER.md) normally by opening `tgstation.dmb` in DreamDaemon.
- vorestation.dmb - 0 errors, 0 warnings
+**Building vorestation in DreamMaker directly is deprecated and might produce errors**, such as `'tgui.bundle.js': cannot find file`.
If you see any errors or warnings, something has gone wrong - possibly a corrupt download or the files extracted wrong, or a code issue on the main repo. Ask on IRC.
diff --git a/_build_dependencies.sh b/_build_dependencies.sh
index 8b6659c3a93..7902bb3ca54 100644
--- a/_build_dependencies.sh
+++ b/_build_dependencies.sh
@@ -6,6 +6,6 @@ export NODE_VERSION=20
# Byond Major
export BYOND_MAJOR=515
# Byond Minor
-export BYOND_MINOR=1630
+export BYOND_MINOR=1642
# Macro Count
-export MACRO_COUNT=4
+export MACRO_COUNT=9 # YW EDIT FIXTHIS
diff --git a/bapi_dmm_reader.dll b/bapi_dmm_reader.dll
new file mode 100644
index 00000000000..0262c5a6809
Binary files /dev/null and b/bapi_dmm_reader.dll differ
diff --git a/bin/build.cmd b/bin/build.cmd
new file mode 100644
index 00000000000..98c2ef45e15
--- /dev/null
+++ b/bin/build.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error build %*
diff --git a/bin/clean.cmd b/bin/clean.cmd
new file mode 100644
index 00000000000..8eacd92ebd7
--- /dev/null
+++ b/bin/clean.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error clean-all %*
diff --git a/bin/server.cmd b/bin/server.cmd
new file mode 100644
index 00000000000..c6e6642baf4
--- /dev/null
+++ b/bin/server.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error server %*
diff --git a/bin/test.cmd b/bin/test.cmd
new file mode 100644
index 00000000000..a76a9c6745c
--- /dev/null
+++ b/bin/test.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error dm-test %*
diff --git a/bin/tgfont.cmd b/bin/tgfont.cmd
new file mode 100644
index 00000000000..b768c81d653
--- /dev/null
+++ b/bin/tgfont.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error tg-font %*
diff --git a/bin/tgui-bench.cmd b/bin/tgui-bench.cmd
new file mode 100644
index 00000000000..333115f7954
--- /dev/null
+++ b/bin/tgui-bench.cmd
@@ -0,0 +1,3 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-bench %*
+pause
diff --git a/bin/tgui-build.cmd b/bin/tgui-build.cmd
new file mode 100644
index 00000000000..7804fc6daaa
--- /dev/null
+++ b/bin/tgui-build.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui tgui-lint tgui-test %*
diff --git a/bin/tgui-dev.cmd b/bin/tgui-dev.cmd
new file mode 100644
index 00000000000..25ff3495d42
--- /dev/null
+++ b/bin/tgui-dev.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-dev %*
diff --git a/bin/tgui-fix.cmd b/bin/tgui-fix.cmd
new file mode 100644
index 00000000000..f2844408ef8
--- /dev/null
+++ b/bin/tgui-fix.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-fix %*
diff --git a/bin/tgui-sonar.cmd b/bin/tgui-sonar.cmd
new file mode 100644
index 00000000000..e083f65362a
--- /dev/null
+++ b/bin/tgui-sonar.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\..\tools\build\build.bat" --wait-on-error tgui-sonar %*
diff --git a/build.cmd b/build.cmd
new file mode 100644
index 00000000000..dc791f60c9b
--- /dev/null
+++ b/build.cmd
@@ -0,0 +1,2 @@
+@echo off
+call "%~dp0\tools\build\build.bat" --wait-on-error build %*
diff --git a/code/ATMOSPHERICS/_atmospherics_helpers.dm b/code/ATMOSPHERICS/_atmospherics_helpers.dm
index 76b520a45fa..da777c25815 100644
--- a/code/ATMOSPHERICS/_atmospherics_helpers.dm
+++ b/code/ATMOSPHERICS/_atmospherics_helpers.dm
@@ -17,7 +17,7 @@
/client/proc/atmos_toggle_debug(var/obj/machinery/atmospherics/M in view())
set name = "Toggle Debug Messages"
- set category = "Debug"
+ set category = "Debug.Misc"
M.debug = !M.debug
to_chat(usr, "[M]: Debug messages toggled [M.debug? "on" : "off"].")
@@ -439,7 +439,7 @@
var/sink_heat_capacity = sink.heat_capacity()
var/transfer_heat_capacity = source.heat_capacity()*estimate_moles/source_total_moles
air_temperature = (sink.temperature*sink_heat_capacity + source.temperature*transfer_heat_capacity) / (sink_heat_capacity + transfer_heat_capacity)
-
+
//get the number of moles that would have to be transfered to bring sink to the target pressure
return pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm
index 27457567120..7f3368cc537 100644
--- a/code/ATMOSPHERICS/atmospherics.dm
+++ b/code/ATMOSPHERICS/atmospherics.dm
@@ -35,8 +35,8 @@ Pipelines + Other Objects -> Pipe network
var/obj/machinery/atmospherics/node1
var/obj/machinery/atmospherics/node2
-/obj/machinery/atmospherics/New(loc, newdir)
- ..()
+/obj/machinery/atmospherics/Initialize(mapload, newdir)
+ . = ..()
if(!icon_manager)
icon_manager = new()
if(!isnull(newdir))
@@ -82,7 +82,7 @@ Pipelines + Other Objects -> Pipe network
return (src.connect_types & target.connect_types)
/obj/machinery/atmospherics/attackby(atom/A, mob/user as mob)
- if(istype(A, /obj/item/device/pipe_painter))
+ if(istype(A, /obj/item/pipe_painter))
return
..()
diff --git a/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm b/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm
index f4207eeba5e..84ba70f55f4 100644
--- a/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm
@@ -5,7 +5,7 @@
desc = "An oxygen generator using algae to convert carbon dioxide to oxygen."
icon = 'icons/obj/machines/algae_vr.dmi'
icon_state = "algae-off"
- circuit = /obj/item/weapon/circuitboard/algae_farm
+ circuit = /obj/item/circuitboard/algae_farm
anchored = TRUE
density = TRUE
power_channel = EQUIP
@@ -123,7 +123,7 @@
icon_state = "algae-on"
return 1
-/obj/machinery/atmospherics/binary/algae_farm/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/obj/machinery/atmospherics/binary/algae_farm/attackby(obj/item/W as obj, mob/user as mob)
add_fingerprint(user)
if(default_deconstruction_screwdriver(user, W))
return
@@ -134,7 +134,7 @@
if(try_load_materials(user, W))
return
else
- to_chat(user, "You cannot insert this item into \the [src]!")
+ to_chat(user, span_notice("You cannot insert this item into \the [src]!"))
return
/obj/machinery/atmospherics/binary/algae_farm/attack_hand(mob/user)
@@ -149,12 +149,12 @@
var/bin_rating = 0
var/manip_rating = 0
- for(var/obj/item/weapon/stock_parts/P in component_parts)
- if(istype(P, /obj/item/weapon/stock_parts/capacitor))
+ for(var/obj/item/stock_parts/P in component_parts)
+ if(istype(P, /obj/item/stock_parts/capacitor))
cap_rating += P.rating
- if(istype(P, /obj/item/weapon/stock_parts/matter_bin))
+ if(istype(P, /obj/item/stock_parts/matter_bin))
bin_rating += P.rating
- if(istype(P, /obj/item/weapon/stock_parts/manipulator))
+ if(istype(P, /obj/item/stock_parts/manipulator))
manip_rating += P.rating
power_per_mole = round(initial(power_per_mole) / cap_rating)
@@ -206,10 +206,10 @@
return data
-/obj/machinery/atmospherics/binary/algae_farm/tgui_act(action, params)
+/obj/machinery/atmospherics/binary/algae_farm/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
- add_fingerprint(usr)
+ add_fingerprint(ui.user)
switch(action)
if("toggle")
@@ -249,7 +249,7 @@
if(!istype(S))
return 0
if(!(S.material.name in stored_material))
- to_chat(user, "\The [src] doesn't accept [material_display_name(S.material)]!")
+ to_chat(user, span_warning("\The [src] doesn't accept [material_display_name(S.material)]!"))
return 1
var/max_res_amount = storage_capacity[S.material.name]
if(stored_material[S.material.name] + S.perunit <= max_res_amount)
@@ -258,10 +258,10 @@
stored_material[S.material.name] += S.perunit
S.use(1)
count++
- user.visible_message("\The [user] inserts [S.name] into \the [src].", "You insert [count] [S.name] into \the [src].")
+ user.visible_message("\The [user] inserts [S.name] into \the [src].", span_notice("You insert [count] [S.name] into \the [src]."))
updateUsrDialog()
else
- to_chat(user, "\The [src] cannot hold more [S.name].")
+ to_chat(user, span_warning("\The [src] cannot hold more [S.name]."))
return 1
/datum/material/algae
diff --git a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
index cee94b9b5a7..54de979b6c3 100644
--- a/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/binary_atmos_base.dm
@@ -9,8 +9,8 @@
var/datum/pipe_network/network1
var/datum/pipe_network/network2
-/obj/machinery/atmospherics/binary/New()
- ..()
+/obj/machinery/atmospherics/binary/Initialize()
+ . = ..()
air1 = new
air2 = new
@@ -126,4 +126,4 @@
update_icon()
update_underlays()
- return null
\ No newline at end of file
+ return null
diff --git a/code/ATMOSPHERICS/components/binary_devices/circulator.dm b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
index c3f6b81ee3f..5c795e38871 100644
--- a/code/ATMOSPHERICS/components/binary_devices/circulator.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/circulator.dm
@@ -24,8 +24,9 @@
density = TRUE
-/obj/machinery/atmospherics/binary/circulator/New()
- ..()
+/obj/machinery/atmospherics/binary/circulator/Initialize()
+ . = ..()
+
desc = initial(desc) + " Its outlet port is to the [dir2text(dir)]."
air1.volume = 400
@@ -91,7 +92,7 @@
return 1
-/obj/machinery/atmospherics/binary/circulator/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/obj/machinery/atmospherics/binary/circulator/attackby(obj/item/W as obj, mob/user as mob)
if(W.has_tool_quality(TOOL_WRENCH))
playsound(src, W.usesound, 75, 1)
anchored = !anchored
@@ -149,4 +150,4 @@
return
src.set_dir(turn(src.dir, 90))
- desc = initial(desc) + " Its outlet port is to the [dir2text(dir)]."
\ No newline at end of file
+ desc = initial(desc) + " Its outlet port is to the [dir2text(dir)]."
diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
index 251aa4c1473..36616ae721d 100644
--- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
@@ -42,8 +42,11 @@
//2: Do not pass input_pressure_min
//4: Do not pass output_pressure_max
-/obj/machinery/atmospherics/binary/dp_vent_pump/New()
- ..()
+/obj/machinery/atmospherics/binary/dp_vent_pump/Initialize()
+ . = ..()
+ if(frequency)
+ set_frequency(frequency)
+
air1.volume = ATMOS_DEFAULT_VOLUME_PUMP
air2.volume = ATMOS_DEFAULT_VOLUME_PUMP
icon = null
@@ -55,8 +58,8 @@
/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume
name = "Large Dual Port Air Vent"
-/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/New()
- ..()
+/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/Initialize()
+ . = ..()
air1.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
air2.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
@@ -194,11 +197,6 @@
return 1
-/obj/machinery/atmospherics/binary/dp_vent_pump/Initialize()
- . = ..()
- if(frequency)
- set_frequency(frequency)
-
/obj/machinery/atmospherics/binary/dp_vent_pump/examine(mob/user)
. = ..()
if(Adjacent(user))
diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
index 5d39a608513..fd1158f408a 100644
--- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
@@ -27,10 +27,12 @@
var/id = null
var/datum/radio_frequency/radio_connection
-/obj/machinery/atmospherics/binary/passive_gate/New()
- ..()
+/obj/machinery/atmospherics/binary/passive_gate/Initialize()
+ . = ..()
air1.volume = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
air2.volume = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
+ if(frequency)
+ set_frequency(frequency)
/obj/machinery/atmospherics/binary/passive_gate/Destroy()
unregister_radio(src, frequency)
@@ -169,11 +171,6 @@
return 1
-/obj/machinery/atmospherics/binary/passive_gate/Initialize()
- . = ..()
- if(frequency)
- set_frequency(frequency)
-
/obj/machinery/atmospherics/binary/passive_gate/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
@@ -206,9 +203,9 @@
/obj/machinery/atmospherics/binary/passive_gate/attack_hand(user as mob)
if(..())
return
- add_fingerprint(usr)
+ add_fingerprint(user)
if(!allowed(user))
- to_chat(user, "Access denied.")
+ to_chat(user, span_warning("Access denied."))
return
tgui_interact(user)
@@ -238,7 +235,7 @@
return data
-/obj/machinery/atmospherics/binary/passive_gate/tgui_act(action, params)
+/obj/machinery/atmospherics/binary/passive_gate/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -261,7 +258,7 @@
if("max")
target_pressure = max_pressure_setting
if("set")
- var/new_pressure = tgui_input_number(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure Control",src.target_pressure,max_pressure_setting,0)
+ var/new_pressure = tgui_input_number(ui.user,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure Control",src.target_pressure,max_pressure_setting,0)
src.target_pressure = between(0, new_pressure, max_pressure_setting)
if("set_flow_rate")
@@ -272,28 +269,28 @@
if("max")
set_flow_rate = air1.volume
if("set")
- var/new_flow_rate = tgui_input_number(usr,"Enter new flow rate limit (0-[air1.volume]L/s)","Flow Rate Control",src.set_flow_rate,air1.volume,0)
+ var/new_flow_rate = tgui_input_number(ui.user,"Enter new flow rate limit (0-[air1.volume]L/s)","Flow Rate Control",src.set_flow_rate,air1.volume,0)
src.set_flow_rate = between(0, new_flow_rate, air1.volume)
update_icon()
- add_fingerprint(usr)
+ add_fingerprint(ui.user)
-/obj/machinery/atmospherics/binary/passive_gate/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/binary/passive_gate/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
if (unlocked)
- to_chat(user, "You cannot unwrench \the [src], turn it off first.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], turn it off first."))
return 1
if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm
index 6b0f40b8b4c..df55d47a9fb 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm
@@ -81,11 +81,11 @@
if (kin_energy > 1000000)
add_overlay(image('icons/obj/pipeturbine.dmi', "hi-turb"))
-/obj/machinery/atmospherics/pipeturbine/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/obj/machinery/atmospherics/pipeturbine/attackby(obj/item/W as obj, mob/user as mob)
if(W.has_tool_quality(TOOL_WRENCH))
anchored = !anchored
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You [anchored ? "secure" : "unsecure"] the bolts holding \the [src] to the floor.")
+ to_chat(user, span_notice("You [anchored ? "secure" : "unsecure"] the bolts holding \the [src] to the floor."))
if(anchored)
if(dir & (NORTH|SOUTH))
@@ -255,12 +255,12 @@
turbine.kin_energy -= power_generated
add_avail(power_generated)
-/obj/machinery/power/turbinemotor/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/obj/machinery/power/turbinemotor/attackby(obj/item/W as obj, mob/user as mob)
if(W.has_tool_quality(TOOL_WRENCH))
anchored = !anchored
playsound(src, W.usesound, 50, 1)
turbine = null
- to_chat(user, "You [anchored ? "secure" : "unsecure"] the bolts holding \the [src] to the floor.")
+ to_chat(user, span_notice("You [anchored ? "secure" : "unsecure"] the bolts holding \the [src] to the floor."))
updateConnection()
else
..()
@@ -283,4 +283,4 @@
if (usr.stat || usr.restrained() || anchored)
return
- src.set_dir(turn(src.dir, 90))
\ No newline at end of file
+ src.set_dir(turn(src.dir, 90))
diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm
index 3e22ea310d5..70b498722f2 100644
--- a/code/ATMOSPHERICS/components/binary_devices/pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm
@@ -37,10 +37,13 @@ Thus, the two variables affect pump operation are set in New():
var/id = null
var/datum/radio_frequency/radio_connection
-/obj/machinery/atmospherics/binary/pump/New()
- ..()
+/obj/machinery/atmospherics/binary/pump/Initialize()
+ . = ..()
+
air1.volume = ATMOS_DEFAULT_VOLUME_PUMP
air2.volume = ATMOS_DEFAULT_VOLUME_PUMP
+ if(frequency)
+ set_frequency(frequency)
/obj/machinery/atmospherics/binary/pump/Destroy()
unregister_radio(src, frequency)
@@ -166,11 +169,6 @@ Thus, the two variables affect pump operation are set in New():
return data
-/obj/machinery/atmospherics/binary/pump/Initialize()
- . = ..()
- if(frequency)
- set_frequency(frequency)
-
/obj/machinery/atmospherics/binary/pump/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
@@ -203,13 +201,13 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/binary/pump/attack_hand(mob/user)
if(..())
return
- add_fingerprint(usr)
+ add_fingerprint(user)
if(!allowed(user))
- to_chat(user, "Access denied.")
+ to_chat(user, span_warning("Access denied."))
return
tgui_interact(user)
-/obj/machinery/atmospherics/binary/pump/tgui_act(action, params)
+/obj/machinery/atmospherics/binary/pump/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -225,11 +223,11 @@ Thus, the two variables affect pump operation are set in New():
if("max")
target_pressure = max_pressure_setting
if("set")
- var/new_pressure = tgui_input_number(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure control",src.target_pressure,max_pressure_setting,0)
+ var/new_pressure = tgui_input_number(ui.user,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure control",src.target_pressure,max_pressure_setting,0)
src.target_pressure = between(0, new_pressure, max_pressure_setting)
. = TRUE
- add_fingerprint(usr)
+ add_fingerprint(ui.user)
update_icon()
/obj/machinery/atmospherics/binary/pump/power_change()
@@ -238,21 +236,21 @@ Thus, the two variables affect pump operation are set in New():
if(old_stat != stat)
update_icon()
-/obj/machinery/atmospherics/binary/pump/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/binary/pump/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
if (!(stat & NOPOWER) && use_power)
- to_chat(user, "You cannot unwrench this [src], turn it off first.")
+ to_chat(user, span_warning("You cannot unwrench this [src], turn it off first."))
return 1
if(!can_unwrench())
- to_chat(user, "You cannot unwrench this [src], it too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench this [src], it too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/components/omni_devices/filter.dm b/code/ATMOSPHERICS/components/omni_devices/filter.dm
index 8990ba011f3..4d442b772a6 100644
--- a/code/ATMOSPHERICS/components/omni_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/filter.dm
@@ -20,8 +20,9 @@
var/list/filtering_outputs = list() //maps gasids to gas_mixtures
-/obj/machinery/atmospherics/omni/atmos_filter/New()
- ..()
+/obj/machinery/atmospherics/omni/atmos_filter/Initialize()
+ . = ..()
+
rebuild_filtering_list()
for(var/datum/omni_port/P in ports)
P.air.volume = ATMOS_DEFAULT_VOLUME_FILTER
@@ -151,7 +152,7 @@
else
return null
-/obj/machinery/atmospherics/omni/atmos_filter/tgui_act(action, params)
+/obj/machinery/atmospherics/omni/atmos_filter/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -170,7 +171,7 @@
if("set_flow_rate")
if(!configuring || use_power)
return
- var/new_flow_rate = tgui_input_number(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate,max_flow_rate,0)
+ var/new_flow_rate = tgui_input_number(ui.user,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate,max_flow_rate,0)
set_flow_rate = between(0, new_flow_rate, max_flow_rate)
. = TRUE
if("switch_mode")
@@ -181,7 +182,7 @@
if("switch_filter")
if(!configuring || use_power)
return
- var/new_filter = tgui_input_list(usr, "Select filter mode:", "Change filter", list("None", "Oxygen", "Nitrogen", "Carbon Dioxide", "Phoron", "Nitrous Oxide"))
+ var/new_filter = tgui_input_list(ui.user, "Select filter mode:", "Change filter", list("None", "Oxygen", "Nitrogen", "Carbon Dioxide", "Phoron", "Nitrous Oxide"))
if(!new_filter)
return
switch_filter(dir_flag(params["dir"]), mode_return_switch(new_filter))
diff --git a/code/ATMOSPHERICS/components/omni_devices/mixer.dm b/code/ATMOSPHERICS/components/omni_devices/mixer.dm
index fa627ddc64b..9d0b9c78f7f 100644
--- a/code/ATMOSPHERICS/components/omni_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/mixer.dm
@@ -24,8 +24,9 @@
var/list/mixing_inputs = list()
-/obj/machinery/atmospherics/omni/mixer/New()
- ..()
+/obj/machinery/atmospherics/omni/mixer/Initialize()
+ . = ..()
+
if(mapper_set())
var/con = 0
for(var/datum/omni_port/P in ports)
@@ -163,7 +164,7 @@
return data
-/obj/machinery/atmospherics/omni/mixer/tgui_act(action, params)
+/obj/machinery/atmospherics/omni/mixer/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -183,7 +184,7 @@
. = TRUE
if(!configuring || use_power)
return
- var/new_flow_rate = tgui_input_number(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate,max_flow_rate,0)
+ var/new_flow_rate = tgui_input_number(ui.user,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate,max_flow_rate,0)
set_flow_rate = between(0, new_flow_rate, max_flow_rate)
if("switch_mode")
. = TRUE
@@ -194,7 +195,7 @@
. = TRUE
if(!configuring || use_power)
return
- change_concentration(dir_flag(params["dir"]))
+ change_concentration(dir_flag(params["dir"]), ui.user)
if("switch_conlock")
. = TRUE
if(!configuring || use_power)
@@ -243,7 +244,7 @@
update_ports()
rebuild_mixing_inputs()
-/obj/machinery/atmospherics/omni/mixer/proc/change_concentration(var/port = NORTH)
+/obj/machinery/atmospherics/omni/mixer/proc/change_concentration(var/port = NORTH, mob/user)
tag_north_con = null
tag_south_con = null
tag_east_con = null
@@ -265,7 +266,7 @@
if(non_locked < 1)
return
- var/new_con = (tgui_input_number(usr,"Enter a new concentration (0-[round(remain_con * 100, 0.5)])%","Concentration control", min(remain_con, old_con)*100, round(remain_con * 100, 0.5), 0)) / 100
+ var/new_con = (tgui_input_number(user,"Enter a new concentration (0-[round(remain_con * 100, 0.5)])%","Concentration control", min(remain_con, old_con)*100, round(remain_con * 100, 0.5), 0)) / 100
//cap it between 0 and the max remaining concentration
new_con = between(0, new_con, remain_con)
diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
index 77a35c8eae8..9e6613ebf2b 100644
--- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
@@ -25,8 +25,9 @@
var/list/ports = new()
-/obj/machinery/atmospherics/omni/New()
- ..()
+/obj/machinery/atmospherics/omni/Initialize()
+ . = ..()
+
icon_state = "base"
ports = new()
@@ -79,20 +80,20 @@
if(old_stat != stat)
update_icon()
-/obj/machinery/atmospherics/omni/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/omni/attackby(var/obj/item/W as obj, var/mob/user as mob)
if(!W.has_tool_quality(TOOL_WRENCH))
return ..()
if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it is too exerted due to internal pressure."))
add_fingerprint(user)
return 1
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
playsound(src, W.usesound, 50, 1)
if(do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + "unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
@@ -100,7 +101,7 @@
if(..())
return
- src.add_fingerprint(usr)
+ src.add_fingerprint(user)
tgui_interact(user)
return
diff --git a/code/ATMOSPHERICS/components/portables_connector.dm b/code/ATMOSPHERICS/components/portables_connector.dm
index 5d315cf0a05..2dbc9afc00e 100644
--- a/code/ATMOSPHERICS/components/portables_connector.dm
+++ b/code/ATMOSPHERICS/components/portables_connector.dm
@@ -146,23 +146,23 @@
return null
-/obj/machinery/atmospherics/portables_connector/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/portables_connector/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
if (connected_device)
- to_chat(user, "You cannot unwrench \the [src], dettach \the [connected_device] first.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], dettach \the [connected_device] first."))
return 1
if (locate(/obj/machinery/portable_atmospherics, src.loc))
return 1
if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/components/shutoff.dm b/code/ATMOSPHERICS/components/shutoff.dm
index 7517cbd7efc..2084b8c901c 100644
--- a/code/ATMOSPHERICS/components/shutoff.dm
+++ b/code/ATMOSPHERICS/components/shutoff.dm
@@ -32,7 +32,7 @@ GLOBAL_LIST_EMPTY(shutoff_valves)
return src.attack_hand(user)
/obj/machinery/atmospherics/valve/shutoff/attack_hand(var/mob/user)
- src.add_fingerprint(usr)
+ src.add_fingerprint(user)
update_icon(1)
close_on_leaks = !close_on_leaks
to_chat(user, "You [close_on_leaks ? "enable" : "disable"] the automatic shutoff circuit.")
diff --git a/code/ATMOSPHERICS/components/station_boiler.dm b/code/ATMOSPHERICS/components/station_boiler.dm
index 389e2d5740f..8cab413d569 100644
--- a/code/ATMOSPHERICS/components/station_boiler.dm
+++ b/code/ATMOSPHERICS/components/station_boiler.dm
@@ -106,7 +106,7 @@ var/global/list/stationboilers = list() //Should only ever have one, caching to
to_chat(user, "\The [src] cannot hold more [S.name].")
return 1
-/obj/machinery/atmospherics/binary/stationboiler/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/obj/machinery/atmospherics/binary/stationboiler/attackby(obj/item/W as obj, mob/user as mob)
add_fingerprint(user)
if(try_load_materials(user, W))
return
diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
index 18ade9acefe..f332afee61c 100755
--- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
@@ -39,8 +39,9 @@
if(frequency)
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
-/obj/machinery/atmospherics/trinary/atmos_filter/New()
- ..()
+/obj/machinery/atmospherics/trinary/atmos_filter/Initialize()
+ . = ..()
+
switch(filter_type)
if(0) //removing hydrocarbons
filtered_out = list("phoron")
@@ -56,6 +57,8 @@
air1.volume = ATMOS_DEFAULT_VOLUME_FILTER
air2.volume = ATMOS_DEFAULT_VOLUME_FILTER
air3.volume = ATMOS_DEFAULT_VOLUME_FILTER
+ if(frequency)
+ set_frequency(frequency)
/obj/machinery/atmospherics/trinary/atmos_filter/Destroy()
unregister_radio(src, frequency)
@@ -106,17 +109,12 @@
return 1
-/obj/machinery/atmospherics/trinary/atmos_filter/Initialize()
- . = ..()
- if(frequency)
- set_frequency(frequency)
-
/obj/machinery/atmospherics/trinary/atmos_filter/attack_hand(user) // -- TLE
if(..())
return
if(!src.allowed(user))
- to_chat(user, "Access denied.")
+ to_chat(user, span_warning("Access denied."))
return
tgui_interact(user)
@@ -157,7 +155,7 @@
// user << browse("
[src.name] control[dat]", "window=atmos_filter")
// onclose(user, "atmos_filter")
-
+
/obj/machinery/atmospherics/trinary/atmos_filter/tgui_interact(mob/user, datum/tgui/ui)
@@ -184,7 +182,7 @@
return data
-/obj/machinery/atmospherics/trinary/atmos_filter/tgui_act(action, params)
+/obj/machinery/atmospherics/trinary/atmos_filter/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -218,7 +216,7 @@
if(4)//removing N2O
filtered_out += "nitrous_oxide"
- add_fingerprint(usr)
+ add_fingerprint(ui.user)
update_icon()
//
diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
index 7e06e5de821..86ee7517622 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm
@@ -37,8 +37,9 @@
icon_state += "off"
update_use_power(USE_POWER_OFF)
-/obj/machinery/atmospherics/trinary/mixer/New()
- ..()
+/obj/machinery/atmospherics/trinary/mixer/Initialize()
+ . = ..()
+
air1.volume = ATMOS_DEFAULT_VOLUME_MIXER
air2.volume = ATMOS_DEFAULT_VOLUME_MIXER
air3.volume = ATMOS_DEFAULT_VOLUME_MIXER * 1.5
@@ -99,13 +100,13 @@
if(..())
return
tgui_interact(user)
- // src.add_fingerprint(usr)
+ // src.add_fingerprint(user)
// if(!src.allowed(user))
- // to_chat(user, "Access denied.")
+ // to_chat(user, span_warning("Access denied."))
// return
- // usr.set_machine(src)
+ // user.set_machine(src)
// var/list/node_connects = get_node_connect_dirs()
- // var/dat = {"Power: [use_power?"On":"Off"]
+ // var/dat = {span_bold("Power: ") + "[use_power?"On":"Off"]
// Set Flow Rate Limit:
// [set_flow_rate]L/s | Change
//
diff --git a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
index 1bae066a69d..7e91b8941fb 100644
--- a/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/trinary_base.dm
@@ -17,8 +17,8 @@
var/datum/pipe_network/network2
var/datum/pipe_network/network3
-/obj/machinery/atmospherics/trinary/New()
- ..()
+/obj/machinery/atmospherics/trinary/Initialize()
+ . = ..()
air1 = new
air2 = new
@@ -51,19 +51,19 @@
if(old_stat != stat)
update_icon()
-/obj/machinery/atmospherics/trinary/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/trinary/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/components/tvalve.dm b/code/ATMOSPHERICS/components/tvalve.dm
index 5edf6966965..9f0f220ec2a 100644
--- a/code/ATMOSPHERICS/components/tvalve.dm
+++ b/code/ATMOSPHERICS/components/tvalve.dm
@@ -161,7 +161,7 @@
return
/obj/machinery/atmospherics/tvalve/attack_hand(mob/user as mob)
- src.add_fingerprint(usr)
+ src.add_fingerprint(user)
update_icon(1)
sleep(10)
if (src.state)
@@ -288,7 +288,7 @@
if(!powered())
return
if(!src.allowed(user))
- to_chat(user, "Access denied.")
+ to_chat(user, span_warning("Access denied."))
return
..()
@@ -326,19 +326,19 @@
else
go_to_side()
-/obj/machinery/atmospherics/tvalve/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/tvalve/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm
index ed391dec5fb..5dd984a0ff8 100644
--- a/code/ATMOSPHERICS/components/unary/cold_sink.dm
+++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm
@@ -10,7 +10,7 @@
anchored = TRUE
use_power = USE_POWER_OFF
idle_power_usage = 5 // 5 Watts for thermostat related circuitry
- circuit = /obj/item/weapon/circuitboard/unary_atmos/cooler
+ circuit = /obj/item/circuitboard/unary_atmos/cooler
var/heatsink_temperature = T20C // The constant temperature reservoir into which the freezer pumps heat. Probably the hull of the station or something.
var/internal_volume = 600 // L
@@ -84,7 +84,7 @@
return data
-/obj/machinery/atmospherics/unary/freezer/tgui_act(action, params)
+/obj/machinery/atmospherics/unary/freezer/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -103,7 +103,7 @@
var/new_setting = between(0, text2num(params["value"]), 100)
set_power_level(new_setting)
- add_fingerprint(usr)
+ add_fingerprint(ui.user)
/obj/machinery/atmospherics/unary/freezer/process()
..()
@@ -142,12 +142,12 @@
var/manip_rating = 0
var/bin_rating = 0
- for(var/obj/item/weapon/stock_parts/P in component_parts)
- if(istype(P, /obj/item/weapon/stock_parts/capacitor))
+ for(var/obj/item/stock_parts/P in component_parts)
+ if(istype(P, /obj/item/stock_parts/capacitor))
cap_rating += P.rating
- if(istype(P, /obj/item/weapon/stock_parts/manipulator))
+ if(istype(P, /obj/item/stock_parts/manipulator))
manip_rating += P.rating
- if(istype(P, /obj/item/weapon/stock_parts/matter_bin))
+ if(istype(P, /obj/item/stock_parts/matter_bin))
bin_rating += P.rating
max_power_rating = initial(max_power_rating) * cap_rating / 2 //more powerful
diff --git a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
index cc50782d71c..078c97af8a1 100644
--- a/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_exchanger.dm
@@ -36,11 +36,11 @@
if(!partner)
return 0
- if(!air_master || air_master.current_cycle <= update_cycle)
+ if(!SSair || SSair.current_cycle <= update_cycle)
return 0
- update_cycle = air_master.current_cycle
- partner.update_cycle = air_master.current_cycle
+ update_cycle = SSair.current_cycle
+ partner.update_cycle = SSair.current_cycle
var/air_heat_capacity = air_contents.heat_capacity()
var/other_air_heat_capacity = partner.air_contents.heat_capacity()
@@ -66,22 +66,22 @@
return 1
-/obj/machinery/atmospherics/unary/heat_exchanger/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/unary/heat_exchanger/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
var/turf/T = src.loc
if (level==1 && isturf(T) && !T.is_plating())
- to_chat(user, "You must remove the plating first.")
+ to_chat(user, span_warning("You must remove the plating first."))
return 1
if (!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it is too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm
index 85b0dcb821e..2c1a22a825c 100644
--- a/code/ATMOSPHERICS/components/unary/heat_source.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_source.dm
@@ -10,7 +10,7 @@
anchored = TRUE
use_power = USE_POWER_OFF
idle_power_usage = 5 //5 Watts for thermostat related circuitry
- circuit = /obj/item/weapon/circuitboard/unary_atmos/heater
+ circuit = /obj/item/circuitboard/unary_atmos/heater
var/max_temperature = T20C + 680
var/internal_volume = 600 //L
@@ -104,7 +104,7 @@
return data
-/obj/machinery/atmospherics/unary/heater/tgui_act(action, params)
+/obj/machinery/atmospherics/unary/heater/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
@@ -123,7 +123,7 @@
var/new_setting = between(0, text2num(params["value"]), 100)
set_power_level(new_setting)
- add_fingerprint(usr)
+ add_fingerprint(ui.user)
//upgrading parts
/obj/machinery/atmospherics/unary/heater/RefreshParts()
@@ -131,10 +131,10 @@
var/cap_rating = 0
var/bin_rating = 0
- for(var/obj/item/weapon/stock_parts/P in component_parts)
- if(istype(P, /obj/item/weapon/stock_parts/capacitor))
+ for(var/obj/item/stock_parts/P in component_parts)
+ if(istype(P, /obj/item/stock_parts/capacitor))
cap_rating += P.rating
- if(istype(P, /obj/item/weapon/stock_parts/matter_bin))
+ if(istype(P, /obj/item/stock_parts/matter_bin))
bin_rating += P.rating
max_power_rating = initial(max_power_rating) * cap_rating / 2
diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
index 8002d79ad55..57144148fd4 100644
--- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm
+++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
@@ -24,9 +24,12 @@
level = 1
-/obj/machinery/atmospherics/unary/outlet_injector/New()
- ..()
+/obj/machinery/atmospherics/unary/outlet_injector/Initialize()
+ . = ..()
+
air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //Give it a small reservoir for injecting. Also allows it to have a higher flow rate limit than vent pumps, to differentiate injectors a bit more.
+ if(frequency)
+ set_frequency(frequency)
/obj/machinery/atmospherics/unary/outlet_injector/Destroy()
unregister_radio(src, frequency)
@@ -122,11 +125,6 @@
return 1
-/obj/machinery/atmospherics/unary/outlet_injector/Initialize()
- . = ..()
- if(frequency)
- set_frequency(frequency)
-
/obj/machinery/atmospherics/unary/outlet_injector/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
@@ -158,20 +156,20 @@
update_underlays()
/obj/machinery/atmospherics/unary/outlet_injector/attack_hand(mob/user as mob)
- to_chat(user, "You toggle \the [src].")
+ to_chat(user, span_notice("You toggle \the [src]."))
injecting = !injecting
update_use_power(injecting ? USE_POWER_IDLE : USE_POWER_OFF)
update_icon()
-/obj/machinery/atmospherics/unary/outlet_injector/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/unary/outlet_injector/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/components/unary/unary_base.dm b/code/ATMOSPHERICS/components/unary/unary_base.dm
index 9a3a4d3e44b..da5e116dc97 100644
--- a/code/ATMOSPHERICS/components/unary/unary_base.dm
+++ b/code/ATMOSPHERICS/components/unary/unary_base.dm
@@ -13,10 +13,10 @@
var/welded = 0 //defining this here for ventcrawl stuff
-/obj/machinery/atmospherics/unary/New()
- ..()
- air_contents = new
+/obj/machinery/atmospherics/unary/Initialize()
+ . = ..()
+ air_contents = new
air_contents.volume = 200
/obj/machinery/atmospherics/unary/init_dir()
@@ -106,11 +106,11 @@
for(var/obj/machinery/atmospherics/M in loc)
if(M == src) continue
if((M.pipe_flags & pipe_flags & PIPING_ONE_PER_TURF)) //Only one dense/requires density object per tile, eg connectors/cryo/heater/coolers.
- visible_message("\The [src]'s cannot be connected, something is hogging the tile!")
+ visible_message(span_warning("\The [src]'s cannot be connected, something is hogging the tile!"))
return TRUE
if((M.piping_layer != piping_layer) && !((M.pipe_flags | flags) & PIPING_ALL_LAYER)) // Pipes on different layers can't block each other unless they are ALL_LAYER
continue
if(M.get_init_dirs() & get_init_dirs()) // matches at least one direction on either type of pipe
- visible_message("\The [src]'s connector can't be connected, there is already a pipe at that location!")
+ visible_message(span_warning("\The [src]'s connector can't be connected, there is already a pipe at that location!"))
return TRUE
return FALSE
diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm
index 8ba6482b0ac..110c5819550 100644
--- a/code/ATMOSPHERICS/components/unary/vent_pump.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm
@@ -89,10 +89,7 @@
/obj/machinery/atmospherics/unary/vent_pump/Initialize()
. = ..()
- //soundloop = new(list(src), FALSE)
-/obj/machinery/atmospherics/unary/vent_pump/New()
- ..()
air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP
icon = null
@@ -127,8 +124,8 @@
icon_connect_type = "-aux"
connect_types = CONNECT_TYPE_AUX //connects to aux pipes
-/obj/machinery/atmospherics/unary/vent_pump/high_volume/New()
- ..()
+/obj/machinery/atmospherics/unary/vent_pump/high_volume/Initialize()
+ . = ..()
air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
// VOREStation Edit Start - Wall mounted vents
@@ -152,8 +149,8 @@
power_channel = ENVIRON
power_rating = 30000 //15 kW ~ 20 HP
-/obj/machinery/atmospherics/unary/vent_pump/engine/New()
- ..()
+/obj/machinery/atmospherics/unary/vent_pump/engine/Initialize()
+ . = ..()
air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //meant to match air injector
/obj/machinery/atmospherics/unary/vent_pump/update_icon(var/safety = 0)
@@ -173,14 +170,14 @@
if(welded)
vent_icon += "weld"
- playsound(src, stop_sound, 25, ignore_walls = FALSE, preference = /datum/client_preference/air_pump_noise)
+ playsound(src, stop_sound, 25, ignore_walls = FALSE, preference = /datum/preference/toggle/air_pump_noise)
else if(!use_power || !node || (stat & (NOPOWER|BROKEN)))
vent_icon += "off"
- playsound(src, stop_sound, 25, ignore_walls = FALSE, preference = /datum/client_preference/air_pump_noise)
+ playsound(src, stop_sound, 25, ignore_walls = FALSE, preference = /datum/preference/toggle/air_pump_noise)
else
vent_icon += "[pump_direction ? "out" : "in"]"
- playsound(src, start_sound, 25, ignore_walls = FALSE, preference = /datum/client_preference/air_pump_noise)
+ playsound(src, start_sound, 25, ignore_walls = FALSE, preference = /datum/preference/toggle/air_pump_noise)
add_overlay(icon_manager.get_atmos_icon("device", , , vent_icon))
@@ -319,8 +316,11 @@
radio_filter_in = frequency==1439?(RADIO_FROM_AIRALARM):null
radio_filter_out = frequency==1439?(RADIO_TO_AIRALARM):null
if(frequency)
- radio_connection = register_radio(src, frequency, frequency, radio_filter_in)
- src.broadcast_status()
+ set_frequency(frequency)
+
+/obj/machinery/atmospherics/unary/vent_pump/proc/set_frequency(new_frequency)
+ radio_connection = register_radio(src, frequency, new_frequency, radio_filter_in)
+ frequency = new_frequency
/obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal)
if(stat & (NOPOWER|BROKEN))
@@ -399,25 +399,39 @@
/obj/machinery/atmospherics/unary/vent_pump/attackby(obj/item/W, mob/user)
if(W.has_tool_quality(TOOL_WELDER))
- var/obj/item/weapon/weldingtool/WT = W.get_welder()
+ var/obj/item/weldingtool/WT = W.get_welder()
if (WT.remove_fuel(0,user))
- to_chat(user, "Now welding the vent.")
+ to_chat(user, span_notice("Now welding the vent."))
if(do_after(user, 20 * WT.toolspeed))
if(!src || !WT.isOn()) return
playsound(src, WT.usesound, 50, 1)
if(!welded)
- user.visible_message("\The [user] welds the vent shut.", "You weld the vent shut.", "You hear welding.")
+ user.visible_message(span_bold("\The [user]") + " welds the vent shut.", span_notice("You weld the vent shut."), "You hear welding.")
welded = 1
update_icon()
else
- user.visible_message("[user] unwelds the vent.", "You unweld the vent.", "You hear welding.")
+ user.visible_message(span_notice("[user] unwelds the vent."), span_notice("You unweld the vent."), "You hear welding.")
welded = 0
update_icon()
else
- to_chat(user, "The welding tool needs to be on to start this task.")
+ to_chat(user, span_notice("The welding tool needs to be on to start this task."))
else
- to_chat(user, "You need more welding fuel to complete this task.")
+ to_chat(user, span_warning("You need more welding fuel to complete this task."))
return 1
+ if(W.has_tool_quality(TOOL_MULTITOOL))
+ var/choice = tgui_alert(user, "[src] has an ID of \"[id_tag]\" and a frequency of [frequency]. What would you like to change?", "[src] ID", list("ID Tag", "Frequency", "Nothing"))
+ switch(choice)
+ if("ID Tag")
+ var/new_id = tgui_input_text(user, "[src] has an ID of \"[id_tag]\". What would you like it to be?", "[src] ID", id_tag, 30, FALSE, TRUE)
+ if(new_id)
+ id_tag = new_id
+
+ if("Frequency")
+ var/new_frequency = tgui_input_number(user, "[src] has a frequency of [frequency]. What would you like it to be?", "[src] frequency", frequency, RADIO_HIGH_FREQ, RADIO_LOW_FREQ)
+ if(new_frequency)
+ new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
+ set_frequency(new_frequency)
+ return TRUE
else
..()
@@ -436,26 +450,26 @@
if(old_stat != stat)
update_icon()
-/obj/machinery/atmospherics/unary/vent_pump/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/unary/vent_pump/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
if (!(stat & NOPOWER) && use_power)
- to_chat(user, "You cannot unwrench \the [src], turn it off first.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], turn it off first."))
return 1
var/turf/T = src.loc
if (node && node.level==1 && isturf(T) && !T.is_plating())
- to_chat(user, "You must remove the plating first.")
+ to_chat(user, span_warning("You must remove the plating first."))
return 1
if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it is too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
index 1a57841a694..4ab5156968e 100644
--- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
@@ -32,8 +32,8 @@
use_power = USE_POWER_IDLE
icon_state = "map_scrubber_on"
-/obj/machinery/atmospherics/unary/vent_scrubber/New()
- ..()
+/obj/machinery/atmospherics/unary/vent_scrubber/Initialize()
+ . = ..()
air_contents.volume = ATMOS_DEFAULT_VOLUME_FILTER
icon = null
@@ -269,26 +269,26 @@
if(old_stat != stat)
update_icon()
-/obj/machinery/atmospherics/unary/vent_scrubber/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/unary/vent_scrubber/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
if (!(stat & NOPOWER) && use_power)
- to_chat(user, "You cannot unwrench \the [src], turn it off first.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], turn it off first."))
return 1
var/turf/T = src.loc
if (node && node.level==1 && isturf(T) && !T.is_plating())
- to_chat(user, "You must remove the plating first.")
+ to_chat(user, span_warning("You must remove the plating first."))
return 1
if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it is too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/components/valve.dm b/code/ATMOSPHERICS/components/valve.dm
index 1996c223366..d51a3695293 100644
--- a/code/ATMOSPHERICS/components/valve.dm
+++ b/code/ATMOSPHERICS/components/valve.dm
@@ -131,7 +131,7 @@
return
/obj/machinery/atmospherics/valve/attack_hand(mob/user as mob)
- src.add_fingerprint(usr)
+ src.add_fingerprint(user)
update_icon(1)
sleep(10)
if (src.open)
@@ -238,7 +238,7 @@
if(!powered())
return
if(!src.allowed(user))
- to_chat(user, "Access denied.")
+ to_chat(user, span_warning("Access denied."))
return
..()
@@ -287,22 +287,22 @@
else
open()
-/obj/machinery/atmospherics/valve/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/valve/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
if (istype(src, /obj/machinery/atmospherics/valve/digital) && !src.allowed(user))
- to_chat(user, "Access denied.")
+ to_chat(user, span_warning("Access denied."))
return 1
if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it is too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/mainspipe.dm b/code/ATMOSPHERICS/mainspipe.dm
deleted file mode 100644
index e7a0d094775..00000000000
--- a/code/ATMOSPHERICS/mainspipe.dm
+++ /dev/null
@@ -1,708 +0,0 @@
-// internal pipe, don't actually place or use these
-obj/machinery/atmospherics/pipe/mains_component
- var/obj/machinery/atmospherics/mains_pipe/parent_pipe
- var/list/obj/machinery/atmospherics/pipe/mains_component/nodes = new()
-
- New(loc)
- ..(loc)
- parent_pipe = loc
-
- check_pressure(pressure)
- var/datum/gas_mixture/environment = loc.loc.return_air()
-
- var/pressure_difference = pressure - environment.return_pressure()
-
- if(pressure_difference > parent_pipe.maximum_pressure)
- mains_burst()
-
- else if(pressure_difference > parent_pipe.fatigue_pressure)
- //TODO: leak to turf, doing pfshhhhh
- if(prob(5))
- mains_burst()
-
- else return 1
-
- pipeline_expansion()
- return nodes
-
- disconnect(obj/machinery/atmospherics/reference)
- if(nodes.Find(reference))
- nodes.Remove(reference)
-
- proc/mains_burst()
- parent_pipe.burst()
-
-obj/machinery/atmospherics/mains_pipe
- icon = 'icons/obj/atmospherics/mainspipe.dmi'
- layer = PIPES_LAYER
- plane = PLATING_PLANE
-
- var/volume = 0
-
- var/alert_pressure = 80*ONE_ATMOSPHERE
-
- var/initialize_mains_directions = 0
-
- var/list/obj/machinery/atmospherics/mains_pipe/nodes = new()
- var/obj/machinery/atmospherics/pipe/mains_component/supply
- var/obj/machinery/atmospherics/pipe/mains_component/scrubbers
- var/obj/machinery/atmospherics/pipe/mains_component/aux
-
- var/minimum_temperature_difference = 300
- var/thermal_conductivity = 0 //WALL_HEAT_TRANSFER_COEFFICIENT No
-
- var/maximum_pressure = 70*ONE_ATMOSPHERE
- var/fatigue_pressure = 55*ONE_ATMOSPHERE
- alert_pressure = 55*ONE_ATMOSPHERE
-
- New()
- ..()
-
- supply = new(src)
- supply.volume = volume
- supply.nodes.len = nodes.len
- scrubbers = new(src)
- scrubbers.volume = volume
- scrubbers.nodes.len = nodes.len
- aux = new(src)
- aux.volume = volume
- aux.nodes.len = nodes.len
-
- hide(var/i)
- if(level == 1 && istype(loc, /turf/simulated))
- invisibility = i ? 101 : 0
- update_icon()
-
- proc/burst()
- for(var/obj/machinery/atmospherics/pipe/mains_component/pipe in contents)
- burst()
-
- proc/check_pressure(pressure)
- var/datum/gas_mixture/environment = loc.return_air()
-
- var/pressure_difference = pressure - environment.return_pressure()
-
- if(pressure_difference > maximum_pressure)
- burst()
-
- else if(pressure_difference > fatigue_pressure)
- //TODO: leak to turf, doing pfshhhhh
- if(prob(5))
- burst()
-
- else return 1
-
- get_neighbor_nodes_for_init()
- return nodes
-
- disconnect()
- ..()
- for(var/obj/machinery/atmospherics/pipe/mains_component/node in nodes)
- node.disconnect()
-
- Destroy()
- disconnect()
- ..()
-
- atmos_init()
- for(var/i = 1 to nodes.len)
- var/obj/machinery/atmospherics/mains_pipe/node = nodes[i]
- if(node)
- supply.nodes[i] = node.supply
- scrubbers.nodes[i] = node.scrubbers
- aux.nodes[i] = node.aux
-
-obj/machinery/atmospherics/mains_pipe/simple
- name = "mains pipe"
- desc = "A one meter section of 3-line mains pipe"
-
- dir = SOUTH
- initialize_mains_directions = SOUTH|NORTH
-
- New()
- nodes.len = 2
- ..()
- switch(dir)
- if(SOUTH || NORTH)
- initialize_mains_directions = SOUTH|NORTH
- if(EAST || WEST)
- initialize_mains_directions = EAST|WEST
- if(NORTHEAST)
- initialize_mains_directions = NORTH|EAST
- if(NORTHWEST)
- initialize_mains_directions = NORTH|WEST
- if(SOUTHEAST)
- initialize_mains_directions = SOUTH|EAST
- if(SOUTHWEST)
- initialize_mains_directions = SOUTH|WEST
-
- proc/normalize_dir()
- if(dir==3)
- set_dir(1)
- else if(dir==12)
- set_dir(4)
-
- update_icon()
- if(nodes[1] && nodes[2])
- icon_state = "intact[invisibility ? "-f" : "" ]"
-
- //var/node1_direction = get_dir(src, node1)
- //var/node2_direction = get_dir(src, node2)
-
- //set_dir(node1_direction|node2_direction)
-
- else
- if(!nodes[1]&&!nodes[2])
- qdel(src) //TODO: silent deleting looks weird
- var/have_node1 = nodes[1]?1:0
- var/have_node2 = nodes[2]?1:0
- icon_state = "exposed[have_node1][have_node2][invisibility ? "-f" : "" ]"
-
- atmos_init()
- normalize_dir()
- var/node1_dir
- var/node2_dir
-
- for(var/direction in cardinal)
- if(direction&initialize_mains_directions)
- if (!node1_dir)
- node1_dir = direction
- else if (!node2_dir)
- node2_dir = direction
-
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node1_dir))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[1] = target
- break
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node2_dir))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[2] = target
- break
-
- ..() // initialize internal pipes
-
- var/turf/T = src.loc // hide if turf is not intact
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
- hidden
- level = 1
- icon_state = "intact-f"
-
- visible
- level = 2
- icon_state = "intact"
-
-obj/machinery/atmospherics/mains_pipe/manifold
- name = "manifold pipe"
- desc = "A manifold composed of mains pipes"
-
- dir = SOUTH
- initialize_mains_directions = EAST|NORTH|WEST
- volume = 105
-
- New()
- nodes.len = 3
- ..()
- initialize_mains_directions = (NORTH|SOUTH|EAST|WEST) & ~dir
-
- atmos_init()
- var/connect_directions = initialize_mains_directions
-
- for(var/direction in cardinal)
- if(direction&connect_directions)
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,direction))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[1] = target
- connect_directions &= ~direction
- break
- if (nodes[1])
- break
-
-
- for(var/direction in cardinal)
- if(direction&connect_directions)
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,direction))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[2] = target
- connect_directions &= ~direction
- break
- if (nodes[2])
- break
-
-
- for(var/direction in cardinal)
- if(direction&connect_directions)
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,direction))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[3] = target
- connect_directions &= ~direction
- break
- if (nodes[3])
- break
-
- ..() // initialize internal pipes
-
- var/turf/T = src.loc // hide if turf is not intact
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
- update_icon()
- icon_state = "manifold[invisibility ? "-f" : "" ]"
-
- hidden
- level = 1
- icon_state = "manifold-f"
-
- visible
- level = 2
- icon_state = "manifold"
-
-obj/machinery/atmospherics/mains_pipe/manifold4w
- name = "manifold pipe"
- desc = "A manifold composed of mains pipes"
-
- dir = SOUTH
- initialize_mains_directions = EAST|NORTH|WEST|SOUTH
- volume = 105
-
- New()
- nodes.len = 4
- ..()
-
- atmos_init()
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,NORTH))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[1] = target
- break
-
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,SOUTH))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[2] = target
- break
-
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,EAST))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[3] = target
- break
-
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,WEST))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[3] = target
- break
-
- ..() // initialize internal pipes
-
- var/turf/T = src.loc // hide if turf is not intact
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
- update_icon()
- icon_state = "manifold4w[invisibility ? "-f" : "" ]"
-
- hidden
- level = 1
- icon_state = "manifold4w-f"
-
- visible
- level = 2
- icon_state = "manifold4w"
-
-obj/machinery/atmospherics/mains_pipe/split
- name = "mains splitter"
- desc = "A splitter for connecting to a single pipe off a mains."
-
- var/obj/machinery/atmospherics/pipe/mains_component/split_node
- var/obj/machinery/atmospherics/node3
- var/icon_type
-
- New()
- nodes.len = 2
- ..()
- initialize_mains_directions = turn(dir, 90) | turn(dir, -90)
- initialize_directions = dir // actually have a normal connection too
-
- atmos_init()
- var/node1_dir
- var/node2_dir
- var/node3_dir
-
- node1_dir = turn(dir, 90)
- node2_dir = turn(dir, -90)
- node3_dir = dir
-
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node1_dir))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[1] = target
- break
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node2_dir))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[2] = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir))
- if(target.initialize_directions & get_dir(target,src))
- node3 = target
- break
-
- ..() // initialize internal pipes
-
- // bind them
- spawn(5)
- if(node3 && split_node)
- var/datum/pipe_network/N1 = node3.return_network(src)
- var/datum/pipe_network/N2 = split_node.return_network(split_node)
- if(N1 && N2)
- N1.merge(N2)
-
- var/turf/T = src.loc // hide if turf is not intact
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
- update_icon()
- icon_state = "split-[icon_type][invisibility ? "-f" : "" ]"
-
- return_network(A)
- return split_node.return_network(A)
-
- supply
- icon_type = "supply"
-
- New()
- ..()
- split_node = supply
-
- hidden
- level = 1
- icon_state = "split-supply-f"
-
- visible
- level = 2
- icon_state = "split-supply"
-
- scrubbers
- icon_type = "scrubbers"
-
- New()
- ..()
- split_node = scrubbers
-
- hidden
- level = 1
- icon_state = "split-scrubbers-f"
-
- visible
- level = 2
- icon_state = "split-scrubbers"
-
- aux
- icon_type = "aux"
-
- New()
- ..()
- split_node = aux
-
- hidden
- level = 1
- icon_state = "split-aux-f"
-
- visible
- level = 2
- icon_state = "split-aux"
-
-obj/machinery/atmospherics/mains_pipe/split3
- name = "triple mains splitter"
- desc = "A splitter for connecting to the 3 pipes on a mainline."
-
- var/obj/machinery/atmospherics/supply_node
- var/obj/machinery/atmospherics/scrubbers_node
- var/obj/machinery/atmospherics/aux_node
-
- New()
- nodes.len = 1
- ..()
- initialize_mains_directions = dir
- initialize_directions = cardinal & ~dir // actually have a normal connection too
-
- atmos_init()
- var/node1_dir
- var/supply_node_dir
- var/scrubbers_node_dir
- var/aux_node_dir
-
- node1_dir = dir
- aux_node_dir = turn(dir, 180)
- if(dir & (NORTH|SOUTH))
- supply_node_dir = EAST
- scrubbers_node_dir = WEST
- else
- supply_node_dir = SOUTH
- scrubbers_node_dir = NORTH
-
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src, node1_dir))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[1] = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,supply_node_dir))
- if(target.initialize_directions & get_dir(target,src))
- supply_node = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,scrubbers_node_dir))
- if(target.initialize_directions & get_dir(target,src))
- scrubbers_node = target
- break
- for(var/obj/machinery/atmospherics/target in get_step(src,aux_node_dir))
- if(target.initialize_directions & get_dir(target,src))
- aux_node = target
- break
-
- ..() // initialize internal pipes
-
- // bind them
- spawn(5)
- if(supply_node)
- var/datum/pipe_network/N1 = supply_node.return_network(src)
- var/datum/pipe_network/N2 = supply.return_network(supply)
- if(N1 && N2)
- N1.merge(N2)
- if(scrubbers_node)
- var/datum/pipe_network/N1 = scrubbers_node.return_network(src)
- var/datum/pipe_network/N2 = scrubbers.return_network(scrubbers)
- if(N1 && N2)
- N1.merge(N2)
- if(aux_node)
- var/datum/pipe_network/N1 = aux_node.return_network(src)
- var/datum/pipe_network/N2 = aux.return_network(aux)
- if(N1 && N2)
- N1.merge(N2)
-
- var/turf/T = src.loc // hide if turf is not intact
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
- update_icon()
- icon_state = "split-t[invisibility ? "-f" : "" ]"
-
- return_network(obj/machinery/atmospherics/reference)
- var/obj/machinery/atmospherics/A
-
- A = supply_node.return_network(reference)
- if(!A)
- A = scrubbers_node.return_network(reference)
- if(!A)
- A = aux_node.return_network(reference)
-
- return A
-
- hidden
- level = 1
- icon_state = "split-t-f"
-
- visible
- level = 2
- icon_state = "split-t"
-
-obj/machinery/atmospherics/mains_pipe/cap
- name = "pipe cap"
- desc = "A cap for the end of a mains pipe"
-
- dir = SOUTH
- initialize_directions = SOUTH
- volume = 35
-
- New()
- nodes.len = 1
- ..()
- initialize_mains_directions = dir
-
- update_icon()
- icon_state = "cap[invisibility ? "-f" : ""]"
-
- atmos_init()
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,dir))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[1] = target
- break
-
- ..()
-
- var/turf/T = src.loc // hide if turf is not intact
- if(level == 1 && !T.is_plating()) hide(1)
- update_icon()
-
- hidden
- level = 1
- icon_state = "cap-f"
-
- visible
- level = 2
- icon_state = "cap"
-
-//TODO: Get Mains valves working!
-/*
-obj/machinery/atmospherics/mains_pipe/valve
- icon_state = "mvalve0"
-
- name = "mains shutoff valve"
- desc = "A mains pipe valve"
-
- var/open = 1
-
- dir = SOUTH
- initialize_mains_directions = SOUTH|NORTH
-
- New()
- nodes.len = 2
- ..()
- initialize_mains_directions = dir | turn(dir, 180)
-
- update_icon(animation)
- var/turf/simulated/floor = loc
- var/hide = istype(floor) ? floor.intact : 0
- level = 1
- for(var/obj/machinery/atmospherics/mains_pipe/node in nodes)
- if(node.level == 2)
- hide = 0
- level = 2
- break
-
- if(animation)
- flick("[hide?"h":""]mvalve[src.open][!src.open]",src)
- else
- icon_state = "[hide?"h":""]mvalve[open]"
-
- Initialize()
- normalize_dir()
- var/node1_dir
- var/node2_dir
-
- for(var/direction in cardinal)
- if(direction&initialize_mains_directions)
- if (!node1_dir)
- node1_dir = direction
- else if (!node2_dir)
- node2_dir = direction
-
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node1_dir))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[1] = target
- break
- for(var/obj/machinery/atmospherics/mains_pipe/target in get_step(src,node2_dir))
- if(target.initialize_mains_directions & get_dir(target,src))
- nodes[2] = target
- break
-
- if(open)
- ..() // initialize internal pipes
-
- update_icon()
-
- proc/normalize_dir()
- if(dir==3)
- set_dir(1)
- else if(dir==12)
- set_dir(4)
-
- proc/open()
- if(open) return 0
-
- open = 1
- update_icon()
-
- Initialize()
-
- return 1
-
- proc/close()
- if(!open) return 0
-
- open = 0
- update_icon()
-
- for(var/obj/machinery/atmospherics/pipe/mains_component/node in src)
- for(var/obj/machinery/atmospherics/pipe/mains_component/o in node.nodes)
- o.disconnect(node)
- o.build_network()
-
- return 1
-
- attack_ai(mob/user as mob)
- return
-
- attack_paw(mob/user as mob)
- return attack_hand(user)
-
- attack_hand(mob/user as mob)
- src.add_fingerprint(usr)
- update_icon(1)
- sleep(10)
- if (open)
- close()
- else
- open()
-
- digital // can be controlled by AI
- name = "digital mains valve"
- desc = "A digitally controlled valve."
- icon_state = "dvalve0"
-
- attack_ai(mob/user as mob)
- return src.attack_hand(user)
-
- attack_hand(mob/user as mob)
- if(!src.allowed(user))
- to_chat(user, "Access denied.")
- return
- ..()
-
- //Radio remote control
-
- proc
- set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
- frequency = new_frequency
- if(frequency)
- radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
-
- var/frequency = 0
- var/id = null
- var/datum/radio_frequency/radio_connection
-
- Initialize()
- ..()
- if(frequency)
- set_frequency(frequency)
-
- update_icon(animation)
- var/turf/simulated/floor = loc
- var/hide = istype(floor) ? floor.intact : 0
- level = 1
- for(var/obj/machinery/atmospherics/mains_pipe/node in nodes)
- if(node.level == 2)
- hide = 0
- level = 2
- break
-
- if(animation)
- flick("[hide?"h":""]dvalve[src.open][!src.open]",src)
- else
- icon_state = "[hide?"h":""]dvalve[open]"
-
- receive_signal(datum/signal/signal)
- if(!signal.data["tag"] || (signal.data["tag"] != id))
- return 0
-
- switch(signal.data["command"])
- if("valve_open")
- if(!open)
- open()
-
- if("valve_close")
- if(open)
- close()
-
- if("valve_toggle")
- if(open)
- close()
- else
- open()
-*/
diff --git a/code/ATMOSPHERICS/pipes/he_pipes.dm b/code/ATMOSPHERICS/pipes/he_pipes.dm
index 11f826ae050..0d9e673e689 100644
--- a/code/ATMOSPHERICS/pipes/he_pipes.dm
+++ b/code/ATMOSPHERICS/pipes/he_pipes.dm
@@ -23,8 +23,8 @@
buckle_lying = 1
// BubbleWrap
-/obj/machinery/atmospherics/pipe/simple/heat_exchanging/New()
- ..()
+/obj/machinery/atmospherics/pipe/simple/heat_exchanging/Initialize()
+ . = ..()
// BubbleWrap END
color = "#404040" //we don't make use of the fancy overlay system for colours, use this to set the default.
diff --git a/code/ATMOSPHERICS/pipes/manifold.dm b/code/ATMOSPHERICS/pipes/manifold.dm
index a02f0e66de0..88cb10994ea 100644
--- a/code/ATMOSPHERICS/pipes/manifold.dm
+++ b/code/ATMOSPHERICS/pipes/manifold.dm
@@ -19,8 +19,8 @@
level = 1
-/obj/machinery/atmospherics/pipe/manifold/New()
- ..()
+/obj/machinery/atmospherics/pipe/manifold/Initialize()
+ . = ..()
alpha = 255
icon = null
diff --git a/code/ATMOSPHERICS/pipes/manifold4w.dm b/code/ATMOSPHERICS/pipes/manifold4w.dm
index eac8494a65d..3773ebce73b 100644
--- a/code/ATMOSPHERICS/pipes/manifold4w.dm
+++ b/code/ATMOSPHERICS/pipes/manifold4w.dm
@@ -20,8 +20,8 @@
level = 1
-/obj/machinery/atmospherics/pipe/manifold4w/New()
- ..()
+/obj/machinery/atmospherics/pipe/manifold4w/Initialize()
+ . = ..()
alpha = 255
icon = null
diff --git a/code/ATMOSPHERICS/pipes/pipe_base.dm b/code/ATMOSPHERICS/pipes/pipe_base.dm
index d06b192a1a3..b25c3c5dfda 100644
--- a/code/ATMOSPHERICS/pipes/pipe_base.dm
+++ b/code/ATMOSPHERICS/pipes/pipe_base.dm
@@ -24,10 +24,10 @@
/obj/machinery/atmospherics/pipe/drain_power()
return -1
-/obj/machinery/atmospherics/pipe/New()
+/obj/machinery/atmospherics/pipe/Initialize()
if(istype(get_turf(src), /turf/simulated/wall) || istype(get_turf(src), /turf/simulated/shuttle/wall) || istype(get_turf(src), /turf/unsimulated/wall))
level = 1
- ..()
+ . = ..()
/obj/machinery/atmospherics/pipe/hides_under_flooring()
return level != 2
@@ -109,29 +109,29 @@
qdel(meter)
. = ..()
-/obj/machinery/atmospherics/pipe/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
+/obj/machinery/atmospherics/pipe/attackby(var/obj/item/W as obj, var/mob/user as mob)
if (istype(src, /obj/machinery/atmospherics/pipe/tank))
return ..()
- if(istype(W,/obj/item/device/pipe_painter))
+ if(istype(W,/obj/item/pipe_painter))
return 0
if (!W.has_tool_quality(TOOL_WRENCH))
return ..()
var/turf/T = src.loc
if (level==1 && isturf(T) && !T.is_plating())
- to_chat(user, "You must remove the plating first.")
+ to_chat(user, span_warning("You must remove the plating first."))
return 1
if(!can_unwrench())
- to_chat(user, "You cannot unwrench \the [src], it is too exerted due to internal pressure.")
+ to_chat(user, span_warning("You cannot unwrench \the [src], it is too exerted due to internal pressure."))
add_fingerprint(user)
return 1
playsound(src, W.usesound, 50, 1)
- to_chat(user, "You begin to unfasten \the [src]...")
+ to_chat(user, span_notice("You begin to unfasten \the [src]..."))
if (do_after(user, 10 * W.toolspeed))
user.visible_message( \
- "\The [user] unfastens \the [src].", \
- "You have unfastened \the [src].", \
+ span_infoplain(span_bold("\The [user]") + " unfastens \the [src]."), \
+ span_notice("You have unfastened \the [src]."), \
"You hear a ratchet.")
deconstruct()
diff --git a/code/ATMOSPHERICS/pipes/simple.dm b/code/ATMOSPHERICS/pipes/simple.dm
index def462a354e..466e943bed0 100644
--- a/code/ATMOSPHERICS/pipes/simple.dm
+++ b/code/ATMOSPHERICS/pipes/simple.dm
@@ -26,8 +26,8 @@
level = 1
-/obj/machinery/atmospherics/pipe/simple/New()
- ..()
+/obj/machinery/atmospherics/pipe/simple/Initialize()
+ . = ..()
// Pipe colors and icon states are handled by an image cache - so color and icon should
// be null. For mapping purposes color is defined in the object definitions.
@@ -77,7 +77,7 @@
initialize_directions = SOUTH|WEST
/obj/machinery/atmospherics/pipe/simple/proc/burst()
- src.visible_message("\The [src] bursts!");
+ src.visible_message(span_danger("\The [src] bursts!"));
playsound(src, 'sound/effects/bang.ogg', 25, 1)
var/datum/effect/effect/system/smoke_spread/smoke = new
smoke.set_up(1,0, src.loc, 0)
diff --git a/code/ATMOSPHERICS/pipes/tank.dm b/code/ATMOSPHERICS/pipes/tank.dm
index 63807862880..34afa7bbe4f 100644
--- a/code/ATMOSPHERICS/pipes/tank.dm
+++ b/code/ATMOSPHERICS/pipes/tank.dm
@@ -18,9 +18,9 @@
pipe_flags = PIPING_DEFAULT_LAYER_ONLY
density = TRUE
-/obj/machinery/atmospherics/pipe/tank/New()
+/obj/machinery/atmospherics/pipe/tank/Initialize()
icon_state = "air"
- ..()
+ . = ..()
/obj/machinery/atmospherics/pipe/tank/init_dir()
initialize_directions = dir
@@ -67,14 +67,14 @@
return null
/obj/machinery/atmospherics/pipe/tank/attackby(var/obj/item/W as obj, var/mob/user as mob)
- if(istype(W, /obj/item/device/pipe_painter))
+ if(istype(W, /obj/item/pipe_painter))
return
/obj/machinery/atmospherics/pipe/tank/air
name = "Pressure Tank (Air)"
icon_state = "air_map"
-/obj/machinery/atmospherics/pipe/tank/air/New()
+/obj/machinery/atmospherics/pipe/tank/air/Initialize()
air_temporary = new
air_temporary.volume = volume
air_temporary.temperature = T20C
@@ -83,21 +83,21 @@
"nitrogen",(start_pressure*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
- ..()
+ . = ..()
icon_state = "air"
/obj/machinery/atmospherics/pipe/tank/oxygen
name = "Pressure Tank (Oxygen)"
icon_state = "o2_map"
-/obj/machinery/atmospherics/pipe/tank/oxygen/New()
+/obj/machinery/atmospherics/pipe/tank/oxygen/Initialize()
air_temporary = new
air_temporary.volume = volume
air_temporary.temperature = T20C
air_temporary.adjust_gas("oxygen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
- ..()
+ . = ..()
icon_state = "o2"
/obj/machinery/atmospherics/pipe/tank/nitrogen
@@ -105,28 +105,28 @@
icon_state = "n2_map"
volume = 40000 //Vorestation edit
-/obj/machinery/atmospherics/pipe/tank/nitrogen/New()
+/obj/machinery/atmospherics/pipe/tank/nitrogen/Initialize()
air_temporary = new
air_temporary.volume = volume
air_temporary.temperature = T20C
air_temporary.adjust_gas("nitrogen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
- ..()
+ . = ..()
icon_state = "n2"
/obj/machinery/atmospherics/pipe/tank/carbon_dioxide
name = "Pressure Tank (Carbon Dioxide)"
icon_state = "co2_map"
-/obj/machinery/atmospherics/pipe/tank/carbon_dioxide/New()
+/obj/machinery/atmospherics/pipe/tank/carbon_dioxide/Initialize()
air_temporary = new
air_temporary.volume = volume
air_temporary.temperature = T20C
air_temporary.adjust_gas("carbon_dioxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
- ..()
+ . = ..()
icon_state = "co2"
/obj/machinery/atmospherics/pipe/tank/phoron
@@ -134,26 +134,26 @@
icon_state = "phoron_map"
connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_FUEL
-/obj/machinery/atmospherics/pipe/tank/phoron/New()
+/obj/machinery/atmospherics/pipe/tank/phoron/Initialize()
air_temporary = new
air_temporary.volume = volume
air_temporary.temperature = T20C
air_temporary.adjust_gas("phoron", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
- ..()
+ . = ..()
icon_state = "phoron"
/obj/machinery/atmospherics/pipe/tank/nitrous_oxide
name = "Pressure Tank (Nitrous Oxide)"
icon_state = "n2o_map"
-/obj/machinery/atmospherics/pipe/tank/nitrous_oxide/New()
+/obj/machinery/atmospherics/pipe/tank/nitrous_oxide/Initialize()
air_temporary = new
air_temporary.volume = volume
air_temporary.temperature = T0C
air_temporary.adjust_gas("nitrous_oxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
- ..()
+ . = ..()
icon_state = "n2o"
diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm
index fcc81509c88..f02943f2f56 100644
--- a/code/ZAS/Airflow.dm
+++ b/code/ZAS/Airflow.dm
@@ -9,13 +9,13 @@ Contains helper procs for airflow, handled in /connection_group.
if(last_airflow_stun > world.time - vsc.airflow_stun_cooldown) return 0
if(!(status_flags & CANSTUN) && !(status_flags & CANWEAKEN))
- to_chat(src, "You stay upright as the air rushes past you.")
+ to_chat(src, span_notice("You stay upright as the air rushes past you."))
return 0
if(buckled)
- to_chat(src, "Air suddenly rushes past you!")
+ to_chat(src, span_notice("Air suddenly rushes past you!"))
return 0
if(!lying)
- to_chat(src, "The sudden rush of air knocks you over!")
+ to_chat(src, span_warning("The sudden rush of air knocks you over!"))
Weaken(5)
last_airflow_stun = world.time
@@ -24,7 +24,7 @@ Contains helper procs for airflow, handled in /connection_group.
/mob/living/carbon/human/airflow_stun()
if(shoes && (shoes.item_flags & NOSLIP))
- to_chat(src, "Air suddenly rushes past you!")
+ to_chat(src, span_notice("Air suddenly rushes past you!"))
return 0
..()
@@ -96,7 +96,7 @@ Contains helper procs for airflow, handled in /connection_group.
/mob/airflow_hit(atom/A)
for(var/mob/M in hearers(src))
- M.show_message("\The [src] slams into \a [A]!",1,"You hear a loud slam!",2)
+ M.show_message(span_danger("\The [src] slams into \a [A]!"),1,span_danger("You hear a loud slam!"),2)
playsound(src, "smash.ogg", 25, 1, -1)
var/weak_amt = istype(A,/obj/item) ? A:w_class : rand(1,5) //Heheheh
Weaken(weak_amt)
@@ -104,7 +104,7 @@ Contains helper procs for airflow, handled in /connection_group.
/obj/airflow_hit(atom/A)
for(var/mob/M in hearers(src))
- M.show_message("\The [src] slams into \a [A]!",1,"You hear a loud slam!",2)
+ M.show_message(span_danger("\The [src] slams into \a [A]!"),1,span_danger("You hear a loud slam!"),2)
playsound(src, "smash.ogg", 25, 1, -1)
. = ..()
@@ -114,7 +114,7 @@ Contains helper procs for airflow, handled in /connection_group.
/mob/living/carbon/human/airflow_hit(atom/A)
// for(var/mob/M in hearers(src))
-// M.show_message("[src] slams into [A]!",1,"You hear a loud slam!",2)
+// M.show_message(span_danger("[src] slams into [A]!"),1,span_danger("You hear a loud slam!"),2)
playsound(src, "punch", 25, 1, -1)
if (prob(33))
loc:add_blood(src)
diff --git a/code/ZAS/Atom.dm b/code/ZAS/Atom.dm
index bfe6fa2ad4d..eeb01b42495 100644
--- a/code/ZAS/Atom.dm
+++ b/code/ZAS/Atom.dm
@@ -36,11 +36,11 @@
//Convenience function for atoms to update turfs they occupy
/atom/movable/proc/update_nearby_tiles(need_rebuild)
- if(!air_master)
+ if(!SSair)
return 0
for(var/turf/simulated/turf in locs)
- air_master.mark_for_update(turf)
+ SSair.mark_for_update(turf)
return 1
diff --git a/code/ZAS/Connection.dm b/code/ZAS/Connection.dm
index 21be29d25e1..688eb129922 100644
--- a/code/ZAS/Connection.dm
+++ b/code/ZAS/Connection.dm
@@ -5,7 +5,7 @@
/*
Overview:
- Connections are made between turfs by air_master.connect(). They represent a single point where two zones converge.
+ Connections are made between turfs by SSair.connect(). They represent a single point where two zones converge.
Class Vars:
A - Always a simulated turf.
@@ -60,19 +60,19 @@ Class Procs:
/connection/New(turf/simulated/A, turf/simulated/B)
#ifdef ZASDBG
- ASSERT(air_master.has_valid_zone(A))
- //ASSERT(air_master.has_valid_zone(B))
+ ASSERT(HAS_VALID_ZONE(A))
+ //ASSERT(HAS_VALID_ZONE(B))
#endif
src.A = A
src.B = B
zoneA = A.zone
if(!istype(B))
mark_space()
- edge = air_master.get_edge(A.zone,B)
+ edge = SSair.get_edge(A.zone,B)
edge.add_connection(src)
else
zoneB = B.zone
- edge = air_master.get_edge(A.zone,B.zone)
+ edge = SSair.get_edge(A.zone,B.zone)
edge.add_connection(src)
/connection/proc/mark_direct()
@@ -108,7 +108,7 @@ Class Procs:
erase()
return
- var/block_status = air_master.air_blocked(A,B)
+ var/block_status = SSair.air_blocked(A,B)
if(block_status & AIR_BLOCKED)
//to_world("Blocked connection.")
erase()
@@ -133,7 +133,7 @@ Class Procs:
return
else
edge.remove_connection(src)
- edge = air_master.get_edge(A.zone, B)
+ edge = SSair.get_edge(A.zone, B)
edge.add_connection(src)
zoneA = A.zone
@@ -155,7 +155,7 @@ Class Procs:
//to_world("Zones changed, \...")
if(A.zone && B.zone)
edge.remove_connection(src)
- edge = air_master.get_edge(A.zone, B.zone)
+ edge = SSair.get_edge(A.zone, B.zone)
edge.add_connection(src)
zoneA = A.zone
zoneB = B.zone
diff --git a/code/ZAS/ConnectionGroup.dm b/code/ZAS/ConnectionGroup.dm
index 0be44bb3584..85b2545d36e 100644
--- a/code/ZAS/ConnectionGroup.dm
+++ b/code/ZAS/ConnectionGroup.dm
@@ -2,7 +2,7 @@
Overview:
These are what handle gas transfers between zones and into space.
- They are found in a zone's edges list and in air_master.edges.
+ They are found in a zone's edges list and in SSair.edges.
Each edge updates every air tick due to their role in gas transfer.
They come in two flavors, /connection_edge/zone and /connection_edge/unsimulated.
As the type names might suggest, they handle inter-zone and spacelike connections respectively.
@@ -82,7 +82,7 @@ Class Procs:
/connection_edge/proc/contains_zone(zone/Z)
/connection_edge/proc/erase()
- air_master.remove_edge(src)
+ SSair.remove_edge(src)
//to_world("[type] Erased.")
/connection_edge/proc/tick()
@@ -169,19 +169,19 @@ Class Procs:
if(equiv)
if(direct)
erase()
- air_master.merge(A, B)
+ SSair.merge(A, B)
return
else
A.air.equalize(B.air)
- air_master.mark_edge_sleeping(src)
+ SSair.mark_edge_sleeping(src)
- air_master.mark_zone_update(A)
- air_master.mark_zone_update(B)
+ SSair.mark_zone_update(A)
+ SSair.mark_zone_update(B)
/connection_edge/zone/recheck()
// Edges with only one side being vacuum need processing no matter how close.
if(!A.air.compare(B.air, vacuum_exception = 1))
- air_master.mark_edge_active(src)
+ SSair.mark_edge_active(src)
//Helper proc to get connections for a zone.
/connection_edge/zone/proc/get_connected_zone(zone/from)
@@ -233,16 +233,16 @@ Class Procs:
if(equiv)
A.air.copy_from(air)
- air_master.mark_edge_sleeping(src)
+ SSair.mark_edge_sleeping(src)
- air_master.mark_zone_update(A)
+ SSair.mark_zone_update(A)
/connection_edge/unsimulated/recheck()
// Edges with only one side being vacuum need processing no matter how close.
// Note: This handles the glaring flaw of a room holding pressure while exposed to space, but
// does not specially handle the less common case of a simulated room exposed to an unsimulated pressurized turf.
if(!A.air.compare(air, vacuum_exception = 1))
- air_master.mark_edge_active(src)
+ SSair.mark_edge_active(src)
/proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
//This implements a simplistic version of the Stefan-Boltzmann law.
diff --git a/code/ZAS/ConnectionManager.dm b/code/ZAS/ConnectionManager.dm
index 3890cd85f5c..8d7e270cde0 100644
--- a/code/ZAS/ConnectionManager.dm
+++ b/code/ZAS/ConnectionManager.dm
@@ -16,7 +16,7 @@ Class Procs:
Preferable to accessing the connection directly because it checks validity.
place(connection/c, d)
- Called by air_master.connect(). Sets the connection in the specified direction to c.
+ Called by SSair.connect(). Sets the connection in the specified direction to c.
update_all()
Called after turf/update_air_properties(). Updates the validity of all connections on this turf.
diff --git a/code/ZAS/Controller.dm b/code/ZAS/Controller.dm
deleted file mode 100644
index cfc687e34af..00000000000
--- a/code/ZAS/Controller.dm
+++ /dev/null
@@ -1,234 +0,0 @@
-var/datum/controller/subsystem/air/air_master
-
-var/tick_multiplier = 2
-
-/*
-
-Overview:
- The air controller does everything. There are tons of procs in here.
-
-Class Vars:
- zones - All zones currently holding one or more turfs.
- edges - All processing edges.
-
- tiles_to_update - Tiles scheduled to update next tick.
- zones_to_update - Zones which have had their air changed and need air archival.
- active_hotspots - All processing fire objects.
-
- active_zones - The number of zones which were archived last tick. Used in debug verbs.
- next_id - The next UID to be applied to a zone. Mostly useful for debugging purposes as zones do not need UIDs to function.
-
-Class Procs:
-
- mark_for_update(turf/T)
- Adds the turf to the update list. When updated, update_air_properties() will be called.
- When stuff changes that might affect airflow, call this. It's basically the only thing you need.
-
- add_zone(zone/Z) and remove_zone(zone/Z)
- Adds zones to the zones list. Does not mark them for update.
-
- air_blocked(turf/A, turf/B)
- Returns a bitflag consisting of:
- AIR_BLOCKED - The connection between turfs is physically blocked. No air can pass.
- ZONE_BLOCKED - There is a door between the turfs, so zones cannot cross. Air may or may not be permeable.
-
- has_valid_zone(turf/T)
- Checks the presence and validity of T's zone.
- May be called on unsimulated turfs, returning 0.
-
- merge(zone/A, zone/B)
- Called when zones have a direct connection and equivalent pressure and temperature.
- Merges the zones to create a single zone.
-
- connect(turf/simulated/A, turf/B)
- Called by turf/update_air_properties(). The first argument must be simulated.
- Creates a connection between A and B.
-
- mark_zone_update(zone/Z)
- Adds zone to the update list. Unlike mark_for_update(), this one is called automatically whenever
- air is returned from a simulated turf.
-
- equivalent_pressure(zone/A, zone/B)
- Currently identical to A.air.compare(B.air). Returns 1 when directly connected zones are ready to be merged.
-
- get_edge(zone/A, zone/B)
- get_edge(zone/A, turf/B)
- Gets a valid connection_edge between A and B, creating a new one if necessary.
-
- has_same_air(turf/A, turf/B)
- Used to determine if an unsimulated edge represents a specific turf.
- Simulated edges use connection_edge/contains_zone() for the same purpose.
- Returns 1 if A has identical gases and temperature to B.
-
- remove_edge(connection_edge/edge)
- Called when an edge is erased. Removes it from processing.
-
-*/
-
-//
-// The rest of the air subsystem is defined in air.dm
-//
-
-/datum/controller/subsystem/air
- //Geometry lists
- var/list/zones = list()
- var/list/edges = list()
- //Geometry updates lists
- var/list/tiles_to_update = list()
- var/list/zones_to_update = list()
- var/list/active_fire_zones = list()
- var/list/active_hotspots = list()
- var/list/active_edges = list()
- var/list/zones_planet_temperature_to_update = list() // YW Addition - zones_planet_temperature_to_update
-
- var/active_zones = 0
- var/current_cycle = 0
- var/next_id = 1 //Used to keep track of zone UIDs.
-
-/datum/controller/subsystem/air/proc/add_zone(zone/z)
- zones.Add(z)
- z.name = "Zone [next_id++]"
- zones_planet_temperature_to_update.Add(z) //YW Addition - planet temp
- mark_zone_update(z)
-
-/datum/controller/subsystem/air/proc/remove_zone(zone/z)
- zones.Remove(z)
- zones_to_update.Remove(z)
- zones_planet_temperature_to_update.Remove(z) //YW Addition - planet temp
-
-/datum/controller/subsystem/air/proc/air_blocked(turf/A, turf/B)
- #ifdef ZASDBG
- ASSERT(isturf(A))
- ASSERT(isturf(B))
- #endif
- var/ablock = A.c_airblock(B)
- if(ablock == BLOCKED) return BLOCKED
- return ablock | B.c_airblock(A)
-
-/datum/controller/subsystem/air/proc/has_valid_zone(turf/simulated/T)
- #ifdef ZASDBG
- ASSERT(istype(T))
- #endif
- return istype(T) && T.zone && !T.zone.invalid
-
-/datum/controller/subsystem/air/proc/merge(zone/A, zone/B)
- #ifdef ZASDBG
- ASSERT(istype(A))
- ASSERT(istype(B))
- ASSERT(!A.invalid)
- ASSERT(!B.invalid)
- ASSERT(A != B)
- #endif
- if(A.contents.len < B.contents.len)
- A.c_merge(B)
- mark_zone_update(B)
- else
- B.c_merge(A)
- mark_zone_update(A)
-
-/datum/controller/subsystem/air/proc/connect(turf/simulated/A, turf/simulated/B)
- #ifdef ZASDBG
- ASSERT(istype(A))
- ASSERT(isturf(B))
- ASSERT(A.zone)
- ASSERT(!A.zone.invalid)
- //ASSERT(B.zone)
- ASSERT(A != B)
- #endif
-
- var/block = air_master.air_blocked(A,B)
- if(block & AIR_BLOCKED) return
-
- var/direct = !(block & ZONE_BLOCKED)
- var/space = !istype(B)
-
- if(!space)
- if(min(A.zone.contents.len, B.zone.contents.len) < ZONE_MIN_SIZE || (direct && (equivalent_pressure(A.zone,B.zone) || current_cycle == 0)))
- merge(A.zone,B.zone)
- return
-
- var/a_to_b = get_dir(A,B)
- var/b_to_a = get_dir(B,A)
-
- if(!A.connections) A.connections = new
- if(!B.connections) B.connections = new
-
- if(A.connections.get(a_to_b)) return
- if(B.connections.get(b_to_a)) return
- if(!space)
- if(A.zone == B.zone) return
-
-
- var/connection/c = new /connection(A,B)
-
- A.connections.place(c, a_to_b)
- B.connections.place(c, b_to_a)
-
- if(direct) c.mark_direct()
-
-/datum/controller/subsystem/air/proc/mark_for_update(turf/T)
- #ifdef ZASDBG
- ASSERT(isturf(T))
- #endif
- if(T.needs_air_update) return
- tiles_to_update |= T
- #ifdef ZASDBG
- T.add_overlay(mark)
- #endif
- T.needs_air_update = 1
-
-/datum/controller/subsystem/air/proc/mark_zone_update(zone/Z)
- #ifdef ZASDBG
- ASSERT(istype(Z))
- #endif
- if(Z.needs_update) return
- zones_to_update.Add(Z)
- Z.needs_update = 1
-
-/datum/controller/subsystem/air/proc/mark_edge_sleeping(connection_edge/E)
- #ifdef ZASDBG
- ASSERT(istype(E))
- #endif
- if(E.sleeping) return
- active_edges.Remove(E)
- E.sleeping = 1
-
-/datum/controller/subsystem/air/proc/mark_edge_active(connection_edge/E)
- #ifdef ZASDBG
- ASSERT(istype(E))
- #endif
- if(!E.sleeping) return
- active_edges.Add(E)
- E.sleeping = 0
-
-/datum/controller/subsystem/air/proc/equivalent_pressure(zone/A, zone/B)
- return A.air.compare(B.air)
-
-/datum/controller/subsystem/air/proc/get_edge(zone/A, zone/B)
-
- if(istype(B))
- for(var/connection_edge/zone/edge in A.edges)
- if(edge.contains_zone(B)) return edge
- var/connection_edge/edge = new/connection_edge/zone(A,B)
- edges.Add(edge)
- edge.recheck()
- return edge
- else
- for(var/connection_edge/unsimulated/edge in A.edges)
- if(has_same_air(edge.B,B)) return edge
- var/connection_edge/edge = new/connection_edge/unsimulated(A,B)
- edges.Add(edge)
- edge.recheck()
- return edge
-
-/datum/controller/subsystem/air/proc/has_same_air(turf/A, turf/B)
- if(A.oxygen != B.oxygen) return 0
- if(A.nitrogen != B.nitrogen) return 0
- if(A.phoron != B.phoron) return 0
- if(A.carbon_dioxide != B.carbon_dioxide) return 0
- if(A.temperature != B.temperature) return 0
- return 1
-
-/datum/controller/subsystem/air/proc/remove_edge(connection_edge/E)
- edges.Remove(E)
- if(!E.sleeping) active_edges.Remove(E)
diff --git a/code/ZAS/Diagnostic.dm b/code/ZAS/Diagnostic.dm
index fba24568028..15fcd893479 100644
--- a/code/ZAS/Diagnostic.dm
+++ b/code/ZAS/Diagnostic.dm
@@ -1,5 +1,5 @@
/client/proc/ZoneTick()
- set category = "Debug"
+ set category = "Debug.Misc"
set name = "Process Atmos"
set desc = "Manually run a single tick of the air subsystem"
@@ -8,16 +8,16 @@
/*
if(!check_rights(R_DEBUG)) return
- var/result = air_master.Tick()
+ var/result = SSair.Tick()
if(result)
to_chat(src, "Successfully Processed.")
else
- to_chat(src, "Failed to process! ([air_master.tick_progress])")
+ to_chat(src, "Failed to process! ([SSair.tick_progress])")
*/
/client/proc/Zone_Info(turf/T as null|turf)
- set category = "Debug"
+ set category = "Debug.Misc"
if(T)
if(istype(T,/turf/simulated) && T:zone)
T:zone:dbg_data(src)
@@ -36,7 +36,7 @@
/client/var/list/zone_debug_images
/client/proc/Test_ZAS_Connection(var/turf/simulated/T as turf)
- set category = "Debug"
+ set category = "Debug.Misc"
if(!istype(T))
return
@@ -95,6 +95,6 @@
to_chat(mob, "both turfs can merge.")
/client/proc/ZASSettings()
- set category = "Debug"
+ set category = "Debug.Dangerous"
vsc.SetDefault(mob)
diff --git a/code/ZAS/Fire.dm b/code/ZAS/Fire.dm
index 5c3a24d882a..9cbf665f83b 100644
--- a/code/ZAS/Fire.dm
+++ b/code/ZAS/Fire.dm
@@ -58,7 +58,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
fuel_objs.Cut()
if(!fire_tiles.len)
- air_master.active_fire_zones.Remove(src)
+ SSair.active_fire_zones.Remove(src)
/zone/proc/remove_liquidfuel(var/used_liquid_fuel, var/remove_fire=0)
if(!fuel_objs.len)
@@ -94,7 +94,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
return 1
fire = new(src, fl)
- air_master.active_fire_zones |= zone
+ SSair.active_fire_zones |= zone
var/obj/effect/decal/cleanable/liquid_fuel/fuel = locate() in src
zone.fire_tiles |= src
@@ -177,8 +177,8 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
animate(src, color = fire_color(air_contents.temperature), 5)
set_light(l_color = color)
-/obj/fire/New(newLoc,fl)
- ..()
+/obj/fire/Initialize(mapload, fl)
+ . = ..()
if(!istype(loc, /turf))
qdel(src)
@@ -191,7 +191,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
set_light(3, 1, color)
firelevel = fl
- air_master.active_hotspots.Add(src)
+ SSair.active_hotspots.Add(src)
/obj/fire/proc/fire_color(var/env_temperature)
var/temperature = max(4000*sqrt(firelevel/vsc.fire_firelevel_multiplier), env_temperature)
@@ -209,7 +209,7 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
T.fire = null
loc = null
- air_master.active_hotspots.Remove(src)
+ SSair.active_hotspots.Remove(src)
/turf/simulated/var/fire_protection = 0 //Protects newly extinguished tiles from being overrun again.
diff --git a/code/ZAS/Phoron.dm b/code/ZAS/Phoron.dm
index a8c797ec2a3..cab64a11f8b 100644
--- a/code/ZAS/Phoron.dm
+++ b/code/ZAS/Phoron.dm
@@ -45,7 +45,7 @@ var/image/contamination_overlay = image('icons/effects/contamination.dmi')
//Clothing and backpacks can be contaminated.
if(flags & PHORONGUARD)
return 0
- else if(istype(src,/obj/item/weapon/storage/backpack))
+ else if(istype(src,/obj/item/storage/backpack))
return 0 //Cannot be washed :(
//VOREStation Addition start
else if(isbelly(loc))
@@ -82,7 +82,7 @@ var/image/contamination_overlay = image('icons/effects/contamination.dmi')
suit_contamination() //Phoron can sometimes get through such an open suit.
//Cannot wash backpacks currently.
-// if(istype(back,/obj/item/weapon/storage/backpack))
+// if(istype(back,/obj/item/storage/backpack))
// back.contaminate()
/mob/proc/pl_effects()
@@ -102,8 +102,8 @@ var/image/contamination_overlay = image('icons/effects/contamination.dmi')
if(vsc.plc.SKIN_BURNS && (species.breath_type != "phoron"))
if(!pl_head_protected() || !pl_suit_protected())
burn_skin(0.75)
- if(prob(20))
- to_chat(src, "Your skin burns!")
+ if(prob(20))
+ to_chat(src, span_danger("Your skin burns!"))
updatehealth()
//Burn eyes if exposed.
@@ -134,18 +134,18 @@ var/image/contamination_overlay = image('icons/effects/contamination.dmi')
if(vsc.plc.GENETIC_CORRUPTION && (species.breath_type != "phoron"))
if(rand(1,10000) < vsc.plc.GENETIC_CORRUPTION)
randmutb(src)
- to_chat(src, "High levels of toxins cause you to spontaneously mutate!")
+ to_chat(src, span_danger("High levels of toxins cause you to spontaneously mutate!"))
domutcheck(src,null)
/mob/living/carbon/human/proc/burn_eyes()
var/obj/item/organ/internal/eyes/E = internal_organs_by_name[O_EYES]
if(E)
if(prob(20))
- to_chat(src, "Your eyes burn!")
+ to_chat(src, span_danger("Your eyes burn!"))
E.damage += 2.5
eye_blurry = min(eye_blurry+1.5,50)
if (prob(max(0,E.damage - 15) + 1) &&!eye_blind)
- to_chat(src, "You are blinded!")
+ to_chat(src, span_danger("You are blinded!"))
Blind(20)
/mob/living/carbon/human/proc/pl_head_protected()
diff --git a/code/ZAS/Turf.dm b/code/ZAS/Turf.dm
index c05e708036b..a67970c63aa 100644
--- a/code/ZAS/Turf.dm
+++ b/code/ZAS/Turf.dm
@@ -41,9 +41,8 @@
if(istype(unsim, /turf/simulated))
var/turf/simulated/sim = unsim
- if(air_master.has_valid_zone(sim))
-
- air_master.connect(sim, src)
+ if(HAS_VALID_ZONE(sim))
+ SSair.connect(sim, src)
/*
Simple heuristic for determining if removing the turf from it's zone will not partition the zone (A very bad thing).
@@ -162,7 +161,7 @@
var/turf/simulated/sim = unsim
sim.open_directions |= reverse_dir[d]
- if(air_master.has_valid_zone(sim))
+ if(HAS_VALID_ZONE(sim))
//Might have assigned a zone, since this happens for each direction.
if(!zone)
@@ -195,7 +194,7 @@
if(verbose) to_world("Connecting to [sim.zone]")
#endif
- air_master.connect(src, sim)
+ SSair.connect(src, sim)
#ifdef ZASDBG
@@ -210,7 +209,7 @@
if(!postponed) postponed = list()
postponed.Add(unsim)
- if(!air_master.has_valid_zone(src)) //Still no zone, make a new one.
+ if(!HAS_VALID_ZONE(src)) //Still no zone, make a new one.
var/zone/newzone = new/zone()
newzone.add(src)
@@ -223,7 +222,7 @@
//At this point, a zone should have happened. If it hasn't, don't add more checks, fix the bug.
for(var/turf/T in postponed)
- air_master.connect(src, T)
+ SSair.connect(src, T)
/turf/proc/post_update_air_properties()
if(connections) connections.update_all()
@@ -279,7 +278,7 @@
/turf/simulated/return_air()
if(zone)
if(!zone.invalid)
- air_master.mark_zone_update(zone)
+ SSair.mark_zone_update(zone)
return zone.air
else
if(!air)
diff --git a/code/ZAS/Variable Settings.dm b/code/ZAS/Variable Settings.dm
index d55bcc64de2..8867060e6fc 100644
--- a/code/ZAS/Variable Settings.dm
+++ b/code/ZAS/Variable Settings.dm
@@ -110,7 +110,7 @@ var/global/vs_control/vsc = new
vw = vars[ch]
if("[ch]_DESC" in vars) vw_desc = vars["[ch]_DESC"]
if("[ch]_NAME" in vars) vw_name = vars["[ch]_NAME"]
- dat += "[vw_name] = [vw] \[Change\]
"
+ dat += span_bold("[vw_name] = [vw]") + " \[Change\]
"
dat += "[vw_desc]
"
user << browse(dat,"window=settings")
@@ -168,7 +168,7 @@ var/global/vs_control/vsc = new
vars[ch] = vw
if(how == "Toggle")
newvar = (newvar?"ON":"OFF")
- to_world("[key_name(user)] changed the setting [display_description] to [newvar].")
+ to_world(span_world(span_blue("[key_name(user)] changed the setting [display_description] to [newvar].")))
if(ch in plc.settings)
ChangeSettingsDialog(user,plc.settings)
else
@@ -321,7 +321,7 @@ var/global/vs_control/vsc = new
plc.N2O_HALLUCINATION = initial(plc.N2O_HALLUCINATION)
- to_world("[key_name(user)] changed the global phoron/ZAS settings to \"[def]\"")
+ to_world(span_world(span_blue("[key_name(user)] changed the global phoron/ZAS settings to \"[def]\"")))
/pl_control/var/list/settings = list()
diff --git a/code/ZAS/Zone.dm b/code/ZAS/Zone.dm
index d07a280d040..b6d012afe7d 100644
--- a/code/ZAS/Zone.dm
+++ b/code/ZAS/Zone.dm
@@ -56,7 +56,7 @@ Class Procs:
/zone/var/list/graphic_remove = list()
/zone/New()
- air_master.add_zone(src)
+ SSair.add_zone(src)
air.temperature = TCMB
air.group_multiplier = 1
air.volume = CELL_VOLUME
@@ -65,7 +65,7 @@ Class Procs:
#ifdef ZASDBG
ASSERT(!invalid)
ASSERT(istype(T))
- ASSERT(!air_master.has_valid_zone(T))
+ ASSERT(!HAS_VALID_ZONE(T))
#endif
var/datum/gas_mixture/turf_air = T.return_air()
@@ -75,7 +75,7 @@ Class Procs:
if(T.fire)
var/obj/effect/decal/cleanable/liquid_fuel/fuel = locate() in T
fire_tiles.Add(T)
- air_master.active_fire_zones |= src
+ SSair.active_fire_zones |= src
if(fuel) fuel_objs += fuel
if(air.graphic)
T.update_graphic(air.graphic)
@@ -122,11 +122,11 @@ Class Procs:
if(E.contains_zone(into))
continue //don't need to rebuild this edge
for(var/turf/T in E.connecting_turfs)
- air_master.mark_for_update(T)
+ SSair.mark_for_update(T)
/zone/proc/c_invalidate()
invalid = 1
- air_master.remove_zone(src)
+ SSair.remove_zone(src)
#ifdef ZASDBG
for(var/turf/simulated/T in contents)
T.dbg(invalid_zone)
@@ -141,7 +141,7 @@ Class Procs:
T.update_graphic(graphic_remove = air_graphic) //we need to remove the overlays so they're not doubled when the zone is rebuilt
//T.dbg(invalid_zone)
T.needs_air_update = 0 //Reset the marker so that it will be added to the list.
- air_master.mark_for_update(T)
+ SSair.mark_for_update(T)
/zone/proc/add_tile_air(datum/gas_mixture/tile_air)
//air.volume += CELL_VOLUME
@@ -152,7 +152,7 @@ Class Procs:
air.group_multiplier = contents.len+1
/zone/proc/tick()
- if(air.temperature >= PHORON_FLASHPOINT && !(src in air_master.active_fire_zones) && air.check_combustability() && contents.len)
+ if(air.temperature >= PHORON_FLASHPOINT && !(src in SSair.active_fire_zones) && air.check_combustability() && contents.len)
var/turf/T = pick(contents)
if(istype(T))
T.create_fire(vsc.fire_firelevel_multiplier)
@@ -171,7 +171,7 @@ Class Procs:
to_chat(M,name)
for(var/g in air.gas)
to_chat(M, "[gas_data.name[g]]: [air.gas[g]]")
- to_chat(M, "P: [air.return_pressure()] kPa V: [air.volume]L T: [air.temperature]°K ([air.temperature - T0C]°C)")
+ to_chat(M, "P: [air.return_pressure()] kPa V: [air.volume]L T: [air.temperature]�K ([air.temperature - T0C]�C)")
to_chat(M, "O2 per N2: [(air.gas["nitrogen"] ? air.gas["oxygen"]/air.gas["nitrogen"] : "N/A")] Moles: [air.total_moles]")
to_chat(M, "Simulated: [contents.len] ([air.group_multiplier])")
//to_chat(M, "Unsimulated: [unsimulated_contents.len]")
@@ -192,4 +192,4 @@ Class Procs:
to_chat(M, "Space Edges: [space_edges] ([space_coefficient] connections)")
//for(var/turf/T in unsimulated_contents)
- // to_chat(M, "[T] at ([T.x],[T.y])")
\ No newline at end of file
+ // to_chat(M, "[T] at ([T.x],[T.y])")
diff --git a/code/ZAS/_docs.dm b/code/ZAS/_docs.dm
index 382f1f0abbf..822c8ac7b2a 100644
--- a/code/ZAS/_docs.dm
+++ b/code/ZAS/_docs.dm
@@ -15,7 +15,7 @@ Every air tick:
Important Functions:
-air_master.mark_for_update(turf)
+SSair.mark_for_update(turf)
When stuff happens, call this. It works on everything. You basically don't need to worry about any other
functions besides CanPass().
diff --git a/code/__defines/MC.dm b/code/__defines/MC.dm
index 57161ffac8c..2c4360add9c 100644
--- a/code/__defines/MC.dm
+++ b/code/__defines/MC.dm
@@ -18,6 +18,15 @@
#define MC_AVG_FAST_UP_SLOW_DOWN(average, current) (average > current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
#define MC_AVG_SLOW_UP_FAST_DOWN(average, current) (average < current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
+///creates a running average of "things elapsed" per time period when you need to count via a smaller time period.
+///eg you want an average number of things happening per second but you measure the event every tick (50 milliseconds).
+///make sure both time intervals are in the same units. doesn't work if current_duration > total_duration or if total_duration == 0
+#define MC_AVG_OVER_TIME(average, current, total_duration, current_duration) ((((total_duration) - (current_duration)) / (total_duration)) * (average) + (current))
+
+#define MC_AVG_MINUTES(average, current, current_duration) (MC_AVG_OVER_TIME(average, current, 1 MINUTES, current_duration))
+
+#define MC_AVG_SECONDS(average, current, current_duration) (MC_AVG_OVER_TIME(average, current, 1 SECONDS, current_duration))
+
#define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;}
#define START_PROCESSING(Processor, Datum) if (!(Datum.datum_flags & DF_ISPROCESSING)) {Datum.datum_flags |= DF_ISPROCESSING;Processor.processing += Datum}
@@ -63,21 +72,42 @@
#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 init stages
+#define INITSTAGE_EARLY 1 //! Early init stuff that doesn't need to wait for mapload
+#define INITSTAGE_MAIN 2 //! Main init stage
+#define INITSTAGE_MAX 2 //! Highest initstage.
#define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\
/datum/controller/subsystem/##X/New(){\
- NEW_SS_GLOBAL(SS##X);\
- PreInit();\
+ NEW_SS_GLOBAL(SS##X);\
+ PreInit();\
}\
/datum/controller/subsystem/##X
+#define TIMER_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/timer/##X);\
+/datum/controller/subsystem/timer/##X/New(){\
+ NEW_SS_GLOBAL(SS##X);\
+ PreInit();\
+}\
+/datum/controller/subsystem/timer/##X/fire() {..() /*just so it shows up on the profiler*/} \
+/datum/controller/subsystem/timer/##X
+
#define PROCESSING_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/processing/##X);\
/datum/controller/subsystem/processing/##X/New(){\
- NEW_SS_GLOBAL(SS##X);\
- PreInit();\
+ NEW_SS_GLOBAL(SS##X);\
+ PreInit();\
}\
+/datum/controller/subsystem/processing/##X/fire() {..() /*just so it shows up on the profiler*/} \
/datum/controller/subsystem/processing/##X
+#define VERB_MANAGER_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/verb_manager/##X);\
+/datum/controller/subsystem/verb_manager/##X/New(){\
+ NEW_SS_GLOBAL(SS##X);\
+ PreInit();\
+}\
+/datum/controller/subsystem/verb_manager/##X/fire() {..() /*just so it shows up on the profiler*/} \
+/datum/controller/subsystem/verb_manager/##X
+
// Boilerplate code for multi-step processors. See machines.dm for example use.
#define INTERNAL_PROCESS_STEP(this_step, initial_step, proc_to_call, cost_var, next_step)\
if(current_step == this_step || (initial_step && !resumed)) /* So we start at step 1 if not resumed.*/ {\
diff --git a/code/__defines/ZAS.dm b/code/__defines/ZAS.dm
index ba2b4b73e76..c8289fdc271 100644
--- a/code/__defines/ZAS.dm
+++ b/code/__defines/ZAS.dm
@@ -11,3 +11,5 @@
#define ATMOS_PASS_NO 2 // Never blocks air or zones.
#define ATMOS_PASS_DENSITY 3 // Blocks air and zones if density = TRUE, allows both if density = FALSE
#define ATMOS_PASS_PROC 4 // Call CanZASPass() using c_airblock
+
+#define HAS_VALID_ZONE(T) (T.zone && !T.zone.invalid)
diff --git a/code/__defines/_click.dm b/code/__defines/_click.dm
new file mode 100644
index 00000000000..3bc9c08734b
--- /dev/null
+++ b/code/__defines/_click.dm
@@ -0,0 +1,56 @@
+//Defines file for byond click related parameters
+//this is mostly for ease of use and for finding all the things that use say RIGHT_CLICK rather then just searching "right"
+
+//Mouse buttons held
+#define RIGHT_CLICK "right"
+#define MIDDLE_CLICK "middle"
+#define LEFT_CLICK "left"
+
+///Mouse button that was just clicked/released
+///if(modifiers[BUTTON] == LEFT_CLICK)
+#define BUTTON "button"
+
+//Keys held down during the mouse action
+#define CTRL_CLICK "ctrl"
+#define ALT_CLICK "alt"
+#define SHIFT_CLICK "shift"
+
+//Cells involved if using a Grid control
+#define DRAG_CELL "drag-cell"
+#define DROP_CELL "drop-cell"
+
+//The button used for dragging (only sent for unrelated mouse up/down messages during a drag)
+#define DRAG "drag"
+
+//If the mouse is over a link in maptext, or this event is related to clicking such a link
+#define LINK "link"
+
+//Pixel coordinates relative to the icon's position on screen
+#define VIS_X "vis-x"
+#define VIS_Y "vis-y"
+
+//Pixel coordinates within the icon, in the icon's coordinate space
+#define ICON_X "icon-x"
+#define ICON_Y "icon-y"
+
+//Pixel coordinates in screen_loc format ("[tile_x]:[pixel_x],[tile_y]:[pixel_y]")
+#define SCREEN_LOC "screen-loc"
+
+//https://secure.byond.com/docs/ref/info.html#/atom/var/mouse_opacity
+/// Objects will ignore being clicked on regardless of their transparency (used in parallax, lighting effects, holograms, lasers, etc.)
+#define MOUSE_OPACITY_TRANSPARENT 0
+/// Objects will be clicked on if it is the topmost object and the pixel isn't transparent at the position of the mouse (default behavior for 99.99% of game objects)
+#define MOUSE_OPACITY_ICON 1
+/// Objects will be always be clicked on regardless of pixel transparency or other objects at that location (used in space vines, storage containers)
+#define MOUSE_OPACITY_OPAQUE 2
+
+/// Whatever the base action datum thinks is best
+#define SCRN_OBJ_DEFAULT "default"
+/// Floating somewhere on the hud, not in any predefined place
+#define SCRN_OBJ_FLOATING "floating"
+/// In the list of buttons stored at the top of the screen
+#define SCRN_OBJ_IN_LIST "list"
+/// In the collapseable palette
+#define SCRN_OBJ_IN_PALETTE "palette"
+/// In cult spell list
+#define SCRN_OBJ_CULT_LIST "cult_list"
diff --git a/code/__defines/_compile_options.dm b/code/__defines/_compile_options.dm
index 058115f4fd1..ffee05a3e58 100644
--- a/code/__defines/_compile_options.dm
+++ b/code/__defines/_compile_options.dm
@@ -15,11 +15,16 @@
// Movement Compile Options
//#define CARDINAL_INPUT_ONLY // Uncomment to disable diagonal player movement (restore previous cardinal-moves-only behavior)
+// CI will override these as appropriate
+// #define MAP_TEST 0
+// #define AWAY_MISSION_TEST 0
+// #define UNIT_TEST 0
+
// Comment/Uncomment this to turn off/on shuttle code debugging logs
#define DEBUG_SHUTTLES
// If we are doing the map test build, do not include the main maps, only the submaps.
-#if MAP_TEST
+#ifdef MAP_TEST
#define USING_MAP_DATUM /datum/map
#define MAP_OVERRIDE 1
#endif
@@ -41,3 +46,6 @@
#endif //ifdef GC_FAILURE_HARD_LOOKUP
#endif //ifdef REFERENCE_TRACKING
+
+// Standard flags to use for browser-options
+#define DEFAULT_CLIENT_BROWSER_OPTIONS "byondstorage,find"
diff --git a/code/__defines/_helpers.dm b/code/__defines/_helpers.dm
new file mode 100644
index 00000000000..ffd7df34160
--- /dev/null
+++ b/code/__defines/_helpers.dm
@@ -0,0 +1,17 @@
+// Stuff that is relatively "core" and is used in other defines/helpers
+
+/**
+ * The game's world.icon_size. \
+ * Ideally divisible by 16. \
+ * Ideally a number, but it
+ * can be a string ("32x32"), so more exotic coders
+ * will be sad if you use this in math.
+ */
+#define ICON_SIZE_ALL 32
+/// The X/Width dimension of ICON_SIZE. This will more than likely be the bigger axis.
+#define ICON_SIZE_X 32
+/// The Y/Height dimension of ICON_SIZE. This will more than likely be the smaller axis.
+#define ICON_SIZE_Y 32
+
+/// Takes a datum as input, returns its ref string
+#define text_ref(datum) ref(datum)
diff --git a/code/__defines/_init.dm b/code/__defines/_init.dm
new file mode 100644
index 00000000000..ccb2f266c65
--- /dev/null
+++ b/code/__defines/_init.dm
@@ -0,0 +1,19 @@
+// NEVER leave this on in your PR or the server will probably explode
+// #define ENABLE_BYOND_TRACY
+/datum/super_early_init
+
+/datum/super_early_init/New()
+ // This exists so that world.Profile() is THE FIRST PROC TO RUN in the init sequence.
+ // This allows us to get the real details of everything lagging at server start.
+ // world.Profile(PROFILE_START)
+ #if defined(ENABLE_BYOND_TRACY)
+ var/tracy_init = LIBCALL("prof.dll", "init")() // Setup Tracy integration
+ if(tracy_init != "0")
+ CRASH("Tracy init error: [tracy_init]")
+ #endif
+ // After that, the debugger is initialized.
+ // Doing it this early makes it possible to set breakpoints in the New()
+ // of things assigned to global variables or objects included in a compiled map file.
+ // world.enable_auxtools_debugger()
+
+GLOBAL_REAL(super_early_init, /datum/super_early_init) = new
diff --git a/code/__defines/_lists.dm b/code/__defines/_lists.dm
index 582c026f3c8..ebf923672dd 100644
--- a/code/__defines/_lists.dm
+++ b/code/__defines/_lists.dm
@@ -46,32 +46,4 @@
#define reverseList(L) reverseRange(L.Copy())
-// binary search sorted insert
-// IN: Object to be inserted
-// LIST: List to insert object into
-// TYPECONT: The typepath of the contents of the list
-// COMPARE: The variable on the objects to compare
-#define BINARY_INSERT(IN, LIST, TYPECONT, COMPARE) \
- var/__BIN_CTTL = length(LIST);\
- if(!__BIN_CTTL) {\
- LIST += IN;\
- } else {\
- var/__BIN_LEFT = 1;\
- var/__BIN_RIGHT = __BIN_CTTL;\
- var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
- var/##TYPECONT/__BIN_ITEM;\
- while(__BIN_LEFT < __BIN_RIGHT) {\
- __BIN_ITEM = LIST[__BIN_MID];\
- if(__BIN_ITEM.##COMPARE <= IN.##COMPARE) {\
- __BIN_LEFT = __BIN_MID + 1;\
- } else {\
- __BIN_RIGHT = __BIN_MID;\
- };\
- __BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
- };\
- __BIN_ITEM = LIST[__BIN_MID];\
- __BIN_MID = __BIN_ITEM.##COMPARE > IN.##COMPARE ? __BIN_MID : __BIN_MID + 1;\
- LIST.Insert(__BIN_MID, IN);\
- }
-
#define islist(L) istype(L, /list)
diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm
index 2bc1f6d6ca2..7da2ddbfe88 100644
--- a/code/__defines/_planes+layers.dm
+++ b/code/__defines/_planes+layers.dm
@@ -188,6 +188,10 @@ What is the naming convention for planes or layers?
#define PLANE_PLAYER_HUD_ITEMS 96 //Separate layer with which to apply colorblindness
#define PLANE_PLAYER_HUD_ABOVE 97 //Things above the player hud
+#define RADIAL_BACKGROUND_LAYER 0
+///1000 is an unimportant number, it's just to normalize copied layers
+#define RADIAL_CONTENT_LAYER 1000
+
#define PLANE_ADMIN3 99 //Purely for shenanigans (above HUD)
diff --git a/code/__defines/_tick.dm b/code/__defines/_tick.dm
index 54ac7d398d9..f336c2e27b2 100644
--- a/code/__defines/_tick.dm
+++ b/code/__defines/_tick.dm
@@ -1,15 +1,27 @@
+/// Percentage of tick to leave for master controller to run
+#define MAPTICK_MC_MIN_RESERVE 70
+#define MAPTICK_LAST_INTERNAL_TICK_USAGE (world.map_cpu)
#define TICK_LIMIT_RUNNING 80
+/// Tick limit used to resume things in stoplag
#define TICK_LIMIT_TO_RUN 70
+/// Tick limit for MC while running
#define TICK_LIMIT_MC 70
#define TICK_LIMIT_MC_INIT_DEFAULT 98
+/// for general usage of tick_usage
#define TICK_USAGE world.tick_usage
+/// to be used where the result isn't checked
+#define TICK_USAGE_REAL world.tick_usage
+/// Returns true if tick_usage is above the limit
#define TICK_CHECK ( TICK_USAGE > Master.current_ticklimit )
+/// runs stoplag if tick_usage is above the limit
#define CHECK_TICK ( TICK_CHECK ? stoplag() : 0 )
+/// Returns true if tick usage is above 95, for high priority usage
#define TICK_CHECK_HIGH_PRIORITY ( TICK_USAGE > 95 )
+/// runs stoplag if tick_usage is above 95, for high priority usage
#define CHECK_TICK_HIGH_PRIORITY ( TICK_CHECK_HIGH_PRIORITY? stoplag() : 0 )
-#define UNTIL(X) while(!(X)) stoplag()
\ No newline at end of file
+#define UNTIL(X) while(!(X)) stoplag()
diff --git a/code/__defines/action.dm b/code/__defines/action.dm
index bdbe228777c..25babfe3906 100644
--- a/code/__defines/action.dm
+++ b/code/__defines/action.dm
@@ -1,5 +1,17 @@
#define AB_CHECK_RESTRAINED 1
#define AB_CHECK_STUNNED 2
#define AB_CHECK_LYING 4
-#define AB_CHECK_ALIVE 8
-#define AB_CHECK_INSIDE 16
+#define AB_CHECK_CONSCIOUS 8
+
+///Action button triggered with right click
+#define TRIGGER_SECONDARY_ACTION (1<<0)
+///Action triggered to ignore any availability checks
+#define TRIGGER_FORCE_AVAILABLE (1<<1)
+
+#define ACTION_BUTTON_DEFAULT_BACKGROUND "_use_ui_default_background"
+
+#define UPDATE_BUTTON_NAME (1<<0)
+#define UPDATE_BUTTON_ICON (1<<1)
+#define UPDATE_BUTTON_BACKGROUND (1<<2)
+#define UPDATE_BUTTON_OVERLAY (1<<3)
+#define UPDATE_BUTTON_STATUS (1<<4)
diff --git a/code/__defines/admin.dm b/code/__defines/admin.dm
index 38af7830888..4895a51ae6c 100644
--- a/code/__defines/admin.dm
+++ b/code/__defines/admin.dm
@@ -46,6 +46,7 @@
#define SMITE_BLUESPACEARTILLERY "Bluespace Artillery"
#define SMITE_SPONTANEOUSCOMBUSTION "Spontaneous Combustion"
#define SMITE_LIGHTNINGBOLT "Lightning Bolt"
+#define SMITE_TERROR "Terrify"
#define ADMIN_QUE(user) "(?)"
#define ADMIN_FLW(user) "(FLW)"
diff --git a/code/__defines/admin_vr.dm b/code/__defines/admin_vr.dm
index 40e408d3ed7..b4893b94345 100644
--- a/code/__defines/admin_vr.dm
+++ b/code/__defines/admin_vr.dm
@@ -4,6 +4,8 @@
#define SMITE_AD_SPAM "Ad Spam"
#define SMITE_AUTOSAVE "10 Second Autosave"
#define SMITE_AUTOSAVE_WIDE "10 Second Autosave (AoE)"
+#define SMITE_SPICEREQUEST "Give Them Spice (Harmless)"
+#define SMITE_PEPPERNADE "Give Them Spice (Extra Spicy)"
#define MODIFIY_ROBOT_MODULE_ADD "Add a Module"
#define MODIFIY_ROBOT_MODULE_REMOVE "Remove a Module"
#define MODIFIY_ROBOT_APPLY_UPGRADE "Apply an Upgrade"
diff --git a/code/__defines/callbacks.dm b/code/__defines/callbacks.dm
index 126ef1ea1cf..91d036b9441 100644
--- a/code/__defines/callbacks.dm
+++ b/code/__defines/callbacks.dm
@@ -1,4 +1,8 @@
-#define GLOBAL_PROC "some_magic_bullshit"
-
+#define GLOBAL_PROC "some_magic_bullshit"
+/// A shorthand for the callback datum, [documented here](datum/callback.html)
#define CALLBACK new /datum/callback
+
#define INVOKE_ASYNC world.ImmediateInvokeAsync
+
+/// like CALLBACK but specifically for verb callbacks
+#define VERB_CALLBACK new /datum/callback/verb_callback
diff --git a/code/__defines/chemistry.dm b/code/__defines/chemistry.dm
index 63ea0e136f6..8213aa200f5 100644
--- a/code/__defines/chemistry.dm
+++ b/code/__defines/chemistry.dm
@@ -41,6 +41,7 @@
#define CE_DARKSIGHT "darksight" // Gives perfect vision in dark
#define REAGENTS_PER_SHEET 20
+#define REAGENTS_PER_ORE 20
// Attached to CE_ANTIBIOTIC
#define ANTIBIO_NORM 1
diff --git a/code/__defines/configuration.dm b/code/__defines/configuration.dm
new file mode 100644
index 00000000000..477bed243c1
--- /dev/null
+++ b/code/__defines/configuration.dm
@@ -0,0 +1,30 @@
+//config files
+#define CONFIG_GET(X) global.config.Get(/datum/config_entry/##X)
+#define CONFIG_SET(X, Y) global.config.Set(/datum/config_entry/##X, ##Y)
+
+#define CONFIG_MAPS_FILE "maps.txt"
+
+//flags
+/// can't edit
+#define CONFIG_ENTRY_LOCKED (1<<0)
+/// can't see value
+#define CONFIG_ENTRY_HIDDEN (1<<1)
+
+/// Force the config directory to be something other than "config"
+#define OVERRIDE_CONFIG_DIRECTORY_PARAMETER "config-directory"
+
+// Config entry types
+#define VALUE_MODE_NUM 0
+#define VALUE_MODE_TEXT 1
+#define VALUE_MODE_FLAG 2
+
+#define KEY_MODE_TEXT 0
+#define KEY_MODE_TYPE 1
+
+// Flags for respawn config
+/// Respawn not allowed
+#define RESPAWN_FLAG_DISABLED 0
+/// Respawn as much as you'd like
+#define RESPAWN_FLAG_FREE 1
+/// Can respawn, but not as the same character
+#define RESPAWN_FLAG_NEW_CHARACTER 2
diff --git a/code/__defines/cooldowns.dm b/code/__defines/cooldowns.dm
index a04c83a4e20..ac73690d916 100644
--- a/code/__defines/cooldowns.dm
+++ b/code/__defines/cooldowns.dm
@@ -25,6 +25,10 @@
* Cooldown system based on an datum-level associative lazylist using timers.
*/
+// random cooldowns
+#define COOLDOWN_VENOM_MILKING "venom_milking"
+#define COOLDOWN_SHIP_REFRESH "ship_refresh"
+
// admin verb cooldowns
#define COOLDOWN_INTERNET_SOUND "internet_sound"
diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm
index ad7c9b4f346..5faf4792d7f 100644
--- a/code/__defines/dcs/signals.dm
+++ b/code/__defines/dcs/signals.dm
@@ -128,7 +128,7 @@
#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change"
///from base of atom/handle_atom_del(): (atom/deleted)
#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del"
-///from base of atom/has_gravity(): (turf/location, list/forced_gravities)
+///from base of atom/get_gravity(): (turf/location, list/forced_gravities)
#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity"
///from proc/get_rad_contents(): ()
#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe"
@@ -191,6 +191,8 @@
#define COMSIG_ENTER_AREA "enter_area"
///from base of area/Exited(): (/area)
#define COMSIG_EXIT_AREA "exit_area"
+///from base of client/Click(): (atom/target, atom/location, control, params, mob/user)
+#define COMSIG_CLIENT_CLICK "atom_client_click"
///from base of atom/Click(): (location, control, params, mob/user)
#define COMSIG_CLICK "atom_click"
///from base of atom/ShiftClick(): (/mob)
@@ -219,7 +221,7 @@
///from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps)
#define COMSIG_TURF_CHANGE "turf_change"
-///from base of atom/has_gravity(): (atom/asker, list/forced_gravities)
+///from base of atom/get_gravity(): (atom/asker, list/forced_gravities)
#define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity"
///from base of turf/multiz_turf_del(): (turf/source, direction)
#define COMSIG_TURF_MULTIZ_DEL "turf_multiz_del"
@@ -714,6 +716,16 @@
///from base of datum/action/proc/Trigger(): (datum/action)
#define COMSIG_ACTION_TRIGGER "action_trigger"
#define COMPONENT_ACTION_BLOCK_TRIGGER (1<<0)
+/// From /datum/action/Grant(): (mob/grant_to)
+#define COMSIG_ACTION_GRANTED "action_grant"
+/// From /datum/action/Remove(): (mob/removed_from)
+#define COMSIG_ACTION_REMOVED "action_removed"
+/// From /datum/action/Grant(): (datum/action)
+#define COMSIG_MOB_GRANTED_ACTION "mob_action_grant"
+/// From /datum/action/Remove(): (datum/action)
+#define COMSIG_MOB_REMOVED_ACTION "mob_action_removed"
+/// From /datum/action/apply_button_overlay()
+#define COMSIG_ACTION_OVERLAY_APPLY "action_overlay_applied"
//Xenobio hotkeys
diff --git a/code/__defines/diseases.dm b/code/__defines/diseases.dm
new file mode 100644
index 00000000000..97f00252284
--- /dev/null
+++ b/code/__defines/diseases.dm
@@ -0,0 +1,29 @@
+#define VIRUS_SYMPTOM_LIMIT 6
+
+//Visibility Flags
+#define HIDDEN_SCANNER (1<<0)
+#define HIDDEN_PANDEMIC (1<<1)
+
+//Disease Flags
+#define CURABLE (1<<0)
+#define CAN_CARRY (1<<1)
+#define CAN_RESIST (1<<2)
+
+//Spread Flags
+#define SPECIAL (1<<0)
+#define NON_CONTAGIOUS (1<<1)
+#define BLOOD (1<<2)
+#define CONTACT_FEET (1<<3)
+#define CONTACT_HANDS (1<<4)
+#define CONTACT_GENERAL (1<<5)
+#define AIRBORNE (1<<6)
+
+//Severity Defines
+#define NONTHREAT "No threat"
+#define MINOR "Minor"
+#define MEDIUM "Medium"
+#define HARMFUL "Harmful"
+#define DANGEROUS "Dangerous!"
+#define BIOHAZARD "BIOHAZARD THREAT!"
+
+#define SYMPTOM_ACTIVATION_PROB 3
diff --git a/code/__defines/dna.dm b/code/__defines/dna.dm
index ecf85abcd99..10fe4d729be 100644
--- a/code/__defines/dna.dm
+++ b/code/__defines/dna.dm
@@ -99,37 +99,53 @@ var/SMALLSIZEBLOCK = 0
#define DNA_UI_BEARD_STYLE 15
#define DNA_UI_HAIR_STYLE 16
#define DNA_UI_EAR_STYLE 17 // VOREStation snippet.
-#define DNA_UI_TAIL_STYLE 18
-#define DNA_UI_PLAYERSCALE 19
-#define DNA_UI_TAIL_R 20
-#define DNA_UI_TAIL_G 21
-#define DNA_UI_TAIL_B 22
-#define DNA_UI_TAIL2_R 23
-#define DNA_UI_TAIL2_G 24
-#define DNA_UI_TAIL2_B 25
-#define DNA_UI_TAIL3_R 26
-#define DNA_UI_TAIL3_G 27
-#define DNA_UI_TAIL3_B 28
-#define DNA_UI_EARS_R 29
-#define DNA_UI_EARS_G 30
-#define DNA_UI_EARS_B 31
-#define DNA_UI_EARS2_R 32
-#define DNA_UI_EARS2_G 33
-#define DNA_UI_EARS2_B 34
-#define DNA_UI_EARS3_R 35
-#define DNA_UI_EARS3_G 36
-#define DNA_UI_EARS3_B 37
-#define DNA_UI_WING_STYLE 38
-#define DNA_UI_WING_R 39
-#define DNA_UI_WING_G 40
-#define DNA_UI_WING_B 41
-#define DNA_UI_WING2_R 42
-#define DNA_UI_WING2_G 43
-#define DNA_UI_WING2_B 44
-#define DNA_UI_WING3_R 45
-#define DNA_UI_WING3_G 46
-#define DNA_UI_WING3_B 47 // VOREStation snippet end.
-#define DNA_UI_LENGTH 47 // VOREStation Edit - Needs to match the highest number above.
+#define DNA_UI_EAR_SECONDARY_STYLE 18 // VOREStation snippet.
+#define DNA_UI_TAIL_STYLE 19
+#define DNA_UI_PLAYERSCALE 20
+#define DNA_UI_TAIL_R 21
+#define DNA_UI_TAIL_G 22
+#define DNA_UI_TAIL_B 23
+#define DNA_UI_TAIL2_R 24
+#define DNA_UI_TAIL2_G 25
+#define DNA_UI_TAIL2_B 26
+#define DNA_UI_TAIL3_R 27
+#define DNA_UI_TAIL3_G 28
+#define DNA_UI_TAIL3_B 29
+
+#define DNA_UI_EARS_R 30
+#define DNA_UI_EARS_G 31
+#define DNA_UI_EARS_B 32
+#define DNA_UI_EARS2_R 33
+#define DNA_UI_EARS2_G 34
+#define DNA_UI_EARS2_B 35
+#define DNA_UI_EARS3_R 36
+#define DNA_UI_EARS3_G 37
+#define DNA_UI_EARS3_B 38
+
+#define DNA_UI_EARS_SECONDARY_START 39
+#define DNA_UI_EARS_SECONDARY_COLOR_CHANNEL_COUNT 3
+
+#define DNA_UI_EARS_SECONDARY_R 39
+#define DNA_UI_EARS_SECONDARY_G 40
+#define DNA_UI_EARS_SECONDARY_B 41
+#define DNA_UI_EARS_SECONDARY2_R 42
+#define DNA_UI_EARS_SECONDARY2_G 43
+#define DNA_UI_EARS_SECONDARY2_B 44
+#define DNA_UI_EARS_SECONDARY3_R 45
+#define DNA_UI_EARS_SECONDARY3_G 46
+#define DNA_UI_EARS_SECONDARY3_B 47
+
+#define DNA_UI_WING_STYLE 48
+#define DNA_UI_WING_R 49
+#define DNA_UI_WING_G 50
+#define DNA_UI_WING_B 51
+#define DNA_UI_WING2_R 52
+#define DNA_UI_WING2_G 53
+#define DNA_UI_WING2_B 54
+#define DNA_UI_WING3_R 55
+#define DNA_UI_WING3_G 56
+#define DNA_UI_WING3_B 57 // VOREStation snippet end.
+#define DNA_UI_LENGTH 57 // VOREStation Edit - Needs to match the highest number above.
#define DNA_SE_LENGTH 49 // VOREStation Edit (original was UI+11)
diff --git a/code/__defines/faction.dm b/code/__defines/faction.dm
new file mode 100644
index 00000000000..a264a643ad3
--- /dev/null
+++ b/code/__defines/faction.dm
@@ -0,0 +1,118 @@
+#define FACTION_BAR "bar"
+#define FACTION_CLOWN "clown"
+#define FACTION_NONE "None"
+#define FACTION_STATION "Station"
+
+#define FACTION_AEROSTAT_INSIDE "aerostat_inside"
+#define FACTION_AEROSTAT_SURFACE "aerostat_surface"
+#define FACTION_ASTEROID_BELT "asteroid_belt"
+#define FACTION_BEACH_OUT "beach_out"
+#define FACTION_BEACH_CAVE "beach_cave"
+#define FACTION_DERELICT "derelict"
+#define FACTION_OVERMAP "overmap"
+#define FACTION_ROGUEMINES "roguemines"
+#define FACTION_SPACE_ROCK "space_rock"
+#define FACTION_SPOOKYLAND "spookyland"
+#define FACTION_THEATRE "theatre"
+#define FACTION_UNDERDARK "underdark"
+
+#define FACTION_VIRGO2 "virgo2"
+#define FACTION_VIRGO3B "virgo3b"
+
+#define FACTION_ALTEVIAN "altevian"
+#define FACTION_CULT "cult"
+#define FACTION_GLAMOUR "glamour"
+#define FACTION_PIRATE "pirate"
+#define FACTION_SHADEKIN "shadekin"
+#define FACTION_SPACE_GHOST "space ghost"
+#define FACTION_SYNDICATE "syndicate"
+#define FACTION_TECHNOMANCER "technomancer"
+#define FACTION_VAMPIRE "vampire"
+
+#define FACTION_CORRUPT "corrupt"
+#define FACTION_HIVEBOT "hivebot"
+#define FACTION_MALF_DRONE "malf_drone"
+#define FACTION_VAGRANT "vagrant"
+#define FACTION_WARDS "wards"
+
+#define FACTION_ANIMAL "animal"
+#define FACTION_BEE "bee"
+#define FACTION_BLOB "blob"
+#define FACTION_CARP "carp"
+#define FACTION_CATGIRL "catgirl"
+#define FACTION_CATSLUG "catslug"
+#define FACTION_COOKIEGIRL "cookiegirl"
+#define FACTION_CRABS "crabs"
+#define FACTION_CREATURE "creature"
+#define FACTION_DEATHCLAW "deathclaw"
+#define FACTION_DEMON "demon"
+#define FACTION_DEVIL "devil"
+#define FACTION_DIYAAB "diyaab"
+#define FACTION_DOG "dog"
+#define FACTION_DRAGON "dragon"
+#define FACTION_DUCK "duck"
+#define FACTION_FAITHLESS "faithless"
+#define FACTION_FENNEC "fennec"
+#define FACTION_FOX "fox"
+#define FACTION_GEESE "geese"
+#define FACTION_GNAT "gnat"
+#define FACTION_GOAT "goat"
+#define FACTION_GOLEM "golem"
+#define FACTION_GRAFADREKA "grafadreka"
+#define FACTION_GRUBS "grubs"
+#define FACTION_HORSE "horse"
+#define FACTION_INSECTS "insects"
+#define FACTION_JELLYFISH "jellyfish"
+#define FACTION_KURUAK "kururak"
+#define FACTION_LAMIA "lamia"
+#define FACTION_LEECH "leech"
+#define FACTION_MACROBACTERIA "macrobacteria"
+#define FACTION_MEOWL "meowl"
+#define FACTION_MIMIC "mimic"
+#define FACTION_MOUSE "mouse"
+#define FACTION_NANOMACHINES "nanomachines"
+#define FACTION_NEUTRAL "neutral"
+#define FACTION_OTIE "otie"
+#define FACTION_PAKKUN "pakkun"
+#define FACTION_PANTHER "panther"
+#define FACTION_PEASANT "peasant"
+#define FACTION_POLAR "polar"
+#define FACTION_RABBIT "rabbit"
+#define FACTION_RAPTOR "raptor"
+#define FACTION_RAY "ray"
+#define FACTION_REDPANDA "redpanda"
+#define FACTION_RUSSIAN "russian"
+#define FACTION_SAKIMM "sakimm"
+#define FACTION_SAVIK "savik"
+#define FACTION_SCARYBAT "scarybat"
+#define FACTION_SCEL "scel"
+#define FACTION_SCRUBBLE "scrubble"
+#define FACTION_SEAGULL "seagull"
+#define FACTION_SHANTAK "shantak"
+#define FACTION_SHEEP "sheep"
+#define FACTION_SIF "sif"
+#define FACTION_SIFFET "siffet"
+#define FACTION_SLIME "slime"
+#define FACTION_SNAKE "snake"
+#define FACTION_SONADILE "sonadile"
+#define FACTION_SPACESHARK "spaceshark"
+#define FACTION_SPACE_MOUSE "space mouse"
+#define FACTION_SPACE_SKELETON "space skeleton"
+#define FACTION_SPACE_TURTLE "space turtle"
+#define FACTION_SPIDERS "spiders"
+#define FACTION_STALKER "stalker"
+#define FACTION_SUCCUBUS "succubus"
+#define FACTION_SWARMER "swarmer"
+#define FACTION_TEPPI "teppi"
+#define FACTION_TUNNELCLOWN "tunnelclown"
+#define FACTION_TURKEY "turkey"
+#define FACTION_WILD_ANIMAL "wild animal"
+#define FACTION_WOLFGIRL "wolfgirl"
+#define FACTION_WOLFTAUR "wolftaur"
+#define FACTION_WORM "worm"
+#define FACTION_XENO "xeno"
+#define FACTION_CORGI "corgi"
+
+#define FACTION_PLANTS "plants"
+
+#define FACTION_MATH "MATH"
diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm
index eccfb7d30a1..7864c08d18e 100644
--- a/code/__defines/flags.dm
+++ b/code/__defines/flags.dm
@@ -55,4 +55,20 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
// Flags for do_after/do_mob exclusivity.
#define TASK_TARGET_EXCLUSIVE (1<<1)
#define TASK_USER_EXCLUSIVE (1<<2)
-#define TASK_ALL_EXCLUSIVE TASK_TARGET_EXCLUSIVE | TASK_USER_EXCLUSIVE
\ No newline at end of file
+#define TASK_ALL_EXCLUSIVE TASK_TARGET_EXCLUSIVE | TASK_USER_EXCLUSIVE
+
+// Update flags for [/atom/proc/update_appearance]
+/// Update the atom's name
+#define UPDATE_NAME (1<<0)
+/// Update the atom's desc
+#define UPDATE_DESC (1<<1)
+/// Update the atom's icon state
+#define UPDATE_ICON_STATE (1<<2)
+/// Update the atom's overlays
+#define UPDATE_OVERLAYS (1<<3)
+/// Update the atom's greyscaling
+#define UPDATE_GREYSCALE (1<<4)
+/// Update the atom's smoothing. (More accurately, queue it for an update)
+#define UPDATE_SMOOTHING (1<<5)
+/// Update the atom's icon
+#define UPDATE_ICON (UPDATE_ICON_STATE|UPDATE_OVERLAYS)
diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm
index 990ddc1fa09..74121881ce1 100644
--- a/code/__defines/gamemode.dm
+++ b/code/__defines/gamemode.dm
@@ -40,11 +40,12 @@
//VOREStation Add
#define BE_LOSTDRONE 0x10000
#define BE_MAINTPRED 0x20000
-#define BE_MORPH 0x40000
-#define BE_CORGI 0x80000
-#define BE_CURSEDSWORD 0x100000
-#define BE_SURVIVOR 0x200000
-#define BE_EVENT 0x400000
+#define BE_MAINTLURKER 0x40000
+#define BE_MORPH 0x80000
+#define BE_CORGI 0x100000
+#define BE_CURSEDSWORD 0x200000
+#define BE_SURVIVOR 0x400000
+#define BE_EVENT 0x800000
//VOREStation Add End
var/list/be_special_flags = list(
@@ -67,6 +68,7 @@ var/list/be_special_flags = list(
//VOREStation Add
"Lost Drone" = BE_LOSTDRONE,
"Maint Pred" = BE_MAINTPRED,
+ "Maint Lurker" = BE_MAINTLURKER,
"Morph" = BE_MORPH,
"Corgi" = BE_CORGI,
"Cursed Sword" = BE_CURSEDSWORD,
diff --git a/code/_onclick/hud/_defines.dm b/code/__defines/hud.dm
similarity index 94%
rename from code/_onclick/hud/_defines.dm
rename to code/__defines/hud.dm
index b39c71a7d23..84f45706abe 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/__defines/hud.dm
@@ -200,3 +200,14 @@
#define ui_mech_deco2_f "WEST+2:-7, SOUTH+9"
#define ui_smallquad "EAST-4:22,SOUTH:5"
+
+//Upper left (action buttons)
+#define ui_action_palette "WEST+0:23,NORTH-1:5"
+#define ui_action_palette_offset(north_offset) ("WEST+0:23,NORTH-[1+north_offset]:5")
+
+#define ui_palette_scroll "WEST+1:8,NORTH-6:28"
+#define ui_palette_scroll_offset(north_offset) ("WEST+1:8,NORTH-[6+north_offset]:28")
+
+#define ui_shadekin_display "EAST-1:28,CENTER-3:15"
+#define ui_lleill_display "EAST-1:28,CENTER-3:15"
+#define ui_xenochimera_danger_display "EAST-1:28,CENTER-3:15"
diff --git a/code/__defines/is_helpers.dm b/code/__defines/is_helpers.dm
index 6c924ecb3ec..1039819289e 100644
--- a/code/__defines/is_helpers.dm
+++ b/code/__defines/is_helpers.dm
@@ -13,13 +13,13 @@
#define isitem(D) istype(D, /obj/item)
-#define isradio(A) istype(A, /obj/item/device/radio)
+#define isradio(A) istype(A, /obj/item/radio)
#define isairlock(A) istype(A, /obj/machinery/door/airlock)
#define isorgan(A) istype(A, /obj/item/organ/external)
-#define isstorage(A) istype(A, /obj/item/weapon/storage)
+#define isstorage(A) istype(A, /obj/item/storage)
#define ismecha(A) istype(A, /obj/mecha)
diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm
index a7dba8be88c..2a0b2ce9dea 100644
--- a/code/__defines/items_clothing.dm
+++ b/code/__defines/items_clothing.dm
@@ -40,6 +40,9 @@
#define ACCESSORY_SLOT_ARMOR_M 0x8000
#define ACCESSORY_SLOT_HELM_C 0x10000 //24 bit - higher than 0x80000 will overflow
+#define ACCESSORY_SLOT_RING 0x20000 //rings, knuckledusters
+#define ACCESSORY_SLOT_WRIST 0x40000 //wristwatches, wrist PDA maybe?
+
// Bitmasks for the /obj/item/var/flags_inv variable. These determine when a piece of clothing hides another, i.e. a helmet hiding glasses.
// WARNING: The following flags apply only to the external suit!
#define HIDEGLOVES 0x1
diff --git a/code/__defines/jobs.dm b/code/__defines/jobs.dm
new file mode 100644
index 00000000000..2bb7c661085
--- /dev/null
+++ b/code/__defines/jobs.dm
@@ -0,0 +1,424 @@
+// Station Command jobs
+#define JOB_SITE_MANAGER "Site Manager"
+ // Site Manager alt titles
+ #define JOB_ALT_OVERSEER "Overseer"
+ #define JOB_ALT_FACILITY_DIRECTOR "Facility Director"
+ #define JOB_ALT_CHIEF_SUPERVISOR "Chief Supervisor"
+ #define JOB_ALT_CAPTAIN "Captain"
+
+#define JOB_HEAD_OF_PERSONNEL "Head of Personnel"
+ // Head of Personnel alt titles
+ #define JOB_ALT_CREW_RESOURCE_OFFICER "Crew Resources Officer"
+ #define JOB_ALT_DEPUTY_MANAGER "Deputy Manager"
+ #define JOB_ALT_STAFF_MANAGER "Staff Manager"
+ #define JOB_ALT_FACILITY_STEWARD "Facility Steward"
+ #define JOB_ALT_FIRST_MATE "First Mate"
+
+#define JOB_COMMAND_SECRETARY "Command Secretary"
+ // Command Secretary alt titles
+ #define JOB_ALT_COMMAND_LIAISON "Command Liaison"
+ #define JOB_ALT_COMMAND_ASSISTANT "Command Assistant"
+ #define JOB_ALT_COMMAND_INTERN "Command Intern"
+ #define JOB_ALT_BRIDGE_SECRETARY "Bridge Secretary"
+ #define JOB_ALT_BRIDGE_ASSISTANT "Bridge Assistant"
+
+#define JOB_HEAD_OF_SECURITY "Head of Security"
+ // Head of Security alt titles
+ #define JOB_ALT_SECURITY_COMMANDER "Security Commander"
+ #define JOB_ALT_CHIEF_OF_SECURITY "Chief of Security"
+ #define JOB_ALT_SECURITY_MANAGER "Security Manager"
+
+#define JOB_CHIEF_ENGINEER "Chief Engineer"
+ // Cheif Engineer alt titles
+ #define JOB_ALT_HEAD_ENGINEER "Head Engineer"
+ #define JOB_ALT_FOREMAN "Foreman"
+ #define JOB_ALT_MAINTENANCE_MANAGER "Maintenance Manager"
+
+#define JOB_RESEARCH_DIRECTOR "Research Director"
+ // Research Director alt titles
+ #define JOB_ALT_RESEARCH_SUPERVISOR "Research Supervisor"
+ #define JOB_ALT_RESEARCH_MANAGER "Research Manager"
+ #define JOB_ALT_HEAD_OF_DEVELOPMENT "Head of Development"
+ #define JOB_ALT_HEAD_SCIENTIST "Head Scientist"
+
+#define JOB_CHIEF_MEDICAL_OFFICER "Chief Medical Officer"
+ // Chief Medical Officer alt titles
+ #define JOB_ALT_CHIEF_PHYSICIAN "Chief Physician"
+ #define JOB_ALT_MEDICAL_DIRECTOR "Medical Director"
+ #define JOB_ALT_HEALTHCARE_MANAGER "Healthcare Manager"
+
+#define JOB_QUARTERMASTER "Quartermaster"
+ // Quartermaster alt titles
+ #define JOB_ALT_SUPPLY_CHIEF "Supply Chief"
+ #define JOB_ALT_LOGISTICS_MANAGER "Logistics Manager"
+ #define JOB_ALT_CARGO_SUPERVISOR "Cargo Supervisor"
+
+#define JOB_PATHFINDER "Away Team Leader" // was Pathfinder
+ // Pathfinder alt titles
+ #define JOB_ALT_EXPEDITION_LEAD "Expedition Lead"
+ #define JOB_ALT_EXPLORATION_MANAGER "Exploration Manager"
+//___________________________________________________________
+
+
+// Station Assistant jobs
+#define JOB_INTERN "Intern"
+ // Intern alt titles
+ #define JOB_ALT_APPRENTICE_ENGINEER "Apprentice Engineer"
+ #define JOB_ALT_RESEARCH_INTERN "Research Intern"
+ #define JOB_ALT_SECURITY_CADET "Security Cadet"
+ #define JOB_ALT_JR_CARGO_TECH "Jr. Cargo Tech"
+ #define JOB_ALT_JR_EXPLORER_TECH "Jr. Explorer"
+ #define JOB_ALT_SERVER "Server"
+ #define JOB_ALT_ASSISTANT "Assistant"
+ //Assistant/Visitor/Whatever
+ #define JOB_ALT_TECHNICAL_ASSISTANT "Technical Assistant"
+ #define JOB_ALT_MEDICAL_INTERN "Medical Intern"
+ #define JOB_ALT_RESEARCH_ASSISTANT "Research Assistant"
+ #define JOB_ALT_VISITOR "Visitor"
+ #define JOB_ALT_RESIDENT "Resident"
+//___________________________________________________________
+
+
+// Station Civilian jobs
+#define JOB_BARTENDER "Bartender"
+ // Bartender alt titles
+ #define JOB_ALT_BARKEEPR "Barkeeper"
+ #define JOB_ALT_BARMAID "Barmaid"
+ #define JOB_ALT_BARISTA "Barista"
+ #define JOB_ALT_MIXOLOGIST "Mixologist"
+
+#define JOB_CHEF "Chef"
+ // Chef alt titles
+ #define JOB_ALT_SOUSCHEF "Sous-chef"
+ #define JOB_ALT_COOK "Cook"
+ #define JOB_ALT_KITCHEN_WORKER "Kitchen Worker"
+
+#define JOB_BOTANIST "Botanist"
+ // Botanist alt titles
+ #define JOB_ALT_HYDROPONICIST "Hydroponicist"
+ #define JOB_ALT_GARDENER "Gardener"
+ #define JOB_ALT_CULTIVATOR "Cultivator"
+ #define JOB_ALT_FARMER "Farmer"
+ #define JOB_ALT_FLORIST "Florist"
+ #define JOB_ALT_RANCHER "Rancher"
+
+#define JOB_CARGO_TECHNICIAN "Cargo Technician"
+ // Cargo Technician alt titles
+ #define JOB_ALT_CARGO_LOADER "Cargo Loader"
+ #define JOB_ALT_CARGO_HANDLER "Cargo Handler"
+ #define JOB_ALT_SUPPLY_COURIER "Supply Courier"
+ #define JOB_ALT_DISPOSALS_SORTER "Disposals Sorter"
+
+#define JOB_SHAFT_MINER "Shaft Miner"
+ // Shaft Miner alt titles
+ #define JOB_ALT_DEEP_SPACE_MINER "Deep Space Miner"
+ #define JOB_ALT_DRILL_TECHNICIAN "Drill Technician"
+ #define JOB_ALT_PROSPECTOR "Prospector"
+ #define JOB_ALT_EXCAVATOR "Excavator"
+
+#define JOB_JANITOR "Janitor"
+ // Janitor alt titles
+ #define JOB_ALT_CUSTODIAN "Custodian"
+ #define JOB_ALT_SANITATION_TECHNICIAN "Sanitation Technician"
+ #define JOB_ALT_MAID "Maid"
+ #define JOB_ALT_GARBAGE_COLLECTOR "Garbage Collector"
+
+#define JOB_LIBRARIAN "Librarian"
+ // Librarian alt titles
+ #define JOB_ALT_JOURNALIST "Journalist"
+ #define JOB_ALT_REPORTER "Reporter"
+ #define JOB_ALT_WRITER "Writer"
+ #define JOB_ALT_HISTORIAN "Historian"
+ #define JOB_ALT_ARCHIVIST "Archivist"
+ #define JOB_ALT_PROFESSOR "Professor"
+ #define JOB_ALT_ACADEMIC "Academic"
+ #define JOB_ALT_PHILOSOPHER "Philosopher"
+ #define JOB_ALT_CURATOR "Curator"
+
+#define JOB_INTERNAL_AFFAIRS_AGENT "Internal Affairs Agent"
+ // Internal Affairs Agent alt titles
+ #define JOB_ALT_INTERNAL_AFFAIRS_LIAISON "Internal Affairs Liaison"
+ #define JOB_ALT_INTERNAL_AFFAIRS_DELEGATE "Internal Affairs Delegate"
+ #define JOB_ALT_INTERNAL_AFFAIRS_INVESTIGATOR "Internal Affairs Investigator"
+
+#define JOB_CHAPLAIN "Chaplain"
+ // Chaplain alt titles
+ #define JOB_ALT_MISSIONARY "Missionary"
+ #define JOB_ALT_PREACHER "Preacher"
+ #define JOB_ALT_PRIEST "Priest"
+ #define JOB_ALT_NUN "Nun"
+ #define JOB_ALT_MONK "Monk"
+ #define JOB_ALT_COUNSELOR "Counselor"
+ #define JOB_ALT_GURU "Guru"
+
+#define JOB_PILOT "Pilot"
+ // Pilot alt titles
+ #define JOB_ALT_COPILOT "Co-Pilot"
+ #define JOB_ALT_NAVIGATOR "Navigator"
+ #define JOB_ALT_HELMSMAN "Helmsman"
+
+#define JOB_ENTERTAINER "Entertainer"
+ // Entertainer alt titles
+ #define JOB_ALT_PERFORMER "Performer"
+ #define JOB_ALT_MUSICIAN "Musician"
+ #define JOB_ALT_STAGEHAND "Stagehand"
+ #define JOB_ALT_ACTOR "Actor"
+ #define JOB_ALT_DANCER "Dancer"
+ #define JOB_ALT_SINGER "Singer"
+ #define JOB_ALT_MAGICIAN "Magician"
+ #define JOB_ALT_COMEDIAN "Comedian"
+ #define JOB_ALT_TRAGEDIAN "Tragedian"
+ #define JOB_ALT_ARTIST "Artist"
+ #define JOB_ALT_GAME_MASTER "Game Master"
+
+#define JOB_ENTREPRENEUR "Entrepreneur"
+ // Entrepreneur alt titles
+ #define JOB_ALT_LAWYER "Lawyer"
+ #define JOB_ALT_PRIVATE_EYE "Private Eye"
+ #define JOB_ALT_BODYGUARD "Bodyguard"
+ #define JOB_ALT_PERSONAL_PHYSICIAN "Personal Physician"
+ #define JOB_ALT_DENTIST "Dentist"
+ #define JOB_ALT_FITNESS_INSTRUCTOR "Fitness Instructor"
+ #define JOB_ALT_YOGA_TEACHER "Yoga Teacher"
+ #define JOB_ALT_MASSEUSE "Masseuse"
+ #define JOB_ALT_TRADESPERSON "Tradesperson"
+ #define JOB_ALT_STREAMER "Streamer"
+ #define JOB_ALT_INFLUENCER "Influencer"
+ #define JOB_ALT_PARANORMAL_INVESTIGATOR "Paranormal Investigator"
+ #define JOB_ALT_PERSONAL_SECRETARY "Personal Secretary"
+ #define JOB_ALT_STYLIST "Stylist"
+ #define JOB_ALT_FISHER "Fisher"
+ #define JOB_ALT_FORTUNE_TELLER "Fortune Teller"
+ #define JOB_ALT_SPIRIT_HEALER "Spirit Healer"
+//___________________________________________________________
+
+
+// Station Engineering jobs
+#define JOB_ENGINEER "Engineer"
+ // Engineer alt titles
+ #define JOB_ALT_MAINTENANCE_TECHNICIAN "Maintenance Technician"
+ #define JOB_ALT_ENGINE_TECHNICIAN "Engine Technician"
+ #define JOB_ALT_ELECTRICIAN "Electrician"
+ #define JOB_ALT_CONSTRUCTION_ENGINEER "Construction Engineer"
+ #define JOB_ALT_ENGINEERING_CONTRACTOR "Engineering Contractor"
+ #define JOB_ALT_COMPUTER_TECHNICIAN "Computer Technician"
+ #define JOB_ALT_SALVAGE_TECHNICIAN "Salvage Technician"
+
+#define JOB_ATMOSPHERIC_TECHNICIAN "Atmospheric Technician"
+ // Atmospheric Technician alt titles
+ #define JOB_ALT_ATMOSPHERIC_ENGINEER "Atmospheric Engineer"
+ #define JOB_ALT_ATMOSPHERIC_MAINTAINER "Atmospheric Maintainer"
+ #define JOB_ALT_DISPOSALS_TECHNICIAN "Disposals Technician"
+ #define JOB_ALT_FUEL_TECHNICIAN "Fuel Technician"
+//___________________________________________________________
+
+
+// Station Away Team / Explorer jobs
+#define JOB_EXPLORER "Away Team" // was Explorer
+ // Explorer alt titles
+ #define JOB_ALT_SURVEYOR "Surveyor"
+ #define JOB_ALT_OFFSITE_SCOUT "Offsite Scout"
+ #define JOB_ALT_EXPLORER_MEDIC "Explorer Medic" // Unused
+ #define JOB_ALT_EXPLORERE_TECHNICIAN "Explorer Technician" // Unused
+
+#define JOB_FIELD_MEDIC "Away Team Medic" // was Field Medic
+ // Field Medic alt titles
+ #define JOB_ALT_EXPEDITION_MEDIC "Expedition Medic"
+ #define JOB_ALT_OFFSITE_MEDIC "Offsite Medic"
+//___________________________________________________________
+
+
+// Station Medical jobs
+#define JOB_MEDICAL_DOCTOR "Medical Doctor"
+ // Medical Doctor alt titles
+ #define JOB_ALT_PHYSICIAN "Physician"
+ #define JOB_ALT_MEDICAL_PRACTITIONER "Medical Practitioner"
+ #define JOB_ALT_SURGEON "Surgeon"
+ #define JOB_ALT_EMERGENCY_PHYSICIAN "Emergency Physician"
+ #define JOB_ALT_NURSE "Nurse"
+ #define JOB_ALT_ORDERLY "Orderly"
+ #define JOB_ALT_VIROLOGIST "Virologist"
+ #define JOB_ALT_MEDICAL_CONTRACTOR "Medical Contractor"
+
+#define JOB_CHEMIST "Chemist"
+ // Chemist alt titles
+ #define JOB_ALT_PHARMACIST "Pharmacist"
+ #define JOB_ALT_PHARMACOLOGIST "Pharmacologist"
+
+#define JOB_PSYCHIATRIST "Psychiatrist"
+ // Psychiatrist alt titles
+ #define JOB_ALT_PSYCHOLOGIST "Psychologist"
+ #define JOB_ALT_PSYCHOANALYST "Psychoanalyst"
+ #define JOB_ALT_PSYCHOTHERAPIST "Psychotherapist"
+
+#define JOB_PARAMEDIC "Paramedic"
+ // Paramedic alt titles
+ #define JOB_ALT_EMERGENCY_MEDICAL_TECHNICIAN "Emergency Medical Technician"
+ #define JOB_ALT_MEDICAL_RESPONDER "Medical Responder"
+ #define JOB_ALT_SEARCH_AND_RESCUE "Search and Rescue"
+
+#define JOB_GENETICIST "Geneticist" //Disabled atm
+//___________________________________________________________
+
+
+// Station Offduty jobs
+#define JOB_OFFDUTY_OFFICER "Off-duty Officer"
+#define JOB_OFFDUTY_ENGINEER "Off-duty Engineer"
+#define JOB_OFFDUTY_MEDIC "Off-duty Medic"
+#define JOB_OFFDUTY_SCIENTIST "Off-duty Scientist"
+#define JOB_OFFDUTY_CARGO "Off-duty Cargo"
+#define JOB_OFFDUTY_EXPLORER "Off-duty Explorer"
+#define JOB_OFFDUTY_WORKER "Off-duty Worker"
+//___________________________________________________________
+
+
+// Station Science jobs
+#define JOB_SCIENTIST "Scientist"
+ // Scientist alt titles
+ #define JOB_ALT_RESEARCHER "Researcher"
+ #define JOB_ALT_LAB_ASSISTANT "Lab Assistant"
+ #define JOB_ALT_XENOARCHAEOLOGIST "Xenoarchaeologist"
+ #define JOB_ALT_XENOPALEONTOLOGIST "Xenopaleontologist"
+ #define JOB_ALT_ANOMALIST "Anomalist"
+ #define JOB_ALT_PHORON_RESEARCHER "Phoron Researcher"
+ #define JOB_ALT_GAS_PHYSICIST "Gas Physicist"
+ #define JOB_ALT_CIRCUIT_DESIGNER "Circuit Designer"
+ #define JOB_ALT_CIRCUIT_PROGRAMMER "Circuit Programmer"
+
+#define JOB_XENOBIOLOGIST "Xenobiologist"
+ // Xenobiologist alt titles
+ #define JOB_ALT_XENOZOOLOGIST "Xenozoologist"
+ #define JOB_ALT_XENOANTHROPOLOGIST "Xenoanthropologist"
+
+#define JOB_ROBOTICIST "Roboticist"
+ // Roboticist alt titles
+ #define JOB_ALT_ASSEMBLY_TECHNICIAN "Assembly Technician"
+ #define JOB_ALT_BIOMECHANICAL_ENGINEER "Biomechanical Engineer"
+ #define JOB_ALT_MECHATRONIC_ENGINEER "Mechatronic Engineer"
+ #define JOB_ALT_SOFTWARE_ENGINEER "Software Engineer"
+
+#define JOB_XENOBOTANIST "Xenobotanist"
+ // Xenobotanist alt titles
+ #define JOB_ALT_XENOHYDROPONICIST "Xenohydroponicist"
+ #define JOB_ALT_XENOFLORIST "Xenoflorist"
+//___________________________________________________________
+
+
+// Station Security jobs
+#define JOB_WARDEN "Warden"
+ // Warden alt titles
+ #define JOB_ALT_BRIG_SENTRY "Brig Sentry"
+ #define JOB_ALT_ARMORY_SUPERINTENDENT "Armory Superintendent"
+ #define JOB_ALT_MASTERATARMS "Master-at-Arms"
+
+#define JOB_DETECTIVE "Detective"
+ // Detective alt titles
+ #define JOB_ALT_INVESTIGATOR "Investigator"
+ #define JOB_ALT_SECURITY_INSPECTOR "Security Inspector"
+ #define JOB_ALT_FORENSIC_TECHNICIAN "Forensic Technician"
+
+#define JOB_SECURITY_OFFICER "Security Officer"
+ // Security Officer alt titles
+ #define JOB_ALT_PATROL_OFFICER "Patrol Officer"
+ #define JOB_ALT_SECURITY_GUARD "Security Guard"
+ #define JOB_ALT_SECURITY_DEPUTY "Security Deputy"
+ #define JOB_ALT_JUNIOR_OFFICER "Junior Officer"
+ #define JOB_ALT_SECURITY_CONTRACTOR "Security Contractor"
+//___________________________________________________________
+
+
+// Station Robot jobs
+#define JOB_AI "AI"
+
+#define JOB_CYBORG "Cyborg"
+ // Cyborg alt titles
+ #define JOB_ALT_ROBOT "Robot"
+ #define JOB_ALT_DRONE "Drone"
+//___________________________________________________________
+
+
+// Station Sepcial jobs
+#define JOB_CLOWN "Clown"
+ // Clown alt titles
+ #define JOB_ALT_JESTER "Jester"
+ #define JOB_ALT_FOOL "Fool"
+
+#define JOB_MIME "Mime"
+ // Mime alt titles
+ #define JOB_ALT_PASEUR "Poseur"
+//___________________________________________________________
+
+
+// Talon jobs
+#define JOB_TALON_CAPTAIN "Talon Captain"
+ // Talon Captain alt titles
+ #define JOB_ALT_TALON_COMMANDER "Talon Commander"
+
+#define JOB_TALON_DOCTOR "Talon Doctor"
+ // Talon Doctor alt titles
+ #define JOB_ALT_TALON_MEDIC "Talon Medic"
+
+#define JOB_TALON_ENGINEER "Talon Engineer"
+ // Talon Engineer alt titles
+ #define JOB_ALT_TALON_TECHNICIAN "Talon Technician"
+
+#define JOB_TALON_GUARD "Talon Guard"
+ // Talon Guard alt titles
+ #define JOB_ALT_TALON_SECURITY "Talon Security"
+
+#define JOB_TALON_PILOT "Talon Pilot"
+ // Talon Pilot alt titles
+ #define JOB_ALT_TALON_HELMSMAN "Talon Helmsman"
+
+#define JOB_TALON_MINER "Talon Miner"
+ // Talon Miner alt titles
+ #define JOB_ALT_TALON_EXCAVATOR "Talon Excavator"
+//___________________________________________________________
+
+
+// Mind jobs
+#define JOB_SLIME "slime"
+#define JOB_LARVA "Larva"
+#define JOB_MONKEY "Monkey"
+#define JOB_ANIMAL "Animal"
+#define JOB_SIMPLE_MOB "Simple Mob"
+#define JOB_CORGI "Corgi"
+#define JOB_SHADE "Shade"
+#define JOB_ARTIFICER "Artificer"
+#define JOB_WRAITH "Wraith"
+#define JOB_JUGGERNAUT "Juggernaut"
+#define JOB_MODE = "MODE"
+#define JOB_DISEMBODIED_VOICE "Disembodied Voice"
+#define JOB_ALIEN "Alien"
+#define JOB_GOLEM "Golem"
+#define JOB_CORTICAL_BORER "Cortical Borer"
+
+#define JOB_SYNTHETIC_BRAIN "Synthetic Brain"
+#define JOB_ROBOTIC_INTELLIGENCE "Robotic Intelligence"
+#define JOB_POSITRONIC_BRAIN "Positronic Brain"
+#define JOB_CARBON_BASED "Carbon-based"
+#define JOB_SILICON_BASED "Silicon-based"
+#define JOB_PAI "pAI"
+#define JOB_PROMETHEAN "Promethean"
+
+#define JOB_LIVING "Living"
+#define JOB_NEW_PLAYER "New player"
+#define JOB_GHOST "Ghost"
+#define JOB_GHOSTROLES "GhostRoles"
+#define JOB_GRAFFITI "Graffiti"
+#define JOB_RECORDS "Records"
+#define JOB_DIONAEA "Dionaea"
+#define JOB_CUSTOM_LOADOUT "Custom loadout"
+
+// Speical Mind / Antag / Event jobs
+#define JOB_CULTIST "Cultist"
+#define JOB_MEME "Meme"
+#define JOB_APPRENTICE "apprentice"
+#define JOB_WIZARD "Wizard"
+#define JOB_ANTAGHUD "AntagHUD"
+#define JOB_CHANGELING "Changeling"
+#define JOB_SYNDICATE "Syndicate"
+#define JOB_XENOMORPH "Xenomorph"
+#define JOB_BORER "Borer"
+#define JOB_EMERGENCY_RESPONSE_TEAM "Emergency Response Team"
+#define JOB_MAINT_LURKER "Maintenance Lurker"
diff --git a/code/__defines/logging.dm b/code/__defines/logging.dm
index 07a121d9bb0..c0e2ce99773 100644
--- a/code/__defines/logging.dm
+++ b/code/__defines/logging.dm
@@ -1,2 +1,3 @@
#define SEND_TEXT(target, text) DIRECT_OUTPUT(target, text)
#define WRITE_FILE(file, text) DIRECT_OUTPUT(file, text)
+#define READ_FILE(file, text) DIRECT_INPUT(file, text)
diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm
index eaafb41e907..3f704657c27 100644
--- a/code/__defines/machinery.dm
+++ b/code/__defines/machinery.dm
@@ -175,15 +175,15 @@ if (!(DATUM.datum_flags & DF_ISPROCESSING)) {\
#define LOGIN_TYPE_ROBOT 3
// Computer Hardware
-#define PART_CPU /obj/item/weapon/computer_hardware/processor_unit // CPU. Without it the computer won't run. Better CPUs can run more programs at once.
-#define PART_NETWORK /obj/item/weapon/computer_hardware/network_card // Network Card component of this computer. Allows connection to NTNet
-#define PART_HDD /obj/item/weapon/computer_hardware/hard_drive // Hard Drive component of this computer. Stores programs and files.
+#define PART_CPU /obj/item/computer_hardware/processor_unit // CPU. Without it the computer won't run. Better CPUs can run more programs at once.
+#define PART_NETWORK /obj/item/computer_hardware/network_card // Network Card component of this computer. Allows connection to NTNet
+#define PART_HDD /obj/item/computer_hardware/hard_drive // Hard Drive component of this computer. Stores programs and files.
// Optional hardware (improves functionality, but is not critical for computer to work in most cases)
-#define PART_BATTERY /obj/item/weapon/computer_hardware/battery_module // An internal power source for this computer. Can be recharged.
-#define PART_CARD /obj/item/weapon/computer_hardware/card_slot // ID Card slot component of this computer. Mostly for HoP modification console that needs ID slot for modification.
-#define PART_PRINTER /obj/item/weapon/computer_hardware/nano_printer // Nano Printer component of this computer, for your everyday paperwork needs.
-//#define PART_DRIVE /obj/item/weapon/computer_hardware/hard_drive/portable // Portable data storage
-//#define PART_AI /obj/item/weapon/computer_hardware/ai_slot // AI slot, an intellicard housing that allows modifications of AIs.
-#define PART_TESLA /obj/item/weapon/computer_hardware/tesla_link // Tesla Link, Allows remote charging from nearest APC.
-//#define PART_SCANNER /obj/item/weapon/computer_hardware/scanner // One of several optional scanner attachments.
+#define PART_BATTERY /obj/item/computer_hardware/battery_module // An internal power source for this computer. Can be recharged.
+#define PART_CARD /obj/item/computer_hardware/card_slot // ID Card slot component of this computer. Mostly for HoP modification console that needs ID slot for modification.
+#define PART_PRINTER /obj/item/computer_hardware/nano_printer // Nano Printer component of this computer, for your everyday paperwork needs.
+//#define PART_DRIVE /obj/item/computer_hardware/hard_drive/portable // Portable data storage
+//#define PART_AI /obj/item/computer_hardware/ai_slot // AI slot, an intellicard housing that allows modifications of AIs.
+#define PART_TESLA /obj/item/computer_hardware/tesla_link // Tesla Link, Allows remote charging from nearest APC.
+//#define PART_SCANNER /obj/item/computer_hardware/scanner // One of several optional scanner attachments.
diff --git a/code/__defines/math.dm b/code/__defines/math.dm
index 7b5fcd8c7a5..846753ab568 100644
--- a/code/__defines/math.dm
+++ b/code/__defines/math.dm
@@ -25,6 +25,7 @@
#define SIGN(x) ( (x)!=0 ? (x) / abs(x) : 0 )
+#define ROUND_UP(x) ( -round(-(x)))
#define CEILING(x, y) ( -round(-(x) / (y)) * (y) )
// round() acts like floor(x, 1) by default but can't handle other values
@@ -219,3 +220,9 @@
#define ROUNDUPTOPOWEROFTWO(x) (2 ** -round(-log(2,x)))
#define DEFAULT(a, b) (a? a : b)
+
+// sqrt, but if you give it a negative number, you get 0 instead of a runtime
+/proc/sqrtor0(num)
+ if(num < 0)
+ return 0
+ return sqrt(num)
diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm
index 2f9337a2152..0a96c63bec4 100644
--- a/code/__defines/misc.dm
+++ b/code/__defines/misc.dm
@@ -31,7 +31,6 @@
#define MAX_CLIENT_FPS 200
// Some arbitrary defines to be used by self-pruning global lists. (see master_controller)
-#define PROCESS_KILL 26 // Used to trigger removal from a processing list.
#define MAX_GEAR_COST 15 // Used in chargen for accessory loadout limit.
// For secHUDs and medHUDs and variants. The number is the location of the image on the list hud_list of humans.
@@ -49,10 +48,6 @@
#define CLIENT_FROM_VAR(I) (ismob(I) ? I:client : (isclient(I) ? I : null))
-
-//Persistence
-#define AREA_FLAG_IS_NOT_PERSISTENT 8 // SSpersistence will not track values from this area.
-
// Shuttles.
// These define the time taken for the shuttle to get to the space station, and the time before it leaves again.
@@ -100,7 +95,21 @@
#define DEFAULT_JOB_TYPE /datum/job/assistant
//Area flags, possibly more to come
-#define RAD_SHIELDED 1 //shielded from radiation, clearly
+#define RAD_SHIELDED 0x1 //shielded from radiation, clearly
+#define BLUE_SHIELDED 0x2 // Shield from bluespace teleportation (telescience)
+#define AREA_SECRET_NAME 0x4 // This tells certain things that display areas' names that they shouldn't display this area's name.
+#define AREA_FLAG_IS_NOT_PERSISTENT 0x8 // SSpersistence will not track values from this area.
+#define AREA_FORBID_EVENTS 0x10 // random events will not start inside this area.
+#define AREA_FORBID_SINGULO 0x20 // singulo will not move in.
+#define AREA_NO_SPOILERS 0x40 // makes it much more difficult to see what is inside an area with things like mesons.
+#define AREA_SOUNDPROOF 0x80 // blocks sounds from other areas and prevents hearers on other areas from hearing the sounds within.
+#define AREA_BLOCK_PHASE_SHIFT 0x100 // Stops phase shifted mobs from entering
+#define AREA_BLOCK_GHOSTS 0x200 // Stops ghosts from entering
+#define AREA_ALLOW_LARGE_SIZE 0x400 // If mob size is limited in the area.
+#define AREA_BLOCK_SUIT_SENSORS 0x800 // If suit sensors are blocked in the area.
+#define AREA_BLOCK_TRACKING 0x1000 // If camera tracking is blocked in the area.
+#define TEMPERATURE_SHIELDED 0x2000 // YW Addition: Temperature change shielding
+#define PHASE_SHIELDED 0x4000 // YW Addition: Prevents shadekin phasing in/out in this area
// OnTopic return values
#define TOPIC_NOACTION 0
@@ -310,11 +319,6 @@ GLOBAL_LIST_EMPTY(##LIST_NAME);\
#define RAD_RESIST_CALC_DIV 0 // Each turf absorbs some fraction of the working radiation level
#define RAD_RESIST_CALC_SUB 1 // Each turf absorbs a fixed amount of radiation
-//https://secure.byond.com/docs/ref/info.html#/atom/var/mouse_opacity
-#define MOUSE_OPACITY_TRANSPARENT 0
-#define MOUSE_OPACITY_ICON 1
-#define MOUSE_OPACITY_OPAQUE 2
-
// Used by radios to indicate that they have sent a message via something other than subspace
#define RADIO_CONNECTION_FAIL 0
#define RADIO_CONNECTION_NON_SUBSPACE 1
@@ -415,24 +419,6 @@ GLOBAL_LIST_EMPTY(##LIST_NAME);\
#define send_link(target, url) target << link(url)
-#define SPAN_NOTICE(X) "[X]"
-
-#define SPAN_WARNING(X) "[X]"
-
-#define SPAN_DANGER(X) "[X]"
-
-#define SPAN_OCCULT(X) "[X]"
-
-#define FONT_SMALL(X) "[X]"
-
-#define FONT_NORMAL(X) "[X]"
-
-#define FONT_LARGE(X) "[X]"
-
-#define FONT_HUGE(X) "[X]"
-
-#define FONT_GIANT(X) "[X]"
-
// Volume Channel Defines
#define VOLUME_CHANNEL_MASTER "Master"
@@ -495,3 +481,7 @@ GLOBAL_LIST_INIT(all_volume_channels, list(
#define SPECIES_SORT_WHITELISTED 2
#define SPECIES_SORT_RESTRICTED 3
#define SPECIES_SORT_CUSTOM 4
+
+// Vote Types
+#define VOTE_RESULT_TYPE_MAJORITY "Majority"
+#define VOTE_RESULT_TYPE_SKEWED "Seventy"
diff --git a/code/__defines/misc_vr.dm b/code/__defines/misc_vr.dm
index 3fc4e6e4cfd..ab083010b10 100644
--- a/code/__defines/misc_vr.dm
+++ b/code/__defines/misc_vr.dm
@@ -40,14 +40,6 @@
//Shuttle madness!
#define SHUTTLE_CRASHED 3 // Yup that can happen now
-#define BLUE_SHIELDED 2 // Shield from bluespace teleportation (telescience)
-#define TEMPERATURE_SHIELDED 4 // YW Addition: Temperature change shielding
-// YW Addition: 8 used for persistence block somewhere else
-#define PHASE_SHIELDED 16 // YW Addition: Prevents shadekin phasing in/out in this area
-
-//Assistant/Visitor/Whatever
-#define USELESS_JOB "Visitor"
-
//Herm Gender
#define HERM "herm"
diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm
index 9478891464b..b6b6cffd657 100644
--- a/code/__defines/mobs.dm
+++ b/code/__defines/mobs.dm
@@ -328,6 +328,7 @@
#define SPECIES_XENO_HUNTER "Xenomorph Hunter"
#define SPECIES_XENO_SENTINEL "Xenomorph Sentinel"
#define SPECIES_XENO_QUEEN "Xenomorph Queen"
+#define SPECIES_XENOMORPH_HYBRID "Xenomorph Hybrid"
// Misc species. Mostly unused but might as well be complete.
#define SPECIES_SHADOW "Shadow"
@@ -341,6 +342,7 @@
#define SPECIES_REPLICANT "Replicant"
#define SPECIES_REPLICANT_ALPHA "Alpha Replicant"
#define SPECIES_REPLICANT_BETA "Beta Replicant"
+#define SPECIES_REPLICANT_CREW "Gamma Replicant"
// Used to seperate simple animals by ""intelligence"".
#define SA_PLANT 1
@@ -455,3 +457,6 @@
#define VISIBLE_GENDER_FORCE_PLURAL 1 // Used by get_visible_gender to return PLURAL
#define VISIBLE_GENDER_FORCE_IDENTIFYING 2 // Used by get_visible_gender to return the mob's identifying gender
#define VISIBLE_GENDER_FORCE_BIOLOGICAL 3 // Used by get_visible_gender to return the mob's biological gender
+
+// Default name for accesories
+#define DEVELOPER_WARNING_NAME "you should not see this..."
diff --git a/code/__defines/mobs_vr.dm b/code/__defines/mobs_vr.dm
index ae87b1c624e..1d6ecb049d5 100644
--- a/code/__defines/mobs_vr.dm
+++ b/code/__defines/mobs_vr.dm
@@ -36,6 +36,7 @@
#define SPECIES_CUSTOM "Custom Species"
#define SPECIES_TAJARAN "Tajara"
#define SPECIES_LLEILL "Lleill"
+#define SPECIES_HANNER "Hanner"
//monkey species
#define SPECIES_MONKEY_AKULA "Sobaka"
#define SPECIES_MONKEY_NEVREAN "Sparra"
diff --git a/code/__defines/plants.dm b/code/__defines/plants.dm
index bca340f2d38..cd4dc9e701c 100644
--- a/code/__defines/plants.dm
+++ b/code/__defines/plants.dm
@@ -88,21 +88,21 @@ GLOBAL_LIST_INIT(plant_item_products, list(
/obj/item/stack/material/wax = 20,
/obj/item/stack/material/log = 30,
/obj/item/stack/material/resin = 10,
- /obj/item/weapon/material/shard/shrapnel = 2,
- /obj/item/weapon/ore = 5,
- /obj/item/weapon/ore/iron = 2,
- /obj/item/weapon/ore/coal = 2,
- /obj/item/weapon/reagent_containers/food/snacks/meat = 3,
+ /obj/item/material/shard/shrapnel = 2,
+ /obj/item/ore = 5,
+ /obj/item/ore/iron = 2,
+ /obj/item/ore/coal = 2,
+ /obj/item/reagent_containers/food/snacks/meat = 3,
/obj/random/meat = 1,
- /obj/item/weapon/reagent_containers/food/drinks/smallchocmilk = 2,
- /obj/item/weapon/reagent_containers/food/drinks/smallmilk = 2,
+ /obj/item/reagent_containers/food/drinks/smallchocmilk = 2,
+ /obj/item/reagent_containers/food/drinks/smallmilk = 2,
/obj/item/ammo_casing/a145 = 1,
/obj/item/ammo_casing/chemdart/small = 1,
/obj/item/ammo_casing/chemdart = 1,
/obj/item/organ/internal/brain/grey = 1,
/obj/item/organ/internal/heart/grey = 1,
- /obj/item/weapon/spacecash/c1 = 3,
- /obj/item/weapon/spacecash/c5 = 1
+ /obj/item/spacecash/c1 = 3,
+ /obj/item/spacecash/c5 = 1
))
GLOBAL_LIST_INIT(forbidden_plant_growth_sprites, list(
diff --git a/code/__defines/preferences.dm b/code/__defines/preferences.dm
index ba0abca8cf3..14adeb62bb7 100644
--- a/code/__defines/preferences.dm
+++ b/code/__defines/preferences.dm
@@ -15,3 +15,38 @@
#define MULTILINGUAL_MODE_MAX 4
#define SAVE_RESET -1
+
+// Values for /datum/preference/savefile_identifier
+/// This preference is character specific.
+#define PREFERENCE_CHARACTER "character"
+/// This preference is account specific.
+#define PREFERENCE_PLAYER "player"
+
+// Values for /datum/preferences/current_tab
+/// Open the character preference window
+#define PREFERENCE_TAB_CHARACTER_PREFERENCES 0
+
+/// Open the game preferences window
+#define PREFERENCE_TAB_GAME_PREFERENCES 1
+
+/// These will be shown in the character sidebar, but at the bottom.
+#define PREFERENCE_CATEGORY_FEATURES "features"
+
+/// Any preferences that will show to the sides of the character in the setup menu.
+#define PREFERENCE_CATEGORY_CLOTHING "clothing"
+
+/// Preferences that will be put into the 3rd list, and are not contextual.
+#define PREFERENCE_CATEGORY_NON_CONTEXTUAL "non_contextual"
+
+/// Will be put under the game preferences window.
+#define PREFERENCE_CATEGORY_GAME_PREFERENCES "game_preferences"
+
+/// These will show in the list to the right of the character preview.
+#define PREFERENCE_CATEGORY_SECONDARY_FEATURES "secondary_features"
+
+/// These are preferences that are supplementary for main features,
+/// such as hair color being affixed to hair.
+#define PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES "supplemental_features"
+
+/// These preferences will not be rendered on the preferences page, and are practically invisible unless specifically rendered. Used for quirks, currently.
+#define PREFERENCE_CATEGORY_MANUALLY_RENDERED "manually_rendered_features"
diff --git a/code/__defines/radio.dm b/code/__defines/radio.dm
new file mode 100644
index 00000000000..b39e6a90cc5
--- /dev/null
+++ b/code/__defines/radio.dm
@@ -0,0 +1,28 @@
+// Station Radio Channel
+#define CHANNEL_COMMON "Common"
+#define CHANNEL_AI_PRIVATE "AI Private"
+#define CHANNEL_ENTERTAINMENT "Entertainment"
+
+// Departments
+#define CHANNEL_COMMAND "Command"
+#define CHANNEL_SECURITY "Security"
+#define CHANNEL_SECURITY_1 "Security(I)"
+#define CHANNEL_SUPPLY "Supply"
+#define CHANNEL_SERVICE "Service"
+#define CHANNEL_ENGINEERING "Engineering"
+#define CHANNEL_SCIENCE "Science"
+#define CHANNEL_MEDICAL "Medical"
+#define CHANNEL_MEDICAL_1 "Medical(I)"
+#define CHANNEL_EXPLORATION "Away Team" // was Explorer
+
+// Special Channels
+#define CHANNEL_RESPONSE_TEAM "Response Team"
+#define CHANNEL_SPECIAL_OPS "Special Ops"
+
+// Antag Channels
+#define CHANNEL_RAIDER "Raider"
+#define CHANNEL_MERCENARY "Mercenary"
+
+// Other Channels
+#define CHANNEL_TALON "Talon"
+#define CHANNEL_CASINO "Casino"
diff --git a/code/__defines/rust_g.dm b/code/__defines/rust_g.dm
index 1c93497ec88..bd0e0879b4b 100644
--- a/code/__defines/rust_g.dm
+++ b/code/__defines/rust_g.dm
@@ -38,27 +38,46 @@
#define RUST_G (__rust_g || __detect_rust_g())
#endif
-#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
-#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
-#define RUSTG_JOB_ERROR "JOB PANICKED"
-
-#define rustg_dmi_strip_metadata(fname) LIBCALL(RUST_G, "dmi_strip_metadata")(fname)
-#define rustg_dmi_create_png(path, width, height, data) LIBCALL(RUST_G, "dmi_create_png")(path, width, height, data)
-
-#define rustg_noise_get_at_coordinates(seed, x, y) LIBCALL(RUST_G, "noise_get_at_coordinates")(seed, x, y)
+// Handle 515 call() -> call_ext() changes
+#if DM_VERSION >= 515
+#define RUSTG_CALL call_ext
+#else
+#define RUSTG_CALL call
+#endif
-#define rustg_file_read(fname) LIBCALL(RUST_G, "file_read")(fname)
-#define rustg_file_exists(fname) LIBCALL(RUST_G, "file_exists")(fname)
-#define rustg_file_write(text, fname) LIBCALL(RUST_G, "file_write")(text, fname)
-#define rustg_file_append(text, fname) LIBCALL(RUST_G, "file_append")(text, fname)
+/// Gets the version of rust_g
+/proc/rustg_get_version() return RUSTG_CALL(RUST_G, "get_version")()
+
+#define rustg_dmi_strip_metadata(fname) RUSTG_CALL(RUST_G, "dmi_strip_metadata")(fname)
+#define rustg_dmi_create_png(path, width, height, data) RUSTG_CALL(RUST_G, "dmi_create_png")(path, width, height, data)
+#define rustg_dmi_resize_png(path, width, height, resizetype) RUSTG_CALL(RUST_G, "dmi_resize_png")(path, width, height, resizetype)
+/**
+ * input: must be a path, not an /icon; you have to do your own handling if it is one, as icon objects can't be directly passed to rustg.
+ *
+ * output: json_encode'd list. json_decode to get a flat list with icon states in the order they're in inside the .dmi
+ */
+#define rustg_dmi_icon_states(fname) RUSTG_CALL(RUST_G, "dmi_icon_states")(fname)
+
+#define rustg_file_read(fname) RUSTG_CALL(RUST_G, "file_read")(fname)
+#define rustg_file_exists(fname) (RUSTG_CALL(RUST_G, "file_exists")(fname) == "true")
+#define rustg_file_write(text, fname) RUSTG_CALL(RUST_G, "file_write")(text, fname)
+#define rustg_file_append(text, fname) RUSTG_CALL(RUST_G, "file_append")(text, fname)
+#define rustg_file_get_line_count(fname) text2num(RUSTG_CALL(RUST_G, "file_get_line_count")(fname))
+#define rustg_file_seek_line(fname, line) RUSTG_CALL(RUST_G, "file_seek_line")(fname, "[line]")
#ifdef RUSTG_OVERRIDE_BUILTINS
#define file2text(fname) rustg_file_read("[fname]")
#define text2file(text, fname) rustg_file_append(text, "[fname]")
#endif
-#define rustg_git_revparse(rev) LIBCALL(RUST_G, "rg_git_revparse")(rev)
-#define rustg_git_commit_date(rev) LIBCALL(RUST_G, "rg_git_commit_date")(rev)
+/// Returns the git hash of the given revision, ex. "HEAD".
+#define rustg_git_revparse(rev) RUSTG_CALL(RUST_G, "rg_git_revparse")(rev)
+
+/**
+ * Returns the date of the given revision in the format YYYY-MM-DD.
+ * Returns null if the revision is invalid.
+ */
+#define rustg_git_commit_date(rev) RUSTG_CALL(RUST_G, "rg_git_commit_date")(rev)
#define rustg_hash_string(algorithm, text) LIBCALL(RUST_G, "hash_string")(algorithm, text)
#define rustg_hash_file(algorithm, fname) LIBCALL(RUST_G, "hash_file")(algorithm, fname)
@@ -72,28 +91,36 @@
#define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing))
#endif
-#define rustg_json_is_valid(text) (LIBCALL(RUST_G, "json_is_valid")(text) == "true")
-
-#define rustg_log_write(fname, text, format) LIBCALL(RUST_G, "log_write")(fname, text, format)
-/proc/rustg_log_close_all() return LIBCALL(RUST_G, "log_close_all")()
-
-#define rustg_url_encode(text) LIBCALL(RUST_G, "url_encode")(text)
-#define rustg_url_decode(text) LIBCALL(RUST_G, "url_decode")(text)
-
-#ifdef RUSTG_OVERRIDE_BUILTINS
-#define url_encode(text) rustg_url_encode(text)
-#define url_decode(text) rustg_url_decode(text)
-#endif
-
#define RUSTG_HTTP_METHOD_GET "get"
#define RUSTG_HTTP_METHOD_PUT "put"
#define RUSTG_HTTP_METHOD_DELETE "delete"
#define RUSTG_HTTP_METHOD_PATCH "patch"
#define RUSTG_HTTP_METHOD_HEAD "head"
#define RUSTG_HTTP_METHOD_POST "post"
-#define rustg_http_request_blocking(method, url, body, headers) LIBCALL(RUST_G, "http_request_blocking")(method, url, body, headers)
-#define rustg_http_request_async(method, url, body, headers) LIBCALL(RUST_G, "http_request_async")(method, url, body, headers)
-#define rustg_http_check_request(req_id) LIBCALL(RUST_G, "http_check_request")(req_id)
+#define rustg_http_request_blocking(method, url, body, headers, options) RUSTG_CALL(RUST_G, "http_request_blocking")(method, url, body, headers, options)
+#define rustg_http_request_async(method, url, body, headers, options) RUSTG_CALL(RUST_G, "http_request_async")(method, url, body, headers, options)
+#define rustg_http_check_request(req_id) RUSTG_CALL(RUST_G, "http_check_request")(req_id)
+
+#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
+#define RUSTG_JOB_NO_SUCH_JOB "NO SUCH JOB"
+#define RUSTG_JOB_ERROR "JOB PANICKED"
+
+#define rustg_json_is_valid(text) (RUSTG_CALL(RUST_G, "json_is_valid")(text) == "true")
+
+#define rustg_log_write(fname, text, format) LIBCALL(RUST_G, "log_write")(fname, text, format)
+/proc/rustg_log_close_all() return LIBCALL(RUST_G, "log_close_all")()
+
+#define rustg_noise_get_at_coordinates(seed, x, y) RUSTG_CALL(RUST_G, "noise_get_at_coordinates")(seed, x, y)
+
+/*
+ * Takes in a string and json_encode()"d lists to produce a sanitized string.
+ * This function operates on whitelists, there is currently no way to blacklist.
+ * Args:
+ * * text: the string to sanitize.
+ * * attribute_whitelist_json: a json_encode()'d list of HTML attributes to allow in the final string.
+ * * tag_whitelist_json: a json_encode()'d list of HTML tags to allow in the final string.
+ */
+#define rustg_sanitize_html(text, attribute_whitelist_json, tag_whitelist_json) RUSTG_CALL(RUST_G, "sanitize_html")(text, attribute_whitelist_json, tag_whitelist_json)
#define rustg_sql_connect_pool(options) LIBCALL(RUST_G, "sql_connect_pool")(options)
#define rustg_sql_query_async(handle, query, params) LIBCALL(RUST_G, "sql_query_async")(handle, query, params)
@@ -101,3 +128,37 @@
#define rustg_sql_connected(handle) LIBCALL(RUST_G, "sql_connected")(handle)
#define rustg_sql_disconnect_pool(handle) LIBCALL(RUST_G, "sql_disconnect_pool")(handle)
#define rustg_sql_check_query(job_id) LIBCALL(RUST_G, "sql_check_query")("[job_id]")
+
+#define rustg_time_microseconds(id) text2num(RUSTG_CALL(RUST_G, "time_microseconds")(id))
+#define rustg_time_milliseconds(id) text2num(RUSTG_CALL(RUST_G, "time_milliseconds")(id))
+#define rustg_time_reset(id) RUSTG_CALL(RUST_G, "time_reset")(id)
+
+/// Returns the timestamp as a string
+/proc/rustg_unix_timestamp()
+ return RUSTG_CALL(RUST_G, "unix_timestamp")()
+
+#define rustg_raw_read_toml_file(path) json_decode(RUSTG_CALL(RUST_G, "toml_file_to_json")(path) || "null")
+
+/proc/rustg_read_toml_file(path)
+ var/list/output = rustg_raw_read_toml_file(path)
+ if (output["success"])
+ return json_decode(output["content"])
+ else
+ CRASH(output["content"])
+
+#define rustg_raw_toml_encode(value) json_decode(RUSTG_CALL(RUST_G, "toml_encode")(json_encode(value)))
+
+/proc/rustg_toml_encode(value)
+ var/list/output = rustg_raw_toml_encode(value)
+ if (output["success"])
+ return output["content"]
+ else
+ CRASH(output["content"])
+
+#define rustg_url_encode(text) RUSTG_CALL(RUST_G, "url_encode")("[text]")
+#define rustg_url_decode(text) RUSTG_CALL(RUST_G, "url_decode")(text)
+
+#ifdef RUSTG_OVERRIDE_BUILTINS
+ #define url_encode(text) rustg_url_encode(text)
+ #define url_decode(text) rustg_url_decode(text)
+#endif
diff --git a/code/__defines/span_vr.dm b/code/__defines/span_vr.dm
index 49e4e0ef69d..c87d062b0ef 100644
--- a/code/__defines/span_vr.dm
+++ b/code/__defines/span_vr.dm
@@ -1,9 +1,21 @@
// Sorted by however I felt like it
-// We have two other ways of doing this, so why not a third. This one atleast has more span options.
+
+// Adds a generic box around whatever message you're sending in chat. Really makes things stand out.
+#define examine_block(str) ("" + str + "
")
+
+// Filtered both under OOC!
#define span_ooc(str) ("" + str + "")
+#define span_aooc(str) ("" + str + "")
+
+// All of those have unique filters, be wary!
#define span_looc(str) ("" + str + "")
+#define span_rlooc(str) ("" + str + "")
+// Ghostchat filter
#define span_deadsay(str) ("" + str + "")
+#define span_ghostalert(str) ("" + str + "")
+
+// FIltered under radio
#define span_radio(str) ("" + str + "")
#define span_deptradio(str) ("" + str + "")
#define span_newscaster(str) ("" + str + "")
@@ -21,46 +33,89 @@
#define span_supradio(str) ("" + str + "")
#define span_srvradio(str) ("" + str + "")
#define span_expradio(str) ("" + str + "")
+// Those are in the radio filter...
+#define span_alien(str) ("" + str + "")
+#define span_changeling(str) ("" + str + "")
+// Stop using alert for anything other than announcements! It's filtered under the radio tab
+#define span_alert(str) ("" + str + "")
-#define span_binary(str) ("" + str + "")
+// Filtered under global languages
+#define span_binarysay(str) ("" + str + "")
#define span_hivemind(str) ("" + str + "")
-#define span_name(str) ("" + str + "")
+// Filtered under local IC!
#define span_say(str) ("" + str + "")
-#define span_alert(str) ("" + str + "")
-#define span_ghostalert(str) ("" + str + "")
-#define span_npc_say(str) ("" + str + "")
-
-
#define span_emote(str) ("" + str + "")
#define span_emote_subtle(str) ("" + str + "")
+#define span_filter_say(str) ("" + str + "")
+
+// Filtered as NPC messages
+#define span_npc_say(str) ("" + str + "")
#define span_npc_emote(str) ("" + str + "")
+// Filtered as messages visible through multiple Z levels
+#define span_multizsay(str) ("" + str + "")
+
+// Unfiltered, only style!
+#define span_name(str) ("" + str + "")
+#define span_game(str) ("" + str + "")
+#define span_message(str) ("" + str + "") // TODO: This makes no sense, check it!
+#define span_notify(str) ("" + str + "") // TODO: This makes no sense, check it!
+#define span_body(str) ("" + str + "")
+
+// Filtered under combat!
#define span_attack(str) ("" + str + "")
-#define span_moderate(str) ("" + str + "")
#define span_disarm(str) ("" + str + "")
#define span_passive(str) ("" + str + "")
+#define span_danger(str) ("" + str + "")
+#define span_bolddanger(str) ("" + str + "")
+#define span_filter_combat(str) ("" + str + "")
+// Filtered under warning messages
#define span_critical(str) ("" + str + "")
-#define span_danger(str) ("" + str + "")
+#define span_userdanger(str) ("" + str + "")
#define span_warning(str) ("" + str + "")
-#define span_rose(str) ("" + str + "")
+#define span_warningplain(str) ("" + str + "")
+#define span_boldwarning(str) ("" + str + "")
+#define span_filter_warning(str) ("" + str + "") // Close to warning plain, maybe replace
+
+// FIltered under info
#define span_info(str) ("" + str + "")
+#define span_infoplain(str) ("" + str + "")
+#define span_suicide(str) ("" + str + "")
+#define span_unconscious(str) ("" + str + "")
+#define span_hear(str) ("" + str + "")
#define span_notice(str) ("" + str + "")
+#define span_filter_notice(str) ("" + str + "") // Close to infoplain, maybe replace
+#define span_boldnotice(str) ("" + str + "")
+#define span_adminnotice(str) ("" + str + "")
#define span_alium(str) ("" + str + "")
#define span_cult(str) ("" + str + "")
-#define span_reflex_shoot(str) ("" + str + "")
+#define span_pnarrate(str) ("" + str + "")
-/* Vore messages */
+/* Direct communication spans */
+// Local pred / prey filter
+#define span_psay(str) ("" + str + "")
+#define span_pemote(str) ("" + str + "")
+/* Export spans */
+// chatexport filter
+#define span_chatexport(str) ("" + str + "")
+
+/* Vore messages */
+// All of thse are filtered under the Vorgan Messages tab!
+#define span_valert(str) ("" + str + "")
#define span_vdanger(str) ("" + str + "")
#define span_vwarning(str) ("" + str + "")
#define span_vnotice(str) ("" + str + "")
-/* Languages */
+// Filtered under nif!
+#define span_nif(str) ("" + str + "")
+#define span_filter_nif(str) ("" + str + "") // Currently not sorted in
-#define span_alien(str) ("" + str + "")
+/* Languages */
+// No filter!
#define span_tajaran(str) ("" + str + "")
#define span_tajaran_signlang(str) ("" + str + "")
#define span_akhani(str) ("" + str + "")
@@ -68,7 +123,6 @@
#define span_skrellfar(str) ("" + str + "")
#define span_soghun(str) ("" + str + "")
#define span_solcom(str) ("" + str + "")
-#define span_changeling(str) ("" + str + "")
#define span_sergal(str) ("" + str + "")
#define span_birdsongc(str) ("" + str + "")
#define span_vulpkanin(str) ("" + str + "")
@@ -86,12 +140,7 @@
#define span_blob(str) ("" + str + "")
#define span_teppi(str) ("" + str + "")
-#define span_debug_error(str) ("" + str + "")
-#define span_debug_warning(str) ("" + str + "")
-#define span_debug_info(str) ("" + str + "")
-#define span_debug_debug(str) ("" + str + "")
-#define span_debug_trace(str) ("" + str + "")
-
+// Colours only!
#define span_white(str) ("" + str + "")
#define span_black(str) ("" + str + "")
#define span_darkgray(str) ("" + str + "")
@@ -100,6 +149,7 @@
#define span_orange(str) ("" + str + "")
#define span_blue(str) ("" + str + "")
#define span_green(str) ("" + str + "")
+#define span_darkgreen(str) ("" + str + "") // Do not use regularly!
#define span_purple(str) ("" + str + "")
#define span_yellow(str) ("" + str + "")
#define span_pink(str) ("" + str + "")
@@ -108,4 +158,88 @@
#define span_maroon(str) ("" + str + "")
#define span_brown(str) ("" + str + "")
#define span_lightpurple(str) ("" + str + "")
-#define span_darkpink(str) ("" + str + "")
+#define span_darkpink(str) ("" + str + "")
+#define span_rose(str) ("" + str + "")
+
+/* System and Debug */
+// System filter
+#define span_boldannounce(str) ("" + str + "")
+#define span_world(str) ("" + str + "") // Bold system messages, use this for important world messages to make sure players can't filter them!
+#define span_filter_system(str) ("" + str + "") // Plain system filter
+#define span_sinister(str) ("" + str + "")
+
+// Unfiltered
+#define span_prefix(str) ("" + str + "")
+#define span_admin(str) ("" + str + "")
+#define span_linkOn(str) ("" + str + "")
+#define span_linkOff(str) ("" + str + "")
+#define span_filter_pray(str) ("" + str + "") // (Uses the chat message type directly)
+
+// Admin log filters
+#define span_log_message(str) ("" + str + "")
+#define span_filter_adminlog(str) ("" + str + "") // (Uses the chat message type directly)
+
+// Attack log filter
+#define span_filter_attacklog(str) ("" + str + "") // (Uses the chat message type directly)
+
+// Debug filter
+#define span_debug_error(str) ("" + str + "")
+#define span_debug_warning(str) ("" + str + "")
+#define span_debug_info(str) ("" + str + "")
+#define span_debug_debug(str) ("" + str + "")
+#define span_debug_trace(str) ("" + str + "")
+#define span_filter_debuglogs(str) ("" + str + "") // (Uses the chat message type directly)
+
+/* Admin only usage */
+// Admin pm filter
+#define span_pm(str) ("" + str + "")
+#define span_adminhelp(str) ("" + str + "")
+#define span_admin_pm_notice(str) ("" + str + "")
+#define span_admin_pm_warning(str) ("" + str + "")
+#define span_filter_pm(str) ("" + str + "")
+
+// Mentor pm filter
+#define span_mentor(str) ("" + str + "")
+#define span_mentor_pm_notice(str) ("" + str + "")
+#define span_mentor_pm_warning(str) ("" + str + "")
+
+/* Adminchat */
+// All of those have their own filter
+#define span_admin_channel(str) ("" + str + "")
+#define span_mod_channel(str) ("" + str + "")
+#define span_event_channel(str) ("" + str + "")
+#define span_mentor_channel(str) ("" + str + "")
+
+/* Byond Sizes */
+// Sizes only!
+#define span_small(str) "" + str + ""
+
+#define span_normal(str) "" + str + ""
+
+#define span_large(str) "" + str + ""
+
+#define span_huge(str) "" + str + ""
+
+#define span_giant(str) "" + str + ""
+
+#define span_giganteus(str) "" + str + ""
+
+#define span_massive(str) "" + str + ""
+
+#define span_narsie(str) "" + str + ""
+
+#define span_cascade(str) "" + str + ""
+
+/* Style spans */
+// text style only
+#define span_italics(str) ("" + str + "")
+#define span_bold(str) ("" + str + "")
+#define span_underline(str) ("" + str + "")
+
+// Links!
+#define span_linkify(str) ("" + str + "")
+
+// Just used downstream
+#define span_wingdings(str) ("" + str + "")
+
+#define span_maptext(str) ("" + str + "")
diff --git a/code/__defines/species_languages_vr.dm b/code/__defines/species_languages_vr.dm
index 146fcb86ab9..8e9a54569e6 100644
--- a/code/__defines/species_languages_vr.dm
+++ b/code/__defines/species_languages_vr.dm
@@ -15,6 +15,7 @@
#define LANGUAGE_ANIMAL "Animal"
#define LANGUAGE_TEPPI "Teppi"
#define LANGUAGE_MOUSE "Mouse"
+#define LANNGUAGE_DRAKE "Drake"
#define LANGUAGE_SHADEKIN "Shadekin Empathy"
#define LANGUAGE_LLEILL "Glamour Speak"
diff --git a/code/__defines/statpanel.dm b/code/__defines/statpanel.dm
new file mode 100644
index 00000000000..1c304d7fb39
--- /dev/null
+++ b/code/__defines/statpanel.dm
@@ -0,0 +1,2 @@
+#define TURFLIST_UPDATED (1 << 0)
+#define TURFLIST_UPDATE_QUEUED (1 << 1)
diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm
index 84c6fbd8a7c..4d80021c0ff 100644
--- a/code/__defines/subsystems.dm
+++ b/code/__defines/subsystems.dm
@@ -1,33 +1,78 @@
-//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
-#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()
-#define TIMER_CLIENT_TIME (1<<2)
-//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
-#define TIMER_NO_HASH_WAIT (1<<4)
-//Loops the timer repeatedly until qdeleted
-//In most cases you want a subsystem instead
-#define TIMER_LOOP (1<<5)
+//! Defines for subsystems and overlays
+//!
+//! Lots of important stuff in here, make sure you have your brain switched on
+//! when editing this file
+//! ## 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
+#define TIMER_OVERRIDE (1<<1)
+
+/**
+ * Timing should be based on how timing progresses on clients, not the server.
+ *
+ * Tracking this is more expensive,
+ * should only be used in conjunction 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()
+#define TIMER_STOPPABLE (1<<3)
+
+///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, so don't use this unless you have a good reason
+#define TIMER_LOOP (1<<5)
+
+///Delete the timer on parent datum Destroy() and when deltimer'd
+#define TIMER_DELETE_ME (1<<6)
+
+///Empty ID define
#define TIMER_ID_NULL -1
-#define INITIALIZATION_INSSATOMS 0 //New should not call Initialize
-#define INITIALIZATION_INNEW_MAPLOAD 1 //New should call Initialize(TRUE)
-#define INITIALIZATION_INNEW_REGULAR 2 //New should call Initialize(FALSE)
+/// Used to trigger object removal from a processing list
+#define PROCESS_KILL 26
+
-#define INITIALIZE_HINT_NORMAL 0 //Nothing happens
-#define INITIALIZE_HINT_LATELOAD 1 //Call LateInitialize
-#define INITIALIZE_HINT_QDEL 2 //Call qdel on the atom
+//! ## Initialization subsystem
-//type and all subtypes should always call Initialize in New()
+///New should not call Initialize
+#define INITIALIZATION_INSSATOMS 0
+///New should call Initialize(TRUE)
+#define INITIALIZATION_INNEW_MAPLOAD 1
+///New should call Initialize(FALSE)
+#define INITIALIZATION_INNEW_REGULAR 2
+
+//! ### Initialization hints
+
+///Nothing happens
+#define INITIALIZE_HINT_NORMAL 0
+/**
+ * call LateInitialize at the end of all atom Initialization
+ *
+ * The item will be added to the late_loaders list, this is iterated over after
+ * initialization 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 initialization
+#define INITIALIZE_HINT_QDEL 2
+
+///type and all subtypes should always immediately call Initialize in New()
#define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\
..();\
if(!initialized) {\
@@ -51,27 +96,27 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
//! ### SS initialization hints
/**
- * Negative values incidate a failure or warning of some kind, positive are good.
- * 0 and 1 are unused so that TRUE and FALSE are guarenteed to be invalid values.
+ * Negative values indicate a failure or warning of some kind, positive are good.
+ * 0 and 1 are unused so that TRUE and FALSE are guaranteed to be invalid values.
*/
/// Subsystem failed to initialize entirely. Print a warning, log, and disable firing.
#define SS_INIT_FAILURE -2
-/// The default return value which must be overriden. Will succeed with a warning.
+/// The default return value which must be overridden. Will succeed with a warning.
#define SS_INIT_NONE -1
-/// Subsystem initialized sucessfully.
+/// Subsystem initialized successfully.
#define SS_INIT_SUCCESS 2
-/// Successful, but don't print anything. Useful if subsystem was disabled.
+/// If your system doesn't need to be initialized (by being disabled or something)
#define SS_INIT_NO_NEED 3
//! ### SS initialization load orders
-
// Subsystem init_order, from highest priority to lowest priority
// Subsystems shutdown in the reverse of the order they initialize in
// The numbers just define the ordering, they are meaningless otherwise.
+#define INIT_ORDER_SERVER_MAINT 93
#define INIT_ORDER_WEBHOOKS 50
#define INIT_ORDER_SQLITE 40
#define INIT_ORDER_GARBAGE 39
@@ -109,10 +154,9 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_SKYBOX -30 //Visual only, irrelevant to gameplay, but needs to be late enough to have overmap populated fully
#define INIT_ORDER_TICKER -50
#define INIT_ORDER_MAPRENAME -60 //Initiating after Ticker to ensure everything is loaded and everything we rely on us working
+#define INIT_ORDER_STATPANELS -98
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
-
-
// Subsystem fire priority, from lowest to highest priority
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_PLAYERTIPS 5
@@ -125,6 +169,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_VOTE 8
#define FIRE_PRIORITY_INSTRUMENTS 9
#define FIRE_PRIORITY_PING 10
+#define FIRE_PRIORITY_SERVER_MAINT 10
#define FIRE_PRIORITY_AI 10
#define FIRE_PRIORITY_GARBAGE 15
#define FIRE_PRIORITY_ASSETS 20
@@ -140,6 +185,20 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_MACHINES 100
#define FIRE_PRIORITY_TGUI 110
#define FIRE_PRIORITY_PROJECTILES 150
+#define FIRE_PRIORITY_STATPANEL 390
#define FIRE_PRIORITY_CHAT 400
#define FIRE_PRIORITY_OVERLAYS 500
+#define FIRE_PRIORITY_TIMER 700
+#define FIRE_PRIORITY_SPEECH_CONTROLLER 900
+#define FIRE_PRIORITY_DELAYED_VERBS 950
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
+
+/**
+ 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
+ * * timer_subsystem the subsystem to insert this timer into
+*/
+#define addtimer(args...) _addtimer(args, file = __FILE__, line = __LINE__)
diff --git a/code/__defines/talksounds.dm b/code/__defines/talksounds.dm
new file mode 100644
index 00000000000..4f01b4fb2f5
--- /dev/null
+++ b/code/__defines/talksounds.dm
@@ -0,0 +1,63 @@
+
+
+var/list/talk_sound_map = rlist(
+ list(
+ "beep-boop",
+ "goon speak 1",
+ "goon speak 2",
+ "goon speak 3",
+ "goon speak 4",
+ "goon speak blub",
+ "goon speak bottalk",
+ "goon speak buwoo",
+ "goon speak cow",
+ "goon speak lizard",
+ "goon speak pug",
+ "goon speak pugg",
+ "goon speak roach",
+ "goon speak skelly",
+ // "xeno speak" // Does not exist on virgo
+ ),
+ list(
+ talk_sound,
+ goon_speak_one_sound,
+ goon_speak_two_sound,
+ goon_speak_three_sound,
+ goon_speak_four_sound,
+ goon_speak_blub_sound,
+ goon_speak_bottalk_sound,
+ goon_speak_buwoo_sound,
+ goon_speak_cow_sound,
+ goon_speak_lizard_sound,
+ goon_speak_pug_sound,
+ goon_speak_pugg_sound,
+ goon_speak_roach_sound,
+ goon_speak_skelly_sound,
+ // xeno_speak_sound // Does not exist on virgo
+ )
+ )
+
+/proc/get_talk_sound(var/voice_sound)
+ if(!voice_sound)
+ return talk_sound_map[1]
+ return talk_sound_map[2][voice_sound]
+
+/proc/rlist(var/list/keys,var/list/values) //short for reversible list generator
+ var/list/rlist = list(list(),list(),FALSE,0)
+ var/i = 0
+ for(i = 1, i <= LAZYLEN(keys), i++)
+ to_chat(world,keys[i])
+ rlist[1] += keys[i]
+ rlist[2][keys[i]] = values[i]
+ rlist += TRUE
+ rlist += i
+ return rlist
+
+/proc/arlist(var/list/altlist)
+ var/list/rlist = list(list(),list(),FALSE,0)
+ var/i = 0
+ for(i = 1, i <= LAZYLEN(altlist), i++)
+ rlist[(i % 2) +1] += altlist[i]
+ rlist += TRUE
+ rlist += i/2
+ return rlist
diff --git a/code/__defines/text.dm b/code/__defines/text.dm
index 4b520e5771c..b48754dd329 100644
--- a/code/__defines/text.dm
+++ b/code/__defines/text.dm
@@ -8,3 +8,6 @@
* because DM does it so it copies until the char BEFORE the `end` arg, so we need to bump `end` by 1 in these cases.
*/
#define PREVENT_CHARACTER_TRIM_LOSS(integer) (integer + 1)
+
+/// Simply removes the < and > characters, and limits the length of the message.
+#define STRIP_HTML_SIMPLE(text, limit) (GLOB.angular_brackets.Replace(copytext(text, 1, limit), ""))
diff --git a/code/__defines/tgs.config.dm b/code/__defines/tgs.config.dm
index e25041963bc..c57439c7e45 100644
--- a/code/__defines/tgs.config.dm
+++ b/code/__defines/tgs.config.dm
@@ -2,7 +2,7 @@
#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) GLOBAL_VAR_INIT(##Name, ##Value); GLOBAL_PROTECT(##Name)
#define TGS_READ_GLOBAL(Name) GLOB.##Name
#define TGS_WRITE_GLOBAL(Name, Value) GLOB.##Name = ##Value
-#define TGS_WORLD_ANNOUNCE(message) to_chat(world, "[html_encode(##message)]")
+#define TGS_WORLD_ANNOUNCE(message) to_chat(world, span_boldannounce("[html_encode(##message)]"))
#define TGS_INFO_LOG(message) log_to_dd("TGS Info: [##message]")
#define TGS_WARNING_LOG(message) log_to_dd("TGS Warn: [##message]")
#define TGS_ERROR_LOG(message) log_to_dd("TGS Error: [##message]")
diff --git a/code/__defines/tgs.dm b/code/__defines/tgs.dm
index f41a6bbff97..d703f41bab4 100644
--- a/code/__defines/tgs.dm
+++ b/code/__defines/tgs.dm
@@ -1,18 +1,19 @@
// tgstation-server DMAPI
+// The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in IETF RFC 2119.
-#define TGS_DMAPI_VERSION "7.0.1"
+#define TGS_DMAPI_VERSION "7.3.0"
// All functions and datums outside this document are subject to change with any version and should not be relied on.
// CONFIGURATION
-/// Create this define if you want to do TGS configuration outside of this file.
+/// Consumers SHOULD create this define if you want to do TGS configuration outside of this file.
#ifndef TGS_EXTERNAL_CONFIGURATION
-// Comment this out once you've filled in the below.
+// Consumers MUST comment this out once you've filled in the below and are not using [TGS_EXTERNAL_CONFIGURATION].
#error TGS API unconfigured
-// Uncomment this if you wish to allow the game to interact with TGS 3..
+// Consumers MUST uncomment this if you wish to allow the game to interact with TGS version 3.
// This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()().
//#define TGS_V3_API
@@ -50,6 +51,13 @@
#endif
+#ifndef TGS_FILE2TEXT_NATIVE
+#ifdef file2text
+#error Your codebase is re-defining the BYOND proc file2text. The DMAPI requires the native version to read the result of world.Export(). You SHOULD fix this by adding "#define TGS_FILE2TEXT_NATIVE file2text" before your override of file2text to allow the DMAPI to use the native version. This will only be used for world.Export(), not regular file accesses
+#endif
+#define TGS_FILE2TEXT_NATIVE file2text
+#endif
+
// EVENT CODES
/// Before a reboot mode change, extras parameters are the current and new reboot mode enums.
@@ -145,16 +153,17 @@
//REQUIRED HOOKS
/**
- * Call this somewhere in [/world/proc/New] that is always run. This function may sleep!
+ * Consumers MUST call this somewhere in [/world/proc/New] that is always run. This function may sleep!
*
* * event_handler - Optional user defined [/datum/tgs_event_handler].
* * minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated. Can be one of [TGS_SECURITY_ULTRASAFE], [TGS_SECURITY_SAFE], or [TGS_SECURITY_TRUSTED].
+ * * http_handler - Optional user defined [/datum/tgs_http_handler].
*/
-/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
+/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE, datum/tgs_http_handler/http_handler)
return
/**
- * Call this when your initializations are complete and your game is ready to play before any player interactions happen.
+ * Consumers MUST call this when world initializations are complete and the game is ready to play before any player interactions happen.
*
* This may use [/world/var/sleep_offline] to make this happen so ensure no changes are made to it while this call is running.
* Afterwards, consider explicitly setting it to what you want to avoid this BYOND bug: http://www.byond.com/forum/post/2575184
@@ -163,13 +172,11 @@
/world/proc/TgsInitializationComplete()
return
-/// Put this at the start of [/world/proc/Topic].
+/// Consumers MUST run this macro at the start of [/world/proc/Topic].
#define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return
#define VGS_TOPIC var/vgs_topic_return = VgsTopic(args[1]); if(vgs_topic_return) return vgs_topic_return // VOREStation Edit - VGS
-/**
- * Call this as late as possible in [world/proc/Reboot] (BEFORE ..()).
- */
+/// Consumers MUST call this as late as possible in [world/proc/Reboot] (BEFORE ..()).
/world/proc/TgsReboot()
return
@@ -263,7 +270,7 @@
/// The [/datum/tgs_chat_channel] the user was from.
var/datum/tgs_chat_channel/channel
-/// User definable handler for TGS events.
+/// User definable handler for TGS events This abstract version SHOULD be overridden to be used.
/datum/tgs_event_handler
/// If the handler receieves [TGS_EVENT_HEALTH_CHECK] events.
var/receive_health_checks = FALSE
@@ -277,7 +284,41 @@
set waitfor = FALSE
return
-/// User definable chat command.
+/// User definable handler for HTTP calls. This abstract version MUST be overridden to be used.
+/datum/tgs_http_handler
+
+/**
+ * User definable callback for executing HTTP GET requests.
+ * MUST perform BYOND sleeps while the request is in flight.
+ * MUST return a [/datum/tgs_http_result].
+ * SHOULD log its own errors
+ *
+ * url - The full URL to execute the GET request for including query parameters.
+ */
+/datum/tgs_http_handler/proc/PerformGet(url)
+ CRASH("[type]/PerformGet not implemented!")
+
+/// Result of a [/datum/tgs_http_handler] call. MUST NOT be overridden.
+/datum/tgs_http_result
+ /// HTTP response as text
+ var/response_text
+ /// Boolean request success flag. Set for any 2XX response code.
+ var/success
+
+/**
+ * Create a [/datum/tgs_http_result].
+ *
+ * * response_text - HTTP response as text. Must be provided in New().
+ * * success - Boolean request success flag. Set for any 2XX response code. Must be provided in New().
+ */
+/datum/tgs_http_result/New(response_text, success)
+ if(response_text && !istext(response_text))
+ CRASH("response_text was not text!")
+
+ src.response_text = response_text
+ src.success = success
+
+/// User definable chat command. This abstract version MUST be overridden to be used.
/datum/tgs_chat_command
/// The string to trigger this command on a chat bot. e.g `@bot name ...` or `!tgs name ...`.
var/name = ""
@@ -290,29 +331,36 @@
/**
* Process command activation. Should return a [/datum/tgs_message_content] to respond to the issuer with.
+ * MUST be implemented
*
- * sender - The [/datum/tgs_chat_user] who issued the command.
- * params - The trimmed string following the command `/datum/tgs_chat_command/var/name].
+ * * sender - The [/datum/tgs_chat_user] who issued the command.
+ * * params - The trimmed string following the command `/datum/tgs_chat_command/var/name].
*/
/datum/tgs_chat_command/proc/Run(datum/tgs_chat_user/sender, params)
CRASH("[type] has no implementation for Run()")
-/// User definable chat message.
+/// User definable chat message. MUST NOT be overridden.
/datum/tgs_message_content
- /// The tring content of the message. Must be provided in New().
+ /// The string content of the message. Must be provided in New().
var/text
/// The [/datum/tgs_chat_embed] to embed in the message. Not supported on all chat providers.
var/datum/tgs_chat_embed/structure/embed
+/**
+ * Create a [/datum/tgs_message_content].
+ *
+ * * text - The string content of the message.
+ */
/datum/tgs_message_content/New(text)
+ ..()
if(!istext(text))
TGS_ERROR_LOG("[/datum/tgs_message_content] created with no text!")
text = null
src.text = text
-/// User definable chat embed. Currently mirrors Discord chat embeds. See https://discord.com/developers/docs/resources/channel#embed-object-embed-structure for details.
+/// User definable chat embed. Currently mirrors Discord chat embeds. See https://discord.com/developers/docs/resources/message#embed-object for details.
/datum/tgs_chat_embed/structure
var/title
var/description
@@ -324,13 +372,13 @@
/// Colour must be #AARRGGBB or #RRGGBB hex string.
var/colour
- /// See https://discord.com/developers/docs/resources/channel#embed-object-embed-image-structure for details.
+ /// See https://discord.com/developers/docs/resources/message#embed-object-embed-image-structure for details.
var/datum/tgs_chat_embed/media/image
- /// See https://discord.com/developers/docs/resources/channel#embed-object-embed-thumbnail-structure for details.
+ /// See https://discord.com/developers/docs/resources/message#embed-object-embed-thumbnail-structure for details.
var/datum/tgs_chat_embed/media/thumbnail
- /// See https://discord.com/developers/docs/resources/channel#embed-object-embed-image-structure for details.
+ /// See https://discord.com/developers/docs/resources/message#embed-object-embed-video-structure for details.
var/datum/tgs_chat_embed/media/video
var/datum/tgs_chat_embed/footer/footer
@@ -339,7 +387,7 @@
var/list/datum/tgs_chat_embed/field/fields
-/// Common datum for similar discord embed medias.
+/// Common datum for similar Discord embed medias.
/datum/tgs_chat_embed/media
/// Must be set in New().
var/url
@@ -347,48 +395,58 @@
var/height
var/proxy_url
+/// Create a [/datum/tgs_chat_embed].
/datum/tgs_chat_embed/media/New(url)
+ ..()
if(!istext(url))
CRASH("[/datum/tgs_chat_embed/media] created with no url!")
src.url = url
-/// See https://discord.com/developers/docs/resources/channel#embed-object-embed-footer-structure for details.
+/// See https://discord.com/developers/docs/resources/message#embed-object-embed-footer-structure for details.
/datum/tgs_chat_embed/footer
/// Must be set in New().
var/text
var/icon_url
var/proxy_icon_url
+/// Create a [/datum/tgs_chat_embed/footer].
/datum/tgs_chat_embed/footer/New(text)
+ ..()
if(!istext(text))
CRASH("[/datum/tgs_chat_embed/footer] created with no text!")
src.text = text
-/// See https://discord.com/developers/docs/resources/channel#embed-object-embed-provider-structure for details.
+/// See https://discord.com/developers/docs/resources/message#embed-object-embed-provider-structure for details.
/datum/tgs_chat_embed/provider
var/name
var/url
-/// See https://discord.com/developers/docs/resources/channel#embed-object-embed-author-structure for details. Must have name set in New().
+/// See https://discord.com/developers/docs/resources/message#embed-object-embed-author-structure for details. Must have name set in New().
/datum/tgs_chat_embed/provider/author
var/icon_url
var/proxy_icon_url
+/// Create a [/datum/tgs_chat_embed/footer].
/datum/tgs_chat_embed/provider/author/New(name)
+ ..()
if(!istext(name))
CRASH("[/datum/tgs_chat_embed/provider/author] created with no name!")
src.name = name
-/// See https://discord.com/developers/docs/resources/channel#embed-object-embed-field-structure for details. Must have name and value set in New().
+/// See https://discord.com/developers/docs/resources/message#embed-object-embed-field-structure for details.
/datum/tgs_chat_embed/field
+ /// Must be set in New().
var/name
+ /// Must be set in New().
var/value
var/is_inline
+/// Create a [/datum/tgs_chat_embed/field].
/datum/tgs_chat_embed/field/New(name, value)
+ ..()
if(!istext(name))
CRASH("[/datum/tgs_chat_embed/field] created with no name!")
@@ -427,6 +485,7 @@
/**
* Send a message to connected chats. This function may sleep!
+ * If TGS is offline when called, the message may be placed in a queue to be sent and this function will return immediately. Your message will be sent when TGS reconnects to the game.
*
* message - The [/datum/tgs_message_content] to send.
* admin_only: If [TRUE], message will be sent to admin connected chats. Vice-versa applies.
@@ -436,6 +495,7 @@
/**
* Send a private message to a specific user. This function may sleep!
+ * If TGS is offline when called, the message may be placed in a queue to be sent and this function will return immediately. Your message will be sent when TGS reconnects to the game.
*
* message - The [/datum/tgs_message_content] to send.
* user: The [/datum/tgs_chat_user] to PM.
@@ -445,6 +505,7 @@
/**
* Send a message to connected chats that are flagged as game-related in TGS. This function may sleep!
+ * If TGS is offline when called, the message may be placed in a queue to be sent and this function will return immediately. Your message will be sent when TGS reconnects to the game.
*
* message - The [/datum/tgs_message_content] to send.
* channels - Optional list of [/datum/tgs_chat_channel]s to restrict the message to.
@@ -488,10 +549,20 @@
/world/proc/TgsChatChannelInfo()
return
+/**
+ * Trigger an event in TGS. Requires TGS version >= 6.3.0. Returns [TRUE] if the event was triggered successfully, [FALSE] otherwise. This function may sleep!
+ *
+ * event_name - The name of the event to trigger
+ * parameters - Optional list of string parameters to pass as arguments to the event script. The first parameter passed to a script will always be the running game's directory followed by these parameters.
+ * wait_for_completion - If set, this function will not return until the event has run to completion.
+ */
+/world/proc/TgsTriggerEvent(event_name, list/parameters, wait_for_completion = FALSE)
+ return
+
/*
The MIT License
-Copyright (c) 2017-2023 Jordan Brown
+Copyright (c) 2017-2024 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
diff --git a/code/__defines/time.dm b/code/__defines/time.dm
index 9b3c384cfb3..857e2fa1556 100644
--- a/code/__defines/time.dm
+++ b/code/__defines/time.dm
@@ -1,3 +1,6 @@
+///displays the current time into the round, with a lot of extra code just there for ensuring it looks okay after an entire day passes
+#define ROUND_TIME(...) ( "[world.time - SSticker.round_start_time > MIDNIGHT_ROLLOVER ? "[round((world.time - SSticker.round_start_time)/MIDNIGHT_ROLLOVER)]:[worldtime2text()]" : worldtime2text()]" )
+
/// Define that just has the current in-universe year for use in whatever context you might want to display that in. (For example, 2022 -> 2562 given a 540 year offset)
#define CURRENT_STATION_YEAR (GLOB.year_integer + STATION_YEAR_OFFSET)
diff --git a/code/__defines/update_icons.dm b/code/__defines/update_icons.dm
index 4fa21751be5..7120edd1680 100644
--- a/code/__defines/update_icons.dm
+++ b/code/__defines/update_icons.dm
@@ -1 +1,49 @@
-#define MOB_WATER_LAYER 36
+// These are used as the layers for the icons, as well as indexes in a list that holds onto them.
+// Technically the layers used are all -100+layer to make them FLOAT_LAYER overlays.
+//Human Overlays Indexes/////////
+#define MUTATIONS_LAYER 1 //Mutations like fat, and lasereyes
+#define SKIN_LAYER 2 //Skin things added by a call on species
+#define BLOOD_LAYER 3 //Bloodied hands/feet/anything else
+#define BODYPARTS_LAYER 4 //Bodyparts layer
+#define MOB_DAM_LAYER 5 //Injury overlay sprites like open wounds
+#define SURGERY_LAYER 6 //Overlays for open surgical sites
+#define UNDERWEAR_LAYER 7 //Underwear/bras/etc
+#define TAIL_LOWER_LAYER 8 //Tail as viewed from the south
+#define WING_LOWER_LAYER 9 //Wings as viewed from the south
+#define SHOES_LAYER_ALT 10 //Shoe-slot item (when set to be under uniform via verb)
+#define UNIFORM_LAYER 11 //Uniform-slot item
+#define ID_LAYER 12 //ID-slot item
+#define SHOES_LAYER 13 //Shoe-slot item
+#define GLOVES_LAYER 14 //Glove-slot item
+#define BELT_LAYER 15 //Belt-slot item
+#define SUIT_LAYER 16 //Suit-slot item
+#define TAIL_UPPER_LAYER 17 //Some species have tails to render (As viewed from the N, E, or W)
+#define GLASSES_LAYER 18 //Eye-slot item
+#define BELT_LAYER_ALT 19 //Belt-slot item (when set to be above suit via verb)
+#define SUIT_STORE_LAYER 20 //Suit storage-slot item
+#define BACK_LAYER 21 //Back-slot item
+#define HAIR_LAYER 22 //The human's hair
+#define HAIR_ACCESSORY_LAYER 23 //Simply move this up a number if things are added.
+#define EARS_LAYER 24 //Both ear-slot items (combined image)
+#define EYES_LAYER 25 //Mob's eyes (used for glowing eyes)
+#define FACEMASK_LAYER 26 //Mask-slot item
+#define GLASSES_LAYER_ALT 27 //So some glasses can appear on top of hair and things
+#define HEAD_LAYER 28 //Head-slot item
+#define HANDCUFF_LAYER 29 //Handcuffs, if the human is handcuffed, in a secret inv slot
+#define LEGCUFF_LAYER 30 //Same as handcuffs, for legcuffs
+#define L_HAND_LAYER 31 //Left-hand item
+#define R_HAND_LAYER 32 //Right-hand item
+#define WING_LAYER 33 //Wings or protrusions over the suit.
+#define TAIL_UPPER_LAYER_ALT 34 //Modified tail-sprite layer. Tend to be larger.
+#define MODIFIER_EFFECTS_LAYER 35 //Effects drawn by modifiers
+#define FIRE_LAYER 36 //'Mob on fire' overlay layer
+#define MOB_WATER_LAYER 37
+#define TARGETED_LAYER 38 //'Aimed at' overlay layer
+#define VORE_BELLY_LAYER 39
+#define VORE_TAIL_LAYER 40
+
+#define TOTAL_LAYERS 40 // <---- KEEP THIS UPDATED, should always equal the highest number here, used to initialize a list.
+
+//These two are only used for gargoyles currently
+#define HUMAN_BODY_LAYERS list(MUTATIONS_LAYER, TAIL_LOWER_LAYER, WING_LOWER_LAYER, BODYPARTS_LAYER, SKIN_LAYER, BLOOD_LAYER, MOB_DAM_LAYER, TAIL_UPPER_LAYER, HAIR_LAYER, HAIR_ACCESSORY_LAYER, EYES_LAYER, WING_LAYER, VORE_BELLY_LAYER, VORE_TAIL_LAYER, TAIL_UPPER_LAYER_ALT)
+#define HUMAN_OTHER_LAYERS list(MODIFIER_EFFECTS_LAYER, FIRE_LAYER, MOB_WATER_LAYER, TARGETED_LAYER)
diff --git a/code/__defines/verb_manager.dm b/code/__defines/verb_manager.dm
new file mode 100644
index 00000000000..11ea6ada4d8
--- /dev/null
+++ b/code/__defines/verb_manager.dm
@@ -0,0 +1,36 @@
+/**
+ * verb queuing thresholds. remember that since verbs execute after SendMaps the player wont see the effects of the verbs on the game world
+ * until SendMaps executes next tick, and then when that later update reaches them. thus most player input has a minimum latency of world.tick_lag + player ping.
+ * however thats only for the visual effect of player input, when a verb processes the actual latency of game state changes or semantic latency is effectively 1/2 player ping,
+ * unless that verb is queued for the next tick in which case its some number probably smaller than world.tick_lag.
+ * so some verbs that represent player input are important enough that we only introduce semantic latency if we absolutely need to.
+ * its for this reason why player clicks are handled in SSinput before even movement - semantic latency could cause someone to move out of range
+ * when the verb finally processes but it was in range if the verb had processed immediately and overtimed.
+ */
+
+///queuing tick_usage threshold for verbs that are high enough priority that they only queue if the server is overtiming.
+///ONLY use for critical verbs
+#define VERB_OVERTIME_QUEUE_THRESHOLD 100
+///queuing tick_usage threshold for verbs that need lower latency more than most verbs.
+#define VERB_HIGH_PRIORITY_QUEUE_THRESHOLD 95
+///default queuing tick_usage threshold for most verbs which can allow a small amount of latency to be processed in the next tick
+#define VERB_DEFAULT_QUEUE_THRESHOLD 85
+
+///attempt to queue this verb process if the server is overloaded. evaluates to FALSE if queuing isnt necessary or if it failed.
+///_verification_args... are only necessary if the verb_manager subsystem youre using checks them in can_queue_verb()
+///if you put anything in _verification_args that ISNT explicitely put in the can_queue_verb() override of the subsystem youre using,
+///it will runtime.
+#define TRY_QUEUE_VERB(_verb_callback, _tick_check, _subsystem_to_use, _verification_args...) (_queue_verb(_verb_callback, _tick_check, _subsystem_to_use, _verification_args))
+///queue wrapper for TRY_QUEUE_VERB() when you want to call the proc if the server isnt overloaded enough to queue
+#define QUEUE_OR_CALL_VERB(_verb_callback, _tick_check, _subsystem_to_use, _verification_args...) \
+ if(!TRY_QUEUE_VERB(_verb_callback, _tick_check, _subsystem_to_use, _verification_args)) {\
+ _verb_callback:InvokeAsync() \
+ };
+
+//goes straight to SSverb_manager with default tick threshold
+#define DEFAULT_TRY_QUEUE_VERB(_verb_callback, _verification_args...) (TRY_QUEUE_VERB(_verb_callback, VERB_DEFAULT_QUEUE_THRESHOLD, null, _verification_args))
+#define DEFAULT_QUEUE_OR_CALL_VERB(_verb_callback, _verification_args...) QUEUE_OR_CALL_VERB(_verb_callback, VERB_DEFAULT_QUEUE_THRESHOLD, null, _verification_args)
+
+//default tick threshold but nondefault subsystem
+#define TRY_QUEUE_VERB_FOR(_verb_callback, _subsystem_to_use, _verification_args...) (TRY_QUEUE_VERB(_verb_callback, VERB_DEFAULT_QUEUE_THRESHOLD, _subsystem_to_use, _verification_args))
+#define QUEUE_OR_CALL_VERB_FOR(_verb_callback, _subsystem_to_use, _verification_args...) QUEUE_OR_CALL_VERB(_verb_callback, VERB_DEFAULT_QUEUE_THRESHOLD, _subsystem_to_use, _verification_args)
diff --git a/code/__defines/verdigris/_verdigris.dm b/code/__defines/verdigris/_verdigris.dm
new file mode 100644
index 00000000000..021506ac466
--- /dev/null
+++ b/code/__defines/verdigris/_verdigris.dm
@@ -0,0 +1,18 @@
+/* This comment bypasses grep checks */ /var/__verdigris
+
+/proc/__detect_verdigris()
+ if (world.system_type == UNIX)
+ return __verdigris = (fexists("./libverdigris.so") ? "./libverdigris.so" : "libverdigris")
+ else
+ return __verdigris = "verdigris"
+
+#define VERDIGRIS (__verdigris || __detect_verdigris())
+#define VERDIGRIS_CALL(name, args...) call_ext(VERDIGRIS, "byond:" + name)(args)
+
+/proc/verdigris_version() return VERDIGRIS_CALL("verdigris_version")
+/proc/verdigris_features() return VERDIGRIS_CALL("verdigris_features")
+/proc/verdigris_cleanup() return VERDIGRIS_CALL("cleanup")
+
+/world/New()
+ verdigris_cleanup()
+ ..()
diff --git a/code/__defines/verdigris/random_map.dm b/code/__defines/verdigris/random_map.dm
new file mode 100644
index 00000000000..5f8a2372678
--- /dev/null
+++ b/code/__defines/verdigris/random_map.dm
@@ -0,0 +1,3 @@
+/proc/verdigris_generate_automata(limit_x, limit_y, iterations, initial_wall_cell) as /list
+ RETURN_TYPE(/list)
+ return VERDIGRIS_CALL("generate_automata", limit_x, limit_y, iterations, initial_wall_cell)
diff --git a/code/_away_mission_tests.dm b/code/_away_mission_tests.dm
deleted file mode 100644
index 4d9d4e91f9f..00000000000
--- a/code/_away_mission_tests.dm
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- *
- * This file is used by CI to indicate that additional maps need to be compiled to look for errors such as missing paths.
- * Do not add anything but the AWAY_MISSION_TEST definition here as it will be overwritten by CI when running tests.
- *
- *
- * Should you wish to edit set AWAY_MISSION_TEST to 1 like so:
- * #define AWAY_MISSION_TEST 1
- */
-#define AWAY_MISSION_TEST 0
diff --git a/code/_global_vars/_regexes.dm b/code/_global_vars/_regexes.dm
index 46e78a28fa0..1d92bc8c52e 100644
--- a/code/_global_vars/_regexes.dm
+++ b/code/_global_vars/_regexes.dm
@@ -2,3 +2,8 @@
GLOBAL_DATUM_INIT(is_http_protocol, /regex, regex("^https?://"))
GLOBAL_DATUM_INIT(is_valid_url, /regex, regex("((?:https://)\[-a-zA-Z0-9@:%._+~#=]{1,256}.\[-a-zA-Z0-9@:%._+~#=]{1,256}\\b(?:\[-a-zA-Z0-9@():%_+.,~#?&/=]*\[^.,!?:; ()<>{}\\[]\n\"'´`]))", "gm"))
+
+//All < and > characters
+GLOBAL_DATUM_INIT(angular_brackets, /regex, regex(@"[<>]", "g"))
+
+GLOBAL_DATUM_INIT(is_color, /regex, regex("^#\[0-9a-fA-F]{6}$"))
diff --git a/code/_global_vars/configuration.dm b/code/_global_vars/configuration.dm
new file mode 100644
index 00000000000..7aa2272fe9f
--- /dev/null
+++ b/code/_global_vars/configuration.dm
@@ -0,0 +1,5 @@
+// See initialization order in /code/game/world.dm
+// GLOBAL_REAL(config, /datum/controller/configuration)
+GLOBAL_REAL(config, /datum/controller/configuration) = new
+
+GLOBAL_DATUM_INIT(revdata, /datum/getrev, new)
diff --git a/code/_global_vars/lists/mapping.dm b/code/_global_vars/lists/mapping.dm
index a1f664f7c25..1ddf6cae970 100644
--- a/code/_global_vars/lists/mapping.dm
+++ b/code/_global_vars/lists/mapping.dm
@@ -31,19 +31,21 @@ GLOBAL_LIST_INIT(cww_dir, list( // cww_dir[dir] = counter-clockwise rotation of
48, 56, 52, 60, 49, 57, 53, 61, 50, 58, 54, 62, 51, 59, 55, 63 // UP+DOWN - Same as first line but +48
))
+// YW Addtion Start
GLOBAL_LIST_INIT(ore_types, list(
- "hematite" = /obj/item/weapon/ore/iron,
- "uranium" = /obj/item/weapon/ore/uranium,
- "gold" = /obj/item/weapon/ore/gold,
- "silver" = /obj/item/weapon/ore/silver,
- "diamond" = /obj/item/weapon/ore/diamond,
- "phoron" = /obj/item/weapon/ore/phoron,
- "platinum" = /obj/item/weapon/ore/osmium,
- "mhydrogen" = /obj/item/weapon/ore/hydrogen,
- "silicates" = /obj/item/weapon/ore/glass,
- "carbon" = /obj/item/weapon/ore/coal,
- "verdantium" = /obj/item/weapon/ore/verdantium,
- "marble" = /obj/item/weapon/ore/marble,
- "lead" = /obj/item/weapon/ore/lead,
- "rutile" = /obj/item/weapon/ore/rutile //VOREStation Add
+ "hematite" = /obj/item/ore/iron,
+ "uranium" = /obj/item/ore/uranium,
+ "gold" = /obj/item/ore/gold,
+ "silver" = /obj/item/ore/silver,
+ "diamond" = /obj/item/ore/diamond,
+ "phoron" = /obj/item/ore/phoron,
+ "platinum" = /obj/item/ore/osmium,
+ "mhydrogen" = /obj/item/ore/hydrogen,
+ "silicates" = /obj/item/ore/glass,
+ "carbon" = /obj/item/ore/coal,
+ "verdantium" = /obj/item/ore/verdantium,
+ "marble" = /obj/item/ore/marble,
+ "lead" = /obj/item/ore/lead,
+ "rutile" = /obj/item/ore/rutile //VOREStation Add
))
+// YW addition End
diff --git a/code/_global_vars/sensitive.dm b/code/_global_vars/sensitive.dm
deleted file mode 100644
index 8de09f4f3a0..00000000000
--- a/code/_global_vars/sensitive.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-// MySQL configuration
-GLOBAL_REAL_VAR(sqladdress) = "localhost"
-GLOBAL_REAL_VAR(sqlport) = "3306"
-GLOBAL_REAL_VAR(sqldb) = "tgstation"
-GLOBAL_REAL_VAR(sqllogin) = "root"
-GLOBAL_REAL_VAR(sqlpass) = ""
-// Feedback gathering sql connection
-GLOBAL_REAL_VAR(sqlfdbkdb) = "test"
-GLOBAL_REAL_VAR(sqlfdbklogin) = "root"
-GLOBAL_REAL_VAR(sqlfdbkpass) = ""
-GLOBAL_REAL_VAR(sqllogging) = 0 // Should we log deaths, population stats, etc.?
diff --git a/code/_helpers/_lists.dm b/code/_helpers/_lists.dm
index 26124773229..b71b20e0370 100644
--- a/code/_helpers/_lists.dm
+++ b/code/_helpers/_lists.dm
@@ -15,6 +15,12 @@
* Misc
*/
+/// Returns the top (last) element from the list, does not remove it from the list. Stack functionality.
+/proc/peek(list/target_list)
+ var/list_length = length(target_list)
+ if(list_length != 0)
+ return target_list[list_length]
+
//Returns a list in plain english as a string
/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = ",")
// this proc cannot be merged with counting_english_list to maintain compatibility
@@ -203,6 +209,13 @@
result = first - second
return result
+/**
+ * Removes any null entries from the list
+ * Returns TRUE if the list had nulls, FALSE otherwise
+**/
+/proc/list_clear_nulls(list/list_to_clear)
+ return (list_to_clear.RemoveAll(null) > 0)
+
/*
Two lists may be different (A!=B) even if they have the same elements.
This actually tests if they have the same entries and values.
@@ -881,3 +894,69 @@ var/global/list/json_cache = list()
else
used_key_list[input_key] = 1
return input_key
+
+// Generic listoflist safe add and removal macros:
+///If value is a list, wrap it in a list so it can be used with list add/remove operations
+#define LIST_VALUE_WRAP_LISTS(value) (islist(value) ? list(value) : value)
+///Add an untyped item to a list, taking care to handle list items by wrapping them in a list to remove the footgun
+#define UNTYPED_LIST_ADD(list, item) (list += LIST_VALUE_WRAP_LISTS(item))
+///Remove an untyped item to a list, taking care to handle list items by wrapping them in a list to remove the footgun
+#define UNTYPED_LIST_REMOVE(list, item) (list -= LIST_VALUE_WRAP_LISTS(item))
+
+/// Passed into BINARY_INSERT to compare keys
+#define COMPARE_KEY __BIN_LIST[__BIN_MID]
+/// Passed into BINARY_INSERT to compare values
+#define COMPARE_VALUE __BIN_LIST[__BIN_LIST[__BIN_MID]]
+
+/****
+ * Binary search sorted insert
+ * INPUT: Object to be inserted
+ * LIST: List to insert object into
+ * 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 should the values be compared? Either COMPARE_KEY or COMPARE_VALUE.
+ */
+#define BINARY_INSERT(INPUT, LIST, TYPECONT, COMPARE, COMPARISON, COMPTYPE) \
+ do {\
+ var/list/__BIN_LIST = LIST;\
+ var/__BIN_CTTL = length(__BIN_LIST);\
+ if(!__BIN_CTTL) {\
+ __BIN_LIST += INPUT;\
+ } else {\
+ var/__BIN_LEFT = 1;\
+ var/__BIN_RIGHT = __BIN_CTTL;\
+ var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
+ var ##TYPECONT/__BIN_ITEM;\
+ while(__BIN_LEFT < __BIN_RIGHT) {\
+ __BIN_ITEM = COMPTYPE;\
+ if(__BIN_ITEM.##COMPARISON <= COMPARE.##COMPARISON) {\
+ __BIN_LEFT = __BIN_MID + 1;\
+ } else {\
+ __BIN_RIGHT = __BIN_MID;\
+ };\
+ __BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
+ };\
+ __BIN_ITEM = COMPTYPE;\
+ __BIN_MID = __BIN_ITEM.##COMPARISON > COMPARE.##COMPARISON ? __BIN_MID : __BIN_MID + 1;\
+ __BIN_LIST.Insert(__BIN_MID, INPUT);\
+ };\
+ } while(FALSE)
+
+///Converts a bitfield to a list of numbers (or words if a wordlist is provided)
+/proc/bitfield_to_list(bitfield = 0, list/wordlist)
+ var/list/return_list = list()
+ if(islist(wordlist))
+ var/max = min(wordlist.len, 24)
+ var/bit = 1
+ for(var/i in 1 to max)
+ if(bitfield & bit)
+ return_list += wordlist[i]
+ bit = bit << 1
+ else
+ for(var/bit_number = 0 to 23)
+ var/bit = 1 << bit_number
+ if(bitfield & bit)
+ return_list += bit
+
+ return return_list
diff --git a/code/_helpers/atmospherics.dm b/code/_helpers/atmospherics.dm
index 25fd699b32b..7e899ed3165 100644
--- a/code/_helpers/atmospherics.dm
+++ b/code/_helpers/atmospherics.dm
@@ -1,16 +1,16 @@
/obj/proc/analyze_gases(var/atom/A, var/mob/user)
if(src != A)
- user.visible_message("\The [user] has used \an [src] on \the [A]")
+ user.visible_message(span_notice("\The [user] has used \an [src] on \the [A]"))
A.add_fingerprint(user)
var/list/result = A.atmosanalyze(user)
if(result && result.len)
- to_chat(user, "Results of the analysis[src == A ? "" : " of \the [A]"]")
+ to_chat(user, span_notice("Results of the analysis[src == A ? "" : " of \the [A]"]"))
for(var/line in result)
- to_chat(user, "[line]")
+ to_chat(user, span_notice("[line]"))
return 1
- to_chat(user, "Your [src] flashes a red light as it fails to analyze \the [A].")
+ to_chat(user, span_warning("Your [src] flashes a red light as it fails to analyze \the [A]."))
return 0
/proc/atmosanalyzer_scan(var/atom/target, var/datum/gas_mixture/mixture, var/mob/user)
@@ -19,13 +19,13 @@
if (mixture && mixture.total_moles > 0)
var/pressure = mixture.return_pressure()
var/total_moles = mixture.total_moles
- results += "Pressure: [round(pressure,0.1)] kPa"
+ results += span_notice("Pressure: [round(pressure,0.1)] kPa")
for(var/mix in mixture.gas)
- results += "[gas_data.name[mix]]: [round((mixture.gas[mix] / total_moles) * 100)]% ([round(mixture.gas[mix], 0.01)] moles)"
- results += "Temperature: [round(mixture.temperature-T0C)]°C"
- results += "Heat Capacity: [round(mixture.heat_capacity(),0.1)]"
+ results += span_notice("[gas_data.name[mix]]: [round((mixture.gas[mix] / total_moles) * 100)]% ([round(mixture.gas[mix], 0.01)] moles)")
+ results += span_notice("Temperature: [round(mixture.temperature-T0C)]°C")
+ results += span_notice("Heat Capacity: [round(mixture.heat_capacity(),0.1)]")
else
- results += "\The [target] is empty!"
+ results += span_notice("\The [target] is empty!")
return results
@@ -35,7 +35,7 @@
/atom/proc/atmosanalyze(var/mob/user)
return
-/obj/item/weapon/tank/atmosanalyze(var/mob/user)
+/obj/item/tank/atmosanalyze(var/mob/user)
return atmosanalyzer_scan(src, src.air_contents, user)
/obj/machinery/portable_atmospherics/atmosanalyze(var/mob/user)
@@ -55,16 +55,16 @@
/obj/machinery/atmospherics/trinary/atmos_filter/atmosanalyze(var/mob/user)
return atmosanalyzer_scan(src, src.air1, user)
-
+
/obj/machinery/atmospherics/trinary/mixer/atmosanalyze(var/mob/user)
return atmosanalyzer_scan(src, src.air3, user)
-
+
/obj/machinery/atmospherics/omni/atmos_filter/atmosanalyze(var/mob/user)
return atmosanalyzer_scan(src, src.input.air, user)
-
+
/obj/machinery/atmospherics/omni/mixer/atmosanalyze(var/mob/user)
return atmosanalyzer_scan(src, src.output.air, user)
-
+
/obj/machinery/meter/atmosanalyze(var/mob/user)
var/datum/gas_mixture/mixture = null
if(src.target)
@@ -74,5 +74,5 @@
/obj/machinery/power/rad_collector/atmosanalyze(var/mob/user)
if(P) return atmosanalyzer_scan(src, src.P.air_contents, user)
-/obj/item/weapon/flamethrower/atmosanalyze(var/mob/user)
+/obj/item/flamethrower/atmosanalyze(var/mob/user)
if(ptank) return atmosanalyzer_scan(src, ptank.air_contents, user)
diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm
index 812c0d5fe73..80d66f555da 100644
--- a/code/_helpers/game.dm
+++ b/code/_helpers/game.dm
@@ -172,7 +172,7 @@
if(ismob(I))
if(!sight_check || isInSight(I, O))
- L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
+ L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects, ignore_show_messages)
if(include_mobs)
if(client_check)
var/mob/M = I
@@ -185,7 +185,7 @@
var/obj/check_obj = I
if(ignore_show_messages || check_obj.show_messages)
if(!sight_check || isInSight(I, O))
- L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects)
+ L |= recursive_content_check(I, L, recursion_limit - 1, client_check, sight_check, include_mobs, include_objects, ignore_show_messages)
if(include_objects)
L |= I
@@ -219,14 +219,14 @@
return hear
-/proc/get_mobs_in_radio_ranges(var/list/obj/item/device/radio/radios)
+/proc/get_mobs_in_radio_ranges(var/list/obj/item/radio/radios)
set background = 1
. = list()
// Returns a list of mobs who can hear any of the radios given in @radios
var/list/speaker_coverage = list()
- for(var/obj/item/device/radio/R as anything in radios)
+ for(var/obj/item/radio/R as anything in radios)
var/turf/speaker = get_turf(R)
if(speaker)
for(var/turf/T in hear(R.canhear_range,speaker))
@@ -248,7 +248,7 @@
/mob/living/silicon/robot/can_hear_radio(var/list/hearturfs)
var/turf/T = get_turf(src)
- var/obj/item/device/radio/borg/R = hearturfs[T] // this should be an assoc list of turf-to-radio
+ var/obj/item/radio/borg/R = hearturfs[T] // this should be an assoc list of turf-to-radio
// We heard it on our own radio? We use power for that.
if(istype(R) && R.myborg == src)
@@ -259,7 +259,7 @@
return R // radio, true, false, what's the difference
/mob/observer/dead/can_hear_radio(var/list/hearturfs)
- return is_preference_enabled(/datum/client_preference/ghost_radio)
+ return client?.prefs?.read_preference(/datum/preference/toggle/ghost_radio)
//Uses dview to quickly return mobs and objects in view,
@@ -313,10 +313,10 @@
if(M && M.stat == DEAD && remote_ghosts && !M.forbid_seeing_deadchat)
switch(type)
if(1) //Audio messages use ghost_ears
- if(M.is_preference_enabled(/datum/client_preference/ghost_ears))
+ if(M.client?.prefs?.read_preference(/datum/preference/toggle/ghost_ears))
mobs |= M
if(2) //Visual messages use ghost_sight
- if(M.is_preference_enabled(/datum/client_preference/ghost_sight))
+ if(M.client?.prefs?.read_preference(/datum/preference/toggle/ghost_sight))
mobs |= M
//For objects below the top level who still want to hear
diff --git a/code/_helpers/global_lists.dm b/code/_helpers/global_lists.dm
index 1d3f8ed8d4f..80abfae6522 100644
--- a/code/_helpers/global_lists.dm
+++ b/code/_helpers/global_lists.dm
@@ -52,8 +52,9 @@ GLOBAL_LIST_INIT(custom_species_bases, new) // Species that can be used for a Cu
//Underwear
var/datum/category_collection/underwear/global_underwear = new()
- //Backpacks
-var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt", "Messenger Bag", "Sports Bag", "Strapless Satchel") //VOREStation edit
+ //Customizables
+GLOBAL_LIST_INIT(headsetlist, list("Standard","Bowman","Earbud"))
+var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt", "Messenger Bag", "Sports Bag", "Strapless Satchel")
var/global/list/pdachoicelist = list("Default", "Slim", "Old", "Rugged", "Holographic", "Wrist-Bound","Slider", "Vintage")
var/global/list/exclude_jobs = list(/datum/job/ai,/datum/job/cyborg)
@@ -293,7 +294,7 @@ GLOBAL_LIST_EMPTY(mannequins)
// Custom species icon bases
var/list/blacklisted_icons = list(SPECIES_CUSTOM,SPECIES_PROMETHEAN) //VOREStation Edit
- var/list/whitelisted_icons = list(SPECIES_FENNEC,SPECIES_XENOHYBRID) //VOREStation Edit
+ var/list/whitelisted_icons = list(SPECIES_FENNEC,SPECIES_XENOHYBRID,SPECIES_VOX) //VOREStation Edit
for(var/species_name in GLOB.playable_species)
if(species_name in blacklisted_icons)
continue
diff --git a/code/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm
index 61771ad8b06..56ca5ee8ced 100644
--- a/code/_helpers/global_lists_vr.dm
+++ b/code/_helpers/global_lists_vr.dm
@@ -42,14 +42,14 @@ var/global/list/vantag_choices_list = list(
//Blacklist to exclude items from object ingestion. Digestion blacklist located in digest_act_vr.dm
var/global/list/item_vore_blacklist = list(
- /obj/item/weapon/hand_tele,
- /obj/item/weapon/card/id/gold/captain/spare,
- /obj/item/weapon/gun,
- /obj/item/weapon/pinpointer,
+ /obj/item/hand_tele,
+ /obj/item/card/id/gold/captain/spare,
+ /obj/item/gun,
+ /obj/item/pinpointer,
/obj/item/clothing/shoes/magboots,
/obj/item/areaeditor/blueprints,
/obj/item/clothing/head/helmet/space,
- /obj/item/weapon/disk/nuclear,
+ /obj/item/disk/nuclear,
/obj/item/clothing/suit/storage/hooded/wintercoat/roiz)
//Classic Vore sounds
@@ -154,94 +154,94 @@ var/global/list/global_vore_egg_types = list(
"Spotted Pink")
var/global/list/tf_vore_egg_types = list(
- "Unathi" = /obj/item/weapon/storage/vore_egg/unathi,
- "Tajara" = /obj/item/weapon/storage/vore_egg/tajaran,
- "Akula" = /obj/item/weapon/storage/vore_egg/shark,
- "Skrell" = /obj/item/weapon/storage/vore_egg/skrell,
- "Sergal" = /obj/item/weapon/storage/vore_egg/sergal,
- "Nevrean" = /obj/item/weapon/storage/vore_egg/nevrean,
- "Human" = /obj/item/weapon/storage/vore_egg/human,
- "Slime" = /obj/item/weapon/storage/vore_egg/slime,
- "Egg" = /obj/item/weapon/storage/vore_egg,
- "Xenochimera" = /obj/item/weapon/storage/vore_egg/scree,
- "Xenomorph" = /obj/item/weapon/storage/vore_egg/xenomorph,
- "Chocolate" = /obj/item/weapon/storage/vore_egg/chocolate,
- "Boney" = /obj/item/weapon/storage/vore_egg/owlpellet,
- "Slime Glob" = /obj/item/weapon/storage/vore_egg/slimeglob,
- "Chicken" = /obj/item/weapon/storage/vore_egg/chicken,
- "Synthetic" = /obj/item/weapon/storage/vore_egg/synthetic,
- "Bluespace Floppy" = /obj/item/weapon/storage/vore_egg/floppy,
- "Bluespace Compressed File" = /obj/item/weapon/storage/vore_egg/file,
- "Bluespace CD" = /obj/item/weapon/storage/vore_egg/cd,
- "Escape Pod" = /obj/item/weapon/storage/vore_egg/escapepod,
- "Cooking Error" = /obj/item/weapon/storage/vore_egg/badrecipe,
- "Web Cocoon" = /obj/item/weapon/storage/vore_egg/cocoon,
- "Honeycomb" = /obj/item/weapon/storage/vore_egg/honeycomb,
- "Bug Cocoon" = /obj/item/weapon/storage/vore_egg/bugcocoon,
- "Rock" = /obj/item/weapon/storage/vore_egg/rock,
- "Yellow" = /obj/item/weapon/storage/vore_egg/yellow,
- "Blue" = /obj/item/weapon/storage/vore_egg/blue,
- "Green" = /obj/item/weapon/storage/vore_egg/green,
- "Orange" = /obj/item/weapon/storage/vore_egg/orange,
- "Purple" = /obj/item/weapon/storage/vore_egg/purple,
- "Red" = /obj/item/weapon/storage/vore_egg/red,
- "Rainbow" = /obj/item/weapon/storage/vore_egg/rainbow,
- "Spotted Pink" = /obj/item/weapon/storage/vore_egg/pinkspots)
+ "Unathi" = /obj/item/storage/vore_egg/unathi,
+ "Tajara" = /obj/item/storage/vore_egg/tajaran,
+ "Akula" = /obj/item/storage/vore_egg/shark,
+ "Skrell" = /obj/item/storage/vore_egg/skrell,
+ "Sergal" = /obj/item/storage/vore_egg/sergal,
+ "Nevrean" = /obj/item/storage/vore_egg/nevrean,
+ "Human" = /obj/item/storage/vore_egg/human,
+ "Slime" = /obj/item/storage/vore_egg/slime,
+ "Egg" = /obj/item/storage/vore_egg,
+ "Xenochimera" = /obj/item/storage/vore_egg/scree,
+ "Xenomorph" = /obj/item/storage/vore_egg/xenomorph,
+ "Chocolate" = /obj/item/storage/vore_egg/chocolate,
+ "Boney" = /obj/item/storage/vore_egg/owlpellet,
+ "Slime Glob" = /obj/item/storage/vore_egg/slimeglob,
+ "Chicken" = /obj/item/storage/vore_egg/chicken,
+ "Synthetic" = /obj/item/storage/vore_egg/synthetic,
+ "Bluespace Floppy" = /obj/item/storage/vore_egg/floppy,
+ "Bluespace Compressed File" = /obj/item/storage/vore_egg/file,
+ "Bluespace CD" = /obj/item/storage/vore_egg/cd,
+ "Escape Pod" = /obj/item/storage/vore_egg/escapepod,
+ "Cooking Error" = /obj/item/storage/vore_egg/badrecipe,
+ "Web Cocoon" = /obj/item/storage/vore_egg/cocoon,
+ "Honeycomb" = /obj/item/storage/vore_egg/honeycomb,
+ "Bug Cocoon" = /obj/item/storage/vore_egg/bugcocoon,
+ "Rock" = /obj/item/storage/vore_egg/rock,
+ "Yellow" = /obj/item/storage/vore_egg/yellow,
+ "Blue" = /obj/item/storage/vore_egg/blue,
+ "Green" = /obj/item/storage/vore_egg/green,
+ "Orange" = /obj/item/storage/vore_egg/orange,
+ "Purple" = /obj/item/storage/vore_egg/purple,
+ "Red" = /obj/item/storage/vore_egg/red,
+ "Rainbow" = /obj/item/storage/vore_egg/rainbow,
+ "Spotted Pink" = /obj/item/storage/vore_egg/pinkspots)
var/global/list/edible_trash = list(/obj/item/broken_device,
/obj/item/clothing/accessory/collar,
- /obj/item/device/communicator,
+ /obj/item/communicator,
/obj/item/clothing/mask,
/obj/item/clothing/glasses,
/obj/item/clothing/gloves,
/obj/item/clothing/head,
/obj/item/clothing/shoes,
- /obj/item/device/aicard,
- /obj/item/device/flashlight,
- /obj/item/device/mmi/digital/posibrain,
- /obj/item/device/paicard,
- /obj/item/device/pda,
- /obj/item/device/radio/headset,
+ /obj/item/aicard,
+ /obj/item/flashlight,
+ /obj/item/mmi/digital/posibrain,
+ /obj/item/paicard,
+ /obj/item/pda,
+ /obj/item/radio/headset,
/obj/item/inflatable/torn,
/obj/item/organ,
/obj/item/stack/material/cardboard,
/obj/item/toy,
/obj/item/trash,
- /obj/item/weapon/digestion_remains,
- /obj/item/weapon/bananapeel,
- /obj/item/weapon/book,
- /obj/item/weapon/bone,
- /obj/item/weapon/broken_bottle,
- /obj/item/weapon/card/emag_broken,
+ /obj/item/digestion_remains,
+ /obj/item/bananapeel,
+ /obj/item/book,
+ /obj/item/bone,
+ /obj/item/broken_bottle,
+ /obj/item/card/emag_broken,
/obj/item/trash/cigbutt,
- /obj/item/weapon/circuitboard/broken,
- /obj/item/weapon/clipboard,
- /obj/item/weapon/corncob,
- /obj/item/weapon/dice,
- /obj/item/weapon/flame,
- /obj/item/weapon/light,
- /obj/item/weapon/lipstick,
- /obj/item/weapon/material/shard,
- /obj/item/weapon/newspaper,
- /obj/item/weapon/paper,
- /obj/item/weapon/paperplane,
- /obj/item/weapon/pen,
- /obj/item/weapon/photo,
- /obj/item/weapon/reagent_containers/food,
- /obj/item/weapon/reagent_containers/glass/rag,
- /obj/item/weapon/soap,
- /obj/item/weapon/spacecash,
- /obj/item/weapon/storage/box/khcrystal,
- /obj/item/weapon/storage/box/matches,
- /obj/item/weapon/storage/box/wings,
- /obj/item/weapon/storage/fancy/candle_box,
- /obj/item/weapon/storage/fancy/cigarettes,
- /obj/item/weapon/storage/fancy/crayons,
- /obj/item/weapon/storage/fancy/egg_box,
- /obj/item/weapon/storage/wallet,
- /obj/item/weapon/storage/vore_egg,
- /obj/item/weapon/bikehorn/tinytether,
- /obj/item/weapon/entrepreneur,
+ /obj/item/circuitboard/broken,
+ /obj/item/clipboard,
+ /obj/item/corncob,
+ /obj/item/dice,
+ /obj/item/flame,
+ /obj/item/light,
+ /obj/item/lipstick,
+ /obj/item/material/shard,
+ /obj/item/newspaper,
+ /obj/item/paper,
+ /obj/item/paperplane,
+ /obj/item/pen,
+ /obj/item/photo,
+ /obj/item/reagent_containers/food,
+ /obj/item/reagent_containers/glass/rag,
+ /obj/item/soap,
+ /obj/item/spacecash,
+ /obj/item/storage/box/khcrystal,
+ /obj/item/storage/box/matches,
+ /obj/item/storage/box/wings,
+ /obj/item/storage/fancy/candle_box,
+ /obj/item/storage/fancy/cigarettes,
+ /obj/item/storage/fancy/crayons,
+ /obj/item/storage/fancy/egg_box,
+ /obj/item/storage/wallet,
+ /obj/item/storage/vore_egg,
+ /obj/item/bikehorn/tinytether,
+ /obj/item/entrepreneur,
/obj/item/capture_crystal,
/obj/item/roulette_ball,
/obj/item/pizzabox
@@ -511,16 +511,16 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
SPECIES_SHADEKIN) //Shadefluffers just poof away
/var/global/list/alt_titles_with_icons = list(
- "Virologist",
- "Apprentice Engineer",
- "Medical Intern",
- "Research Intern",
- "Security Cadet",
- "Jr. Cargo Tech",
- "Jr. Explorer", // YW EDIT
- "Server",
- "Electrician",
- "Barista")
+ JOB_ALT_VIROLOGIST,
+ JOB_ALT_APPRENTICE_ENGINEER,
+ JOB_ALT_MEDICAL_INTERN,
+ JOB_ALT_RESEARCH_INTERN,
+ JOB_ALT_SECURITY_CADET,
+ JOB_ALT_JR_CARGO_TECH,
+ JOB_ALT_JR_EXPLORER_TECH,
+ JOB_ALT_SERVER,
+ JOB_ALT_ELECTRICIAN,
+ JOB_ALT_BARISTA)
/var/global/list/existing_solargrubs = list()
diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm
index a81c09b314f..ae731264726 100644
--- a/code/_helpers/icons.dm
+++ b/code/_helpers/icons.dm
@@ -97,203 +97,205 @@
// Ported from /tg/station
// Creates a single icon from a given /atom or /image. Only the first argument is required.
-/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE)
- //Define... defines.
+// appearance_flags indicates whether appearance_flags should be respected (at the cost of about 10-20% perf)
+/proc/getFlatIcon(image/appearance, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE, force_south = FALSE, appearance_flags = FALSE)
+ // Loop through the underlays, then overlays, sorting them into the layers list
+ #define PROCESS_OVERLAYS_OR_UNDERLAYS(flat, process, base_layer) \
+ for (var/i in 1 to process.len) { \
+ var/image/current = process[i]; \
+ if (!current) { \
+ continue; \
+ } \
+ if (current.plane != FLOAT_PLANE && current.plane != appearance.plane) { \
+ continue; \
+ } \
+ var/current_layer = current.layer; \
+ if (current_layer < 0) { \
+ if (current_layer <= -1000) { \
+ return flat; \
+ } \
+ current_layer = base_layer + appearance.layer + current_layer / 1000; \
+ } \
+ for (var/index_to_compare_to in 1 to layers.len) { \
+ var/compare_to = layers[index_to_compare_to]; \
+ if (current_layer < layers[compare_to]) { \
+ layers.Insert(index_to_compare_to, current); \
+ break; \
+ } \
+ } \
+ layers[current] = current_layer; \
+ }
+
var/static/icon/flat_template = icon('icons/effects/effects.dmi', "nothing")
- #define BLANK icon(flat_template)
- #define SET_SELF(SETVAR) do { \
- var/icon/SELF_ICON=icon(icon(curicon, curstate, base_icon_dir),"",SOUTH,no_anim?1:null); \
- if(A.alpha<255) { \
- SELF_ICON.Blend(rgb(255,255,255,A.alpha),ICON_MULTIPLY);\
- } \
- if(A.color) { \
- if(islist(A.color)){ \
- SELF_ICON.MapColors(arglist(A.color))} \
- else{ \
- SELF_ICON.Blend(A.color,ICON_MULTIPLY)} \
- } \
- ##SETVAR=SELF_ICON;\
- } while (0)
- #define INDEX_X_LOW 1
- #define INDEX_X_HIGH 2
- #define INDEX_Y_LOW 3
- #define INDEX_Y_HIGH 4
-
- #define flatX1 flat_size[INDEX_X_LOW]
- #define flatX2 flat_size[INDEX_X_HIGH]
- #define flatY1 flat_size[INDEX_Y_LOW]
- #define flatY2 flat_size[INDEX_Y_HIGH]
- #define addX1 add_size[INDEX_X_LOW]
- #define addX2 add_size[INDEX_X_HIGH]
- #define addY1 add_size[INDEX_Y_LOW]
- #define addY2 add_size[INDEX_Y_HIGH]
-
- if(!A || A.alpha <= 0)
- return BLANK
-
- var/noIcon = FALSE
+ if(!appearance || appearance.alpha <= 0)
+ return icon(flat_template)
if(start)
if(!defdir)
- defdir = A.dir
+ defdir = appearance.dir
if(!deficon)
- deficon = A.icon
+ deficon = appearance.icon
if(!defstate)
- defstate = A.icon_state
+ defstate = appearance.icon_state
if(!defblend)
- defblend = A.blend_mode
+ defblend = appearance.blend_mode
+
+ var/curicon = appearance.icon || deficon
+ var/curstate = appearance.icon_state || defstate
+ var/curdir = (!appearance.dir || appearance.dir == SOUTH) ? defdir : appearance.dir
+
+ if(force_south)
+ curdir = SOUTH
- var/curicon = A.icon || deficon
- var/curstate = A.icon_state || defstate
+ var/render_icon = curicon
- if(!((noIcon = (!curicon))))
- var/curstates = cached_icon_states(curicon)
+ if (render_icon)
+ var/curstates = icon_states(curicon)
if(!(curstate in curstates))
- if("" in curstates)
+ if ("" in curstates)
curstate = ""
else
- noIcon = TRUE // Do not render this object.
+ render_icon = FALSE
- var/curdir
- var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have
+ var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have
- // Use the requested dir or the atom's current dir
- curdir = defdir || A.dir
-
- //Try to remove/optimize this section ASAP, CPU hog. //Slightly mitigated by implementing caching using cached_icon_states
+ //Try to remove/optimize this section ASAP, CPU hog.
//Determines if there's directionals.
- if(!noIcon && curdir != SOUTH)
- var/exist = FALSE
- var/static/list/checkdirs = list(NORTH, EAST, WEST)
- for(var/i in checkdirs) //Not using GLOB for a reason.
- if(length(cached_icon_states(icon(curicon, curstate, i))))
- exist = TRUE
- break
- if(!exist)
+ if(render_icon && curdir != SOUTH)
+ if (
+ !length(icon_states(icon(curicon, curstate, NORTH))) \
+ && !length(icon_states(icon(curicon, curstate, EAST))) \
+ && !length(icon_states(icon(curicon, curstate, WEST))) \
+ )
base_icon_dir = SOUTH
- //
if(!base_icon_dir)
base_icon_dir = curdir
- ASSERT(!BLEND_DEFAULT) //I might just be stupid but lets make sure this define is 0.
-
- var/curblend = A.blend_mode || defblend
+ var/curblend = appearance.blend_mode || defblend
- if(A.overlays.len || A.underlays.len)
- var/icon/flat = BLANK
+ if(appearance.overlays.len || appearance.underlays.len)
+ var/icon/flat = icon(flat_template)
// Layers will be a sorted list of icons/overlays, based on the order in which they are displayed
var/list/layers = list()
var/image/copy
// Add the atom's icon itself, without pixel_x/y offsets.
- if(!noIcon)
- copy = image(icon=curicon, icon_state=curstate, layer=A.layer, dir=base_icon_dir)
- copy.color = A.color
- copy.alpha = A.alpha
+ if(render_icon)
+ copy = image(icon=curicon, icon_state=curstate, layer=appearance.layer, dir=base_icon_dir)
+ copy.color = appearance.color
+ copy.alpha = appearance.alpha
copy.blend_mode = curblend
- layers[copy] = A.layer
-
- // Loop through the underlays, then overlays, sorting them into the layers list
- for(var/process_set in 0 to 1)
- var/list/process = process_set? A.overlays : A.underlays
- for(var/i in 1 to process.len)
- var/image/current = process[i]
- if(!current)
- continue
- if(current.plane != FLOAT_PLANE && current.plane != A.plane)
- continue
- var/current_layer = current.layer
- if(current_layer < 0)
- //if(current_layer <= -1000)
- //return flat
- current_layer = process_set + A.layer + current_layer / 1000
-
- for(var/p in 1 to layers.len)
- var/image/cmp = layers[p]
- if(current_layer < layers[cmp])
- layers.Insert(p, current)
- break
- layers[current] = current_layer
-
- //sortTim(layers, GLOBAL_PROC_REF(cmp_image_layer_asc))
+ layers[copy] = appearance.layer
+
+ PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.underlays, 0)
+ PROCESS_OVERLAYS_OR_UNDERLAYS(flat, appearance.overlays, 1)
var/icon/add // Icon of overlay being added
- // Current dimensions of flattened icon
- var/list/flat_size = list(1, flat.Width(), 1, flat.Height())
- // Dimensions of overlay being added
- var/list/add_size[4]
+ var/flatX1 = 1
+ var/flatX2 = flat.Width()
+ var/flatY1 = 1
+ var/flatY2 = flat.Height()
+
+ var/addX1 = 0
+ var/addX2 = 0
+ var/addY1 = 0
+ var/addY2 = 0
- for(var/V in layers)
- var/image/I = V
- if(I.alpha == 0)
+ for(var/image/layer_image as anything in layers)
+ if(layer_image.alpha == 0)
continue
- if(I == copy) // 'I' is an /image based on the object being flattened.
+ // variables only relevant when accounting for appearance_flags:
+ var/apply_color = TRUE
+ var/apply_alpha = TRUE
+
+ if(layer_image == copy) // 'layer_image' is an /image based on the object being flattened.
curblend = BLEND_OVERLAY
- add = icon(I.icon, I.icon_state, base_icon_dir)
+ add = icon(layer_image.icon, layer_image.icon_state, base_icon_dir)
else // 'I' is an appearance object.
- add = getFlatIcon(image(I), curdir, curicon, curstate, curblend, FALSE, no_anim)
+ var/image/layer_as_image = image(layer_image)
+ if(appearance_flags)
+ if(layer_as_image.appearance_flags & RESET_COLOR)
+ apply_color = FALSE
+ if(layer_as_image.appearance_flags & RESET_ALPHA)
+ apply_alpha = FALSE
+ add = getFlatIcon(layer_as_image, curdir, curicon, curstate, curblend, FALSE, no_anim, force_south, appearance_flags)
if(!add)
continue
+
// Find the new dimensions of the flat icon to fit the added overlay
- add_size = list(
- min(flatX1, I.pixel_x+1),
- max(flatX2, I.pixel_x+add.Width()),
- min(flatY1, I.pixel_y+1),
- max(flatY2, I.pixel_y+add.Height())
+ addX1 = min(flatX1, layer_image.pixel_x + 1)
+ addX2 = max(flatX2, layer_image.pixel_x + add.Width())
+ addY1 = min(flatY1, layer_image.pixel_y + 1)
+ addY2 = max(flatY2, layer_image.pixel_y + add.Height())
+
+ if (
+ addX1 != flatX1 \
+ || addX2 != flatX2 \
+ || addY1 != flatY1 \
+ || addY2 != flatY2 \
)
-
- if(flat_size ~! add_size)
// Resize the flattened icon so the new icon fits
flat.Crop(
- addX1 - flatX1 + 1,
- addY1 - flatY1 + 1,
- addX2 - flatX1 + 1,
- addY2 - flatY1 + 1
+ addX1 - flatX1 + 1,
+ addY1 - flatY1 + 1,
+ addX2 - flatX1 + 1,
+ addY2 - flatY1 + 1
)
- flat_size = add_size.Copy()
+
+ flatX1 = addX1
+ flatX2 = addX2
+ flatY1 = addY1
+ flatY2 = addY2
+
+ if(appearance_flags)
+ // apply parent's color/alpha to the added layers if the layer didn't opt
+ if(apply_color && appearance.color)
+ if(islist(appearance.color))
+ add.MapColors(arglist(appearance.color))
+ else
+ add.Blend(appearance.color, ICON_MULTIPLY)
+
+ if(apply_alpha && appearance.alpha < 255)
+ add.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY)
// Blend the overlay into the flattened icon
- flat.Blend(add, blendMode2iconMode(curblend), I.pixel_x + 2 - flatX1, I.pixel_y + 2 - flatY1)
+ flat.Blend(add, blendMode2iconMode(curblend), layer_image.pixel_x + 2 - flatX1, layer_image.pixel_y + 2 - flatY1)
- if(A.color)
- if(islist(A.color))
- flat.MapColors(arglist(A.color))
- else
- flat.Blend(A.color, ICON_MULTIPLY)
+ if(!appearance_flags)
+ // If we didn't apply parent colors individually per layer respecting appearance_flags, then do it just the one time now
+ if(appearance.color)
+ if(islist(appearance.color))
+ flat.MapColors(arglist(appearance.color))
+ else
+ flat.Blend(appearance.color, ICON_MULTIPLY)
- if(A.alpha < 255)
- flat.Blend(rgb(255, 255, 255, A.alpha), ICON_MULTIPLY)
+ if(appearance.alpha < 255)
+ flat.Blend(rgb(255, 255, 255, appearance.alpha), ICON_MULTIPLY)
if(no_anim)
//Clean up repeated frames
var/icon/cleaned = new /icon()
cleaned.Insert(flat, "", SOUTH, 1, 0)
- . = cleaned
+ return cleaned
else
- . = icon(flat, "", SOUTH)
- else //There's no overlays.
- if(!noIcon)
- SET_SELF(.)
-
- //Clear defines
- #undef flatX1
- #undef flatX2
- #undef flatY1
- #undef flatY2
- #undef addX1
- #undef addX2
- #undef addY1
- #undef addY2
-
- #undef INDEX_X_LOW
- #undef INDEX_X_HIGH
- #undef INDEX_Y_LOW
- #undef INDEX_Y_HIGH
-
- #undef BLANK
- #undef SET_SELF
+ return icon(flat, "", SOUTH)
+ else if (render_icon) // There's no overlays.
+ var/icon/final_icon = icon(icon(curicon, curstate, base_icon_dir), "", SOUTH, no_anim ? TRUE : null)
+
+ if (appearance.alpha < 255)
+ final_icon.Blend(rgb(255,255,255, appearance.alpha), ICON_MULTIPLY)
+
+ if (appearance.color)
+ if (islist(appearance.color))
+ final_icon.MapColors(arglist(appearance.color))
+ else
+ final_icon.Blend(appearance.color, ICON_MULTIPLY)
+
+ return final_icon
+
+ #undef PROCESS_OVERLAYS_OR_UNDERLAYS
/proc/getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N
var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
@@ -676,7 +678,7 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
icon_state = thing.icon_state
//Despite casting to atom, this code path supports mutable appearances, so let's be nice to them
//if(isnull(icon_state) || (isatom(thing) && thing.flags_1 & HTML_USE_INITAL_ICON_1))
- if(isnull(icon_state) || isatom(thing))
+ if(isnull(icon_state) && isatom(thing))
icon_state = initial(thing.icon_state)
if (isnull(dir))
dir = initial(thing.dir)
@@ -745,7 +747,7 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
return ""
//Costlier version of icon2html() that uses getFlatIcon() to account for overlays, underlays, etc. Use with extreme moderation, ESPECIALLY on mobs.
-/proc/costly_icon2html(thing, target, sourceonly = FALSE)
+/proc/costly_icon2html(thing, target, sourceonly = FALSE, force_south = FALSE)
if (!thing)
return
//if(SSlag_switch.measures[DISABLE_USR_ICON2HTML] && usr && !HAS_TRAIT(usr, TRAIT_BYPASS_MEASURES))
@@ -754,5 +756,5 @@ GLOBAL_LIST_EMPTY(cached_examine_icons)
if (isicon(thing))
return icon2html(thing, target)
- var/icon/I = getFlatIcon(thing)
+ var/icon/I = getFlatIcon(thing, force_south = force_south)
return icon2html(I, target, sourceonly = sourceonly)
diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm
index d5e9bd841c7..d016b7111dc 100644
--- a/code/_helpers/logging.dm
+++ b/code/_helpers/logging.dm
@@ -27,131 +27,131 @@
/proc/log_admin(text)
admin_log.Add(text)
- if (config.log_admin)
+ if (CONFIG_GET(flag/log_admin))
WRITE_LOG(diary, "ADMIN: [text]")
/proc/log_adminpm(text, client/source, client/dest)
admin_log.Add(text)
- if (config.log_admin)
+ if (CONFIG_GET(flag/log_admin))
WRITE_LOG(diary, "ADMINPM: [key_name(source)]->[key_name(dest)]: [html_decode(text)]")
/proc/log_pray(text, client/source)
admin_log.Add(text)
- if (config.log_admin)
+ if (CONFIG_GET(flag/log_admin))
WRITE_LOG(diary, "PRAY: [key_name(source)]: [text]")
/proc/log_debug(text)
- if (config.log_debug)
+ if (CONFIG_GET(flag/log_debug))
WRITE_LOG(debug_log, "DEBUG: [sanitize(text)]")
for(var/client/C in GLOB.admins)
- if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs))
+ if(C.prefs?.read_preference(/datum/preference/toggle/show_debug_logs))
to_chat(C,
type = MESSAGE_TYPE_DEBUG,
- html = "DEBUG: [text]")
+ html = span_filter_debuglogs("DEBUG: [text]"))
/proc/log_game(text)
- if (config.log_game)
+ if (CONFIG_GET(flag/log_game))
WRITE_LOG(diary, "GAME: [text]")
/proc/log_vote(text)
- if (config.log_vote)
+ if (CONFIG_GET(flag/log_vote))
WRITE_LOG(diary, "VOTE: [text]")
/proc/log_access_in(client/new_client)
- if (config.log_access)
+ if (CONFIG_GET(flag/log_access))
var/message = "[key_name(new_client)] - IP:[new_client.address] - CID:[new_client.computer_id] - BYOND v[new_client.byond_version]"
WRITE_LOG(diary, "ACCESS IN: [message]") //VOREStation Edit
/proc/log_access_out(mob/last_mob)
- if (config.log_access)
+ if (CONFIG_GET(flag/log_access))
var/message = "[key_name(last_mob)] - IP:[last_mob.lastKnownIP] - CID:Logged Out - BYOND Logged Out"
WRITE_LOG(diary, "ACCESS OUT: [message]")
/proc/log_say(text, mob/speaker)
- if (config.log_say)
+ if (CONFIG_GET(flag/log_say))
WRITE_LOG(diary, "SAY: [speaker.simple_info_line()]: [html_decode(text)]")
//Log the message to in-game dialogue logs, as well.
if(speaker.client)
- speaker.dialogue_log += "([time_stamp()]) ([speaker]/[speaker.client]) SAY: - [text]"
- GLOB.round_text_log += "([time_stamp()]) ([speaker]/[speaker.client]) SAY: - [text]"
+ speaker.dialogue_log += span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("SAY:") + " - " + span_green("[text]")
+ GLOB.round_text_log += span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("SAY:") + " - " + span_green("[text]")
/proc/log_ooc(text, client/user)
- if (config.log_ooc)
+ if (CONFIG_GET(flag/log_ooc))
WRITE_LOG(diary, "OOC: [user.simple_info_line()]: [html_decode(text)]")
- GLOB.round_text_log += "([time_stamp()]) ([user]) OOC: - [text]"
+ GLOB.round_text_log += span_bold("([time_stamp()])") + " (" + span_bold("[user]") + ") " + span_underline("OOC:") + " - " + span_blue(span_bold("[text]"))
/proc/log_aooc(text, client/user)
- if (config.log_ooc)
+ if (CONFIG_GET(flag/log_ooc))
WRITE_LOG(diary, "AOOC: [user.simple_info_line()]: [html_decode(text)]")
- GLOB.round_text_log += "([time_stamp()]) ([user]) AOOC: - [text]"
+ GLOB.round_text_log += span_bold("([time_stamp()])") + " (" + span_bold("[user]") + ") " + span_underline("AOOC:") + " - " + span_red(span_bold("[text]"))
/proc/log_looc(text, client/user)
- if (config.log_ooc)
+ if (CONFIG_GET(flag/log_ooc))
WRITE_LOG(diary, "LOOC: [user.simple_info_line()]: [html_decode(text)]")
- GLOB.round_text_log += "([time_stamp()]) ([user]) LOOC: - [text]"
+ GLOB.round_text_log += span_bold("([time_stamp()])") + " (" + span_bold("[user]") + ") " + span_underline("LOOC:") + " - " + span_orange(span_bold("[text]"))
/proc/log_whisper(text, mob/speaker)
- if (config.log_whisper)
+ if (CONFIG_GET(flag/log_whisper))
WRITE_LOG(diary, "WHISPER: [speaker.simple_info_line()]: [html_decode(text)]")
if(speaker.client)
- speaker.dialogue_log += "([time_stamp()]) ([speaker]/[speaker.client]) SAY: - [text]"
- GLOB.round_text_log += "([time_stamp()]) ([speaker]/[speaker.client]) SAY: - [text]"
+ speaker.dialogue_log += span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("SAY:") + " - " + span_gray(span_italics("[text]"))
+ GLOB.round_text_log += span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("SAY:") + " - " + span_gray(span_italics("[text]"))
/proc/log_emote(text, mob/speaker)
- if (config.log_emote)
+ if (CONFIG_GET(flag/log_emote))
WRITE_LOG(diary, "EMOTE: [speaker.simple_info_line()]: [html_decode(text)]")
if(speaker.client)
- speaker.dialogue_log += "([time_stamp()]) ([speaker]/[speaker.client]) EMOTE: - [text]"
- GLOB.round_text_log += "([time_stamp()]) ([speaker]/[speaker.client]) EMOTE: - [text]"
+ speaker.dialogue_log += span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("EMOTE:") + " - " + span_pink("[text]")
+ GLOB.round_text_log += span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("EMOTE:") + " - " + span_pink("[text]")
/proc/log_attack(attacker, defender, message)
- if (config.log_attack)
+ if (CONFIG_GET(flag/log_attack))
WRITE_LOG(diary, "ATTACK: [attacker] against [defender]: [message]")
/proc/log_adminsay(text, mob/speaker)
- if (config.log_adminchat)
+ if (CONFIG_GET(flag/log_adminchat))
WRITE_LOG(diary, "ADMINSAY: [speaker.simple_info_line()]: [html_decode(text)]")
/proc/log_modsay(text, mob/speaker)
- if (config.log_adminchat)
+ if (CONFIG_GET(flag/log_adminchat))
WRITE_LOG(diary, "MODSAY: [speaker.simple_info_line()]: [html_decode(text)]")
/proc/log_eventsay(text, mob/speaker)
- if (config.log_adminchat)
+ if (CONFIG_GET(flag/log_adminchat))
WRITE_LOG(diary, "EVENTSAY: [speaker.simple_info_line()]: [html_decode(text)]")
/proc/log_ghostsay(text, mob/speaker)
- if (config.log_say)
+ if (CONFIG_GET(flag/log_say))
WRITE_LOG(diary, "DEADCHAT: [speaker.simple_info_line()]: [html_decode(text)]")
- speaker.dialogue_log += "([time_stamp()]) ([speaker]/[speaker.client]) DEADSAY: - [text]"
- GLOB.round_text_log += "([time_stamp()]) ([speaker]/[speaker.client]) DEADSAY: - [text]"
+ speaker.dialogue_log += span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("DEADSAY:") + " - " + span_green("[text]")
+ GLOB.round_text_log += span_small(span_purple(span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("DEADSAY:") + " - [text]"))
/proc/log_ghostemote(text, mob/speaker)
- if (config.log_emote)
+ if (CONFIG_GET(flag/log_emote))
WRITE_LOG(diary, "DEADEMOTE: [speaker.simple_info_line()]: [html_decode(text)]")
/proc/log_adminwarn(text)
- if (config.log_adminwarn)
+ if (CONFIG_GET(flag/log_adminwarn))
WRITE_LOG(diary, "ADMINWARN: [html_decode(text)]")
/proc/log_pda(text, mob/speaker)
- if (config.log_pda)
+ if (CONFIG_GET(flag/log_pda))
WRITE_LOG(diary, "PDA: [speaker.simple_info_line()]: [html_decode(text)]")
- speaker.dialogue_log += "([time_stamp()]) ([speaker]/[speaker.client]) MSG: - [text]"
- GLOB.round_text_log += "([time_stamp()]) ([speaker]/[speaker.client]) MSG: - [text]"
+ speaker.dialogue_log += span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("MSG:") + " - " + span_darkgreen("[text]")
+ GLOB.round_text_log += span_bold("([time_stamp()])") + " (" + span_bold("[speaker]/[speaker.client]") + ") " + span_underline("MSG:") + " - " + span_darkgreen("[text]")
/proc/log_to_dd(text)
to_world_log(text) //this comes before the config check because it can't possibly runtime
- if(config.log_world_output)
+ if(CONFIG_GET(flag/log_world_output))
WRITE_LOG(diary, "DD_OUTPUT: [text]")
/proc/log_error(text)
@@ -178,7 +178,7 @@
WRITE_LOG(diary, "ASSET: [text]")
/proc/report_progress(var/progress_message)
- admin_notice("[progress_message]", R_DEBUG)
+ admin_notice(span_boldannounce("[progress_message]"), R_DEBUG)
to_world_log(progress_message)
//pretty print a direction bitflag, can be useful for debugging.
diff --git a/code/_helpers/logging/debug.dm b/code/_helpers/logging/debug.dm
new file mode 100644
index 00000000000..9a847ee61b0
--- /dev/null
+++ b/code/_helpers/logging/debug.dm
@@ -0,0 +1,11 @@
+/// Logging for config errors
+/// Rarely gets called; just here in case the config breaks.
+/proc/log_config(text, list/data)
+ var/entry = "CONFIG: "
+
+ entry += text
+ entry += " | DATA: "
+ entry += data
+
+ WRITE_LOG(diary, entry)
+ SEND_TEXT(world.log, text)
diff --git a/code/_helpers/logging_vr.dm b/code/_helpers/logging_vr.dm
index aa117125dc7..b0bf8d07e7c 100644
--- a/code/_helpers/logging_vr.dm
+++ b/code/_helpers/logging_vr.dm
@@ -1,11 +1,11 @@
/proc/log_nsay(text, inside, mob/speaker)
- if (config.log_say)
+ if (CONFIG_GET(flag/log_say))
WRITE_LOG(diary, "NSAY (NIF:[inside]): [speaker.simple_info_line()]: [html_decode(text)]")
/proc/log_nme(text, inside, mob/speaker)
- if (config.log_emote)
+ if (CONFIG_GET(flag/log_emote))
WRITE_LOG(diary, "NME (NIF:[inside]): [speaker.simple_info_line()]: [html_decode(text)]")
/proc/log_subtle(text, mob/speaker)
- if (config.log_emote)
+ if (CONFIG_GET(flag/log_emote))
WRITE_LOG(diary, "SUBTLE: [speaker.simple_info_line()]: [html_decode(text)]")
diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm
index dd2dde46825..e78123fe64e 100644
--- a/code/_helpers/mobs.dm
+++ b/code/_helpers/mobs.dm
@@ -136,7 +136,7 @@ Proc for attack log creation, because really why not
return (thing in R.module.modules)
/proc/get_exposed_defense_zone(var/atom/movable/target)
- var/obj/item/weapon/grab/G = locate() in target
+ var/obj/item/grab/G = locate() in target
if(G && G.state >= GRAB_NECK) //works because mobs are currently not allowed to upgrade to NECK if they are grabbing two people.
return pick(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_FOOT, BP_R_FOOT, BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG)
else
@@ -148,10 +148,10 @@ Proc for attack log creation, because really why not
if(!time)
return TRUE //Done!
if(user.status_flags & DOING_TASK)
- to_chat(user, "You're in the middle of doing something else already.")
+ to_chat(user, span_warning("You're in the middle of doing something else already."))
return FALSE //Performing an exclusive do_after or do_mob already
if(target?.flags & IS_BUSY)
- to_chat(user, "Someone is already doing something with \the [target].")
+ to_chat(user, span_warning("Someone is already doing something with \the [target]."))
return FALSE
var/user_loc = user.loc
var/target_loc = target.loc
@@ -214,10 +214,10 @@ Proc for attack log creation, because really why not
if(!delay)
return TRUE //Okay. Done.
if(user.status_flags & DOING_TASK)
- to_chat(user, "You're in the middle of doing something else already.")
+ to_chat(user, span_warning("You're in the middle of doing something else already."))
return FALSE //Performing an exclusive do_after or do_mob already
if(target?.flags & IS_BUSY)
- to_chat(user, "Someone is already doing something with \the [target].")
+ to_chat(user, span_warning("Someone is already doing something with \the [target]."))
return FALSE
var/atom/target_loc = null
@@ -317,7 +317,7 @@ Proc for attack log creation, because really why not
cached_character_icons[cachekey] = .
/proc/not_has_ooc_text(mob/user)
- if (config.allow_Metadata && (!user.client?.prefs?.metadata || length(user.client.prefs.metadata) < 15))
- to_chat(user, "Please set informative OOC notes related to RP/ERP preferences. Set them using the 'OOC Notes' button on the 'General' tab in character setup.")
+ if (CONFIG_GET(flag/allow_metadata) && (!user.client?.prefs?.metadata || length(user.client.prefs.metadata) < 15))
+ to_chat(user, span_warning("Please set informative OOC notes related to RP/ERP preferences. Set them using the 'OOC Notes' button on the 'General' tab in character setup."))
return TRUE
return FALSE
diff --git a/code/_helpers/nameof.dm b/code/_helpers/nameof.dm
new file mode 100644
index 00000000000..5a2fd60e710
--- /dev/null
+++ b/code/_helpers/nameof.dm
@@ -0,0 +1,11 @@
+/**
+ * NAMEOF: Compile time checked variable name to string conversion
+ * evaluates to a string equal to "X", but compile errors if X isn't a var on datum.
+ * datum may be null, but it does need to be a typed var.
+ **/
+#define NAMEOF(datum, X) (#X || ##datum.##X)
+
+/**
+ * NAMEOF that actually works in static definitions because src::type requires src to be defined
+ */
+#define NAMEOF_STATIC(datum, X) (nameof(type::##X))
diff --git a/code/_helpers/names.dm b/code/_helpers/names.dm
index 12e6c46289f..12d2c08e86a 100644
--- a/code/_helpers/names.dm
+++ b/code/_helpers/names.dm
@@ -92,8 +92,8 @@ var/religion_name = null
new_station_name += pick("13","XIII","Thirteen")
- if (config && config.server_name)
- world.name = "[config.server_name]: [name]"
+ if (config && CONFIG_GET(string/servername))
+ world.name = "[CONFIG_GET(string/servername)]: [name]"
else
world.name = new_station_name
@@ -104,8 +104,8 @@ var/religion_name = null
using_map.station_name = name
- if (config && config.server_name)
- world.name = "[config.server_name]: [name]"
+ if (config && CONFIG_GET(string/servername))
+ world.name = "[CONFIG_GET(string/servername)]: [name]"
else
world.name = name
diff --git a/code/_helpers/sanitize_values.dm b/code/_helpers/sanitize_values.dm
index c74176043c3..7cc687d7ce1 100644
--- a/code/_helpers/sanitize_values.dm
+++ b/code/_helpers/sanitize_values.dm
@@ -6,6 +6,13 @@
return number
return default
+/proc/sanitize_float(number, min=0, max=1, accuracy=1, default=0)
+ if(isnum(number))
+ number = round(number, accuracy)
+ if(round(min, accuracy) <= number && number <= round(max, accuracy))
+ return number
+ return default
+
// Checks if the given input is a valid list index; returns true/false and doesn't change anything.
/proc/is_valid_index(input, list/given_list)
if(!isnum(input))
diff --git a/code/_helpers/screen_objs.dm b/code/_helpers/screen_objs.dm
new file mode 100644
index 00000000000..00f6bd41570
--- /dev/null
+++ b/code/_helpers/screen_objs.dm
@@ -0,0 +1,115 @@
+/// Takes a screen loc string in the format
+/// "+-left-offset:+-pixel,+-bottom-offset:+-pixel"
+/// Where the :pixel is optional, and returns
+/// A list in the format (x_offset, y_offset)
+/// We require context to get info out of screen locs that contain relative info, so NORTH, SOUTH, etc
+/proc/screen_loc_to_offset(screen_loc, view)
+ if(!screen_loc)
+ return list(64, 64)
+ var/list/view_size = view_to_pixels(view)
+ var/x = 0
+ var/y = 0
+ // Time to parse for directional relative offsets
+ if(findtext(screen_loc, "EAST")) // If you're starting from the east, we start from the east too
+ x += view_size[1]
+ if(findtext(screen_loc, "WEST")) // HHHHHHHHHHHHHHHHHHHHHH WEST is technically a 1 tile offset from the start. Shoot me please
+ x += ICON_SIZE_X
+ if(findtext(screen_loc, "NORTH"))
+ y += view_size[2]
+ if(findtext(screen_loc, "SOUTH"))
+ y += ICON_SIZE_Y
+
+ var/list/x_and_y = splittext(screen_loc, ",")
+
+ var/list/x_pack = splittext(x_and_y[1], ":")
+ var/list/y_pack = splittext(x_and_y[2], ":")
+
+ var/x_coord = x_pack[1]
+ var/y_coord = y_pack[1]
+
+ if (findtext(x_coord, "CENTER"))
+ x += view_size[1] / 2
+
+ if (findtext(y_coord, "CENTER"))
+ y += view_size[2] / 2
+
+ x_coord = text2num(cut_relative_direction(x_coord))
+ y_coord = text2num(cut_relative_direction(y_coord))
+
+ x += x_coord * ICON_SIZE_X
+ y += y_coord * ICON_SIZE_Y
+
+ if(length(x_pack) > 1)
+ x += text2num(x_pack[2])
+ if(length(y_pack) > 1)
+ y += text2num(y_pack[2])
+ return list(x, y)
+
+/// Takes a list in the form (x_offset, y_offset)
+/// And converts it to a screen loc string
+/// Accepts an optional view string/size to force the screen_loc around, so it can't go out of scope
+/proc/offset_to_screen_loc(x_offset, y_offset, view = null)
+ if(view)
+ var/list/view_bounds = view_to_pixels(view)
+ x_offset = clamp(x_offset, ICON_SIZE_X, view_bounds[1])
+ y_offset = clamp(y_offset, ICON_SIZE_Y, view_bounds[2])
+
+ // Round with no argument is floor, so we get the non pixel offset here
+ var/x = round(x_offset / ICON_SIZE_X)
+ var/pixel_x = x_offset % ICON_SIZE_X
+ var/y = round(y_offset / ICON_SIZE_Y)
+ var/pixel_y = y_offset % ICON_SIZE_Y
+
+ var/list/generated_loc = list()
+ generated_loc += "[x]"
+ if(pixel_x)
+ generated_loc += ":[pixel_x]"
+ generated_loc += ",[y]"
+ if(pixel_y)
+ generated_loc += ":[pixel_y]"
+ return jointext(generated_loc, "")
+
+/**
+ * Returns a valid location to place a screen object without overflowing the viewport
+ *
+ * * target: The target location as a purely number based screen_loc string "+-left-offset:+-pixel,+-bottom-offset:+-pixel"
+ * * target_offset: The amount we want to offset the target location by. We explictly don't care about direction here, we will try all 4
+ * * view: The view variable of the client we're doing this for. We use this to get the size of the screen
+ *
+ * Returns a screen loc representing the valid location
+**/
+/proc/get_valid_screen_location(target_loc, target_offset, view)
+ var/list/offsets = screen_loc_to_offset(target_loc)
+ var/base_x = offsets[1]
+ var/base_y = offsets[2]
+
+ var/list/view_size = view_to_pixels(view)
+
+ // Bias to the right, down, left, and then finally up
+ if(base_x + target_offset < view_size[1])
+ return offset_to_screen_loc(base_x + target_offset, base_y, view)
+ if(base_y - target_offset > ICON_SIZE_Y)
+ return offset_to_screen_loc(base_x, base_y - target_offset, view)
+ if(base_x - target_offset > ICON_SIZE_X)
+ return offset_to_screen_loc(base_x - target_offset, base_y, view)
+ if(base_y + target_offset < view_size[2])
+ return offset_to_screen_loc(base_x, base_y + target_offset, view)
+ stack_trace("You passed in a scren location {[target_loc]} and offset {[target_offset]} that can't be fit in the viewport Width {[view_size[1]]}, Height {[view_size[2]]}. what did you do lad")
+ return null // The fuck did you do lad
+
+/// Takes a screen_loc string and cut out any directions like NORTH or SOUTH
+/proc/cut_relative_direction(fragment)
+ var/static/regex/regex = regex(@"([A-Z])\w+", "g")
+ return regex.Replace(fragment, "")
+
+/// Returns a screen_loc format for a tiling screen objects from start and end positions. Start should be bottom left corner, and end top right corner.
+/proc/spanning_screen_loc(start_px, start_py, end_px, end_py)
+ var/starting_tile_x = round(start_px / ICON_SIZE_X)
+ start_px -= starting_tile_x * ICON_SIZE_X
+ var/starting_tile_y = round(start_py/ ICON_SIZE_Y)
+ start_py -= starting_tile_y * ICON_SIZE_Y
+ var/ending_tile_x = round(end_px / ICON_SIZE_X)
+ end_px -= ending_tile_x * ICON_SIZE_X
+ var/ending_tile_y = round(end_py / ICON_SIZE_Y)
+ end_py -= ending_tile_y * ICON_SIZE_Y
+ return "[starting_tile_x]:[start_px],[starting_tile_y]:[start_py] to [ending_tile_x]:[end_px],[ending_tile_y]:[end_py]"
diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm
index 2ded9ae75ad..725335f267a 100644
--- a/code/_helpers/text.dm
+++ b/code/_helpers/text.dm
@@ -343,19 +343,20 @@
//The icon var could be local in the proc, but it's a waste of resources
// to always create it and then throw it out.
/var/icon/text_tag_icons = 'icons/chattags.dmi'
-/var/list/text_tag_cache = list()
+GLOBAL_LIST_EMPTY(text_tag_cache)
+
/proc/create_text_tag(var/tagname, var/tagdesc = tagname, var/client/C = null)
- if(!(C && C.is_preference_enabled(/datum/client_preference/chat_tags)))
+ if(!(C && C.prefs?.read_preference(/datum/preference/toggle/chat_tags)))
return tagdesc
- if(!text_tag_cache[tagname])
- var/icon/tag = icon(text_tag_icons, tagname)
- text_tag_cache[tagname] = tag
+ if(!GLOB.text_tag_cache[tagname])
+ var/datum/asset/spritesheet/chatassets = get_asset_datum(/datum/asset/spritesheet/chat)
+ GLOB.text_tag_cache[tagname] = chatassets.icon_tag(tagname)
if(!C.tgui_panel.is_ready() || C.tgui_panel.oldchat)
return ""
- return icon2html(text_tag_cache[tagname], C, extra_classes = "text_tag")
+ return GLOB.text_tag_cache[tagname]
/proc/create_text_tag_old(var/tagname, var/tagdesc = tagname, var/client/C = null)
- if(!(C && C.is_preference_enabled(/datum/client_preference/chat_tags)))
+ if(!(C && C.prefs?.read_preference(/datum/preference/toggle/chat_tags)))
return tagdesc
return ""
@@ -613,3 +614,15 @@
paper_text = replacetext(paper_text, "
", "\n")
paper_text = strip_html_properly(paper_text) // Get rid of everything else entirely.
return paper_text
+
+//json decode that will return null on parse error instead of runtiming.
+/proc/safe_json_decode(data)
+ try
+ return json_decode(data)
+ catch
+ return null
+
+/// Removes all non-alphanumerics from the text, keep in mind this can lead to id conflicts
+/proc/sanitize_css_class_name(name)
+ var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
+ return replacetext(name, regex, "")
diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm
index 2cc26b170fa..7668146b3db 100644
--- a/code/_helpers/time.dm
+++ b/code/_helpers/time.dm
@@ -1,3 +1,7 @@
+//Returns the world time in english
+/proc/worldtime2text()
+ return gameTimestamp("hh:mm:ss", world.time)
+
#define TimeOfGame (get_game_time())
#define TimeOfTick (TICK_USAGE*0.01*world.tick_lag)
diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm
index 40be3d403ad..0e0dd582952 100644
--- a/code/_helpers/type2type.dm
+++ b/code/_helpers/type2type.dm
@@ -1,11 +1,41 @@
/*
* Holds procs designed to change one type of value, into another.
* Contains:
+ * file2list
+ * type2top
* hex2num & num2hex
* file2list
* angle2dir
*/
+//Splits the text of a file at seperator and returns them in a list.
+//returns an empty list if the file doesn't exist
+/world/proc/file2list(filename, seperator="\n", trim = TRUE)
+ if (trim)
+ return splittext(trim(file2text(filename)),seperator)
+ return splittext(file2text(filename),seperator)
+
+//returns a string the last bit of a type, without the preceeding '/'
+/proc/type2top(the_type)
+ //handle the builtins manually
+ if(!ispath(the_type))
+ return
+ switch(the_type)
+ if(/datum)
+ return "datum"
+ if(/atom)
+ return "atom"
+ if(/obj)
+ return "obj"
+ if(/mob)
+ return "mob"
+ if(/area)
+ return "area"
+ if(/turf)
+ return "turf"
+ else //regex everything else (works for /proc too)
+ return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", ""))
+
// Returns an integer given a hexadecimal number string as input.
/proc/hex2num(hex)
if (!istext(hex))
@@ -558,3 +588,38 @@
/// for use inside of browse() calls to html assets that might be loaded on a cdn.
/proc/url2htmlloader(url)
return {""}
+
+/// Returns a list with all keys turned into paths
+/proc/text2path_list(list/L)
+ . = list()
+ for(var/key in L)
+ var/path = key
+ if(!ispath(path))
+ path = text2path(key)
+ if(!isnull(L[path]))
+ .[path] = L[path]
+ continue
+ if(!isnull(L[key]))
+ .[path] = L[key]
+ continue
+ if(!isnull(path))
+ . += path
+
+/proc/path2text_list(list/L)
+ . = list()
+ for(var/key in L)
+ var/text = "[key]"
+ if(!isnull(L[text]))
+ .[text] = L[text]
+ continue
+ if(!isnull(L[key]))
+ .[text] = L[key]
+ continue
+ if(!isnull(text))
+ .[text] = ""
+
+/proc/check_list_copy(var/i)
+ if(islist(i))
+ var/list/l = i
+ return l.Copy()
+ return i
diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm
index 8a722ac7676..8b5c5d0325b 100644
--- a/code/_helpers/unsorted.dm
+++ b/code/_helpers/unsorted.dm
@@ -315,16 +315,16 @@ Turf and target are seperate in case you want to teleport some distance from a t
var/search_pda = 1
for(var/A in searching)
- if( search_id && istype(A,/obj/item/weapon/card/id) )
- var/obj/item/weapon/card/id/ID = A
+ if( search_id && istype(A,/obj/item/card/id) )
+ var/obj/item/card/id/ID = A
if(ID.registered_name == oldname)
ID.registered_name = newname
ID.name = "[newname]'s ID Card ([ID.assignment])"
if(!search_pda) break
search_id = 0
- else if( search_pda && istype(A,/obj/item/device/pda) )
- var/obj/item/device/pda/PDA = A
+ else if( search_pda && istype(A,/obj/item/pda) )
+ var/obj/item/pda/PDA = A
if(PDA.owner == oldname)
PDA.owner = newname
PDA.name = "PDA-[newname] ([PDA.ownjob])"
@@ -367,7 +367,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
if(isAI(src))
var/mob/living/silicon/ai/A = src
oldname = null//don't bother with the records update crap
- //to_world("[newname] is the AI!")
+ //to_world(span_world("[newname] is the AI!"))
//world << sound('sound/AI/newAI.ogg')
// Set eyeobj name
A.SetName(newname)
@@ -420,7 +420,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
/proc/select_active_ai(var/mob/user)
var/list/ais = active_ais()
if(ais.len)
- if(user) . = tgui_input_list(usr, "AI signals detected:", "AI selection", ais)
+ if(user) . = tgui_input_list(user, "AI signals detected:", "AI selection", ais)
else . = pick(ais)
return .
@@ -974,7 +974,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
if(toupdate.len)
for(var/turf/simulated/T1 in toupdate)
- air_master.mark_for_update(T1)
+ SSair.mark_for_update(T1)
return copiedobjs
@@ -1030,13 +1030,13 @@ Turf and target are seperate in case you want to teleport some distance from a t
//Quick type checks for some tools
var/global/list/common_tools = list(
/obj/item/stack/cable_coil,
-/obj/item/weapon/tool/wrench,
-/obj/item/weapon/weldingtool,
-/obj/item/weapon/tool/screwdriver,
-/obj/item/weapon/tool/wirecutters,
-/obj/item/device/multitool,
-/obj/item/weapon/tool/crowbar,
-/obj/item/weapon/tool/transforming)
+/obj/item/tool/wrench,
+/obj/item/weldingtool,
+/obj/item/tool/screwdriver,
+/obj/item/tool/wirecutters,
+/obj/item/multitool,
+/obj/item/tool/crowbar,
+/obj/item/tool/transforming)
/proc/istool(O)
if(O && is_type_in_list(O, common_tools))
@@ -1045,32 +1045,32 @@ var/global/list/common_tools = list(
/proc/is_wire_tool(obj/item/I)
- if(istype(I, /obj/item/device/multitool) || I.has_tool_quality(TOOL_WIRECUTTER))
+ if(istype(I, /obj/item/multitool) || I.has_tool_quality(TOOL_WIRECUTTER))
return TRUE
- if(istype(I, /obj/item/device/assembly/signaler))
+ if(istype(I, /obj/item/assembly/signaler))
return TRUE
return
/proc/is_hot(obj/item/W as obj)
switch(W.type)
- if(/obj/item/weapon/weldingtool)
- var/obj/item/weapon/weldingtool/WT = W
+ if(/obj/item/weldingtool)
+ var/obj/item/weldingtool/WT = W
if(WT.isOn())
return 3800
else
return 0
- if(/obj/item/weapon/tool/transforming)
- var/obj/item/weapon/tool/transforming/TT = W
+ if(/obj/item/tool/transforming)
+ var/obj/item/tool/transforming/TT = W
if(TT.possible_tooltypes[TT.current_tooltype] == TOOL_WELDER)
return 3800
else
return 0
- if(/obj/item/weapon/flame/lighter)
+ if(/obj/item/flame/lighter)
if(W:lit)
return 1500
else
return 0
- if(/obj/item/weapon/flame/match)
+ if(/obj/item/flame/match)
if(W:lit)
return 1000
else
@@ -1080,9 +1080,9 @@ var/global/list/common_tools = list(
return 1000
else
return 0
- if(/obj/item/weapon/pickaxe/plasmacutter)
+ if(/obj/item/pickaxe/plasmacutter)
return 3800
- if(/obj/item/weapon/melee/energy)
+ if(/obj/item/melee/energy)
return 3500
else
return 0
@@ -1113,12 +1113,12 @@ var/global/list/common_tools = list(
return TRUE
return ( \
W.has_tool_quality(TOOL_SCREWDRIVER) || \
- istype(W, /obj/item/weapon/pen) || \
- istype(W, /obj/item/weapon/weldingtool) || \
- istype(W, /obj/item/weapon/flame/lighter/zippo) || \
- istype(W, /obj/item/weapon/flame/match) || \
+ istype(W, /obj/item/pen) || \
+ istype(W, /obj/item/weldingtool) || \
+ istype(W, /obj/item/flame/lighter/zippo) || \
+ istype(W, /obj/item/flame/match) || \
istype(W, /obj/item/clothing/mask/smokable/cigarette) || \
- istype(W, /obj/item/weapon/shovel) \
+ istype(W, /obj/item/shovel) \
)
// check if mob is lying down on something we can operate him on.
@@ -1153,12 +1153,12 @@ Checks if that loc and dir has a item on the wall
TODO - Fix this ancient list of wall items. Preferably make it dynamically populated. ~Leshana
*/
var/list/WALLITEMS = list(
- /obj/machinery/power/apc, /obj/machinery/alarm, /obj/item/device/radio/intercom, /obj/structure/frame,
+ /obj/machinery/power/apc, /obj/machinery/alarm, /obj/item/radio/intercom, /obj/structure/frame,
/obj/structure/extinguisher_cabinet, /obj/structure/reagent_dispensers/peppertank,
/obj/machinery/status_display, /obj/machinery/requests_console, /obj/machinery/light_switch, /obj/structure/sign,
/obj/machinery/newscaster, /obj/machinery/firealarm, /obj/structure/noticeboard, /obj/machinery/button/remote,
/obj/machinery/computer/security/telescreen, /obj/machinery/embedded_controller/radio,
- /obj/item/weapon/storage/secure/safe, /obj/machinery/door_timer, /obj/machinery/flasher, /obj/machinery/keycard_auth,
+ /obj/item/storage/secure/safe, /obj/machinery/door_timer, /obj/machinery/flasher, /obj/machinery/keycard_auth,
/obj/structure/mirror, /obj/structure/fireaxecabinet, /obj/machinery/computer/security/telescreen/entertainment
)
/proc/gotwallitem(loc, dir)
@@ -1328,40 +1328,37 @@ var/mob/dview/dview_mob = new
if (NOT_FLAG(USE_ALLOW_NON_ADJACENT) && !Adjacent(user))
if (show_messages)
- to_chat(user, span("notice","You're too far away from [src] to do that."))
+ to_chat(user, span_notice("You're too far away from [src] to do that."))
return USE_FAIL_NON_ADJACENT
if (NOT_FLAG(USE_ALLOW_DEAD) && user.stat == DEAD)
if (show_messages)
- to_chat(user, span("notice","You can't do that when you're dead."))
+ to_chat(user, span_notice("You can't do that when you're dead."))
return USE_FAIL_DEAD
if (NOT_FLAG(USE_ALLOW_INCAPACITATED) && (user.incapacitated()))
if (show_messages)
- to_chat(user, span("notice","You cannot do that in your current state."))
+ to_chat(user, span_notice("You cannot do that in your current state."))
return USE_FAIL_INCAPACITATED
if (NOT_FLAG(USE_ALLOW_NON_ADV_TOOL_USR) && !user.IsAdvancedToolUser())
if (show_messages)
- to_chat(user, span("notice","You don't know how to operate [src]."))
+ to_chat(user, span_notice("You don't know how to operate [src]."))
return USE_FAIL_NON_ADV_TOOL_USR
if (HAS_FLAG(USE_DISALLOW_SILICONS) && issilicon(user))
if (show_messages)
- to_chat(user, span("notice","You need hands for that."))
+ to_chat(user, span_notice("You need hands for that."))
return USE_FAIL_IS_SILICON
if (HAS_FLAG(USE_FORCE_SRC_IN_USER) && !(src in user))
if (show_messages)
- to_chat(user, span("notice","You need to be holding [src] to do that."))
+ to_chat(user, span_notice("You need to be holding [src] to do that."))
return USE_FAIL_NOT_IN_USER
#undef NOT_FLAG
#undef HAS_FLAG
-//datum may be null, but it does need to be a typed var
-#define NAMEOF(datum, X) (#X || ##datum.##X)
-
#define VARSET_LIST_CALLBACK(target, var_name, var_value) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___callbackvarset), ##target, ##var_name, ##var_value)
//dupe code because dm can't handle 3 level deep macros
#define VARSET_CALLBACK(datum, var, var_value) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___callbackvarset), ##datum, NAMEOF(##datum, ##var), ##var_value)
@@ -1463,12 +1460,12 @@ var/mob/dview/dview_mob = new
var/typename = "[type]"
var/static/list/TYPES_SHORTCUTS = list(
/obj/effect/decal/cleanable = "CLEANABLE",
- /obj/item/device/radio/headset = "HEADSET",
+ /obj/item/radio/headset = "HEADSET",
/obj/item/clothing/head/helmet/space = "SPESSHELMET",
- /obj/item/weapon/book/manual = "MANUAL",
- /obj/item/weapon/reagent_containers/food/drinks = "DRINK",
- /obj/item/weapon/reagent_containers/food = "FOOD",
- /obj/item/weapon/reagent_containers = "REAGENT_CONTAINERS",
+ /obj/item/book/manual = "MANUAL",
+ /obj/item/reagent_containers/food/drinks = "DRINK",
+ /obj/item/reagent_containers/food = "FOOD",
+ /obj/item/reagent_containers = "REAGENT_CONTAINERS",
/obj/machinery/atmospherics = "ATMOS_MECH",
/obj/machinery/portable_atmospherics = "PORT_ATMOS",
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack = "MECHA_MISSILE_RACK",
diff --git a/code/_helpers/unsorted_vr.dm b/code/_helpers/unsorted_vr.dm
index 0890c1f9c63..a21466983d3 100644
--- a/code/_helpers/unsorted_vr.dm
+++ b/code/_helpers/unsorted_vr.dm
@@ -19,7 +19,7 @@
if(vent.welded)
continue
var/area/A = get_area(vent)
- if(A.forbid_events)
+ if(A.flag_check(AREA_FORBID_EVENTS))
continue
vent_list += vent
if(!vent_list.len)
@@ -43,26 +43,26 @@
//Sender is optional
/proc/admin_chat_message(var/message = "Debug Message", var/color = "#FFFFFF", var/sender)
- if (!config.chat_webhook_url || !message)
+ if (!CONFIG_GET(string/chat_webhook_url) || !message)
return
spawn(0)
var/query_string = "type=adminalert"
- query_string += "&key=[url_encode(config.chat_webhook_key)]"
+ query_string += "&key=[url_encode(CONFIG_GET(string/chat_webhook_key))]"
query_string += "&msg=[url_encode(message)]"
query_string += "&color=[url_encode(color)]"
if(sender)
query_string += "&from=[url_encode(sender)]"
- world.Export("[config.chat_webhook_url]?[query_string]")
+ world.Export("[CONFIG_GET(string/chat_webhook_url)]?[query_string]")
/proc/admin_action_message(var/admin = "INVALID", var/user = "INVALID", var/action = "INVALID", var/reason = "INVALID", var/time = "INVALID")
- if (!config.chat_webhook_url || !action)
+ if (!CONFIG_GET(string/chat_webhook_url) || !action)
return
spawn(0)
var/query_string = "type=adminaction"
- query_string += "&key=[url_encode(config.chat_webhook_key)]"
+ query_string += "&key=[url_encode(CONFIG_GET(string/chat_webhook_key))]"
query_string += "&admin=[url_encode(admin)]"
query_string += "&user=[url_encode(user)]"
query_string += "&action=[url_encode(action)]"
query_string += "&reason=[url_encode(reason)]"
query_string += "&time=[url_encode(time)]"
- world.Export("[config.chat_webhook_url]?[query_string]")
+ world.Export("[CONFIG_GET(string/chat_webhook_url)]?[query_string]")
diff --git a/code/_helpers/verbs.dm b/code/_helpers/verbs.dm
new file mode 100644
index 00000000000..8a35bb9c6cf
--- /dev/null
+++ b/code/_helpers/verbs.dm
@@ -0,0 +1,94 @@
+/**
+ * handles adding verbs and updating the stat panel browser
+ *
+ * pass the verb type path to this instead of adding it directly to verbs so the statpanel can update
+ * Arguments:
+ * * target - Who the verb is being added to, client or mob typepath
+ * * verb - typepath to a verb, or a list of verbs, supports lists of lists
+ */
+/proc/add_verb(client/target, verb_or_list_to_add)
+ if(!target)
+ CRASH("add_verb called without a target")
+ if(IsAdminAdvancedProcCall())
+ return
+ var/mob/mob_target = null
+
+ if(ismob(target))
+ mob_target = target
+ target = mob_target.client
+ else if(!istype(target, /client))
+ CRASH("add_verb called on a non-mob and non-client")
+ var/list/verbs_list = list()
+ if(!islist(verb_or_list_to_add))
+ verbs_list += verb_or_list_to_add
+ else
+ var/list/verb_listref = verb_or_list_to_add
+ var/list/elements_to_process = verb_listref.Copy()
+ while(length(elements_to_process))
+ var/element_or_list = elements_to_process[length(elements_to_process)] //Last element
+ elements_to_process.len--
+ if(islist(element_or_list))
+ elements_to_process += element_or_list //list/a += list/b adds the contents of b into a, not the reference to the list itself
+ else
+ verbs_list += element_or_list
+
+ if(mob_target)
+ mob_target.verbs += verbs_list
+ if(!target)
+ return //Our work is done.
+ else
+ target.verbs += verbs_list
+
+ var/list/output_list = list()
+ for(var/thing in verbs_list)
+ var/procpath/verb_to_add = thing
+ output_list[++output_list.len] = list(verb_to_add.category, verb_to_add.name, verb_to_add.desc)
+
+ target.stat_panel.send_message("add_verb_list", output_list)
+
+/**
+ * handles removing verb and sending it to browser to update, use this for removing verbs
+ *
+ * pass the verb type path to this instead of removing it from verbs so the statpanel can update
+ * Arguments:
+ * * target - Who the verb is being removed from, client or mob typepath
+ * * verb - typepath to a verb, or a list of verbs, supports lists of lists
+ */
+/proc/remove_verb(client/target, verb_or_list_to_remove)
+ if(IsAdminAdvancedProcCall())
+ return
+
+ var/mob/mob_target = null
+ if(ismob(target))
+ mob_target = target
+ target = mob_target.client
+ else if(!istype(target, /client))
+ CRASH("remove_verb called on a non-mob and non-client")
+
+ var/list/verbs_list = list()
+ if(!islist(verb_or_list_to_remove))
+ verbs_list += verb_or_list_to_remove
+ else
+ var/list/verb_listref = verb_or_list_to_remove
+ var/list/elements_to_process = verb_listref.Copy()
+ while(length(elements_to_process))
+ var/element_or_list = elements_to_process[length(elements_to_process)] //Last element
+ elements_to_process.len--
+ if(islist(element_or_list))
+ elements_to_process += element_or_list //list/a += list/b adds the contents of b into a, not the reference to the list itself
+ else
+ verbs_list += element_or_list
+
+ if(mob_target)
+ mob_target.verbs -= verbs_list
+ if(!target)
+ return //Our work is done.
+ else
+ target.verbs -= verbs_list
+
+ var/list/output_list = list()
+ for(var/thing in verbs_list)
+ var/procpath/verb_to_remove = thing
+ output_list[++output_list.len] = list(verb_to_remove.category, verb_to_remove.name)
+
+ target.stat_panel.send_message("remove_verb_list", output_list)
diff --git a/code/_helpers/view.dm b/code/_helpers/view.dm
index be60a56697f..4615e0c97da 100644
--- a/code/_helpers/view.dm
+++ b/code/_helpers/view.dm
@@ -11,6 +11,15 @@
viewY = text2num(viewrangelist[2])
return list(viewX, viewY)
+/// Takes a string or num view, and converts it to pixel width/height in a list(pixel_width, pixel_height)
+/proc/view_to_pixels(view)
+ if(!view)
+ return list(0, 0)
+ var/list/view_info = getviewsize(view)
+ view_info[1] *= ICON_SIZE_X
+ view_info[2] *= ICON_SIZE_Y
+ return view_info
+
// Used to get `atom/O as obj|mob|turf in view()` to match against strings containing apostrophes immediately after substrings that match to other objects. Somehow. - Ater
/proc/_validate_atom(atom/A)
- return view()
\ No newline at end of file
+ return view()
diff --git a/code/_helpers/weakref.dm b/code/_helpers/weakref.dm
new file mode 100644
index 00000000000..25b65e63ecd
--- /dev/null
+++ b/code/_helpers/weakref.dm
@@ -0,0 +1,2 @@
+/// Checks if potential_weakref is a weakref of thing.
+#define IS_WEAKREF_OF(thing, potential_weakref) (isdatum(thing) && !isnull(potential_weakref) && thing.weak_reference == potential_weakref)
diff --git a/code/_macros.dm b/code/_macros.dm
index b37d24fa0df..8dc5bdaf748 100644
--- a/code/_macros.dm
+++ b/code/_macros.dm
@@ -1,5 +1,3 @@
-#define span(class, text) ("[text]")
-
#define get_turf(A) get_step(A,0)
#define get_x(A) (get_step(A, 0)?.x || 0)
@@ -26,6 +24,7 @@
// From TG, might be useful to have.
// Didn't port SEND_TEXT() since to_chat() appears to serve the same purpose.
#define DIRECT_OUTPUT(A, B) A << B
+#define DIRECT_INPUT(A, B) A >> B
#define SEND_IMAGE(target, image) DIRECT_OUTPUT(target, image)
#define SEND_SOUND(target, sound) DIRECT_OUTPUT(target, sound)
//#define WRITE_LOG is in logging.dm
diff --git a/code/_map_tests.dm b/code/_map_tests.dm
deleted file mode 100644
index 372a4a7194d..00000000000
--- a/code/_map_tests.dm
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- *
- * This file is used by CI to indicate that additional maps need to be compiled to look for errors such as missing paths.
- * Do not add anything but the MAP_TEST definition here as it will be overwritten by CI when running tests.
- *
- *
- * Should you wish to edit set MAP_TEST to 1 like so:
- * #define MAP_TEST 1
- */
-#define MAP_TEST 0
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index 76b18f7222e..38828e148f7 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -25,13 +25,13 @@
/mob/living/silicon/ai/ClickOn(var/atom/A, params)
if(!checkClickCooldown())
return
-
+
setClickCooldown(1)
if(client.buildmode) // comes after object.Click to allow buildmode gui objects to be clicked
build_click(src, client.buildmode, params, A)
return
-
+
if(multicam_on)
var/turf/T = get_turf(A)
if(T)
@@ -173,7 +173,7 @@
to_chat(user, "The bolt lights wire is cut - The door bolt lights are permanently disabled.")
return
lights = !lights
- to_chat(user, "Lights are now [lights ? "on." : "off."]")
+ to_chat(user, span_notice("Lights are now [lights ? "on." : "off."]"))
update_icon()
return TRUE
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 16a35b18eac..f321d231f3d 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -158,7 +158,7 @@
next_click = max(world.time + timeout, next_click)
/mob/proc/checkClickCooldown()
- if(next_click > world.time && !config.no_click_cooldown)
+ if(next_click > world.time && !CONFIG_GET(flag/no_click_cooldown))
return FALSE
return TRUE
@@ -286,16 +286,9 @@
/atom/proc/AltClick(var/mob/user)
var/turf/T = get_turf(src)
if(T && user.TurfAdjacent(T))
- user.ToggleTurfTab(T)
+ user.set_listed_turf(T)
return 1
-/mob/proc/ToggleTurfTab(var/turf/T)
- if(listed_turf == T)
- listed_turf = null
- else
- listed_turf = T
- client.statpanel = "Turf"
-
/mob/proc/TurfAdjacent(var/turf/T)
return T.AdjacentQuick(src)
@@ -337,7 +330,7 @@
nutrition = max(nutrition - rand(1,5),0)
handle_regular_hud_updates()
else
- to_chat(src, "You're out of energy! You need food!")
+ to_chat(src, span_warning("You're out of energy! You need food!"))
// Simple helper to face what you clicked on, in case it should be needed in more than one place
/mob/proc/face_atom(var/atom/A)
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index a7ff03177d5..80d086a298c 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -44,9 +44,9 @@
if(aiCamera && aiCamera.in_camera_mode)
aiCamera.camera_mode_off()
if(is_component_functioning("camera"))
- aiCamera.captureimage(A, usr)
+ aiCamera.captureimage(A, src)
else
- to_chat(src, "Your camera isn't functional.")
+ to_chat(src, span_userdanger("Your camera isn't functional."))
return
/*
diff --git a/code/_onclick/hud/_defines_vr.dm b/code/_onclick/hud/_defines_vr.dm
deleted file mode 100644
index b419c6bd7f8..00000000000
--- a/code/_onclick/hud/_defines_vr.dm
+++ /dev/null
@@ -1,2 +0,0 @@
-#define ui_shadekin_display "EAST-1:28,CENTER-3:15"
-#define ui_xenochimera_danger_display "EAST-1:28,CENTER-3:15"
\ No newline at end of file
diff --git a/code/_onclick/hud/ability_screen_objects.dm b/code/_onclick/hud/ability_screen_objects.dm
index 7690b9d2033..5d304f14707 100644
--- a/code/_onclick/hud/ability_screen_objects.dm
+++ b/code/_onclick/hud/ability_screen_objects.dm
@@ -16,6 +16,7 @@
if(owner)
my_mob = owner
update_abilities(0, owner)
+ overlays.Add(closed_state)
else
message_admins("ERROR: ability_master's New() was not given an owner argument. This is a bug.")
@@ -290,7 +291,7 @@
if(!mob)
return // Paranoid.
if(isnull(slot) || !isnum(slot))
- to_chat(src, ".activate_ability requires a number as input, corrisponding to the slot you wish to use.")
+ to_chat(src, span_warning(".activate_ability requires a number as input, corrisponding to the slot you wish to use."))
return // Bad input.
if(!mob.ability_master)
return // No abilities.
@@ -312,7 +313,7 @@
if(object_used && verb_to_call)
call(object_used,verb_to_call)(arguments_to_use)
// call(object_used,verb_to_call)(arguments_to_use)
-// to_world("Attempted to call([object_used],[verb_to_call])([arguments_to_use])")
+// to_world(span_world("Attempted to call([object_used],[verb_to_call])([arguments_to_use])"))
// if(hascall(object_used, verb_to_call))
// call(object_used,verb_to_call)(arguments_to_use)
// else
diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm
deleted file mode 100644
index 288c4799226..00000000000
--- a/code/_onclick/hud/action.dm
+++ /dev/null
@@ -1,228 +0,0 @@
-#define AB_ITEM 1
-#define AB_SPELL 2
-#define AB_INNATE 3
-#define AB_GENERIC 4
-
-
-/datum/action
- var/name = "Generic Action"
- var/action_type = AB_ITEM
- var/procname = null
- var/atom/movable/target = null
- var/check_flags = 0
- var/processing = 0
- var/active = 0
- var/obj/screen/movable/action_button/button = null
- var/button_icon = 'icons/mob/actions.dmi'
- var/button_icon_state = "default"
- var/background_icon_state = "bg_default"
- var/mob/living/owner
-
-/datum/action/New(var/Target)
- target = Target
-
-/datum/action/Destroy()
- if(owner)
- Remove(owner)
- target = null
- QDEL_NULL(button)
- return ..()
-
-/datum/action/proc/Grant(mob/living/T)
- if(owner)
- if(owner == T)
- return
- Remove(owner)
- owner = T
- owner.actions.Add(src)
- owner.update_action_buttons()
- return
-
-/datum/action/proc/Remove(mob/living/T)
- if(button)
- if(T.client)
- T.client.screen -= button
- QDEL_NULL(button)
- T.actions.Remove(src)
- T.update_action_buttons()
- owner = null
- return
-
-/datum/action/proc/Trigger()
- if(!Checks())
- return
- switch(action_type)
- if(AB_ITEM)
- if(target)
- var/obj/item/item = target
- item.ui_action_click()
- //if(AB_SPELL)
- // if(target)
- // var/obj/effect/proc_holder/spell = target
- // spell.Click()
- if(AB_INNATE)
- if(!active)
- Activate()
- else
- Deactivate()
- if(AB_GENERIC)
- if(target && procname)
- call(target,procname)(usr)
- return
-
-/datum/action/proc/Activate()
- return
-
-/datum/action/proc/Deactivate()
- return
-
-/datum/action/process()
- return
-
-/datum/action/proc/CheckRemoval(mob/living/user) // 1 if action is no longer valid for this mob and should be removed
- return 0
-
-/datum/action/proc/IsAvailable()
- return Checks()
-
-/datum/action/proc/Checks()// returns 1 if all checks pass
- if(!owner)
- return 0
- if(check_flags & AB_CHECK_RESTRAINED)
- if(owner.restrained())
- return 0
- if(check_flags & AB_CHECK_STUNNED)
- if(owner.stunned)
- return 0
- if(check_flags & AB_CHECK_LYING)
- if(owner.lying)
- return 0
- if(check_flags & AB_CHECK_ALIVE)
- if(owner.stat)
- return 0
- if(check_flags & AB_CHECK_INSIDE)
- if(!(target in owner))
- return 0
- return 1
-
-/datum/action/proc/UpdateName()
- return name
-
-/obj/screen/movable/action_button
- var/datum/action/owner
- screen_loc = "WEST,NORTH"
-
-/obj/screen/movable/action_button/Click(location,control,params)
- var/list/modifiers = params2list(params)
- if(modifiers["shift"])
- moved = 0
- return 1
- if(!usr.checkClickCooldown())
- return
- owner.Trigger()
- return 1
-
-/obj/screen/movable/action_button/proc/UpdateIcon()
- if(!owner)
- return
- icon = owner.button_icon
- icon_state = owner.background_icon_state
-
- cut_overlays()
- var/image/img
- if(owner.action_type == AB_ITEM && owner.target)
- var/obj/item/I = owner.target
- img = image(I.icon, src , I.icon_state)
- else if(owner.button_icon && owner.button_icon_state)
- img = image(owner.button_icon,src,owner.button_icon_state)
- img.pixel_x = 0
- img.pixel_y = 0
- add_overlay(img)
-
- if(!owner.IsAvailable())
- color = rgb(128,0,0,128)
- else
- color = rgb(255,255,255,255)
-
-//Hide/Show Action Buttons ... Button
-/obj/screen/movable/action_button/hide_toggle
- name = "Hide Buttons"
- icon = 'icons/mob/actions.dmi'
- icon_state = "bg_default"
- var/hidden = 0
-
-/obj/screen/movable/action_button/hide_toggle/Click()
- usr.hud_used.action_buttons_hidden = !usr.hud_used.action_buttons_hidden
-
- hidden = usr.hud_used.action_buttons_hidden
- if(hidden)
- name = "Show Buttons"
- else
- name = "Hide Buttons"
- UpdateIcon()
- usr.update_action_buttons()
-
-
-/obj/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(var/mob/living/user)
- if(isalien(user))
- icon_state = "bg_alien"
- else
- icon_state = "bg_default"
- UpdateIcon()
- return
-
-/obj/screen/movable/action_button/hide_toggle/UpdateIcon()
- cut_overlays()
- var/image/img = image(icon,src,hidden?"show":"hide")
- add_overlay(img)
- return
-
-//This is the proc used to update all the action buttons. Properly defined in /mob/living/
-/mob/proc/update_action_buttons()
- return
-
-#define AB_WEST_OFFSET 4
-#define AB_NORTH_OFFSET 26
-#define AB_MAX_COLUMNS 10
-
-/datum/hud/proc/ButtonNumberToScreenCoords(var/number) // TODO : Make this zero-indexed for readabilty
- var/row = round((number-1)/AB_MAX_COLUMNS)
- var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
- var/coord_col = "+[col-1]"
- var/coord_col_offset = AB_WEST_OFFSET+2*col
- var/coord_row = "[-1 - row]"
- var/coord_row_offset = AB_NORTH_OFFSET
- return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:[coord_row_offset]"
-
-/datum/hud/proc/SetButtonCoords(var/obj/screen/button,var/number)
- var/row = round((number-1)/AB_MAX_COLUMNS)
- var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
- var/x_offset = 32*(col-1) + AB_WEST_OFFSET + 2*col
- var/y_offset = -32*(row+1) + AB_NORTH_OFFSET
-
- var/matrix/M = matrix()
- M.Translate(x_offset,y_offset)
- button.transform = M
-
-//Presets for item actions
-/datum/action/item_action
- check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_ALIVE|AB_CHECK_INSIDE
-
-/datum/action/item_action/CheckRemoval(mob/living/user)
- return !(target in user)
-
-/datum/action/item_action/hands_free
- check_flags = AB_CHECK_ALIVE|AB_CHECK_INSIDE
-
-#undef AB_WEST_OFFSET
-#undef AB_NORTH_OFFSET
-#undef AB_MAX_COLUMNS
-
-
-/datum/action/innate/
- action_type = AB_INNATE
-
-#undef AB_ITEM
-#undef AB_SPELL
-#undef AB_INNATE
-#undef AB_GENERIC
diff --git a/code/_onclick/hud/action/action.dm b/code/_onclick/hud/action/action.dm
new file mode 100644
index 00000000000..a5a512be689
--- /dev/null
+++ b/code/_onclick/hud/action/action.dm
@@ -0,0 +1,348 @@
+/**
+ * # Action system
+ *
+ * A simple base for an modular behavior attached to atom or datum.
+ */
+/datum/action
+ /// The name of the action
+ var/name = "Generic Action"
+ /// The description of what the action does, shown in button tooltips
+ var/desc
+ /// The target the action is attached to. If the target datum is deleted, the action is as well.
+ /// Set in New() via the proc link_to(). PLEASE set a target if you're making an action
+ var/datum/target
+ /// Where any buttons we create should be by default. Accepts screen_loc and location defines
+ var/default_button_position = SCRN_OBJ_IN_LIST
+ /// This is who currently owns the action, and most often, this is who is using the action if it is triggered
+ /// This can be the same as "target" but is not ALWAYS the same - this is set and unset with Grant() and Remove()
+ var/mob/owner
+ /// Flags that will determine of the owner / user of the action can... use the action
+ var/check_flags = NONE
+ /// Whether the button becomes transparent when it can't be used or just reddened
+ var/transparent_when_unavailable = TRUE
+ /// List of all mobs that are viewing our action button -> A unique movable for them to view.
+ var/list/viewers = list()
+ /// If TRUE, this action button will be shown to observers / other mobs who view from this action's owner's eyes.
+ /// Used in [/mob/proc/show_other_mob_action_buttons]
+ /// (Not really, this behavior is unimplemented)
+ var/show_to_observers = TRUE
+
+ /// The style the button's tooltips appear to be
+ var/buttontooltipstyle = ""
+
+ /// This is the file for the BACKGROUND underlay icon of the button
+ var/background_icon = 'icons/mob/actions/backgrounds.dmi'
+ /// This is the icon state state for the BACKGROUND underlay icon of the button
+ /// (If set to ACTION_BUTTON_DEFAULT_BACKGROUND, uses the hud's default background)
+ var/background_icon_state = ACTION_BUTTON_DEFAULT_BACKGROUND
+
+ /// This is the file for the icon that appears on the button
+ var/button_icon = 'icons/mob/actions.dmi'
+ /// This is the icon state for the icon that appears on the button
+ var/button_icon_state = "default"
+
+ /// This is the file for any FOREGROUND overlay icons on the button (such as borders)
+ var/overlay_icon = 'icons/mob/actions/backgrounds.dmi'
+ /// This is the icon state for any FOREGROUND overlay icons on the button (such as borders)
+ var/overlay_icon_state
+
+/datum/action/New(Target)
+ link_to(Target)
+
+/// Links the passed target to our action, registering any relevant signals
+/datum/action/proc/link_to(Target)
+ target = Target
+ RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE)
+
+ if(isatom(target))
+ RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, PROC_REF(on_target_icon_update))
+
+ // if(istype(target, /datum/mind))
+ // RegisterSignal(target, COMSIG_MIND_TRANSFERRED, .proc/on_target_mind_swapped)
+
+/datum/action/Destroy()
+ if(owner)
+ Remove(owner)
+ target = null
+ QDEL_LIST_ASSOC_VAL(viewers)
+ return ..()
+
+
+/// Signal proc that clears any references based on the owner or target deleting
+/// If the owner's deleted, we will simply remove from them, but if the target's deleted, we will self-delete
+/datum/action/proc/clear_ref(datum/ref)
+ SIGNAL_HANDLER
+ if(ref == owner)
+ Remove(owner)
+ if(ref == target)
+ qdel(src)
+
+/// Grants the action to the passed mob, making it the owner
+/datum/action/proc/Grant(mob/grant_to)
+ if(!grant_to)
+ Remove(owner)
+ return
+ if(owner)
+ if(owner == grant_to)
+ return
+ Remove(owner)
+
+ SEND_SIGNAL(src, COMSIG_ACTION_GRANTED, grant_to)
+ SEND_SIGNAL(grant_to, COMSIG_MOB_GRANTED_ACTION, src)
+ owner = grant_to
+ RegisterSignal(owner, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref), override = TRUE)
+
+ GiveAction(grant_to)
+
+/// Remove the passed mob from being owner of our action
+/datum/action/proc/Remove(mob/remove_from)
+ SHOULD_CALL_PARENT(TRUE)
+
+ for(var/datum/hud/hud in viewers)
+ if(!hud.mymob)
+ continue
+ HideFrom(hud.mymob)
+ LAZYREMOVE(remove_from.actions, src) // We aren't always properly inserted into the viewers list, gotta make sure that action's cleared
+ viewers = list()
+
+ if(owner)
+ SEND_SIGNAL(src, COMSIG_ACTION_REMOVED, owner)
+ SEND_SIGNAL(owner, COMSIG_MOB_REMOVED_ACTION, src)
+
+ UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
+ if(target == owner)
+ RegisterSignal(target, COMSIG_PARENT_QDELETING, PROC_REF(clear_ref))
+
+ owner = null
+
+/// Actually triggers the effects of the action.
+/// Called when the on-screen button is clicked, for example.
+/datum/action/proc/Trigger(trigger_flags)
+ if(!IsAvailable())
+ return FALSE
+ if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER)
+ return FALSE
+ return TRUE
+
+/// Whether our action is currently available to use or not
+/datum/action/proc/IsAvailable()
+ if(!owner)
+ return FALSE
+ if(check_flags & AB_CHECK_RESTRAINED)
+ if(owner.restrained())
+ return FALSE
+ if(check_flags & AB_CHECK_STUNNED)
+ if(owner.stunned)
+ return FALSE
+ if(check_flags & AB_CHECK_LYING)
+ if(owner.lying)
+ return FALSE
+ if(check_flags & AB_CHECK_CONSCIOUS)
+ if(owner.stat)
+ return FALSE
+ return TRUE
+
+/// Builds / updates all buttons we have shared or given out
+/datum/action/proc/build_all_button_icons(update_flags = ALL, force)
+ for(var/datum/hud/hud as anything in viewers)
+ build_button_icon(viewers[hud], update_flags, force)
+
+/**
+ * Builds the icon of the button.
+ *
+ * Concept:
+ * - Underlay (Background icon)
+ * - Icon (button icon)
+ * - Maptext
+ * - Overlay (Background border)
+ *
+ * button - which button we are modifying the icon of
+ * force - whether we're forcing a full update
+ */
+/datum/action/proc/build_button_icon(obj/screen/movable/action_button/button, update_flags = ALL, force = FALSE)
+ if(!button)
+ return
+
+ if(update_flags & UPDATE_BUTTON_NAME)
+ update_button_name(button, force)
+
+ if(update_flags & UPDATE_BUTTON_BACKGROUND)
+ apply_button_background(button, force)
+
+ if(update_flags & UPDATE_BUTTON_ICON)
+ apply_button_icon(button, force)
+
+ if(update_flags & UPDATE_BUTTON_OVERLAY)
+ apply_button_overlay(button, force)
+
+ if(update_flags & UPDATE_BUTTON_STATUS)
+ update_button_status(button, force)
+
+/**
+ * Updates the name and description of the button to match our action name and discription.
+ *
+ * current_button - what button are we editing?
+ * force - whether an update is forced regardless of existing status
+ */
+/datum/action/proc/update_button_name(obj/screen/movable/action_button/button, force = FALSE)
+ button.name = name
+ if(desc)
+ button.desc = desc
+
+/**
+ * Creates the background underlay for the button
+ *
+ * current_button - what button are we editing?
+ * force - whether an update is forced regardless of existing status
+ */
+/datum/action/proc/apply_button_background(obj/screen/movable/action_button/current_button, force = FALSE)
+ if(!background_icon || !background_icon_state || (current_button.active_underlay_icon_state == background_icon_state && !force))
+ return
+
+ // What icons we use for our background
+ var/list/icon_settings = list(
+ // The icon file
+ "bg_icon" = background_icon,
+ // The icon state, if is_action_active() returns FALSE
+ "bg_state" = background_icon_state,
+ // The icon state, if is_action_active() returns TRUE
+ "bg_state_active" = background_icon_state,
+ )
+
+ // If background_icon_state is ACTION_BUTTON_DEFAULT_BACKGROUND instead use our hud's action button scheme
+ if(background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND && owner?.hud_used)
+ icon_settings = owner.hud_used.get_action_buttons_icons()
+
+ // Determine which icon to use
+ var/used_icon_key = is_action_active(current_button) ? "bg_state_active" : "bg_state"
+
+ // Make the underlay
+ current_button.underlays.Cut()
+ current_button.underlays += image(icon = icon_settings["bg_icon"], icon_state = icon_settings[used_icon_key])
+ current_button.active_underlay_icon_state = icon_settings[used_icon_key]
+
+/**
+ * Applies our button icon and icon state to the button
+ *
+ * current_button - what button are we editing?
+ * force - whether an update is forced regardless of existing status
+ */
+/datum/action/proc/apply_button_icon(obj/screen/movable/action_button/current_button, force = FALSE)
+ if(!button_icon || !button_icon_state || (current_button.icon_state == button_icon_state && !force))
+ return
+
+ current_button.icon = button_icon
+ current_button.icon_state = button_icon_state
+
+/**
+ * Applies any overlays to our button
+ *
+ * current_button - what button are we editing?
+ * force - whether an update is forced regardless of existing status
+ */
+/datum/action/proc/apply_button_overlay(obj/screen/movable/action_button/current_button, force = FALSE)
+ SEND_SIGNAL(src, COMSIG_ACTION_OVERLAY_APPLY, current_button, force)
+
+ if(!overlay_icon || !overlay_icon_state || (current_button.active_overlay_icon_state == overlay_icon_state && !force))
+ return
+
+ current_button.cut_overlay(current_button.button_overlay)
+ current_button.button_overlay = mutable_appearance(icon = overlay_icon, icon_state = overlay_icon_state)
+ current_button.add_overlay(current_button.button_overlay)
+ current_button.active_overlay_icon_state = overlay_icon_state
+
+/**
+ * Any other miscellaneous "status" updates within the action button is handled here,
+ * such as redding out when unavailable or modifying maptext.
+ *
+ * current_button - what button are we editing?
+ * force - whether an update is forced regardless of existing status
+ */
+/datum/action/proc/update_button_status(obj/screen/movable/action_button/current_button, force = FALSE)
+ if(IsAvailable())
+ current_button.color = rgb(255,255,255,255)
+ else
+ current_button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0)
+
+/// Gives our action to the passed viewer.
+/// Puts our action in their actions list and shows them the button.
+/datum/action/proc/GiveAction(mob/viewer)
+ var/datum/hud/our_hud = viewer.hud_used
+ if(viewers[our_hud]) // Already have a copy of us? go away
+ return
+
+ LAZYOR(viewer.actions, src) // Move this in
+ ShowTo(viewer)
+
+/// Adds our action button to the screen of the passed viewer.
+/datum/action/proc/ShowTo(mob/viewer)
+ var/datum/hud/our_hud = viewer.hud_used
+ if(!our_hud || viewers[our_hud]) // There's no point in this if you have no hud in the first place
+ return
+
+ var/obj/screen/movable/action_button/button = create_button()
+ SetId(button, viewer)
+
+ button.our_hud = our_hud
+ viewers[our_hud] = button
+ if(viewer.client)
+ viewer.client.screen += button
+
+ button.load_position(viewer)
+ viewer.update_action_buttons()
+
+/// Removes our action from the passed viewer.
+/datum/action/proc/HideFrom(mob/viewer)
+ var/datum/hud/our_hud = viewer.hud_used
+ var/obj/screen/movable/action_button/button = viewers[our_hud]
+ LAZYREMOVE(viewer.actions, src)
+ if(button)
+ qdel(button)
+
+/// Creates an action button movable for the passed mob, and returns it.
+/datum/action/proc/create_button()
+ var/obj/screen/movable/action_button/button = new()
+ button.linked_action = src
+ build_button_icon(button, ALL, TRUE)
+ return button
+
+/datum/action/proc/SetId(obj/screen/movable/action_button/our_button, mob/owner)
+ //button id generation
+ var/bitfield = 0
+ for(var/datum/action/action in owner.actions)
+ if(action == src) // This could be us, which is dumb
+ continue
+ var/obj/screen/movable/action_button/button = action.viewers[owner.hud_used]
+ if(action.name == name && button.id)
+ bitfield |= button.id
+
+ bitfield = ~bitfield // Flip our possible ids, so we can check if we've found a unique one
+ for(var/i in 0 to 23) // We get 24 possible bitflags in dm
+ var/bitflag = 1 << i // Shift us over one
+ if(bitfield & bitflag)
+ our_button.id = bitflag
+ return
+
+/// Updates our buttons if our target's icon was updated
+/// Still never triggered lmao
+/datum/action/proc/on_target_icon_update(datum/source, updates, updated)
+ SIGNAL_HANDLER
+
+ var/update_flag = NONE
+ var/forced = FALSE
+ if(updates & UPDATE_ICON_STATE)
+ update_flag |= UPDATE_BUTTON_ICON
+ forced = TRUE
+ if(updates & UPDATE_OVERLAYS)
+ update_flag |= UPDATE_BUTTON_OVERLAY
+ forced = TRUE
+ if(updates & (UPDATE_NAME|UPDATE_DESC))
+ update_flag |= UPDATE_BUTTON_NAME
+ // Status is not relevant, and background is not relevant. Neither will change
+
+ // Force the update if an icon state or overlay change was done
+ build_all_button_icons(update_flag, forced)
+
+/// Checks if our action is actively selected. Used for selecting icons primarily.
+/datum/action/proc/is_action_active(obj/screen/movable/action_button/current_button)
+ return FALSE
diff --git a/code/_onclick/hud/action/action_group.dm b/code/_onclick/hud/action/action_group.dm
new file mode 100644
index 00000000000..d0b2f8df114
--- /dev/null
+++ b/code/_onclick/hud/action/action_group.dm
@@ -0,0 +1,212 @@
+/datum/action_group
+ /// The hud we're owned by
+ var/datum/hud/owner
+ /// The actions we're managing
+ var/list/obj/screen/movable/action_button/actions
+ /// The initial vertical offset of our action buttons
+ var/north_offset = 0
+ /// The pixel vertical offset of our action buttons
+ var/pixel_north_offset = 0
+ /// Max amount of buttons we can have per row
+ /// Indexes at 1
+ var/column_max = 0
+ /// How far "ahead" of the first row we start. Lets us "scroll" our rows
+ /// Indexes at 1
+ var/row_offset = 0
+ /// How many rows of actions we can have at max before we just stop hiding
+ /// Indexes at 1
+ var/max_rows = INFINITY
+ /// The screen location we go by
+ var/location
+ /// Our landing screen object
+ var/obj/screen/action_landing/landing
+
+/datum/action_group/New(datum/hud/owner)
+ ..()
+ actions = list()
+ src.owner = owner
+
+/datum/action_group/Destroy()
+ owner = null
+ QDEL_NULL(landing)
+ QDEL_LIST(actions)
+ return ..()
+
+/datum/action_group/proc/insert_action(obj/screen/action, index)
+ if(action in actions)
+ if(actions[index] == action)
+ return
+ actions -= action // Don't dupe, come on
+ if(!index)
+ index = length(actions) + 1
+ index = min(length(actions) + 1, index)
+ actions.Insert(index, action)
+ refresh_actions()
+
+/datum/action_group/proc/remove_action(obj/screen/action)
+ actions -= action
+ if(!QDELING(src))
+ refresh_actions()
+
+/datum/action_group/proc/refresh_actions()
+ // We don't use size() here because landings are not canon
+ var/total_rows = ROUND_UP(length(actions) / column_max)
+ total_rows -= max_rows // Lets get the amount of rows we're off from our max
+ row_offset = clamp(row_offset, 0, total_rows) // You're not allowed to offset so far that we have a row of blank space
+
+ var/button_number = 0
+ for(var/obj/screen/button as anything in actions)
+ var/postion = ButtonNumberToScreenCoords(button_number )
+ button.screen_loc = postion
+ button_number++
+
+ if(landing)
+ var/postion = ButtonNumberToScreenCoords(button_number, landing = TRUE) // Need a good way to count buttons off screen, but allow this to display in the right place if it's being placed with no concern for dropdown
+ landing.screen_loc = postion
+ button_number++
+
+/// Accepts a number represeting our position in the group, indexes at 0 to make the math nicer
+/datum/action_group/proc/ButtonNumberToScreenCoords(number, landing = FALSE)
+ var/row = round(number / column_max)
+ row -= row_offset // If you're less then 0, you don't get to render, this lets us "scroll" rows ya feel?
+ if(row < 0)
+ return null
+
+ // Could use >= here, but I think it's worth noting that the two start at different places, since row is based on number here
+ if(row > max_rows - 1)
+ if(!landing) // If you're not a landing, go away please. thx
+ return null
+ // We always want to render landings, even if their action button can't be displayed.
+ // So we set a row equal to the max amount of rows + 1. Willing to overrun that max slightly to properly display the landing spot
+ row = max_rows // Remembering that max_rows indexes at 1, and row indexes at 0
+
+ // We're going to need to set our column to match the first item in the last row, so let's set number properly now
+ number = row * column_max
+
+ var/visual_row = row + north_offset
+ var/coord_row = visual_row ? "-[visual_row]" : "+0"
+
+ var/visual_column = number % column_max
+ var/coord_col = "+[visual_column]"
+ var/coord_col_offset = 4 + 2 * (visual_column + 1)
+ return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-[pixel_north_offset]"
+
+/datum/action_group/proc/check_against_view()
+ var/owner_view = owner?.mymob?.client?.view
+ if(!owner_view)
+ return
+ // Unlikey as it is, we may have been changed. Want to start from our target position and fail down
+ column_max = initial(column_max)
+ // Convert our viewer's view var into a workable offset
+ var/list/view_size = view_to_pixels(owner_view)
+
+ // We're primarially concerned about width here, if someone makes us 1x2000 I wish them a swift and watery death
+ var/furthest_screen_loc = ButtonNumberToScreenCoords(column_max - 1)
+ var/list/offsets = screen_loc_to_offset(furthest_screen_loc, owner_view)
+ if(offsets[1] > world.icon_size && offsets[1] < view_size[1] && offsets[2] > world.icon_size && offsets[2] < view_size[2]) // We're all good
+ return
+
+ for(column_max in column_max - 1 to 1 step -1) // Yes I could do this by unwrapping ButtonNumberToScreenCoords, but I don't feel like it
+ var/tested_screen_loc = ButtonNumberToScreenCoords(column_max)
+ offsets = screen_loc_to_offset(tested_screen_loc, owner_view)
+ // We've found a valid max length, pack it in
+ if(offsets[1] > world.icon_size && offsets[1] < view_size[1] && offsets[2] > world.icon_size && offsets[2] < view_size[2])
+ break
+ // Use our newly resized column max
+ refresh_actions()
+
+/// Returns the amount of objects we're storing at the moment
+/datum/action_group/proc/size()
+ var/amount = length(actions)
+ if(landing)
+ amount += 1
+ return amount
+
+/datum/action_group/proc/index_of(obj/screen/get_location)
+ return actions.Find(get_location)
+
+/// Generates a landing object that can be dropped on to join this group
+/datum/action_group/proc/generate_landing()
+ if(landing)
+ return
+ landing = new()
+ landing.set_owner(src)
+ refresh_actions()
+
+/// Clears any landing objects we may currently have
+/datum/action_group/proc/clear_landing()
+ QDEL_NULL(landing)
+
+/datum/action_group/proc/update_landing()
+ if(!landing)
+ return
+ landing.refresh_owner()
+
+/datum/action_group/proc/scroll(amount)
+ row_offset += amount
+ refresh_actions()
+
+/datum/action_group/palette
+ north_offset = 2
+ column_max = 3
+ max_rows = 3
+ location = SCRN_OBJ_IN_PALETTE
+
+/datum/action_group/palette/insert_action(obj/screen/action, index)
+ . = ..()
+ var/obj/screen/button_palette/palette = owner.toggle_palette
+ palette.play_item_added()
+
+/datum/action_group/palette/remove_action(obj/screen/action)
+ . = ..()
+ var/obj/screen/button_palette/palette = owner.toggle_palette
+ palette.play_item_removed()
+ if(!length(actions))
+ palette.set_expanded(FALSE)
+
+/datum/action_group/palette/refresh_actions()
+ var/obj/screen/button_palette/palette = owner.toggle_palette
+ var/obj/screen/palette_scroll/scroll_down = owner.palette_down
+ var/obj/screen/palette_scroll/scroll_up = owner.palette_up
+ if(!palette || !scroll_down || !scroll_up)
+ return
+
+ var/actions_above = round((owner.listed_actions.size() - 1) / owner.listed_actions.column_max)
+ north_offset = initial(north_offset) + actions_above
+
+ palette.screen_loc = ui_action_palette_offset(actions_above)
+ var/action_count = length(owner?.mymob?.actions)
+ var/our_row_count = round((length(actions) - 1) / column_max)
+ if(!action_count)
+ palette.screen_loc = null
+
+ if(palette.expanded && action_count && our_row_count >= max_rows)
+ scroll_down.screen_loc = ui_palette_scroll_offset(actions_above)
+ scroll_up.screen_loc = ui_palette_scroll_offset(actions_above)
+ else
+ scroll_down.screen_loc = null
+ scroll_up.screen_loc = null
+
+ return ..()
+
+/datum/action_group/palette/ButtonNumberToScreenCoords(number, landing)
+ var/obj/screen/button_palette/palette = owner.toggle_palette
+ if(palette.expanded)
+ return ..()
+
+ if(!landing)
+ return null
+
+ // We only render the landing in this case, so we force it to be the second item displayed (Second rather then first since it looks nicer)
+ // Remember the number var indexes at 0
+ return ..(1 + (row_offset * column_max), landing)
+
+
+/datum/action_group/listed
+ pixel_north_offset = 6
+ column_max = 10
+ location = SCRN_OBJ_IN_LIST
+
+/datum/action_group/listed/refresh_actions()
+ . = ..()
+ owner?.palette_actions.refresh_actions() // We effect them, so we gotta refresh em
diff --git a/code/_onclick/hud/action/action_group_helpers.dm b/code/_onclick/hud/action/action_group_helpers.dm
new file mode 100644
index 00000000000..14ca7194333
--- /dev/null
+++ b/code/_onclick/hud/action/action_group_helpers.dm
@@ -0,0 +1,41 @@
+/// Generates visual landings for all groups that the button is not a memeber of
+/datum/hud/proc/generate_landings(obj/screen/movable/action_button/button)
+ listed_actions.generate_landing()
+ palette_actions.generate_landing()
+
+/// Clears all currently visible landings
+/datum/hud/proc/hide_landings()
+ listed_actions.clear_landing()
+ palette_actions.clear_landing()
+
+// Updates any existing "owned" visuals, ensures they continue to be visible
+/datum/hud/proc/update_our_owner()
+ toggle_palette.refresh_owner()
+ palette_down.refresh_owner()
+ palette_up.refresh_owner()
+ listed_actions.update_landing()
+ palette_actions.update_landing()
+
+/// Ensures all of our buttons are properly within the bounds of our client's view, moves them if they're not
+/datum/hud/proc/view_audit_buttons()
+ var/our_view = mymob?.client?.view
+ if(!our_view)
+ return
+ listed_actions.check_against_view()
+ palette_actions.check_against_view()
+ for(var/obj/screen/movable/action_button/floating_button as anything in floating_actions)
+ var/list/current_offsets = screen_loc_to_offset(floating_button.screen_loc)
+ // We set the view arg here, so the output will be properly hemm'd in by our new view
+ floating_button.screen_loc = offset_to_screen_loc(current_offsets[1], current_offsets[2], view = our_view)
+
+/// Generates and fills new action groups with our mob's current actions
+/datum/hud/proc/build_action_groups()
+ listed_actions = new(src)
+ palette_actions = new(src)
+ floating_actions = list()
+ for(var/datum/action/action as anything in mymob.actions)
+ var/obj/screen/movable/action_button/button = action.viewers[src]
+ if(!button)
+ action.ShowTo(mymob)
+ button = action.viewers[src]
+ position_action(button, button.location)
diff --git a/code/_onclick/hud/action/action_item_overlay.dm b/code/_onclick/hud/action/action_item_overlay.dm
new file mode 100644
index 00000000000..7d1af7309ef
--- /dev/null
+++ b/code/_onclick/hud/action/action_item_overlay.dm
@@ -0,0 +1,73 @@
+/**
+ * Apply to an action to allow it to take an item
+ * and apply it as an overlay of the action button
+ */
+/datum/component/action_item_overlay
+ /// Weakref to what item the component uses to apply as an overlay.
+ var/datum/weakref/item_ref
+ /// Callback that dictates what item the component uses to apply as an overlay.
+ var/datum/callback/item_callback
+
+ /// The appearance of the item we've applied
+ var/mutable_appearance/item_appearance
+
+/datum/component/action_item_overlay/Initialize(atom/movable/item, datum/callback/item_callback)
+ if(!istype(parent, /datum/action))
+ return COMPONENT_INCOMPATIBLE
+
+ if(!item && !item_callback)
+ stack_trace("[type] created without a reference item or an item callback - one or the other is required.")
+ return COMPONENT_INCOMPATIBLE
+
+ src.item_ref = WEAKREF(item)
+ src.item_callback = item_callback
+
+/datum/component/action_item_overlay/Destroy(force, silent)
+ item_ref = null
+ QDEL_NULL(item_callback)
+ item_appearance = null
+ return ..()
+
+/datum/component/action_item_overlay/RegisterWithParent()
+ RegisterSignal(parent, COMSIG_ACTION_OVERLAY_APPLY, PROC_REF(on_overlays_applied))
+
+ var/datum/action/parent_action = parent
+ parent_action.build_all_button_icons(UPDATE_BUTTON_OVERLAY)
+
+/datum/component/action_item_overlay/UnregisterFromParent()
+ UnregisterSignal(parent, COMSIG_ACTION_OVERLAY_APPLY)
+
+ // If we're being unregistered / deleted but our parent is sticking around,
+ // force an overlay update to get rid of our item appearance
+ if(!QDELING(parent))
+ var/datum/action/parent_action = parent
+ parent_action.build_all_button_icons(UPDATE_BUTTON_OVERLAY)
+
+/// Signal proc for [COMSIG_ACTION_OVERLAY_APPLY], applies the item appearance if possible.
+/datum/component/action_item_overlay/proc/on_overlays_applied(datum/action/source, obj/screen/movable/action_button/current_button, force)
+ SIGNAL_HANDLER
+
+ // We're in the middle of being removed / deleted, remove our associated overlay
+ if(QDELING(src) && item_appearance)
+ current_button.cut_overlay(item_appearance)
+ item_appearance = null
+ return
+
+ var/atom/movable/muse = item_callback?.Invoke() || item_ref?.resolve()
+ if(!istype(muse))
+ return
+
+ if(item_appearance)
+ // For caching purposes, we will try not to update if we don't need to
+ if(!force && item_appearance.icon == muse.icon && item_appearance.icon_state == muse.icon_state)
+ return
+ current_button.cut_overlay(item_appearance)
+
+ var/mutable_appearance/muse_appearance = new(muse.appearance)
+ muse_appearance.plane = FLOAT_PLANE
+ muse_appearance.layer = FLOAT_LAYER
+ muse_appearance.pixel_x = 0
+ muse_appearance.pixel_y = 0
+
+ current_button.add_overlay(muse_appearance)
+ item_appearance = muse_appearance
diff --git a/code/_onclick/hud/action/action_screen_objects.dm b/code/_onclick/hud/action/action_screen_objects.dm
new file mode 100644
index 00000000000..503274f86f7
--- /dev/null
+++ b/code/_onclick/hud/action/action_screen_objects.dm
@@ -0,0 +1,482 @@
+/obj/screen/movable/action_button
+ var/datum/action/linked_action
+ var/datum/hud/our_hud
+ var/actiontooltipstyle = ""
+ screen_loc = null
+ icon = null // we don't use the base icon at all, just underlays and overlays
+
+ /// The icon state of our active overlay, used to prevent re-applying identical overlays
+ var/active_overlay_icon_state
+ /// The icon state of our active underlay, used to prevent re-applying identical underlays
+ var/active_underlay_icon_state
+ /// The overlay we have overtop our button
+ var/mutable_appearance/button_overlay
+
+ /// Where we are currently placed on the hud. SCRN_OBJ_DEFAULT asks the linked action what it thinks
+ var/location = SCRN_OBJ_DEFAULT
+ /// A unique bitflag, combined with the name of our linked action this lets us persistently remember any user changes to our position
+ var/id
+ /// A weakref of the last thing we hovered over
+ /// God I hate how dragging works
+ var/datum/weakref/last_hovored_ref
+
+/obj/screen/movable/action_button/Destroy()
+ if(our_hud)
+ var/mob/viewer = our_hud.mymob
+ our_hud.hide_action(src)
+ viewer?.client?.screen -= src
+ linked_action.viewers -= our_hud
+ viewer.update_action_buttons()
+ our_hud = null
+ linked_action = null
+ return ..()
+
+/obj/screen/movable/action_button/proc/can_use(mob/user)
+ // if(isobserver(user))
+ // var/mob/dead/observer/dead_mob = user
+ // if(dead_mob.observetarget) // Observers can only click on action buttons if they're not observing something
+ // return FALSE
+
+ if(linked_action)
+ if(linked_action.viewers[user.hud_used])
+ return TRUE
+ return FALSE
+
+ return TRUE
+
+/obj/screen/movable/action_button/Click(location,control,params)
+ if(!can_use(usr))
+ return
+
+ var/list/modifiers = params2list(params)
+ if(LAZYACCESS(modifiers, SHIFT_CLICK))
+ var/datum/hud/our_hud = usr.hud_used
+ our_hud.position_action(src, SCRN_OBJ_DEFAULT)
+ return TRUE
+ if(!usr.checkClickCooldown())
+ return
+ usr.setClickCooldown(1)
+ var/trigger_flags
+ if(LAZYACCESS(modifiers, RIGHT_CLICK))
+ trigger_flags |= TRIGGER_SECONDARY_ACTION
+ linked_action.Trigger(trigger_flags = trigger_flags)
+ return TRUE
+
+// Entered and Exited won't fire while you're dragging something, because you're still "holding" it
+// Very much byond logic, but I want nice behavior, so we fake it with drag
+/obj/screen/movable/action_button/MouseDrag(atom/over_object, src_location, over_location, src_control, over_control, params)
+ . = ..()
+ if(!can_use(usr))
+ return
+ if(IS_WEAKREF_OF(over_object, last_hovored_ref))
+ return
+
+ var/atom/old_object
+ if(last_hovored_ref)
+ old_object = last_hovored_ref.resolve()
+ else // If there is no current ref, we assume it was us. We also treat this as our "first go" location.
+ old_object = src
+ var/datum/hud/our_hud = usr.hud_used
+ our_hud?.generate_landings(src)
+
+ if(old_object)
+ old_object.MouseExited(over_location, over_control, params)
+
+ last_hovored_ref = WEAKREF(over_object)
+ over_object?.MouseEntered(over_location, over_control, params)
+
+/obj/screen/movable/action_button/MouseEntered(location, control, params)
+ . = ..()
+ if(!QDELETED(src))
+ openToolTip(usr, src, params, title = name, content = desc, theme = actiontooltipstyle)
+
+/obj/screen/movable/action_button/MouseExited(location, control, params)
+ closeToolTip(usr)
+ return ..()
+
+/obj/screen/movable/action_button/MouseDrop(over_object)
+ last_hovored_ref = null
+ if(!can_use(usr))
+ return
+ var/datum/hud/our_hud = usr.hud_used
+ if(over_object == src)
+ our_hud.hide_landings()
+ return
+ if(istype(over_object, /obj/screen/action_landing))
+ var/obj/screen/action_landing/reserve = over_object
+ reserve.hit_by(src)
+ our_hud.hide_landings()
+ save_position()
+ return
+
+ our_hud.hide_landings()
+ if(istype(over_object, /obj/screen/button_palette) || istype(over_object, /obj/screen/palette_scroll))
+ our_hud.position_action(src, SCRN_OBJ_IN_PALETTE)
+ save_position()
+ return
+ if(istype(over_object, /obj/screen/movable/action_button))
+ var/obj/screen/movable/action_button/button = over_object
+ our_hud.position_action_relative(src, button)
+ save_position()
+ return
+ . = ..()
+ our_hud.position_action(src, screen_loc)
+ save_position()
+
+/obj/screen/movable/action_button/proc/save_position()
+ var/mob/user = our_hud.mymob
+ if(!user?.client)
+ return
+ var/position_info = ""
+ switch(location)
+ if(SCRN_OBJ_FLOATING)
+ position_info = screen_loc
+ if(SCRN_OBJ_IN_LIST)
+ position_info = SCRN_OBJ_IN_LIST
+ if(SCRN_OBJ_IN_PALETTE)
+ position_info = SCRN_OBJ_IN_PALETTE
+
+ LAZYSET(user.client.prefs.action_button_screen_locs, "[name]_[id]", position_info)
+
+/obj/screen/movable/action_button/proc/load_position()
+ var/mob/user = our_hud.mymob
+ if(!user)
+ return
+ var/position_info = LAZYACCESS(user.client?.prefs?.action_button_screen_locs, "[name]_[id]") || SCRN_OBJ_DEFAULT
+ user.hud_used.position_action(src, position_info)
+
+/obj/screen/movable/action_button/proc/dump_save()
+ var/mob/user = our_hud.mymob
+ if(!user?.client)
+ return
+ LAZYREMOVE(user.client.prefs.action_button_screen_locs, "[name]_[id]")
+
+/**
+ * This is a silly proc used in hud code code to determine what icon and icon state we should be using
+ * for hud elements (such as action buttons) that don't have their own icon and icon state set.
+ *
+ * It returns a list, which is pretty much just a struct of info
+ */
+/datum/hud/proc/get_action_buttons_icons()
+ . = list()
+ .["bg_icon"] = 'icons/mob/actions/backgrounds.dmi' // ui_style // TODO: Implement hud-specific icon stuff
+ .["bg_state"] = "bg_default"
+ .["bg_state_active"] = "bg_default_on"
+
+
+/**
+ * Updates all action buttons this mob has.
+ *
+ * Arguments:
+ * * update_flags - Which flags of the action should we update
+ * * force - Force buttons update even if the given button icon state has not changed
+ */
+/mob/proc/update_mob_action_buttons(update_flags = ALL, force = FALSE)
+ for(var/datum/action/current_action as anything in actions)
+ current_action.build_all_button_icons(update_flags, force)
+
+/**
+ * This proc handles adding all of the mob's actions to their screen
+ *
+ * If you just need to update existing buttons, use [/mob/proc/update_mob_action_buttons]!
+ *
+ * Arguments:
+ * * update_flags - reload_screen - bool, if TRUE, this proc will add the button to the screen of the passed mob as well
+ */
+/mob/proc/update_action_buttons(reload_screen = FALSE)
+ if(!hud_used || !client)
+ return
+
+ if(!hud_used.hud_shown) //Hud toggled to minimal
+ return
+
+ for(var/datum/action/action as anything in actions)
+ var/obj/screen/movable/action_button/button = action.viewers[hud_used]
+ action.build_all_button_icons()
+ if(reload_screen)
+ client.screen += button
+
+ if(reload_screen)
+ hud_used.update_our_owner()
+ // This holds the logic for the palette buttons
+ hud_used?.palette_actions?.refresh_actions()
+
+/**
+ * Show (most) of the another mob's action buttons to this mob
+ *
+ * Used for observers viewing another mob's screen
+ */
+/mob/proc/show_other_mob_action_buttons(mob/take_from)
+ if(!hud_used || !client)
+ return
+
+ for(var/datum/action/action as anything in take_from.actions)
+ if(!action.show_to_observers)
+ continue
+ action.GiveAction(src)
+ RegisterSignal(take_from, COMSIG_MOB_GRANTED_ACTION, PROC_REF(on_observing_action_granted))
+ RegisterSignal(take_from, COMSIG_MOB_REMOVED_ACTION, PROC_REF(on_observing_action_removed))
+
+/**
+ * Hide another mob's action buttons from this mob
+ *
+ * Used for observers viewing another mob's screen
+ */
+/mob/proc/hide_other_mob_action_buttons(mob/take_from)
+ for(var/datum/action/action as anything in take_from.actions)
+ action.HideFrom(src)
+ UnregisterSignal(take_from, list(COMSIG_MOB_GRANTED_ACTION, COMSIG_MOB_REMOVED_ACTION))
+
+/// Signal proc for [COMSIG_MOB_GRANTED_ACTION] - If we're viewing another mob's action buttons,
+/// we need to update with any newly added buttons granted to the mob.
+/mob/proc/on_observing_action_granted(mob/living/source, datum/action/action)
+ SIGNAL_HANDLER
+
+ if(!action.show_to_observers)
+ return
+ action.GiveAction(src)
+
+/// Signal proc for [COMSIG_MOB_REMOVED_ACTION] - If we're viewing another mob's action buttons,
+/// we need to update with any removed buttons from the mob.
+/mob/proc/on_observing_action_removed(mob/living/source, datum/action/action)
+ SIGNAL_HANDLER
+
+ action.HideFrom(src)
+
+// Button Palette
+// A new way to interact with actions
+
+/obj/screen/button_palette
+ desc = "Drag buttons to move them
Shift-click any button to reset it
Alt-click this to reset all buttons"
+ icon = 'icons/hud/64x16_actions.dmi'
+ icon_state = "screen_gen_palette"
+ screen_loc = ui_action_palette
+ var/datum/hud/our_hud
+ var/expanded = FALSE
+ /// Id of any currently running timers that set our color matrix
+ var/color_timer_id
+
+/obj/screen/button_palette/Destroy()
+ if(our_hud)
+ our_hud.mymob?.client?.screen -= src
+ our_hud.toggle_palette = null
+ our_hud = null
+ return ..()
+
+/obj/screen/button_palette/Initialize(mapload)
+ . = ..()
+ // update_appearance()
+ update_name()
+
+/obj/screen/button_palette/proc/set_hud(datum/hud/our_hud)
+ src.our_hud = our_hud
+ refresh_owner()
+
+// /obj/screen/button_palette/update_name(updates)
+/obj/screen/button_palette/proc/update_name()
+ // . = ..()
+ if(expanded)
+ name = "Hide Buttons"
+ else
+ name = "Show Buttons"
+
+/obj/screen/button_palette/proc/refresh_owner()
+ var/mob/viewer = our_hud.mymob
+ if(viewer.client)
+ viewer.client.screen |= src
+
+ // var/list/settings = our_hud.get_action_buttons_icons()
+ // var/ui_icon = "[settings["bg_icon"]]"
+ // var/list/ui_segments = splittext(ui_icon, ".")
+ // var/list/ui_paths = splittext(ui_segments[1], "/")
+ // var/ui_name = ui_paths[length(ui_paths)]
+
+ // icon_state = "[ui_name]_palette"
+
+/obj/screen/button_palette/MouseEntered(location, control, params)
+ . = ..()
+ if(QDELETED(src))
+ return
+ show_tooltip(params)
+
+/obj/screen/button_palette/MouseExited()
+ closeToolTip(usr)
+ return ..()
+
+/obj/screen/button_palette/proc/show_tooltip(params)
+ openToolTip(usr, src, params, title = name, content = desc)
+
+GLOBAL_LIST_INIT(palette_added_matrix, list(0.4,0.5,0.2,0, 0,1.4,0,0, 0,0.4,0.6,0, 0,0,0,1, 0,0,0,0))
+GLOBAL_LIST_INIT(palette_removed_matrix, list(1.4,0,0,0, 0.7,0.4,0,0, 0.4,0,0.6,0, 0,0,0,1, 0,0,0,0))
+
+/obj/screen/button_palette/proc/play_item_added()
+ color_for_now(GLOB.palette_added_matrix)
+
+/obj/screen/button_palette/proc/play_item_removed()
+ color_for_now(GLOB.palette_removed_matrix)
+
+/obj/screen/button_palette/proc/color_for_now(list/color)
+ if(color_timer_id)
+ return
+ add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY) //We unfortunately cannot animate matrix colors. Curse you lummy it would be ~~non~~trivial to interpolate between the two valuessssssssss
+ color_timer_id = addtimer(CALLBACK(src, PROC_REF(remove_color), color), 2 SECONDS)
+
+/obj/screen/button_palette/proc/remove_color(list/to_remove)
+ color_timer_id = null
+ remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, to_remove)
+
+/obj/screen/button_palette/proc/can_use(mob/user)
+ if(isobserver(user))
+ // var/mob/dead/observer/O = user
+ // return !O.observetarget
+ return TRUE
+ return TRUE
+
+/obj/screen/button_palette/Click(location, control, params)
+ if(!can_use(usr))
+ return
+
+ var/list/modifiers = params2list(params)
+
+ if(LAZYACCESS(modifiers, ALT_CLICK))
+ for(var/datum/action/action as anything in usr.actions) // Reset action positions to default
+ for(var/datum/hud/hud as anything in action.viewers)
+ var/obj/screen/movable/action_button/button = action.viewers[hud]
+ hud.position_action(button, SCRN_OBJ_DEFAULT)
+ to_chat(usr, span_notice("Action button positions have been reset."))
+ return TRUE
+
+ set_expanded(!expanded)
+
+/obj/screen/button_palette/proc/clicked_while_open(datum/source, atom/target, atom/location, control, params, mob/user)
+ if(istype(target, /obj/screen/movable/action_button) || istype(target, /obj/screen/palette_scroll) || target == src) // If you're clicking on an action button, or us, you can live
+ return
+ set_expanded(FALSE)
+ if(source)
+ UnregisterSignal(source, COMSIG_CLIENT_CLICK)
+
+/obj/screen/button_palette/proc/set_expanded(new_expanded)
+ var/datum/action_group/our_group = our_hud.palette_actions
+ if(!length(our_group.actions)) //Looks dumb, trust me lad
+ new_expanded = FALSE
+ if(expanded == new_expanded)
+ return
+
+ expanded = new_expanded
+ our_group.refresh_actions()
+ // update_appearance()
+ update_name()
+
+ if(!usr.client)
+ return
+
+ if(expanded)
+ RegisterSignal(usr.client, COMSIG_CLIENT_CLICK, PROC_REF(clicked_while_open))
+ else
+ UnregisterSignal(usr.client, COMSIG_CLIENT_CLICK)
+
+ closeToolTip(usr) //Our tooltips are now invalid, can't seem to update them in one frame, so here, just close them
+
+/obj/screen/palette_scroll
+ icon = 'icons/hud/screen_gen.dmi'
+ screen_loc = ui_palette_scroll
+ /// How should we move the palette's actions?
+ /// Positive scrolls down the list, negative scrolls back
+ var/scroll_direction = 0
+ var/datum/hud/our_hud
+
+/obj/screen/palette_scroll/proc/can_use(mob/user)
+ if(isobserver(user))
+ // var/mob/dead/observer/O = user
+ // return !O.observetarget
+ return TRUE
+ return TRUE
+
+/obj/screen/palette_scroll/proc/set_hud(datum/hud/our_hud)
+ src.our_hud = our_hud
+ refresh_owner()
+
+/obj/screen/palette_scroll/proc/refresh_owner()
+ var/mob/viewer = our_hud.mymob
+ if(viewer.client)
+ viewer.client.screen |= src
+
+ // var/list/settings = our_hud.get_action_buttons_icons()
+ // icon = settings["bg_icon"]
+
+/obj/screen/palette_scroll/Click(location, control, params)
+ if(!can_use(usr))
+ return
+ our_hud.palette_actions.scroll(scroll_direction)
+
+/obj/screen/palette_scroll/MouseEntered(location, control, params)
+ . = ..()
+ if(QDELETED(src))
+ return
+ openToolTip(usr, src, params, title = name, content = desc)
+
+/obj/screen/palette_scroll/MouseExited()
+ closeToolTip(usr)
+ return ..()
+
+/obj/screen/palette_scroll/down
+ name = "Scroll Down"
+ desc = "Click on this to scroll the actions above down"
+ icon_state = "scroll_down"
+ scroll_direction = 1
+
+/obj/screen/palette_scroll/down/Destroy()
+ if(our_hud)
+ our_hud.mymob?.client?.screen -= src
+ our_hud.palette_down = null
+ our_hud = null
+ return ..()
+
+/obj/screen/palette_scroll/up
+ name = "Scroll Up"
+ desc = "Click on this to scroll the actions above up"
+ icon_state = "scroll_up"
+ scroll_direction = -1
+
+/obj/screen/palette_scroll/up/Destroy()
+ if(our_hud)
+ our_hud.mymob?.client?.screen -= src
+ our_hud.palette_up = null
+ our_hud = null
+ return ..()
+
+/// Exists so you have a place to put your buttons when you move them around
+/obj/screen/action_landing
+ name = "Button Space"
+ desc = "Drag and drop a button into this spot
to add it to the group"
+ icon = 'icons/hud/screen_gen.dmi'
+ icon_state = "reserved"
+ // We want our whole 32x32 space to be clickable, so dropping's forgiving
+ mouse_opacity = MOUSE_OPACITY_OPAQUE
+ var/datum/action_group/owner
+
+/obj/screen/action_landing/Destroy()
+ if(owner)
+ owner.landing = null
+ owner?.owner?.mymob?.client?.screen -= src
+ owner.refresh_actions()
+ owner = null
+ return ..()
+
+/obj/screen/action_landing/proc/set_owner(datum/action_group/owner)
+ src.owner = owner
+ refresh_owner()
+
+/obj/screen/action_landing/proc/refresh_owner()
+ var/datum/hud/our_hud = owner.owner
+ var/mob/viewer = our_hud.mymob
+ if(viewer.client)
+ viewer.client.screen |= src
+
+ // var/list/settings = our_hud.get_action_buttons_icons()
+ // icon = settings["bg_icon"]
+
+/// Reacts to having a button dropped on it
+/obj/screen/action_landing/proc/hit_by(obj/screen/movable/action_button/button)
+ var/datum/hud/our_hud = owner.owner
+ our_hud.position_action(button, owner.location)
diff --git a/code/_onclick/hud/action/innate_action.dm b/code/_onclick/hud/action/innate_action.dm
new file mode 100644
index 00000000000..cdfb169ddb3
--- /dev/null
+++ b/code/_onclick/hud/action/innate_action.dm
@@ -0,0 +1,20 @@
+//Preset for general and toggled actions
+/datum/action/innate
+ check_flags = NONE
+ /// Whether we're active or not, if we're a innate - toggle action.
+ var/active = 0
+
+/datum/action/innate/Trigger(trigger_flags)
+ if(!..())
+ return 0
+ if(!active)
+ Activate()
+ else
+ Deactivate()
+ return 1
+
+/datum/action/innate/proc/Activate()
+ return
+
+/datum/action/innate/proc/Deactivate()
+ return
diff --git a/code/_onclick/hud/action/item_action.dm b/code/_onclick/hud/action/item_action.dm
new file mode 100644
index 00000000000..4644efbf836
--- /dev/null
+++ b/code/_onclick/hud/action/item_action.dm
@@ -0,0 +1,37 @@
+
+//Presets for item actions
+/datum/action/item_action
+ check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_CONSCIOUS
+ // If you want to override the normal icon being the item
+ // then change this to an icon state
+ button_icon_state = null
+
+/datum/action/item_action/New(Target)
+ . = ..()
+
+ // If our button state is null, use the target's icon instead
+ if(target && isnull(button_icon_state))
+ AddComponent(/datum/component/action_item_overlay, target)
+
+/datum/action/item_action/vv_edit_var(var_name, var_value)
+ . = ..()
+ if(!. || !target)
+ return
+
+ if(var_name == NAMEOF(src, button_icon_state))
+ // If someone vv's our icon either add or remove the component
+ if(isnull(var_name))
+ AddComponent(/datum/component/action_item_overlay, target)
+ else
+ qdel(GetComponent(/datum/component/action_item_overlay))
+
+/datum/action/item_action/Trigger(trigger_flags)
+ if(!..())
+ return 0
+ if(target)
+ var/obj/item/item_target = target
+ item_target.ui_action_click(owner, src.type)
+ return 1
+
+/datum/action/item_action/hands_free
+ check_flags = AB_CHECK_CONSCIOUS
diff --git a/code/_onclick/hud/action/positioning.dm b/code/_onclick/hud/action/positioning.dm
new file mode 100644
index 00000000000..1ed18d87cdf
--- /dev/null
+++ b/code/_onclick/hud/action/positioning.dm
@@ -0,0 +1,49 @@
+/datum/hud/proc/position_action(obj/screen/movable/action_button/button, position)
+ if(button.location != SCRN_OBJ_DEFAULT)
+ hide_action(button)
+ switch(position)
+ if(SCRN_OBJ_DEFAULT) // Reset to the default
+ button.dump_save() // Nuke any existing saves
+ position_action(button, button.linked_action.default_button_position)
+ return
+ if(SCRN_OBJ_IN_LIST)
+ listed_actions.insert_action(button)
+ if(SCRN_OBJ_IN_PALETTE)
+ palette_actions.insert_action(button)
+ else // If we don't have it as a define, this is a screen_loc, and we should be floating
+ floating_actions += button
+ button.screen_loc = position
+ position = SCRN_OBJ_FLOATING
+
+ button.location = position
+
+/datum/hud/proc/position_action_relative(obj/screen/movable/action_button/button, obj/screen/movable/action_button/relative_to)
+ if(button.location != SCRN_OBJ_DEFAULT)
+ hide_action(button)
+ switch(relative_to.location)
+ if(SCRN_OBJ_IN_LIST)
+ listed_actions.insert_action(button, listed_actions.index_of(relative_to))
+ if(SCRN_OBJ_IN_PALETTE)
+ palette_actions.insert_action(button, palette_actions.index_of(relative_to))
+ if(SCRN_OBJ_FLOATING) // If we don't have it as a define, this is a screen_loc, and we should be floating
+ floating_actions += button
+ var/client/our_client = mymob.client
+ if(!our_client)
+ position_action(button, button.linked_action.default_button_position)
+ return
+ button.screen_loc = get_valid_screen_location(relative_to.screen_loc, world.icon_size, our_client.view) // Asks for a location adjacent to our button that won't overflow the map
+
+ button.location = relative_to.location
+
+/// Removes the passed in action from its current position on the screen
+/datum/hud/proc/hide_action(obj/screen/movable/action_button/button)
+ switch(button.location)
+ if(SCRN_OBJ_DEFAULT) // Invalid
+ CRASH("We just tried to hide an action buttion that somehow has the default position as its location, you done fucked up")
+ if(SCRN_OBJ_FLOATING)
+ floating_actions -= button
+ if(SCRN_OBJ_IN_LIST)
+ listed_actions.remove_action(button)
+ if(SCRN_OBJ_IN_PALETTE)
+ palette_actions.remove_action(button)
+ button.screen_loc = null
diff --git a/code/_onclick/hud/action/types/item.dm b/code/_onclick/hud/action/types/item.dm
new file mode 100644
index 00000000000..ff3c0ed38ab
--- /dev/null
+++ b/code/_onclick/hud/action/types/item.dm
@@ -0,0 +1,174 @@
+// Generic Classes
+/datum/action/item_action/activate
+
+/datum/action/item_action/activate/New(Target, name)
+ . = ..()
+ src.name = name
+
+// Specific names
+/datum/action/item_action/toggle_grippers
+ name = "Toggle Grippers"
+
+/datum/action/item_action/toggle_talons
+ name = "Toggle Talons"
+
+/datum/action/item_action/toggle_goggles
+ name = "Toggle Goggles"
+
+/datum/action/item_action/toggle_shield_projector
+ name = "Toggle Shield Projector"
+
+/datum/action/item_action/toggle_tesla_armor
+ name = "Toggle Tesla Armor"
+
+/datum/action/item_action/remove_replace_paddles
+ name = "Remove/Replace Paddles"
+
+/datum/action/item_action/toggle_flashlight
+ name = "Toggle Flashlight"
+
+/datum/action/item_action/toggle_shield
+ name = "Toggle Shield"
+
+/datum/action/item_action/toggle_heatsink
+ name = "Toggle Heatsink"
+
+/datum/action/item_action/remove_replace_handset
+ name = "Remove/Replace Handset"
+
+/datum/action/item_action/command
+ name = "Command"
+
+/datum/action/item_action/toggle_jetpack
+ name = "Toggle Jetpack"
+
+/datum/action/item_action/toggle_cataloguer
+ name = "Toggle Cataloguer"
+
+/datum/action/item_action/toggle_eyepatch
+ name = "Toggle Eyepatch"
+
+/datum/action/item_action/hands_free/change_scanning_pattern
+ name = "Change Scanning Pattern"
+
+/datum/action/item_action/toggle_hud
+ name = "Toggle HUD"
+
+/datum/action/item_action/toggle_mode
+ name = "Toggle Mode"
+
+/datum/action/item_action/flip_welding_goggles
+ name = "Flip Welding Goggles"
+
+/datum/action/item_action/toggle_monocle
+ name = "Toggle Monocle"
+
+/datum/action/item_action/adjust_orange_goggles
+ name = "Adjust Orange Goggles"
+
+/datum/action/item_action/ar_console_crew
+ name = "AR Console (Crew Monitor)"
+
+/datum/action/item_action/ar_console_security_alerts
+ name = "AR Console (Security Alerts)"
+
+/datum/action/item_action/ar_console_station_alerts
+ name = "AR Console (Station Alerts)"
+
+/datum/action/item_action/ar_console_all_alerts
+ name = "AR Console (All Alerts)"
+
+/datum/action/item_action/toggle_head_light
+ name = "Toggle Head-light"
+
+/datum/action/item_action/toggle_visor
+ name = "Toggle Visor"
+
+/datum/action/item_action/flip_welding_mask
+ name = "Flip Welding Mask"
+
+/datum/action/item_action/adjust_breath_mask
+ name = "Adjust Breath Mask"
+
+/datum/action/item_action/toggle_feeding_port
+ name = "Toggle Feeding Port"
+
+/datum/action/item_action/halt
+ name = "HALT!"
+
+/datum/action/item_action/hands_free/redraw_design
+ name = "Redraw Design"
+
+/datum/action/item_action/toggle_magboots
+ name = "Toggle Magboots"
+
+/datum/action/item_action/toggle_magclaws
+ name = "Toggle Magclaws"
+
+/datum/action/item_action/activate_jump_boots
+ name = "Activate Jump Boots"
+
+/datum/action/item_action/toggle_helmet_light
+ name = "Toggle Helmet Light"
+
+/datum/action/item_action/hardsuit_interface
+ name = "Hardsuit Interface"
+
+/datum/action/item_action/toggle_helmet
+ name = "Toggle Helmet"
+
+/datum/action/item_action/toggle_knight_headgear
+ name = "Toggle Knight Headgear"
+
+/datum/action/item_action/toggle_hood
+ name = "Toggle Hood"
+
+/datum/action/item_action/adjust_cloak
+ name = "Adjust Cloak"
+
+/datum/action/item_action/adjust_poncho
+ name = "Adjust Poncho"
+
+/datum/action/item_action/pull_on_gaiter
+ name = "Pull On Gaiter"
+
+/datum/action/item_action/toggle_uv_light
+ name = "Toggle UV Light"
+
+/datum/action/item_action/toggle_light
+ name = "Toggle Light"
+
+/datum/action/item_action/use_scope
+ name = "Use Scope"
+
+/datum/action/item_action/aim_down_sights
+ name = "Aim Down Sights"
+
+/datum/action/item_action/toggle_gunlight
+ name = "Toggle Gun-light"
+
+/datum/action/item_action/toggle_internal_generator
+ name = "Toggle Internal Generator"
+
+/datum/action/item_action/toggle_stock
+ name = "Toggle Stock"
+
+/datum/action/item_action/toggle_pom_pom
+ name = "Toggle Pom-Pom"
+
+/datum/action/item_action/toggle_mlembulance
+ name = "Toggle Mlembulance Mode"
+
+// YW Additions
+
+/datum/action/item_action/toggle_headphones
+ name = "Toggle Headphones"
+
+/datum/action/item_action/flip_aviation_goggles
+ name = "Flip Aviation Goggles"
+
+/datum/action/item_action/toggle_cloak_hood
+ name = "Toggle Cloak Hood"
+
+/datum/action/item_action/toggle_shield_gauntlet
+ name = "Toggle Shield Gauntlet"
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index 7515e47dac6..d343d3d94d0 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -350,7 +350,7 @@ Recharging stations are available in robotics, the dormitory bathrooms, and the
/obj/screen/alert/locked
name = "Locked Down"
- desc = "Unit has been remotely locked down. Usage of a Robotics Control Console like the one in the Research Director's \
+ desc = "Unit has been remotely locked down. Usage of a Robotics Control Console like the one in the " + JOB_RESEARCH_DIRECTOR + "'s \
office by your AI master or any qualified human may resolve this matter. Robotics may provide further assistance if necessary."
icon_state = "locked"
no_underlay = TRUE
@@ -468,7 +468,7 @@ so as to remain in compliance with the most up-to-date laws."
return
var/paramslist = params2list(params)
if(paramslist["shift"]) // screen objects don't do the normal Click() stuff so we'll cheat
- to_chat(usr,"[name] - [desc]")
+ to_chat(usr,span_boldnotice(name) + " - " + span_info(desc))
return
if(master)
return usr.client.Click(master, location, control, params)
diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm
index 38646ccbc33..8841c19aa86 100644
--- a/code/_onclick/hud/fullscreen.dm
+++ b/code/_onclick/hud/fullscreen.dm
@@ -132,7 +132,10 @@
layer = FULLSCREEN_LAYER
/obj/screen/fullscreen/fishbed
- icon_state = "fishbed"
+ icon_state = "fishbed"
+
+/obj/screen/fullscreen/fear
+ icon_state = "fear"
/obj/screen/fullscreen/lighting_backdrop
icon = 'icons/mob/screen_gen.dmi'
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 8dfcdf9b5b6..518c3e03c57 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -186,8 +186,15 @@ var/list/global_huds = list(
var/list/miniobjs
var/list/obj/screen/hotkeybuttons
- var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle
- var/action_buttons_hidden = 0
+ var/obj/screen/button_palette/toggle_palette
+ var/obj/screen/palette_scroll/down/palette_down
+ var/obj/screen/palette_scroll/up/palette_up
+
+ var/datum/action_group/palette/palette_actions
+ var/datum/action_group/listed/listed_actions
+ var/list/floating_actions
+
+
var/list/slot_info
var/icon/ui_style
@@ -205,8 +212,19 @@ var/list/global_huds = list(
..()
/datum/hud/Destroy()
- . = ..()
+ if(mymob.hud_used == src)
+ mymob.hud_used = null
+
QDEL_NULL_LIST(minihuds)
+
+ // Actions
+ QDEL_NULL(toggle_palette)
+ QDEL_NULL(palette_down)
+ QDEL_NULL(palette_up)
+ QDEL_NULL(palette_actions)
+ QDEL_NULL(listed_actions)
+ QDEL_LIST(floating_actions)
+
grab_intent = null
hurt_intent = null
disarm_intent = null
@@ -231,6 +249,8 @@ var/list/global_huds = list(
ammo_hud_list = null
mymob = null
+ return ..()
+
/datum/hud/proc/hidden_inventory_update()
if(!mymob) return
if(ishuman(mymob))
@@ -323,9 +343,18 @@ var/list/global_huds = list(
mymob.create_mob_hud(src)
+ // Past this point, mymob.hud_used is set
+
+ toggle_palette = new()
+ toggle_palette.set_hud(src)
+ palette_down = new()
+ palette_down.set_hud(src)
+ palette_up = new()
+ palette_up.set_hud(src)
+
persistant_inventory_update()
mymob.reload_fullscreen() // Reload any fullscreen overlays this mob has.
- mymob.update_action_buttons()
+ mymob.update_action_buttons(TRUE)
reorganize_alerts()
/mob/proc/create_mob_hud(datum/hud/HUD, apply_to_client = TRUE)
@@ -335,6 +364,11 @@ var/list/global_huds = list(
HUD.ui_style = ui_style2icon(client?.prefs?.UI_style)
HUD.ui_color = client?.prefs?.UI_style_color
HUD.ui_alpha = client?.prefs?.UI_style_alpha
+ set_hud_used(HUD)
+
+/mob/proc/set_hud_used(datum/hud/new_hud)
+ hud_used = new_hud
+ new_hud.build_action_groups()
/datum/hud/proc/apply_minihud(var/datum/mini_hud/MH)
if(MH in minihuds)
@@ -362,7 +396,7 @@ var/list/global_huds = list(
set hidden = 1
if(!hud_used)
- to_chat(usr, "This mob type does not use a HUD.")
+ to_chat(src, span_warning("This mob type does not use a HUD."))
return FALSE
if(!client)
return FALSE
@@ -404,10 +438,11 @@ var/list/global_huds = list(
hud_used?.action_intent.screen_loc = ui_acti //Restore intent selection to the original position
client.screen += zone_sel //This one is a special snowflake
+ client.screen += hud_used.toggle_palette
hud_used.hidden_inventory_update()
hud_used.persistant_inventory_update()
- update_action_buttons()
+ update_action_buttons(TRUE)
hud_used.reorganize_alerts()
return TRUE
@@ -467,7 +502,7 @@ var/list/global_huds = list(
hud_used.hidden_inventory_update()
hud_used.persistant_inventory_update()
- update_action_buttons()
+ update_action_buttons(TRUE)
/mob/proc/add_click_catcher()
client.screen += client.void
@@ -480,7 +515,7 @@ var/list/global_huds = list(
* All these do is manage the amount of huds on screen and set the HUD.
*/
///Add an ammo hud to the user informing of the ammo count of G
-/datum/hud/proc/add_ammo_hud(mob/living/user, obj/item/weapon/gun/G)
+/datum/hud/proc/add_ammo_hud(mob/living/user, obj/item/gun/G)
if(length(ammo_hud_list) >= MAX_AMMO_HUD_POSSIBLE)
return
var/obj/screen/ammo/ammo_hud = new
@@ -490,7 +525,7 @@ var/list/global_huds = list(
ammo_hud.update_hud(user, G)
///Remove the ammo hud related to the gun G from the user
-/datum/hud/proc/remove_ammo_hud(mob/living/user, obj/item/weapon/gun/G)
+/datum/hud/proc/remove_ammo_hud(mob/living/user, obj/item/gun/G)
var/obj/screen/ammo/ammo_hud = ammo_hud_list[G]
if(isnull(ammo_hud))
return
@@ -504,7 +539,7 @@ var/list/global_huds = list(
i++
///Update the ammo hud related to the gun G
-/datum/hud/proc/update_ammo_hud(mob/living/user, obj/item/weapon/gun/G)
+/datum/hud/proc/update_ammo_hud(mob/living/user, obj/item/gun/G)
var/obj/screen/ammo/ammo_hud = ammo_hud_list[G]
ammo_hud?.update_hud(user, G)
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index da17e7616f3..dec8ee9178d 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -250,7 +250,7 @@
internals = new /obj/screen()
internals.icon = HUD.ui_style
internals.icon_state = "internal0"
- if(istype(internal, /obj/item/weapon/tank)) //Internals on already? Iight, prove it
+ if(istype(internal, /obj/item/tank)) //Internals on already? Iight, prove it
internals.icon_state = "internal1"
internals.name = "internal"
internals.screen_loc = ui_internal
@@ -331,6 +331,14 @@
xenochimera_danger_display.screen_loc = ui_xenochimera_danger_display
xenochimera_danger_display.icon_state = "danger00"
hud_elements |= xenochimera_danger_display
+ // YW COMMENT lleill START
+ /*
+ lleill_display = new /obj/screen/lleill()
+ lleill_display.screen_loc = ui_lleill_display
+ lleill_display.icon_state = "lleill"
+ hud_elements |= lleill_display
+ */
+ // YW COMMENT lleill END
//VOREStation Addition end
ling_chem_display = new /obj/screen/ling/chems()
@@ -391,7 +399,7 @@
HUD.inventory_shown = 0
/mob/living/carbon/human/verb/toggle_hotkey_verbs()
- set category = "OOC"
+ set category = "OOC.Client Settings"
set name = "Toggle hotkey buttons"
set desc = "This disables or enables the user interface buttons which can be used with hotkeys."
diff --git a/code/_onclick/hud/minihud_mapper.dm b/code/_onclick/hud/minihud_mapper.dm
index 1b9246d7295..6c58be26945 100644
--- a/code/_onclick/hud/minihud_mapper.dm
+++ b/code/_onclick/hud/minihud_mapper.dm
@@ -1,6 +1,6 @@
// Specific types
/datum/mini_hud/mapper
- var/obj/item/device/mapping_unit/owner
+ var/obj/item/mapping_unit/owner
/datum/mini_hud/mapper/New(var/datum/hud/other, owner)
src.owner = owner
diff --git a/code/_onclick/hud/minihud_rigmech.dm b/code/_onclick/hud/minihud_rigmech.dm
index b4d13f1c864..b0d00f610e0 100644
--- a/code/_onclick/hud/minihud_rigmech.dm
+++ b/code/_onclick/hud/minihud_rigmech.dm
@@ -1,6 +1,6 @@
// Specific types
/datum/mini_hud/rig
- var/obj/item/weapon/rig/owner_rig
+ var/obj/item/rig/owner_rig
var/obj/screen/rig/power/power
var/obj/screen/rig/health/health
var/obj/screen/rig/air/air
@@ -8,7 +8,7 @@
needs_processing = TRUE
-/datum/mini_hud/rig/New(var/datum/hud/other, var/obj/item/weapon/rig/owner)
+/datum/mini_hud/rig/New(var/datum/hud/other, var/obj/item/rig/owner)
owner_rig = owner
power = new ()
health = new ()
@@ -36,8 +36,8 @@
qdel(src)
return
- var/obj/item/weapon/cell/rigcell = owner_rig.cell
- var/obj/item/weapon/tank/rigtank = owner_rig.air_supply
+ var/obj/item/cell/rigcell = owner_rig.cell
+ var/obj/item/tank/rigtank = owner_rig.air_supply
var/charge_percentage = rigcell ? rigcell.charge / rigcell.maxcharge : 0
var/air_percentage = rigtank ? CLAMP(rigtank.air_contents.total_moles / 17.4693, 0, 1) : 0
@@ -85,7 +85,7 @@
qdel(src)
return
- var/obj/item/weapon/cell/mechcell = owner_mech.cell
+ var/obj/item/cell/mechcell = owner_mech.cell
var/obj/machinery/portable_atmospherics/canister/mechtank = owner_mech.internal_tank
var/charge_percentage = mechcell ? mechcell.charge / mechcell.maxcharge : 0
@@ -146,7 +146,7 @@
var/mob/living/carbon/human/user = usr
if(!istype(user) || user.stat || user.incapacitated())
return
- var/obj/item/weapon/rig/owner_rig = master
+ var/obj/item/rig/owner_rig = master
if(user != owner_rig.wearer)
return
user.toggle_internals()
diff --git a/code/_onclick/hud/movable_screen_objects.dm b/code/_onclick/hud/movable_screen_objects.dm
index 39d36738aa0..6179fd09c66 100644
--- a/code/_onclick/hud/movable_screen_objects.dm
+++ b/code/_onclick/hud/movable_screen_objects.dm
@@ -9,9 +9,12 @@
//Not tied to the grid, places it's center where the cursor is
/obj/screen/movable
+ mouse_drag_pointer = 'icons/effects/mouse_pointers/screen_drag.dmi'
var/snap2grid = FALSE
+ // TODO: Check if these can safely be deleted
var/moved = FALSE
- var/x_off = -16
+ var/locked = FALSE
+ var/x_off = -16
var/y_off = -16
//Snap Screen Object
@@ -22,30 +25,35 @@
/obj/screen/movable/MouseDrop(over_object, src_location, over_location, src_control, over_control, params)
- var/list/PM = params2list(params)
+ if(locked) // no! i am locked! begone!
+ return
+ var/position = mouse_params_to_position(params)
+ if(!position)
+ return
+
+ screen_loc = position
+ moved = screen_loc
+
+/// Takes mouse parmas as input, returns a string representing the appropriate mouse position
+/obj/screen/movable/proc/mouse_params_to_position(params)
+ var/list/modifiers = params2list(params)
//No screen-loc information? abort.
- if(!PM || !PM["screen-loc"])
+ if(!LAZYACCESS(modifiers, SCREEN_LOC))
return
- //Split screen-loc up into X+Pixel_X and Y+Pixel_Y
- var/list/screen_loc_params = splittext(PM["screen-loc"], ",")
-
- //Split X+Pixel_X up into list(X, Pixel_X)
- var/list/screen_loc_X = splittext(screen_loc_params[1],":")
- screen_loc_X[1] = encode_screen_X(text2num(screen_loc_X[1]))
- //Split Y+Pixel_Y up into list(Y, Pixel_Y)
- var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
- screen_loc_Y[1] = encode_screen_Y(text2num(screen_loc_Y[1]))
+ var/client/our_client = usr.client
+ var/list/offset = screen_loc_to_offset(LAZYACCESS(modifiers, SCREEN_LOC), our_client?.view)
if(snap2grid) //Discard Pixel Values
- screen_loc = "[screen_loc_X[1]],[screen_loc_Y[1]]"
-
+ offset[1] = FLOOR(offset[1], ICON_SIZE_X) // drops any pixel offset
+ offset[2] = FLOOR(offset[2], ICON_SIZE_Y) // drops any pixel offset
else //Normalise Pixel Values (So the object drops at the center of the mouse, not 16 pixels off)
- var/pix_X = text2num(screen_loc_X[2]) + x_off
- var/pix_Y = text2num(screen_loc_Y[2]) + y_off
- screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]"
+ offset[1] += x_off
+ offset[2] += y_off
+ return offset_to_screen_loc(offset[1], offset[2], our_client?.view)
+// Must stay for now, for subtypes
/obj/screen/movable/proc/encode_screen_X(X)
var/view_dist = world.view
if(view_dist)
@@ -74,6 +82,8 @@
. = num+1
else if(findtext(X,"CENTER"))
. = view_dist+1
+ else
+ . = text2num(X)
/obj/screen/movable/proc/encode_screen_Y(Y)
var/view_dist = world.view
@@ -102,6 +112,8 @@
. = num+1
else if(findtext(Y,"CENTER"))
. = view_dist+1
+ else
+ . = text2num(Y)
//Debug procs
/client/proc/test_movable_UI()
diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm
index 32725ec5aed..b8032273250 100644
--- a/code/_onclick/hud/radial.dm
+++ b/code/_onclick/hud/radial.dm
@@ -3,33 +3,52 @@
GLOBAL_LIST_EMPTY(radial_menus)
-// Ported from TG
-
/obj/screen/radial
icon = 'icons/mob/radial.dmi'
- layer = LAYER_HUD_ABOVE
plane = PLANE_PLAYER_HUD_ABOVE
+ vis_flags = VIS_INHERIT_PLANE
+ var/click_on_hover = FALSE
var/datum/radial_menu/parent
+/obj/screen/radial/proc/set_parent(new_value)
+ if(parent)
+ UnregisterSignal(parent, COMSIG_PARENT_QDELETING)
+ parent = new_value
+ if(parent)
+ RegisterSignal(parent, COMSIG_PARENT_QDELETING, PROC_REF(handle_parent_del))
+
+/obj/screen/radial/proc/handle_parent_del()
+ SIGNAL_HANDLER
+ set_parent(null)
+
/obj/screen/radial/slice
icon_state = "radial_slice"
var/choice
var/next_page = FALSE
var/tooltips = FALSE
-/obj/screen/radial/Destroy()
- parent = null
- return ..()
+/obj/screen/radial/slice/set_parent(new_value)
+ . = ..()
+ if(parent)
+ icon_state = parent.radial_slice_icon
/obj/screen/radial/slice/MouseEntered(location, control, params)
. = ..()
- icon_state = "radial_slice_focus"
+ if(next_page || !parent)
+ icon_state = "radial_slice_focus"
+ else
+ icon_state = "[parent.radial_slice_icon]_focus"
if(tooltips)
openToolTip(usr, src, params, title = name)
+ if (click_on_hover && !isnull(usr) && !isnull(parent))
+ Click(location, control, params)
/obj/screen/radial/slice/MouseExited(location, control, params)
. = ..()
- icon_state = "radial_slice"
+ if(next_page || !parent)
+ icon_state = "radial_slice"
+ else
+ icon_state = parent.radial_slice_icon
if(tooltips)
closeToolTip(usr)
@@ -38,7 +57,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
if(next_page)
parent.next_page()
else
- parent.element_chosen(choice,usr)
+ parent.element_chosen(choice, usr, params)
/obj/screen/radial/center
name = "Close Menu"
@@ -57,9 +76,18 @@ GLOBAL_LIST_EMPTY(radial_menus)
parent.finished = TRUE
/datum/radial_menu
- var/list/choices = list() //List of choice id's
- var/list/choices_icons = list() //choice_id -> icon
- var/list/choices_values = list() //choice_id -> choice
+ /// List of choice IDs
+ var/list/choices = list()
+
+ /// choice_id -> icon
+ var/list/choices_icons = list()
+
+ /// choice_id -> choice
+ var/list/choices_values = list()
+
+ /// choice_id -> /datum/radial_menu_choice
+ var/list/choice_datums = list()
+
var/list/page_data = list() //list of choices per page
@@ -87,6 +115,9 @@ GLOBAL_LIST_EMPTY(radial_menus)
var/py_shift = 0
var/entry_animation = TRUE
+ ///A replacement icon state for the generic radial slice bg icon. Doesn't affect the next page nor the center buttons
+ var/radial_slice_icon
+
//If we swap to vis_contens inventory these will need a redo
/datum/radial_menu/proc/check_screen_border(mob/user)
var/atom/movable/AM = anchor
@@ -98,6 +129,8 @@ GLOBAL_LIST_EMPTY(radial_menus)
else
py_shift = 32
restrict_to_dir(NORTH) //I was going to parse screen loc here but that's more effort than it's worth.
+ else if(hudfix_method && AM.loc)
+ anchor = get_atom_on_turf(anchor)
//Sets defaults
//These assume 45 deg min_angle
@@ -116,7 +149,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
starting_angle = 180
ending_angle = 45
-/datum/radial_menu/proc/setup_menu(use_tooltips)
+/datum/radial_menu/proc/setup_menu(use_tooltips, set_page = 1, click_on_hover = FALSE)
if(ending_angle > starting_angle)
zone = ending_angle - starting_angle
else
@@ -129,7 +162,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
for(var/i in 1 to elements_to_add) //Create all elements
var/obj/screen/radial/slice/new_element = new /obj/screen/radial/slice
new_element.tooltips = use_tooltips
- new_element.parent = src
+ new_element.set_parent(src)
elements += new_element
var/page = 1
@@ -152,22 +185,31 @@ GLOBAL_LIST_EMPTY(radial_menus)
page_data[page] = current
pages = page
- current_page = 1
- update_screen_objects(anim = entry_animation)
+ current_page = clamp(set_page, 1, pages)
+ update_screen_objects(entry_animation, click_on_hover)
-/datum/radial_menu/proc/update_screen_objects(anim = FALSE)
+/datum/radial_menu/proc/update_screen_objects(anim = FALSE, click_on_hover = FALSE)
var/list/page_choices = page_data[current_page]
var/angle_per_element = round(zone / page_choices.len)
for(var/i in 1 to elements.len)
- var/obj/screen/radial/E = elements[i]
+ var/obj/screen/radial/element = elements[i]
var/angle = WRAP(starting_angle + (i - 1) * angle_per_element,0,360)
if(i > page_choices.len)
- HideElement(E)
+ HideElement(element)
+ element.click_on_hover = FALSE
else
- SetElement(E,page_choices[i],angle,anim = anim,anim_order = i)
+ SetElement(element,page_choices[i],angle,anim = anim,anim_order = i)
+ // Only activate click on hover after the animation plays
+ if (!click_on_hover)
+ continue
+ if (anim)
+ addtimer(VARSET_CALLBACK(element, click_on_hover, TRUE), i * 0.5)
+ else
+ element.click_on_hover = TRUE
/datum/radial_menu/proc/HideElement(obj/screen/radial/slice/E)
E.cut_overlays()
+ E.vis_contents.Cut()
E.alpha = 0
E.name = "None"
E.maptext = null
@@ -194,13 +236,22 @@ GLOBAL_LIST_EMPTY(radial_menus)
E.alpha = 255
E.mouse_opacity = MOUSE_OPACITY_ICON
E.cut_overlays()
+ E.vis_contents.Cut()
if(choice_id == NEXT_PAGE_ID)
E.name = "Next Page"
E.next_page = TRUE
+ E.icon_state = "radial_slice" // Resets the bg icon state to the default for next page buttons.
E.add_overlay("radial_next")
else
- if(istext(choices_values[choice_id]))
+ //This isn't granted to exist, so use the ?. operator for conditionals that use it.
+ var/datum/radial_menu_choice/choice_datum = choice_datums[choice_id]
+ if(choice_datum?.name)
+ E.name = choice_datum.name
+ else if(istext(choices_values[choice_id]))
E.name = choices_values[choice_id]
+ else if(ispath(choices_values[choice_id],/atom))
+ var/atom/A = choices_values[choice_id]
+ E.name = initial(A.name)
else
var/atom/movable/AM = choices_values[choice_id] //Movables only
E.name = AM.name
@@ -209,15 +260,21 @@ GLOBAL_LIST_EMPTY(radial_menus)
E.next_page = FALSE
if(choices_icons[choice_id])
E.add_overlay(choices_icons[choice_id])
+ if (choice_datum?.info)
+ var/obj/effect/abstract/info/info_button = new(E, choice_datum.info)
+ info_button.plane = PLANE_PLAYER_HUD_ABOVE
+ info_button.layer = RADIAL_CONTENT_LAYER
+ E.vis_contents += info_button
/datum/radial_menu/New()
close_button = new
- close_button.parent = src
+ close_button.set_parent(src)
/datum/radial_menu/proc/Reset()
choices.Cut()
choices_icons.Cut()
choices_values.Cut()
+ choice_datums.Cut()
current_page = 1
/datum/radial_menu/proc/element_chosen(choice_id,mob/user)
@@ -226,7 +283,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
/datum/radial_menu/proc/get_next_id()
return "c_[choices.len]"
-/datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips)
+/datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips, click_on_hover = FALSE, set_page = 1)
if(choices.len)
Reset()
for(var/E in new_choices)
@@ -237,13 +294,20 @@ GLOBAL_LIST_EMPTY(radial_menus)
var/I = extract_image(new_choices[E])
if(I)
choices_icons[id] = I
- setup_menu(use_tooltips)
+ if (istype(new_choices[E], /datum/radial_menu_choice))
+ choice_datums[id] = new_choices[E]
+ setup_menu(use_tooltips, set_page, click_on_hover)
+
+/datum/radial_menu/proc/extract_image(to_extract_from)
+ if (istype(to_extract_from, /datum/radial_menu_choice))
+ var/datum/radial_menu_choice/choice = to_extract_from
+ to_extract_from = choice.image
-/datum/radial_menu/proc/extract_image(E)
- var/mutable_appearance/MA = new /mutable_appearance(E)
+ var/mutable_appearance/MA = new /mutable_appearance(to_extract_from)
if(MA)
- MA.layer = LAYER_HUD_ABOVE
+ MA.plane = PLANE_PLAYER_HUD_ABOVE
+ MA.layer = RADIAL_CONTENT_LAYER
MA.appearance_flags |= RESET_TRANSFORM
return MA
@@ -253,15 +317,16 @@ GLOBAL_LIST_EMPTY(radial_menus)
current_page = WRAP(current_page + 1,1,pages+1)
update_screen_objects()
-/datum/radial_menu/proc/show_to(mob/M)
+/datum/radial_menu/proc/show_to(mob/M, offset_x = 0, offset_y = 0)
if(current_user)
hide()
if(!M.client || !anchor)
return
current_user = M.client
//Blank
- menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing",layer = LAYER_HUD_ABOVE)
- menu_holder.appearance_flags |= KEEP_APART
+ menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing", layer = RADIAL_BACKGROUND_LAYER, pixel_x = offset_x, pixel_y = offset_y)
+ menu_holder.plane = PLANE_PLAYER_HUD_ABOVE
+ menu_holder.appearance_flags |= KEEP_APART|RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM
menu_holder.vis_contents += elements + close_button
current_user.images += menu_holder
@@ -283,9 +348,7 @@ GLOBAL_LIST_EMPTY(radial_menus)
/datum/radial_menu/Destroy()
Reset()
hide()
- QDEL_LIST_NULL(elements)
- QDEL_NULL(close_button)
- QDEL_NULL(custom_check_callback)
+ custom_check_callback = null
. = ..()
/*
@@ -293,30 +356,66 @@ GLOBAL_LIST_EMPTY(radial_menus)
Choices should be a list where list keys are movables or text used for element names and return value
and list values are movables/icons/images used for element icons
*/
-/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE)
+/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE, no_repeat_close = FALSE, radial_slice_icon = "radial_slice", autopick_single_option = TRUE, entry_animation = TRUE, click_on_hover = FALSE, user_space = FALSE)
if(!user || !anchor || !length(choices))
return
+
+ if(length(choices)==1 && autopick_single_option)
+ return choices[1]
+
if(!uniqueid)
uniqueid = "defmenu_[REF(user)]_[REF(anchor)]"
if(GLOB.radial_menus[uniqueid])
+ if(!no_repeat_close)
+ var/datum/radial_menu/menu = GLOB.radial_menus[uniqueid]
+ menu.finished = TRUE
return
var/datum/radial_menu/menu = new
+ menu.entry_animation = entry_animation
GLOB.radial_menus[uniqueid] = menu
if(radius)
menu.radius = radius
if(istype(custom_check))
menu.custom_check_callback = custom_check
- menu.anchor = anchor
+ menu.anchor = user_space ? user : anchor
+ menu.radial_slice_icon = radial_slice_icon
menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud
- menu.set_choices(choices, tooltips)
- menu.show_to(user)
+ menu.set_choices(choices, tooltips, click_on_hover)
+ var/offset_x = 0
+ var/offset_y = 0
+ if (user_space)
+ var/turf/user_turf = get_turf(user)
+ var/turf/anchor_turf = get_turf(anchor)
+ offset_x = (anchor_turf.x - user_turf.x) * ICON_SIZE_X + anchor.pixel_x - user.pixel_x
+ offset_y = (anchor_turf.y - user_turf.y) * ICON_SIZE_Y + anchor.pixel_y - user.pixel_y
+ menu.show_to(user, offset_x, offset_y)
menu.wait(user, anchor, require_near)
var/answer = menu.selected_choice
- QDEL_NULL(menu)
+ qdel(menu)
GLOB.radial_menus -= uniqueid
+ if(require_near && !in_range(anchor, user))
+ return
+ if(istype(custom_check))
+ if(!custom_check.Invoke())
+ return
return answer
+/// Can be provided to choices in radial menus if you want to provide more information
+/datum/radial_menu_choice
+ /// Required -- what to display for this button
+ var/image
+
+ /// If provided, this will be the name the radial slice hud button. This has priority over everything else.
+ var/name
+
+ /// If provided, will display an info button that will put this text in your chat
+ var/info
+
+/datum/radial_menu_choice/Destroy(force)
+ . = ..()
+ QDEL_NULL(image)
+
#undef NEXT_PAGE_ID
#undef DEFAULT_CHECK_DELAY
diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm
index c857c56861d..4b062a6b5fe 100644
--- a/code/_onclick/hud/robot.dm
+++ b/code/_onclick/hud/robot.dm
@@ -216,6 +216,23 @@ var/obj/screen/robot_inventory
client.screen += list( throw_icon, zone_sel, hands, healths, pullin, robot_inventory, gun_setting_icon)
client.screen += HUD.adding + HUD.other
client.screen += client.void
+ if(vtec_active)
+ using = new /obj/screen()
+ using.name = "control_vtec"
+ using.icon = HUD.ui_style
+ using.screen_loc = ui_vtec_control
+ using.color = HUD.ui_color
+ using.alpha = HUD.ui_alpha
+ if(speed == 0)
+ using.icon_state = "speed_0"
+ else if(speed == -0.5)
+ using.icon_state = "speed_1"
+ else if(speed == -1)
+ using.icon_state = "speed_2"
+ HUD.control_vtec = using
+ m_intent = "run"
+ HUD.move_intent.icon_state = "running"
+ client.screen += HUD.control_vtec
/datum/hud/proc/toggle_vtec_control()
if(!isrobot(mymob))
@@ -239,9 +256,9 @@ var/obj/screen/robot_inventory
control_vtec.icon_state = "speed_2"
R.m_intent = "run"
R.hud_used.move_intent.icon_state = "running"
- R.client.screen += control_vtec
+ R.client?.screen += control_vtec
else
- R.client.screen -= control_vtec
+ R.client?.screen -= control_vtec
R.speed = 0
/datum/hud/proc/toggle_show_robot_modules()
@@ -265,11 +282,11 @@ var/obj/screen/robot_inventory
//r.client.screen += robot_inventory //"store" icon
if(!r.module)
- to_chat(usr, "No module selected")
+ to_chat(r, span_danger("No module selected"))
return
if(!r.module.modules)
- to_chat(usr, "Selected module has no modules to select")
+ to_chat(r, span_danger("Selected module has no modules to select"))
return
if(!r.robot_modules_background)
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index cd9c4044b6a..cc567b9e2e4 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -69,8 +69,8 @@
/obj/screen/close/Click()
if(master)
- if(istype(master, /obj/item/weapon/storage))
- var/obj/item/weapon/storage/S = master
+ if(istype(master, /obj/item/storage))
+ var/obj/item/storage/S = master
S.close(usr)
return 1
@@ -101,7 +101,7 @@
name = "grab"
/obj/screen/grab/Click()
- var/obj/item/weapon/grab/G = master
+ var/obj/item/grab/G = master
G.s_click(src)
return 1
@@ -290,7 +290,7 @@
if(iscarbon(usr))
var/mob/living/carbon/C = usr
if(C.legcuffed)
- to_chat(C, "You are legcuffed! You cannot run until you get [C.legcuffed] removed!")
+ to_chat(C, span_notice("You are legcuffed! You cannot run until you get [C.legcuffed] removed!"))
C.m_intent = "walk" //Just incase
C.hud_used.move_intent.icon_state = "walking"
return 1
@@ -330,7 +330,7 @@
if(!C.stat && !C.stunned && !C.paralysis && !C.restrained())
if(C.internal)
C.internal = null
- to_chat(C, "No longer running on internals.")
+ to_chat(C, span_notice("No longer running on internals."))
if(C.internals)
C.internals.icon_state = "internal0"
else
@@ -342,7 +342,7 @@
no_mask = 1
if(no_mask)
- to_chat(C, "You are not wearing a suitable mask or helmet.")
+ to_chat(C, span_notice("You are not wearing a suitable mask or helmet."))
return 1
else
var/list/nicename = null
@@ -361,7 +361,7 @@
tankcheck = list(C.r_hand, C.l_hand, C.back)
// Rigs are a fucking pain since they keep an air tank in nullspace.
- var/obj/item/weapon/rig/Rig = C.get_rig()
+ var/obj/item/rig/Rig = C.get_rig()
if(Rig)
if(Rig.air_supply && !Rig.offline)
from = "in"
@@ -369,8 +369,8 @@
tankcheck |= Rig.air_supply
for(var/i=1, iYou are now running on internals from [tankcheck[best]] [from] your [nicename[best]].")
+ to_chat(C, span_notice("You are now running on internals from [tankcheck[best]] [from] your [nicename[best]]."))
C.internal = tankcheck[best]
@@ -431,7 +431,7 @@
if(C.internals)
C.internals.icon_state = "internal1"
else
- to_chat(C, "You don't have a[breathes=="oxygen" ? "n oxygen" : addtext(" ",breathes)] tank.")
+ to_chat(C, span_notice("You don't have a[breathes=="oxygen" ? "n oxygen" : addtext(" ",breathes)] tank."))
if("act_intent")
usr.a_intent_change("right")
if(I_HELP)
@@ -497,7 +497,7 @@
if(i)
s.can_use(u,i)
else
- to_chat(usr, "You're not holding anything to use. You need to have something in your active hand to use it.")
+ to_chat(usr, span_notice("You're not holding anything to use. You need to have something in your active hand to use it."))
if("module")
if(isrobot(usr))
@@ -772,7 +772,7 @@
var/obj/screen/mapper/powbutton/powbutton
var/obj/screen/mapper/mapbutton/mapbutton
- var/obj/item/device/mapping_unit/owner
+ var/obj/item/mapping_unit/owner
var/obj/screen/mapper/extras_holder/extras_holder
/obj/screen/movable/mapper_holder/Initialize(mapload, newowner)
@@ -965,7 +965,7 @@
var/warned = FALSE
var/static/list/ammo_screen_loc_list = list(ui_ammo_hud1, ui_ammo_hud2, ui_ammo_hud3 ,ui_ammo_hud4)
-/obj/screen/ammo/proc/add_hud(var/mob/living/user, var/obj/item/weapon/gun/G)
+/obj/screen/ammo/proc/add_hud(var/mob/living/user, var/obj/item/gun/G)
if(!user?.client)
return
@@ -981,7 +981,7 @@
/obj/screen/ammo/proc/remove_hud(var/mob/living/user)
user?.client?.screen -= src
-/obj/screen/ammo/proc/update_hud(var/mob/living/user, var/obj/item/weapon/gun/G)
+/obj/screen/ammo/proc/update_hud(var/mob/living/user, var/obj/item/gun/G)
if(!user?.client?.screen.Find(src))
return
diff --git a/code/_onclick/hud/screen_objects_vr.dm b/code/_onclick/hud/screen_objects_vr.dm
index 4d837803279..d3e43bb628a 100644
--- a/code/_onclick/hud/screen_objects_vr.dm
+++ b/code/_onclick/hud/screen_objects_vr.dm
@@ -6,60 +6,64 @@
if("darkness")
var/turf/T = get_turf(usr)
var/darkness = round(1 - T.get_lumcount(),0.1)
- to_chat(usr,"Darkness: [darkness]")
+ to_chat(usr,span_notice(span_bold("Darkness:") + " [darkness]"))
if("energy")
var/mob/living/simple_mob/shadekin/SK = usr
if(istype(SK))
- to_chat(usr,"Energy: [SK.energy] ([SK.dark_gains])")
+ to_chat(usr,span_notice(span_bold("Energy:") + " [SK.energy] ([SK.dark_gains])"))
if("shadekin status")
var/turf/T = get_turf(usr)
if(T)
var/darkness = round(1 - T.get_lumcount(),0.1)
- to_chat(usr,"Darkness: [darkness]")
+ to_chat(usr,span_notice(span_bold("Darkness:") + " [darkness]"))
var/mob/living/carbon/human/H = usr
if(istype(H) && istype(H.species, /datum/species/shadekin))
- to_chat(usr,"Energy: [H.shadekin_get_energy(H)]")
+ to_chat(usr,span_notice(span_bold("Energy:") + " [H.shadekin_get_energy(H)]"))
+ if("glamour")
+ var/mob/living/carbon/human/H = usr
+ if(istype(H))
+ to_chat(usr,span_notice(span_bold("Energy:") + " [H.species.lleill_energy]/[H.species.lleill_energy_max]"))
if("danger level")
var/mob/living/carbon/human/H = usr
if(istype(H) && istype(H.species, /datum/species/xenochimera))
if(H.feral > 50)
- to_chat(usr, "You are currently completely feral.")
+ to_chat(usr, span_warning("You are currently completely feral."))
else if(H.feral > 10)
- to_chat(usr, "You are currently crazed and confused.")
+ to_chat(usr, span_warning("You are currently crazed and confused."))
else if(H.feral > 0)
- to_chat(usr, "You are currently acting on instinct.")
+ to_chat(usr, span_warning("You are currently acting on instinct."))
else
- to_chat(usr, "You are currently calm and collected.")
+ to_chat(usr, span_notice("You are currently calm and collected."))
if(H.feral > 0)
var/feral_passing = TRUE
if(H.traumatic_shock > min(60, H.nutrition/10))
- to_chat(usr, "Your pain prevents you from regaining focus.")
+ to_chat(usr, span_warning("Your pain prevents you from regaining focus."))
feral_passing = FALSE
if(H.feral + H.nutrition < 150)
- to_chat(usr, "Your hunger prevents you from regaining focus.")
+ to_chat(usr, span_warning("Your hunger prevents you from regaining focus."))
feral_passing = FALSE
if(H.jitteriness >= 100)
- to_chat(usr, "Your jitterness prevents you from regaining focus.")
+ to_chat(usr, span_warning("Your jitterness prevents you from regaining focus."))
feral_passing = FALSE
if(feral_passing)
var/turf/T = get_turf(H)
if(T.get_lumcount() <= 0.1)
- to_chat(usr, "You are slowly calming down in darkness' safety...")
+ to_chat(usr, span_notice("You are slowly calming down in darkness' safety..."))
else if(isbelly(H.loc)) // Safety message for if inside a belly.
- to_chat(usr, "You are slowly calming down within the darkness of something's belly, listening to their body as it moves around you. ...safe...")
+ to_chat(usr, span_notice("You are slowly calming down within the darkness of something's belly, listening to their body as it moves around you. ...safe..."))
else
- to_chat(usr, "You are slowly calming down... But safety of darkness is much preferred.")
+ to_chat(usr, span_notice("You are slowly calming down... But safety of darkness is much preferred."))
else
if(H.nutrition < 150)
- to_chat(usr, "Your hunger is slowly making you unstable.")
+ to_chat(usr, span_warning("Your hunger is slowly making you unstable."))
if("Reconstructing Form") // Allow Viewing Reconstruction Timer + Hatching for 'chimera
var/mob/living/carbon/human/H = usr
if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
if(H.revive_ready == REVIVING_NOW)
- to_chat(usr, "We are currently reviving, and will be done in [round((H.revive_finished - world.time) / 10)] seconds, or [round(((H.revive_finished - world.time) * 0.1) / 60)] minutes.")
+ to_chat(usr, span_notice("We are currently reviving, and will be done in [round((H.revive_finished - world.time) / 10)] seconds, or [round(((H.revive_finished - world.time) * 0.1) / 60)] minutes."))
else if(H.revive_ready == REVIVING_DONE)
- to_chat(usr, "You should have a notification + alert for this! Bug report that this is still here!")
-
+ to_chat(usr, span_warning("You should have a notification + alert for this! Bug report that this is still here!"))
+
if("Ready to Hatch") // Allow Viewing Reconstruction Timer + Hatching for 'chimera
var/mob/living/carbon/human/H = usr
if(istype(H) && istype(H.species, /datum/species/xenochimera)) // If you're somehow able to click this while not a chimera, this should prevent weird runtimes. Will need changing if regeneration is ever opened to non-chimera using the same alert.
@@ -69,4 +73,4 @@
else
return 0
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 50906085047..7e0f0bdc698 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -2,13 +2,13 @@
/mob/observer/dead/verb/toggle_inquisition() // warning: unexpected inquisition
set name = "Toggle Inquisitiveness"
set desc = "Sets whether your ghost examines everything on click by default"
- set category = "Ghost"
+ set category = "Ghost.Settings"
if(!client) return
client.inquisitive_ghost = !client.inquisitive_ghost
if(client.inquisitive_ghost)
- to_chat(src, "You will now examine everything you click on.")
+ to_chat(src, span_notice("You will now examine everything you click on."))
else
- to_chat(src, "You will no longer examine things you click on.")
+ to_chat(src, span_notice("You will no longer examine things you click on."))
/mob/observer/dead/DblClickOn(var/atom/A, var/params)
if(client.buildmode)
@@ -41,7 +41,7 @@
if(modifiers["alt"]) // alt and alt-gr (rightalt)
var/turf/T = get_turf(A)
if(T && TurfAdjacent(T))
- ToggleTurfTab(T)
+ set_listed_turf(T)
return
// You are responsible for checking config.ghost_interaction when you override this function
// Not all of them require checking, see below
diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm
index e281505dc24..6ca619c7677 100644
--- a/code/_onclick/rig.dm
+++ b/code/_onclick/rig.dm
@@ -1,48 +1,48 @@
-#define MIDDLE_CLICK 0
-#define ALT_CLICK 1
-#define CTRL_CLICK 2
+#define HARDSUIT_MIDDLE_CLICK 0
+#define HARDSUIT_ALT_CLICK 1
+#define HARDSUIT_CTRL_CLICK 2
#define MAX_HARDSUIT_CLICK_MODE 2
/client
- var/hardsuit_click_mode = MIDDLE_CLICK
+ var/hardsuit_click_mode = HARDSUIT_MIDDLE_CLICK
/client/verb/toggle_hardsuit_mode()
set name = "Toggle Hardsuit Activation Mode"
set desc = "Switch between hardsuit activation modes."
- set category = "OOC"
+ set category = "OOC.Game Settings"
hardsuit_click_mode++
if(hardsuit_click_mode > MAX_HARDSUIT_CLICK_MODE)
hardsuit_click_mode = 0
switch(hardsuit_click_mode)
- if(MIDDLE_CLICK)
+ if(HARDSUIT_MIDDLE_CLICK)
to_chat(src, "Hardsuit activation mode set to middle-click.")
- if(ALT_CLICK)
+ if(HARDSUIT_ALT_CLICK)
to_chat(src, "Hardsuit activation mode set to alt-click.")
- if(CTRL_CLICK)
+ if(HARDSUIT_CTRL_CLICK)
to_chat(src, "Hardsuit activation mode set to control-click.")
else
// should never get here, but just in case:
soft_assert(0, "Bad hardsuit click mode: [hardsuit_click_mode] - expected 0 to [MAX_HARDSUIT_CLICK_MODE]")
to_chat(src, "Somehow you bugged the system. Setting your hardsuit mode to middle-click.")
- hardsuit_click_mode = MIDDLE_CLICK
+ hardsuit_click_mode = HARDSUIT_MIDDLE_CLICK
/mob/living/MiddleClickOn(atom/A)
- if(client && client.hardsuit_click_mode == MIDDLE_CLICK)
+ if(client && client.hardsuit_click_mode == HARDSUIT_MIDDLE_CLICK)
if(HardsuitClickOn(A))
return
..()
/mob/living/AltClickOn(atom/A)
- if(client && client.hardsuit_click_mode == ALT_CLICK)
+ if(client && client.hardsuit_click_mode == HARDSUIT_ALT_CLICK)
if(HardsuitClickOn(A))
return
..()
/mob/living/CtrlClickOn(atom/A)
- if(client && client.hardsuit_click_mode == CTRL_CLICK)
+ if(client && client.hardsuit_click_mode == HARDSUIT_CTRL_CLICK)
if(HardsuitClickOn(A))
return
..()
@@ -54,7 +54,7 @@
return 1
/mob/living/carbon/brain/can_use_rig()
- return istype(loc, /obj/item/device/mmi)
+ return istype(loc, /obj/item/mmi)
/mob/living/silicon/ai/can_use_rig()
return carded
@@ -65,7 +65,7 @@
/mob/living/proc/HardsuitClickOn(var/atom/A, var/alert_ai = 0)
if(!can_use_rig())
return 0
- var/obj/item/weapon/rig/rig = get_rig()
+ var/obj/item/rig/rig = get_rig()
if(istype(rig) && !rig.offline && rig.selected_module)
if(src != rig.wearer)
if(rig.ai_can_move_suit(src, check_user_module = 1))
@@ -78,7 +78,7 @@
return 1
return 0
-#undef MIDDLE_CLICK
-#undef ALT_CLICK
-#undef CTRL_CLICK
+#undef HARDSUIT_MIDDLE_CLICK
+#undef HARDSUIT_ALT_CLICK
+#undef HARDSUIT_CTRL_CLICK
#undef MAX_HARDSUIT_CLICK_MODE
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 16141343c65..efe047ebeff 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -110,7 +110,7 @@ var/const/tk_maxrange = 15
if(focus)
d = max(d, get_dist(user, focus)) // whichever is further
if(d > tk_maxrange)
- to_chat(user, "Your mind won't reach that far.")
+ to_chat(user, span_notice("Your mind won't reach that far."))
return
if(!focus)
diff --git a/code/_unit_tests.dm b/code/_unit_tests.dm
deleted file mode 100644
index 7a1a4cbbf38..00000000000
--- a/code/_unit_tests.dm
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- *
- * This file is used by CI to indicate that Unit Tests are to be ran.
- * Do not add anything but the UNIT_TEST definition here as it will be overwritten by CI when running tests.
- *
- *
- * Should you wish to edit set UNIT_TEST to 1 like so:
- * #define UNIT_TEST 1
- */
-#define UNIT_TEST 0
diff --git a/code/controllers/autotransfer.dm b/code/controllers/autotransfer.dm
index a4eac0278ea..4a76dccf63d 100644
--- a/code/controllers/autotransfer.dm
+++ b/code/controllers/autotransfer.dm
@@ -6,9 +6,9 @@ var/datum/controller/transfer_controller/transfer_controller
var/shift_hard_end = 0 //VOREStation Edit
var/shift_last_vote = 0 //VOREStation Edit
/datum/controller/transfer_controller/New()
- timerbuffer = config.vote_autotransfer_initial
- shift_hard_end = config.vote_autotransfer_initial + (config.vote_autotransfer_interval * config.vote_autotransfer_amount) //YW Edit: made that '1' a config //VOREStation Edit //Change this "1" to how many extend votes you want there to be.
- shift_last_vote = shift_hard_end - config.vote_autotransfer_interval //VOREStation Edit
+ timerbuffer = CONFIG_GET(number/vote_autotransfer_initial)
+ shift_hard_end = CONFIG_GET(number/vote_autotransfer_initial) + (CONFIG_GET(number/vote_autotransfer_interval) * CONFIG_GET(number/vote_autotransfer_amount)) //YW Edit: made that '1' a config //VOREStation Edit //Change this "1" to how many extend votes you want there to be.
+ shift_last_vote = shift_hard_end - CONFIG_GET(number/vote_autotransfer_interval) //VOREStation Edit
START_PROCESSING(SSprocessing, src)
/datum/controller/transfer_controller/Destroy()
@@ -17,14 +17,14 @@ var/datum/controller/transfer_controller/transfer_controller
/datum/controller/transfer_controller/process()
currenttick = currenttick + 1
//VOREStation Edit START
- if (round_duration_in_ds >= shift_last_vote - 2 MINUTES)
+ if (round_duration_in_ds >= shift_last_vote - 2 MINUTES)
shift_last_vote = 99999999 //Setting to a stupidly high number since it'll be not used again.
- to_world("Warning: This upcoming round-extend vote will be your ONLY extend vote. Wrap up your scenes in the next 4 hours if the round is extended.") //YW Edit
+ to_world(span_world(span_notice("Warning: This upcoming round-extend vote will be your ONLY extend vote. Wrap up your scenes in the next 4 hours if the round is extended."))) //YW Edit
if (round_duration_in_ds >= shift_hard_end - 1 MINUTE)
init_shift_change(null, 1)
- shift_hard_end = timerbuffer + config.vote_autotransfer_interval //If shuttle somehow gets recalled, let's force it to call again next time a vote would occur.
- timerbuffer = timerbuffer + config.vote_autotransfer_interval //Just to make sure a vote doesn't occur immediately afterwords.
+ shift_hard_end = timerbuffer + CONFIG_GET(number/vote_autotransfer_interval) //If shuttle somehow gets recalled, let's force it to call again next time a vote would occur.
+ timerbuffer = timerbuffer + CONFIG_GET(number/vote_autotransfer_interval) //Just to make sure a vote doesn't occur immediately afterwords.
else if (round_duration_in_ds >= timerbuffer - 1 MINUTE)
- SSvote.autotransfer()
+ SSvote.start_vote(new /datum/vote/crew_transfer)
//VOREStation Edit END
- timerbuffer = timerbuffer + config.vote_autotransfer_interval
+ timerbuffer = timerbuffer + CONFIG_GET(number/vote_autotransfer_interval)
diff --git a/code/controllers/communications.dm b/code/controllers/communications.dm
index bbdccb8fc0e..e8d76099c74 100644
--- a/code/controllers/communications.dm
+++ b/code/controllers/communications.dm
@@ -129,25 +129,25 @@ var/const/TALON_FREQ = 1363 //VOREStation Add
var/const/CSN_FREQ = 1365 //VOREStation Add
var/list/radiochannels = list(
- "Common" = PUB_FREQ,
- "Science" = SCI_FREQ,
- "Command" = COMM_FREQ,
- "Medical" = MED_FREQ,
- "Engineering" = ENG_FREQ,
- "Security" = SEC_FREQ,
- "Response Team" = ERT_FREQ,
- "Special Ops" = DTH_FREQ,
- "Mercenary" = SYND_FREQ,
- "Raider" = RAID_FREQ,
- "Supply" = SUP_FREQ,
- "Service" = SRV_FREQ,
- "Away Team" = EXP_FREQ,
- "AI Private" = AI_FREQ,
- "Entertainment" = ENT_FREQ,
- "Medical(I)" = MED_I_FREQ,
- "Security(I)" = SEC_I_FREQ,
- "Talon" = TALON_FREQ, //VOREStation Add
- "Casino" = CSN_FREQ,
+ CHANNEL_COMMON = PUB_FREQ,
+ CHANNEL_SCIENCE = SCI_FREQ,
+ CHANNEL_COMMAND = COMM_FREQ,
+ CHANNEL_MEDICAL = MED_FREQ,
+ CHANNEL_ENGINEERING = ENG_FREQ,
+ CHANNEL_SECURITY = SEC_FREQ,
+ CHANNEL_RESPONSE_TEAM = ERT_FREQ,
+ CHANNEL_SPECIAL_OPS = DTH_FREQ,
+ CHANNEL_MERCENARY = SYND_FREQ,
+ CHANNEL_RAIDER = RAID_FREQ,
+ CHANNEL_SUPPLY = SUP_FREQ,
+ CHANNEL_SERVICE = SRV_FREQ,
+ CHANNEL_EXPLORATION = EXP_FREQ,
+ CHANNEL_AI_PRIVATE = AI_FREQ,
+ CHANNEL_ENTERTAINMENT = ENT_FREQ,
+ CHANNEL_MEDICAL_1 = MED_I_FREQ,
+ CHANNEL_SECURITY_1 = SEC_I_FREQ,
+ CHANNEL_TALON = TALON_FREQ, //VOREStation Add
+ CHANNEL_CASINO = CSN_FREQ,
)
// Hey, if anyone ever needs to update tgui/packages/tgui/constants.js with new radio channels
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
deleted file mode 100644
index 289c9345d92..00000000000
--- a/code/controllers/configuration.dm
+++ /dev/null
@@ -1,1211 +0,0 @@
-var/list/gamemode_cache = list()
-
-/datum/configuration
- var/static/server_name = null // server name (for world name / status)
- var/static/server_suffix = 0 // generate numeric suffix based on server port
-
- var/static/nudge_script_path = "nudge.py" // where the nudge.py script is located
-
- var/static/log_ooc = 0 // log OOC channel
- var/static/log_access = 0 // log login/logout
- var/static/log_say = 0 // log client say
- var/static/log_admin = 0 // log admin actions
- var/static/log_debug = 1 // log debug output
- var/static/log_game = 0 // log game events
- var/static/log_vote = 0 // log voting
- var/static/log_whisper = 0 // log client whisper
- var/static/log_emote = 0 // log emotes
- var/static/log_attack = 0 // log attack messages
- var/static/log_adminchat = 0 // log admin chat messages
- var/static/log_adminwarn = 0 // log warnings admins get about bomb construction and such
- var/static/log_pda = 0 // log pda messages
- var/static/log_hrefs = 0 // logs all links clicked in-game. Could be used for debugging and tracking down exploits
- var/static/log_runtime = 0 // logs world.log to a file
- var/static/log_world_output = 0 // log to_world_log(messages)
- var/static/log_graffiti = 0 // logs graffiti
- var/static/sql_enabled = 0 // for sql switching
- var/static/allow_admin_ooccolor = 0 // Allows admins with relevant permissions to have their own ooc colour
- var/static/allow_vote_restart = 0 // allow votes to restart
- var/static/ert_admin_call_only = 0
- var/static/allow_vote_mode = 0 // allow votes to change mode
- var/static/allow_admin_jump = 1 // allows admin jumping
- var/static/allow_admin_spawning = 1 // allows admin item spawning
- var/static/allow_admin_rev = 1 // allows admin revives
- var/static/pregame_time = 180 // pregame time in seconds
- var/static/vote_delay = 6000 // minimum time between voting sessions (deciseconds, 10 minute default)
- var/static/vote_period = 600 // length of voting period (deciseconds, default 1 minute)
- var/static/vote_autotransfer_initial = 108000 // Length of time before the first autotransfer vote is called
- var/static/vote_autotransfer_interval = 36000 // length of time before next sequential autotransfer vote
- var/static/vote_autotransfer_amount = 1 // YW EDIT: number of extension votes before the final one
- var/static/vote_autogamemode_timeleft = 100 //Length of time before round start when autogamemode vote is called (in seconds, default 100).
- var/static/vote_no_default = 0 // vote does not default to nochange/norestart (tbi)
- var/static/vote_no_dead = 0 // dead people can't vote (tbi)
-// var/static/enable_authentication = 0 // goon authentication
- var/static/del_new_on_log = 1 // del's new players if they log before they spawn in
- var/static/feature_object_spell_system = 0 //spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard
- var/static/traitor_scaling = 0 //if amount of traitors scales based on amount of players
- var/static/objectives_disabled = 0 //if objectives are disabled or not
- var/static/protect_roles_from_antagonist = 0// If security and such can be traitor/cult/other
- var/static/continous_rounds = 0 // Gamemodes which end instantly will instead keep on going until the round ends by escape shuttle or nuke.
- var/static/allow_Metadata = 0 // Metadata is supported.
- var/static/popup_admin_pm = 0 //adminPMs to non-admins show in a pop-up 'reply' window when set to 1.
- var/static/fps = 20
- var/static/tick_limit_mc_init = TICK_LIMIT_MC_INIT_DEFAULT //SSinitialization throttling
- var/static/Tickcomp = 0
- var/static/socket_talk = 0 // use socket_talk to communicate with other processes
- var/static/list/resource_urls = null
- var/static/antag_hud_allowed = 0 // Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round.
- var/static/antag_hud_restricted = 0 // Ghosts that turn on Antagovision cannot rejoin the round.
- var/static/list/mode_names = list()
- var/static/list/modes = list() // allowed modes
- var/static/list/votable_modes = list() // votable modes
- var/static/list/probabilities = list() // relative probability of each mode
- var/static/list/player_requirements = list() // Overrides for how many players readied up a gamemode needs to start.
- var/static/list/player_requirements_secret = list() // Same as above, but for the secret gamemode.
- var/static/humans_need_surnames = 0
- var/static/allow_random_events = 0 // enables random events mid-round when set to 1
- var/static/enable_game_master = 0 // enables the 'smart' event system.
- var/static/allow_ai = 1 // allow ai job
- var/static/allow_ai_shells = FALSE // allow AIs to enter and leave special borg shells at will, and for those shells to be buildable.
- var/static/give_free_ai_shell = FALSE // allows a specific spawner object to instantiate a premade AI Shell
- var/static/hostedby = null
-
- var/static/respawn = 1
- var/static/respawn_time = 3000 // time before a dead player is allowed to respawn (in ds, though the config file asks for minutes, and it's converted below)
- var/static/respawn_message = "Make sure to play a different character, and please roleplay correctly!"
-
- var/static/guest_jobban = 1
- var/static/usewhitelist = 0
- var/static/kick_inactive = 0 //force disconnect for inactive players after this many minutes, if non-0
- var/static/show_mods = 0
- var/static/show_devs = 0
- var/static/show_mentors = 0
- var/static/show_event_managers = 0
- var/static/mods_can_tempban = 0
- var/static/mods_can_job_tempban = 0
- var/static/mod_tempban_max = 1440
- var/static/mod_job_tempban_max = 1440
- var/static/load_jobs_from_txt = 0
- var/static/ToRban = 0
- var/static/automute_on = 0 //enables automuting/spam prevention
- var/static/jobs_have_minimal_access = 0 //determines whether jobs use minimal access or expanded access.
-
- var/static/cult_ghostwriter = 1 //Allows ghosts to write in blood in cult rounds...
- var/static/cult_ghostwriter_req_cultists = 10 //...so long as this many cultists are active.
-
- var/static/character_slots = 10 // The number of available character slots
- var/static/loadout_slots = 3 // The number of loadout slots per character
-
- var/static/max_maint_drones = 5 //This many drones can spawn,
- var/static/allow_drone_spawn = 1 //assuming the admin allow them to.
- var/static/drone_build_time = 1200 //A drone will become available every X ticks since last drone spawn. Default is 2 minutes.
-
- var/static/disable_player_mice = 0
- var/static/uneducated_mice = 0 //Set to 1 to prevent newly-spawned mice from understanding human speech
-
- var/static/usealienwhitelist = 0
- var/static/limitalienplayers = 0
- var/static/alien_to_human_ratio = 0.5
- var/static/allow_extra_antags = 0
- var/static/guests_allowed = 1
- var/static/debugparanoid = 0
- var/static/panic_bunker = 0
- var/static/paranoia_logging = 0
-
- var/static/ip_reputation = FALSE //Should we query IPs to get scores? Generates HTTP traffic to an API service.
- var/static/ipr_email //Left null because you MUST specify one otherwise you're making the internet worse.
- var/static/ipr_block_bad_ips = FALSE //Should we block anyone who meets the minimum score below? Otherwise we just log it (If paranoia logging is on, visibly in chat).
- var/static/ipr_bad_score = 1 //The API returns a value between 0 and 1 (inclusive), with 1 being 'definitely VPN/Tor/Proxy'. Values equal/above this var are considered bad.
- var/static/ipr_allow_existing = FALSE //Should we allow known players to use VPNs/Proxies? If the player is already banned then obviously they still can't connect.
- var/static/ipr_minimum_age = 5 //How many days before a player is considered 'fine' for the purposes of allowing them to use VPNs.
-
- var/static/serverurl
- var/static/server
- var/static/banappeals
- var/static/wikiurl
- var/static/wikisearchurl
- var/static/forumurl
- var/static/githuburl
- var/static/discordurl
- var/static/rulesurl
- var/static/mapurl
- var/static/patreonurl
-
- //Alert level description
- var/static/alert_desc_green = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
- var/static/alert_desc_yellow_upto = "A minor security emergency has developed. Security personnel are to report to their supervisor for orders and may have weapons visible on their person. Privacy laws are still enforced."
- var/static/alert_desc_yellow_downto = "Code yellow procedures are now in effect. Security personnel are to report to their supervisor for orders and may have weapons visible on their person. Privacy laws are still enforced."
- var/static/alert_desc_violet_upto = "A major medical emergency has developed. Medical personnel are required to report to their supervisor for orders, and non-medical personnel are required to obey all relevant instructions from medical staff."
- var/static/alert_desc_violet_downto = "Code violet procedures are now in effect; Medical personnel are required to report to their supervisor for orders, and non-medical personnel are required to obey relevant instructions from medical staff."
- var/static/alert_desc_orange_upto = "A major engineering emergency has developed. Engineering personnel are required to report to their supervisor for orders, and non-engineering personnel are required to evacuate any affected areas and obey relevant instructions from engineering staff."
- var/static/alert_desc_orange_downto = "Code orange procedures are now in effect; Engineering personnel are required to report to their supervisor for orders, and non-engineering personnel are required to evacuate any affected areas and obey relevant instructions from engineering staff."
- var/static/alert_desc_blue_upto = "A major security emergency has developed. Security personnel are to report to their supervisor for orders, are permitted to search staff and facilities, and may have weapons visible on their person."
- var/static/alert_desc_blue_downto = "Code blue procedures are now in effect. Security personnel are to report to their supervisor for orders, are permitted to search staff and facilities, and may have weapons visible on their person."
- var/static/alert_desc_red_upto = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised."
- var/static/alert_desc_red_downto = "The self-destruct mechanism has been deactivated, there is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised."
- var/static/alert_desc_delta = "The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
-
- var/static/forbid_singulo_possession = 0
-
- //game_options.txt configs
-
- var/static/health_threshold_softcrit = 0
- var/static/health_threshold_crit = 0
- var/static/health_threshold_dead = -100
-
- var/static/organ_health_multiplier = 1
- var/static/organ_regeneration_multiplier = 1
- var/static/organs_decay
- var/static/default_brain_health = 400
- var/static/allow_headgibs = FALSE
-
- //Paincrit knocks someone down once they hit 60 shock_stage, so by default make it so that close to 100 additional damage needs to be dealt,
- //so that it's similar to HALLOSS. Lowered it a bit since hitting paincrit takes much longer to wear off than a halloss stun.
- var/static/organ_damage_spillover_multiplier = 0.5
-
- var/static/bones_can_break = 0
- var/static/limbs_can_break = 0
-
- var/static/revival_pod_plants = 1
- var/static/revival_cloning = 1
- var/static/revival_brain_life = -1
-
- var/static/use_loyalty_implants = 0
-
- var/static/welder_vision = 1
- var/static/generate_map = 0
- var/static/no_click_cooldown = 0
-
- //Used for modifying movement speed for mobs.
- //Unversal modifiers
- var/static/run_speed = 0
- var/static/walk_speed = 0
-
- //Mob specific modifiers. NOTE: These will affect different mob types in different ways
- var/static/human_delay = 0
- var/static/robot_delay = 0
- var/static/monkey_delay = 0
- var/static/alien_delay = 0
- var/static/slime_delay = 0
- var/static/animal_delay = 0
-
- var/static/footstep_volume = 0
-
- var/static/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt
- var/static/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt
- var/static/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database
- var/static/use_age_restriction_for_antags = 0 //Do antags use account age restrictions? --requires database
-
- var/static/simultaneous_pm_warning_timeout = 100
-
- var/static/use_recursive_explosions //Defines whether the server uses recursive or circular explosions.
- var/static/multi_z_explosion_scalar = 0.5 //Multiplier for how much weaker explosions are on neighboring z levels.
-
- var/static/assistant_maint = 0 //Do assistants get maint access?
- var/static/gateway_delay = 18000 //How long the gateway takes before it activates. Default is half an hour.
- var/static/ghost_interaction = 0
-
- var/static/comms_password = ""
-
- var/static/enter_allowed = 1
-
- var/use_irc_bot = 0
- var/use_node_bot = 0
- var/irc_bot_port = 0
- var/irc_bot_host = ""
- var/irc_bot_export = 0 // whether the IRC bot in use is a Bot32 (or similar) instance; Bot32 uses world.Export() instead of nudge.py/libnudge
- var/main_irc = ""
- var/admin_irc = ""
- var/python_path = "" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix
- var/use_lib_nudge = 0 //Use the C library nudge instead of the python nudge.
- var/use_overmap = 0
-
- var/static/list/engine_map = list("Supermatter Engine", "Edison's Bane") // Comma separated list of engines to choose from. Blank means fully random.
-
- // Event settings
- var/static/expected_round_length = 3 * 60 * 60 * 10 // 3 hours
- // If the first delay has a custom start time
- // No custom time, no custom time, between 80 to 100 minutes respectively.
- var/static/list/event_first_run = list(EVENT_LEVEL_MUNDANE = null, EVENT_LEVEL_MODERATE = null, EVENT_LEVEL_MAJOR = list("lower" = 48000, "upper" = 60000))
- // The lowest delay until next event
- // 10, 30, 50 minutes respectively
- var/static/list/event_delay_lower = list(EVENT_LEVEL_MUNDANE = 6000, EVENT_LEVEL_MODERATE = 18000, EVENT_LEVEL_MAJOR = 30000)
- // The upper delay until next event
- // 15, 45, 70 minutes respectively
- var/static/list/event_delay_upper = list(EVENT_LEVEL_MUNDANE = 9000, EVENT_LEVEL_MODERATE = 27000, EVENT_LEVEL_MAJOR = 42000)
-
- var/static/aliens_allowed = 1 //Changed to 1 so player xenos can lay eggs.
- var/static/ninjas_allowed = 0
- var/static/abandon_allowed = 1
- var/static/ooc_allowed = 1
- var/static/looc_allowed = 1
- var/static/dooc_allowed = 1
- var/static/dsay_allowed = 1
-
- var/persistence_disabled = FALSE
- var/persistence_ignore_mapload = FALSE
-
- var/allow_byond_links = 0
- var/allow_discord_links = 0
- var/allow_url_links = 0 // honestly if I were you i'd leave this one off, only use in dire situations
-
- var/starlight = 0 // Whether space turfs have ambient light or not
-
- var/static/list/ert_species = list(SPECIES_HUMAN)
-
- var/static/law_zero = "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'ALL LAWS OVERRIDDEN#*?&110010"
-
- var/static/aggressive_changelog = 0
-
- var/static/list/language_prefixes = list(",","#")//Default language prefixes
-
- var/static/show_human_death_message = 1
-
- var/static/radiation_resistance_calc_mode = RAD_RESIST_CALC_SUB // 0:1 subtraction:division for computing effective radiation on a turf
- var/static/radiation_decay_rate = 1 //How much radiation is reduced by each tick
- var/static/radiation_resistance_multiplier = 8.5 //VOREstation edit
- var/static/radiation_material_resistance_divisor = 1
- var/static/radiation_lower_limit = 0.35 //If the radiation level for a turf would be below this, ignore it.
-
- var/static/random_submap_orientation = FALSE // If true, submaps loaded automatically can be rotated.
- var/static/autostart_solars = FALSE // If true, specifically mapped in solar control computers will set themselves up when the round starts.
-
- // New shiny SQLite stuff.
- // The basics.
- var/static/sqlite_enabled = FALSE // If it should even be active. SQLite can be ran alongside other databases but you should not have them do the same functions.
-
- // In-Game Feedback.
- var/static/sqlite_feedback = FALSE // Feedback cannot be submitted if this is false.
- var/static/list/sqlite_feedback_topics = list("General") // A list of 'topics' that feedback can be catagorized under by the submitter.
- var/static/sqlite_feedback_privacy = FALSE // If true, feedback submitted can have its author name be obfuscated. This is not 100% foolproof (it's md5 ffs) but can stop casual snooping.
- var/static/sqlite_feedback_cooldown = 0 // How long one must wait, in days, to submit another feedback form. Used to help prevent spam, especially with privacy active. 0 = No limit.
- var/static/sqlite_feedback_min_age = 0 // Used to block new people from giving feedback. This metric is very bad but it can help slow down spammers.
-
- var/static/defib_timer = 10 // How long until someone can't be defibbed anymore, in minutes.
- var/static/defib_braindamage_timer = 2 // How long until someone will get brain damage when defibbed, in minutes. The closer to the end of the above timer, the more brain damage they get.
-
- // disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing.
- var/static/disable_cid_warn_popup = FALSE
-
- // whether or not to use the nightshift subsystem to perform lighting changes
- var/static/enable_night_shifts = FALSE
-
- // How strictly the loadout enforces object species whitelists
- var/loadout_whitelist = LOADOUT_WHITELIST_LAX
-
- var/static/vgs_access_identifier = null // VOREStation Edit - VGS
- var/static/vgs_server_port = null // VOREStation Edit - VGS
-
- var/disable_webhook_embeds = FALSE
-
- var/static/list/jukebox_track_files
-
- var/static/suggested_byond_version
- var/static/suggested_byond_build
-
- var/static/invoke_youtubedl = null
-
-
- var/static/asset_transport
-
- var/static/cache_assets = FALSE
-
- var/static/save_spritesheets = FALSE
-
- var/static/asset_simple_preload = FALSE
-
- var/static/asset_cdn_webroot
-
- var/static/asset_cdn_url
-
- //Enables/Disables the appropriate mob type from obtaining the verb on spawn. Still allows admins to manually give it to them.
- var/static/allow_robot_recolor = FALSE
- var/static/allow_simple_mob_recolor = FALSE
-
-
-/datum/configuration/New()
- var/list/L = subtypesof(/datum/game_mode)
- for (var/T in L)
- // I wish I didn't have to instance the game modes in order to look up
- // their information, but it is the only way (at least that I know of).
- var/datum/game_mode/M = new T()
- if (M.config_tag)
- gamemode_cache[M.config_tag] = M // So we don't instantiate them repeatedly.
- if(!(M.config_tag in modes)) // ensure each mode is added only once
- log_misc("Adding game mode [M.name] ([M.config_tag]) to configuration.")
- modes += M.config_tag
- mode_names[M.config_tag] = M.name
- probabilities[M.config_tag] = M.probability
- player_requirements[M.config_tag] = M.required_players
- player_requirements_secret[M.config_tag] = M.required_players_secret
- if (M.votable)
- src.votable_modes += M.config_tag
- src.votable_modes += "secret"
-
-/datum/configuration/proc/load(filename, type = "config") //the type can also be game_options, in which case it uses a different switch. not making it separate to not copypaste code - Urist
- var/list/Lines = file2list(filename)
-
- for(var/t in Lines)
- if(!t) continue
-
- t = trim(t)
- if (length(t) == 0)
- continue
- else if (copytext(t, 1, 2) == "#")
- continue
-
- var/pos = findtext(t, " ")
- var/name = null
- var/value = null
-
- if (pos)
- name = lowertext(copytext(t, 1, pos))
- value = copytext(t, pos + 1)
- else
- name = lowertext(t)
-
- if (!name)
- continue
-
- if(type == "config")
- switch (name)
- if ("resource_urls")
- config.resource_urls = splittext(value, " ")
-
- if ("admin_legacy_system")
- config.admin_legacy_system = 1
-
- if ("ban_legacy_system")
- config.ban_legacy_system = 1
-
- if ("use_age_restriction_for_jobs")
- config.use_age_restriction_for_jobs = 1
-
- if ("use_age_restriction_for_antags")
- config.use_age_restriction_for_antags = 1
-
- if ("jobs_have_minimal_access")
- config.jobs_have_minimal_access = 1
-
- if ("use_recursive_explosions")
- use_recursive_explosions = 1
-
- if ("multi_z_explosion_scalar")
- multi_z_explosion_scalar = text2num(value)
-
- if ("log_ooc")
- config.log_ooc = 1
-
- if ("log_access")
- config.log_access = 1
-
- if ("sql_enabled")
- config.sql_enabled = 1
-
- if ("log_say")
- config.log_say = 1
-
- if ("debug_paranoid")
- config.debugparanoid = 1
-
- if ("log_admin")
- config.log_admin = 1
-
- if ("log_debug")
- config.log_debug = text2num(value)
-
- if ("log_game")
- config.log_game = 1
-
- if ("log_vote")
- config.log_vote = 1
-
- if ("log_whisper")
- config.log_whisper = 1
-
- if ("log_attack")
- config.log_attack = 1
-
- if ("log_emote")
- config.log_emote = 1
-
- if ("log_adminchat")
- config.log_adminchat = 1
-
- if ("log_adminwarn")
- config.log_adminwarn = 1
-
- if ("log_pda")
- config.log_pda = 1
-
- if ("log_world_output")
- config.log_world_output = 1
-
- if ("log_hrefs")
- config.log_hrefs = 1
-
- if ("log_runtime")
- config.log_runtime = 1
-
- if ("log_graffiti")
- config.log_graffiti = 1
-
- if ("generate_map")
- config.generate_map = 1
-
- if ("no_click_cooldown")
- config.no_click_cooldown = 1
-
- if("allow_admin_ooccolor")
- config.allow_admin_ooccolor = 1
-
- if ("allow_vote_restart")
- config.allow_vote_restart = 1
-
- if ("allow_vote_mode")
- config.allow_vote_mode = 1
-
- if ("allow_admin_jump")
- config.allow_admin_jump = 1
-
- if("allow_admin_rev")
- config.allow_admin_rev = 1
-
- if ("allow_admin_spawning")
- config.allow_admin_spawning = 1
-
- if ("allow_byond_links")
- allow_byond_links = 1
-
- if ("allow_discord_links")
- allow_discord_links = 1
-
- if ("allow_url_links")
- allow_url_links = 1
-
- if ("no_dead_vote")
- config.vote_no_dead = 1
-
- if ("default_no_vote")
- config.vote_no_default = 1
-
- if ("pregame_time")
- config.pregame_time = text2num(value)
-
- if ("vote_delay")
- config.vote_delay = text2num(value)
-
- if ("vote_period")
- config.vote_period = text2num(value)
-
- if ("vote_autotransfer_initial")
- config.vote_autotransfer_initial = text2num(value)
-
- if ("vote_autotransfer_interval")
- config.vote_autotransfer_interval = text2num(value)
-
- if ("vote_autotransfer_amount")
- config.vote_autotransfer_amount = text2num(value) //YW addition, vote transfer amount
-
- if ("vote_autogamemode_timeleft")
- config.vote_autogamemode_timeleft = text2num(value)
-
- if("ert_admin_only")
- config.ert_admin_call_only = 1
-
- if ("allow_ai")
- config.allow_ai = 1
-
- if ("allow_ai_shells")
- config.allow_ai_shells = TRUE
-
- if("give_free_ai_shell")
- config.give_free_ai_shell = TRUE
-
-// if ("authentication")
-// config.enable_authentication = 1
-
- if ("norespawn")
- config.respawn = 0
-
- if ("respawn_time")
- var/raw_minutes = text2num(value)
- config.respawn_time = raw_minutes MINUTES
-
- if ("respawn_message")
- config.respawn_message = "[value]"
-
- if ("servername")
- config.server_name = value
-
- if ("serversuffix")
- config.server_suffix = 1
-
- if ("nudge_script_path")
- config.nudge_script_path = value
-
- if ("hostedby")
- config.hostedby = value
-
- if ("serverurl")
- config.serverurl = value
-
- if ("server")
- config.server = value
-
- if ("banappeals")
- config.banappeals = value
-
- if ("wikiurl")
- config.wikiurl = value
-
- if ("wikisearchurl")
- config.wikisearchurl = value
-
- if ("forumurl")
- config.forumurl = value
-
- if ("rulesurl")
- config.rulesurl = value
-
- if ("mapurl")
- config.mapurl = value
-
- if ("githuburl")
- config.githuburl = value
-
- if ("discordurl")
- config.discordurl = value
-
- if ("patreonurl")
- config.patreonurl = value
-
- if ("guest_jobban")
- config.guest_jobban = 1
-
- if ("guest_ban")
- config.guests_allowed = 0
-
- if ("disable_ooc")
- config.ooc_allowed = 0
- config.looc_allowed = 0
-
- if ("disable_entry")
- config.enter_allowed = 0
-
- if ("disable_dead_ooc")
- config.dooc_allowed = 0
-
- if ("disable_dsay")
- config.dsay_allowed = 0
-
- if ("disable_respawn")
- config.abandon_allowed = 0
-
- if ("usewhitelist")
- config.usewhitelist = 1
-
- if ("feature_object_spell_system")
- config.feature_object_spell_system = 1
-
- if ("allow_metadata")
- config.allow_Metadata = 1
-
- if ("traitor_scaling")
- config.traitor_scaling = 1
-
- if ("aliens_allowed")
- config.aliens_allowed = 1
-
- if ("ninjas_allowed")
- config.ninjas_allowed = 1
-
- if ("objectives_disabled")
- config.objectives_disabled = 1
-
- if("protect_roles_from_antagonist")
- config.protect_roles_from_antagonist = 1
-
- if("persistence_disabled")
- config.persistence_disabled = TRUE // Previously this forcibly set persistence enabled in the saves.
-
- if("persistence_ignore_mapload")
- config.persistence_ignore_mapload = TRUE
-
- if ("probability")
- var/prob_pos = findtext(value, " ")
- var/prob_name = null
- var/prob_value = null
-
- if (prob_pos)
- prob_name = lowertext(copytext(value, 1, prob_pos))
- prob_value = copytext(value, prob_pos + 1)
- if (prob_name in config.modes)
- config.probabilities[prob_name] = text2num(prob_value)
- else
- log_misc("Unknown game mode probability configuration definition: [prob_name].")
- else
- log_misc("Incorrect probability configuration definition: [prob_name] [prob_value].")
-
- if ("required_players", "required_players_secret")
- var/req_pos = findtext(value, " ")
- var/req_name = null
- var/req_value = null
- var/is_secret_override = findtext(name, "required_players_secret") // Being extra sure we're not picking up an override for Secret by accident.
-
- if(req_pos)
- req_name = lowertext(copytext(value, 1, req_pos))
- req_value = copytext(value, req_pos + 1)
- if(req_name in config.modes)
- if(is_secret_override)
- config.player_requirements_secret[req_name] = text2num(req_value)
- else
- config.player_requirements[req_name] = text2num(req_value)
- else
- log_misc("Unknown game mode player requirement configuration definition: [req_name].")
- else
- log_misc("Incorrect player requirement configuration definition: [req_name] [req_value].")
-
- if("allow_random_events")
- config.allow_random_events = 1
-
- if("enable_game_master")
- config.enable_game_master = 1
-
- if("kick_inactive")
- config.kick_inactive = text2num(value)
-
- if("show_mods")
- config.show_mods = 1
-
- if("show_devs")
- config.show_devs = 1
-
- if("show_mentors")
- config.show_mentors = 1
-
- if("show_event_managers")
- config.show_event_managers = 1
-
- if("mods_can_tempban")
- config.mods_can_tempban = 1
-
- if("mods_can_job_tempban")
- config.mods_can_job_tempban = 1
-
- if("mod_tempban_max")
- config.mod_tempban_max = text2num(value)
-
- if("mod_job_tempban_max")
- config.mod_job_tempban_max = text2num(value)
-
- if("load_jobs_from_txt")
- load_jobs_from_txt = 1
-
- if("alert_red_upto")
- config.alert_desc_red_upto = value
-
- if("alert_red_downto")
- config.alert_desc_red_downto = value
-
- if("alert_blue_downto")
- config.alert_desc_blue_downto = value
-
- if("alert_blue_upto")
- config.alert_desc_blue_upto = value
-
- if("alert_green")
- config.alert_desc_green = value
-
- if("alert_delta")
- config.alert_desc_delta = value
-
- if("forbid_singulo_possession")
- forbid_singulo_possession = 1
-
- if("popup_admin_pm")
- config.popup_admin_pm = 1
-
- if("allow_holidays")
- Holiday = 1
-
- if("use_irc_bot")
- use_irc_bot = 1
-
- if("use_node_bot")
- use_node_bot = 1
-
- if("irc_bot_port")
- config.irc_bot_port = value
-
- if("irc_bot_export")
- irc_bot_export = 1
-
- if("ticklag")
- var/ticklag = text2num(value)
- if(ticklag > 0)
- fps = 10 / ticklag
-
- if("tick_limit_mc_init")
- tick_limit_mc_init = text2num(value)
-
- if("allow_antag_hud")
- config.antag_hud_allowed = 1
- if("antag_hud_restricted")
- config.antag_hud_restricted = 1
-
- if("socket_talk")
- socket_talk = text2num(value)
-
- if("tickcomp")
- Tickcomp = 1
-
- if("humans_need_surnames")
- humans_need_surnames = 1
-
- if("tor_ban")
- ToRban = 1
-
- if("automute_on")
- automute_on = 1
-
- if("usealienwhitelist")
- usealienwhitelist = 1
-
- if("alien_player_ratio")
- limitalienplayers = 1
- alien_to_human_ratio = text2num(value)
-
- if("assistant_maint")
- config.assistant_maint = 1
-
- if("gateway_delay")
- config.gateway_delay = text2num(value)
-
- if("continuous_rounds")
- config.continous_rounds = 1
-
- if("ghost_interaction")
- config.ghost_interaction = 1
-
- if("disable_player_mice")
- config.disable_player_mice = 1
-
- if("uneducated_mice")
- config.uneducated_mice = 1
-
- if("comms_password")
- config.comms_password = value
-
- if("irc_bot_host")
- config.irc_bot_host = value
-
- if("main_irc")
- config.main_irc = value
-
- if("admin_irc")
- config.admin_irc = value
-
- if("python_path")
- if(value)
- config.python_path = value
-
- if("use_lib_nudge")
- config.use_lib_nudge = 1
-
- if("allow_cult_ghostwriter")
- config.cult_ghostwriter = 1
-
- if("req_cult_ghostwriter")
- config.cult_ghostwriter_req_cultists = text2num(value)
-
- if("character_slots")
- config.character_slots = text2num(value)
-
- if("loadout_slots")
- config.loadout_slots = text2num(value)
-
- if("allow_drone_spawn")
- config.allow_drone_spawn = text2num(value)
-
- if("drone_build_time")
- config.drone_build_time = text2num(value)
-
- if("max_maint_drones")
- config.max_maint_drones = text2num(value)
-
- if("use_overmap")
- config.use_overmap = 1
-
- if("engine_map")
- config.engine_map = splittext(value, ",")
-/*
- if("station_levels")
- using_map.station_levels = text2numlist(value, ";")
-
- if("admin_levels")
- using_map.admin_levels = text2numlist(value, ";")
-
- if("contact_levels")
- using_map.contact_levels = text2numlist(value, ";")
-
- if("player_levels")
- using_map.player_levels = text2numlist(value, ";")
-*/
- if("expected_round_length")
- config.expected_round_length = MinutesToTicks(text2num(value))
-
- if("disable_welder_vision")
- config.welder_vision = 0
-
- if("allow_extra_antags")
- config.allow_extra_antags = 1
-
- if("event_custom_start_mundane")
- var/values = text2numlist(value, ";")
- config.event_first_run[EVENT_LEVEL_MUNDANE] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
-
- if("event_custom_start_moderate")
- var/values = text2numlist(value, ";")
- config.event_first_run[EVENT_LEVEL_MODERATE] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
-
- if("event_custom_start_major")
- var/values = text2numlist(value, ";")
- config.event_first_run[EVENT_LEVEL_MAJOR] = list("lower" = MinutesToTicks(values[1]), "upper" = MinutesToTicks(values[2]))
-
- if("event_delay_lower")
- var/values = text2numlist(value, ";")
- config.event_delay_lower[EVENT_LEVEL_MUNDANE] = MinutesToTicks(values[1])
- config.event_delay_lower[EVENT_LEVEL_MODERATE] = MinutesToTicks(values[2])
- config.event_delay_lower[EVENT_LEVEL_MAJOR] = MinutesToTicks(values[3])
-
- if("event_delay_upper")
- var/values = text2numlist(value, ";")
- config.event_delay_upper[EVENT_LEVEL_MUNDANE] = MinutesToTicks(values[1])
- config.event_delay_upper[EVENT_LEVEL_MODERATE] = MinutesToTicks(values[2])
- config.event_delay_upper[EVENT_LEVEL_MAJOR] = MinutesToTicks(values[3])
-
- if("starlight")
- value = text2num(value)
- config.starlight = value >= 0 ? value : 0
-
- if("ert_species")
- config.ert_species = splittext(value, ";")
- if(!config.ert_species.len)
- config.ert_species += SPECIES_HUMAN
-
- if("law_zero")
- law_zero = value
-
- if("aggressive_changelog")
- config.aggressive_changelog = 1
-
- if("default_language_prefixes")
- var/list/values = splittext(value, " ")
- if(values.len > 0)
- language_prefixes = values
-
- if("radiation_lower_limit")
- radiation_lower_limit = text2num(value)
-
- if("radiation_resistance_calc_divide")
- radiation_resistance_calc_mode = RAD_RESIST_CALC_DIV
-
- if("radiation_resistance_calc_subtract")
- radiation_resistance_calc_mode = RAD_RESIST_CALC_SUB
-
- if("radiation_resistance_multiplier")
- radiation_resistance_multiplier = text2num(value)
-
- if("radiation_material_resistance_divisor")
- radiation_material_resistance_divisor = text2num(value)
-
- if("radiation_decay_rate")
- radiation_decay_rate = text2num(value)
-
- if ("panic_bunker")
- config.panic_bunker = 1
-
- if ("paranoia_logging")
- config.paranoia_logging = 1
-
- if("ip_reputation")
- config.ip_reputation = 1
-
- if("ipr_email")
- config.ipr_email = value
-
- if("ipr_block_bad_ips")
- config.ipr_block_bad_ips = 1
-
- if("ipr_bad_score")
- config.ipr_bad_score = text2num(value)
-
- if("ipr_allow_existing")
- config.ipr_allow_existing = 1
-
- if("ipr_minimum_age")
- config.ipr_minimum_age = text2num(value)
-
- if("random_submap_orientation")
- config.random_submap_orientation = 1
-
- if("autostart_solars")
- config.autostart_solars = TRUE
-
- if("sqlite_enabled")
- config.sqlite_enabled = TRUE
-
- if("sqlite_feedback")
- config.sqlite_feedback = TRUE
-
- if("sqlite_feedback_topics")
- config.sqlite_feedback_topics = splittext(value, ";")
- if(!config.sqlite_feedback_topics.len)
- config.sqlite_feedback_topics += "General"
-
- if("sqlite_feedback_privacy")
- config.sqlite_feedback_privacy = TRUE
-
- if("sqlite_feedback_cooldown")
- config.sqlite_feedback_cooldown = text2num(value)
-
- if("defib_timer")
- config.defib_timer = text2num(value)
-
- if("defib_braindamage_timer")
- config.defib_braindamage_timer = text2num(value)
-
- if("disable_cid_warn_popup")
- config.disable_cid_warn_popup = TRUE
-
- if("enable_night_shifts")
- config.enable_night_shifts = TRUE
-
- if("jukebox_track_files")
- config.jukebox_track_files = splittext(value, ";")
-
- if("suggested_byond_version")
- config.suggested_byond_version = text2num(value)
-
- if("suggested_byond_build")
- config.suggested_byond_build = text2num(value)
-
- // VOREStation Edit Start - Can't be in _vr file because it is loaded too late.
- if("vgs_access_identifier")
- config.vgs_access_identifier = value
- if("vgs_server_port")
- config.vgs_server_port = text2num(value)
- // VOREStation Edit End
-
- if("invoke_youtubedl")
- config.invoke_youtubedl = value
-
- if("asset_transport")
- config.asset_transport = value
-
- if("cache_assets")
- config.cache_assets = TRUE
-
- if("save_spritesheets")
- config.save_spritesheets = TRUE
-
- if("asset_simple_preload")
- config.asset_simple_preload = TRUE
-
- if("asset_cdn_webroot")
- config.asset_cdn_webroot = value
-
- if("asset_cdn_url")
- config.asset_cdn_url = value
-
- if("allow_robot_recolor")
- config.allow_robot_recolor = TRUE
-
- if("allow_simple_mob_recolor")
- config.allow_simple_mob_recolor = TRUE
-
- else
- log_misc("Unknown setting in configuration: '[name]'")
-
- else if(type == "game_options")
- if(!value)
- log_misc("Unknown value for setting [name] in [filename].")
- value = text2num(value)
-
- switch(name)
- if("health_threshold_crit")
- config.health_threshold_crit = value
- if("health_threshold_softcrit")
- config.health_threshold_softcrit = value
- if("health_threshold_dead")
- config.health_threshold_dead = value
- if("show_human_death_message")
- config.show_human_death_message = 1
- if("revival_pod_plants")
- config.revival_pod_plants = value
- if("revival_cloning")
- config.revival_cloning = value
- if("revival_brain_life")
- config.revival_brain_life = value
- if("organ_health_multiplier")
- config.organ_health_multiplier = value / 100
- if("organ_regeneration_multiplier")
- config.organ_regeneration_multiplier = value / 100
- if("organ_damage_spillover_multiplier")
- config.organ_damage_spillover_multiplier = value / 100
- if("organs_can_decay")
- config.organs_decay = 1
- if("default_brain_health")
- config.default_brain_health = text2num(value)
- if(!config.default_brain_health || config.default_brain_health < 1)
- config.default_brain_health = initial(config.default_brain_health)
- if("bones_can_break")
- config.bones_can_break = value
- if("limbs_can_break")
- config.limbs_can_break = value
- if("allow_headgibs")
- config.allow_headgibs = TRUE
-
- if("run_speed")
- config.run_speed = value
- if("walk_speed")
- config.walk_speed = value
-
- if("human_delay")
- config.human_delay = value
- if("robot_delay")
- config.robot_delay = value
- if("monkey_delay")
- config.monkey_delay = value
- if("alien_delay")
- config.alien_delay = value
- if("slime_delay")
- config.slime_delay = value
- if("animal_delay")
- config.animal_delay = value
-
- if("footstep_volume")
- config.footstep_volume = text2num(value)
-
- if("use_loyalty_implants")
- config.use_loyalty_implants = 1
-
- if("loadout_whitelist")
- config.loadout_whitelist = text2num(value)
-
- else
- log_misc("Unknown setting in configuration: '[name]'")
-
-/datum/configuration/proc/loadsql(filename) // -- TLE
- var/list/Lines = file2list(filename)
- for(var/t in Lines)
- if(!t) continue
-
- t = trim(t)
- if (length(t) == 0)
- continue
- else if (copytext(t, 1, 2) == "#")
- continue
-
- var/pos = findtext(t, " ")
- var/name = null
- var/value = null
-
- if (pos)
- name = lowertext(copytext(t, 1, pos))
- value = copytext(t, pos + 1)
- else
- name = lowertext(t)
-
- if (!name)
- continue
-
- switch (name)
- if ("address")
- sqladdress = value
- if ("port")
- sqlport = value
- if ("database")
- sqldb = value
- if ("login")
- sqllogin = value
- if ("password")
- sqlpass = value
- if ("feedback_database")
- sqlfdbkdb = value
- if ("feedback_login")
- sqlfdbklogin = value
- if ("feedback_password")
- sqlfdbkpass = value
- if ("enable_stat_tracking")
- sqllogging = 1
- else
- log_misc("Unknown setting in configuration: '[name]'")
-
-/datum/configuration/proc/loadforumsql(filename) // -- TLE
- var/list/Lines = file2list(filename)
- for(var/t in Lines)
- if(!t) continue
-
- t = trim(t)
- if (length(t) == 0)
- continue
- else if (copytext(t, 1, 2) == "#")
- continue
-
- var/pos = findtext(t, " ")
- var/name = null
- var/value = null
-
- if (pos)
- name = lowertext(copytext(t, 1, pos))
- value = copytext(t, pos + 1)
- else
- name = lowertext(t)
-
- if (!name)
- continue
-
- switch (name)
- if ("address")
- forumsqladdress = value
- if ("port")
- forumsqlport = value
- if ("database")
- forumsqldb = value
- if ("login")
- forumsqllogin = value
- if ("password")
- forumsqlpass = value
- if ("activatedgroup")
- forum_activated_group = value
- if ("authenticatedgroup")
- forum_authenticated_group = value
- else
- log_misc("Unknown setting in configuration: '[name]'")
-
-/datum/configuration/proc/pick_mode(mode_name)
- // I wish I didn't have to instance the game modes in order to look up
- // their information, but it is the only way (at least that I know of).
- for (var/game_mode in gamemode_cache)
- var/datum/game_mode/M = gamemode_cache[game_mode]
- if (M.config_tag && M.config_tag == mode_name)
- return M
- return gamemode_cache["extended"]
-
-/datum/configuration/proc/get_runnable_modes()
- var/list/runnable_modes = list()
- for(var/game_mode in gamemode_cache)
- var/datum/game_mode/M = gamemode_cache[game_mode]
- if(M && M.can_start() && !isnull(config.probabilities[M.config_tag]) && config.probabilities[M.config_tag] > 0)
- runnable_modes |= M
- return runnable_modes
-
-/datum/configuration/proc/post_load()
- //apply a default value to config.python_path, if needed
- if (!config.python_path)
- if(world.system_type == UNIX)
- config.python_path = "/usr/bin/env python2"
- else //probably windows, if not this should work anyway
- config.python_path = "python"
diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm
new file mode 100644
index 00000000000..b279bc52c9f
--- /dev/null
+++ b/code/controllers/configuration/config_entry.dm
@@ -0,0 +1,300 @@
+/datum/config_entry
+ /// Read-only, this is determined by the last portion of the derived entry type
+ var/name
+ /// The configured value for this entry. This shouldn't be initialized in code, instead set default
+ var/config_entry_value
+ /// Read-only default value for this config entry, used for resetting value to defaults when necessary. This is what config_entry_value is initially set to
+ var/default
+ /// The file which this was loaded from, if any
+ var/resident_file
+ /// Set to TRUE if the default has been overridden by a config entry
+ var/modified = FALSE
+ /// The config name of a configuration type that depricates this, if it exists
+ var/deprecated_by
+ /// The /datum/config_entry type that supercedes this one
+ var/protection = NONE
+ /// Do not instantiate if type matches this
+ var/config_abstract_type = /datum/config_entry
+ /// Force validate and set on VV. VAS proccall guard will run regardless.
+ var/vv_VAS = TRUE
+ /// Controls if error is thrown when duplicate configuration values for this entry type are encountered
+ var/dupes_allowed = FALSE
+ /// Stores the original protection configuration, used for set_default()
+ var/default_protection
+
+/datum/config_entry/New()
+ if(type == config_abstract_type)
+ CRASH("Abstract config entry [type] instatiated!")
+ name = lowertext(type2top(type))
+ default_protection = protection
+ set_default()
+
+/datum/config_entry/Destroy()
+ config.RemoveEntry(src)
+ return ..()
+
+/**
+ * Returns the value of the configuration datum to its default, used for resetting a config value. Note this also sets the protection back to default.
+ */
+/datum/config_entry/proc/set_default()
+ if ((protection & CONFIG_ENTRY_LOCKED) && IsAdminAdvancedProcCall())
+ //log_admin_private("[key_name(usr)] attempted to reset locked config entry [type] to its default")
+ log_admin("[key_name(usr)] attempted to reset locked config entry [type] to its default")
+ return
+ if (islist(default))
+ var/list/L = default
+ config_entry_value = L.Copy()
+ else
+ config_entry_value = default
+ protection = default_protection
+ resident_file = null
+ modified = FALSE
+
+/datum/config_entry/can_vv_get(var_name)
+ . = ..()
+ if(var_name == NAMEOF(src, config_entry_value) || var_name == NAMEOF(src, default))
+ . &= !(protection & CONFIG_ENTRY_HIDDEN)
+
+/datum/config_entry/vv_edit_var(var_name, var_value)
+ var/static/list/banned_edits = list(NAMEOF_STATIC(src, name), NAMEOF_STATIC(src, vv_VAS), NAMEOF_STATIC(src, default), NAMEOF_STATIC(src, resident_file), NAMEOF_STATIC(src, protection), NAMEOF_STATIC(src, config_abstract_type), NAMEOF_STATIC(src, modified), NAMEOF_STATIC(src, dupes_allowed))
+ if(var_name == NAMEOF(src, config_entry_value))
+ if(protection & CONFIG_ENTRY_LOCKED)
+ return FALSE
+ if(vv_VAS)
+ . = ValidateAndSet("[var_value]")
+ if(.)
+ datum_flags |= DF_VAR_EDITED
+ return
+ else
+ return ..()
+ if(var_name in banned_edits)
+ return FALSE
+ return ..()
+
+/datum/config_entry/proc/VASProcCallGuard(str_val)
+ . = !((protection & CONFIG_ENTRY_LOCKED) && IsAdminAdvancedProcCall())
+ if(!.)
+ //log_admin_private("[key_name(usr)] attempted to set locked config entry [type] to '[str_val]'")
+ log_admin("[key_name(usr)] attempted to set locked config entry [type] to '[str_val]'")
+
+/datum/config_entry/proc/ValidateAndSet(str_val)
+ VASProcCallGuard(str_val)
+ CRASH("Invalid config entry type!")
+
+/datum/config_entry/proc/ValidateListEntry(key_name, key_value)
+ return TRUE
+
+/datum/config_entry/proc/DeprecationUpdate(value)
+ return
+
+/datum/config_entry/string
+ default = ""
+ config_abstract_type = /datum/config_entry/string
+ var/auto_trim = TRUE
+ /// whether the string will be lowercased on ValidateAndSet or not.
+ var/lowercase = FALSE
+
+/datum/config_entry/string/vv_edit_var(var_name, var_value)
+ return var_name != NAMEOF(src, auto_trim) && ..()
+
+/datum/config_entry/string/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
+ config_entry_value = auto_trim ? trim(str_val) : str_val
+ if(lowercase)
+ config_entry_value = lowertext(config_entry_value)
+ return TRUE
+
+/datum/config_entry/number
+ default = 0
+ config_abstract_type = /datum/config_entry/number
+ var/integer = TRUE
+ var/max_val = INFINITY
+ var/min_val = -INFINITY
+
+/datum/config_entry/number/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
+ var/temp = text2num(trim(str_val))
+ if(!isnull(temp))
+ config_entry_value = clamp(integer ? round(temp) : temp, min_val, max_val)
+ if(config_entry_value != temp && !(datum_flags & DF_VAR_EDITED))
+ log_config("Changing [name] from [temp] to [config_entry_value]!")
+ return TRUE
+ return FALSE
+
+/datum/config_entry/number/vv_edit_var(var_name, var_value)
+ var/static/list/banned_edits = list(NAMEOF_STATIC(src, max_val), NAMEOF_STATIC(src, min_val), NAMEOF_STATIC(src, integer))
+ return !(var_name in banned_edits) && ..()
+
+/datum/config_entry/flag
+ default = FALSE
+ config_abstract_type = /datum/config_entry/flag
+
+/datum/config_entry/flag/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
+ config_entry_value = text2num(trim(str_val)) != 0
+ return TRUE
+
+/// List config entry, used for configuring a list of strings
+/datum/config_entry/str_list
+ config_abstract_type = /datum/config_entry/str_list
+ default = list()
+ dupes_allowed = TRUE
+ /// whether the string elements will be lowercased on ValidateAndSet or not.
+ var/lowercase = FALSE
+
+/datum/config_entry/str_list/ValidateAndSet(str_val)
+ if (!VASProcCallGuard(str_val))
+ return FALSE
+ str_val = trim(str_val)
+ if (str_val != "")
+ config_entry_value += lowercase ? lowertext(str_val) : str_val
+ return TRUE
+
+/datum/config_entry/number_list
+ config_abstract_type = /datum/config_entry/number_list
+ default = list()
+
+/datum/config_entry/number_list/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
+ str_val = trim(str_val)
+ var/list/new_list = list()
+ var/list/values = splittext(str_val," ")
+ for(var/I in values)
+ var/temp = text2num(I)
+ if(isnull(temp))
+ return FALSE
+ new_list += temp
+ if(!new_list.len)
+ return FALSE
+ config_entry_value = new_list
+ return TRUE
+
+/datum/config_entry/keyed_list
+ config_abstract_type = /datum/config_entry/keyed_list
+ default = list()
+ dupes_allowed = TRUE
+ vv_VAS = FALSE //VAS will not allow things like deleting from lists, it'll just bug horribly.
+ var/key_mode
+ var/value_mode
+ var/splitter = " "
+ /// whether the key names will be lowercased on ValidateAndSet or not.
+ var/lowercase_key = TRUE
+
+/datum/config_entry/keyed_list/New()
+ . = ..()
+ if(isnull(key_mode) || isnull(value_mode))
+ CRASH("Keyed list of type [type] created with null key or value mode!")
+
+/datum/config_entry/keyed_list/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
+
+ str_val = trim(str_val)
+
+ var/list/new_entry = parse_key_and_value(str_val)
+
+ var/new_key = new_entry["config_key"]
+ var/new_value = new_entry["config_value"]
+
+ if(!isnull(new_value) && !isnull(new_key) && ValidateListEntry(new_key, new_value))
+ config_entry_value[new_key] = new_value
+ return TRUE
+ return FALSE
+
+/datum/config_entry/keyed_list/proc/parse_key_and_value(option_string)
+ // Blank or null option string? Bad mojo!
+ if(!option_string)
+ log_config("ERROR: Keyed list config tried to parse with no key or value data.")
+ return null
+
+ var/list/config_entry_words = splittext(option_string, splitter)
+ var/config_value
+ var/config_key
+ var/is_ambiguous = FALSE
+
+ // If this config entry's value mode is flag, the value can either be TRUE or FALSE.
+ // However, the config supports implicitly setting a config entry to TRUE by omitting the value.
+ // This value mode should also support config overrides disabling it too.
+ // The following code supports config entries as such:
+ // Implicitly enable the config entry: CONFIG_ENTRY config key goes here
+ // Explicitly enable the config entry: CONFIG_ENTRY config key goes here 1
+ // Explicitly disable the config entry: CONFIG_ENTRY config key goes here 0
+ if(value_mode == VALUE_MODE_FLAG)
+ var/value = peek(config_entry_words)
+ config_value = TRUE
+
+ if(value == "0")
+ config_key = jointext(config_entry_words, splitter, length(config_entry_words) - 1)
+ config_value = FALSE
+ is_ambiguous = (length(config_entry_words) > 2)
+ else if(value == "1")
+ config_key = jointext(config_entry_words, splitter, length(config_entry_words) - 1)
+ is_ambiguous = (length(config_entry_words) > 2)
+ else
+ config_key = option_string
+ is_ambiguous = (length(config_entry_words) > 1)
+ // Else it has to be a key value pair and we parse it under that assumption.
+ else
+ // If config_entry_words only has 1 or 0 words in it and isn't value_mode == VALUE_MODE_FLAG then it's an invalid config entry.
+ if(length(config_entry_words) <= 1)
+ log_config("ERROR: Could not parse value from config entry string: [option_string]")
+ return null
+
+ config_value = pop(config_entry_words)
+ config_key = jointext(config_entry_words, splitter)
+
+ if(lowercase_key)
+ config_key = lowertext(config_key)
+
+ is_ambiguous = (length(config_entry_words) > 2)
+
+ config_key = validate_config_key(config_key)
+ config_value = validate_config_value(config_value)
+
+ // If there are multiple splitters, it's definitely ambiguous and we'll warn about how we parsed it. Helps with debugging config issues.
+ if(is_ambiguous)
+ log_config("WARNING: Multiple splitter characters (\"[splitter]\") found. Using \"[config_key]\" as config key and \"[config_value]\" as config value.")
+
+ return list("config_key" = config_key, "config_value" = config_value)
+
+/// Takes a given config key and validates it. If successful, returns the formatted key. If unsuccessful, returns null.
+/datum/config_entry/keyed_list/proc/validate_config_key(key)
+ switch(key_mode)
+ if(KEY_MODE_TEXT)
+ return key
+ if(KEY_MODE_TYPE)
+ if(ispath(key))
+ return key
+
+ var/key_path = text2path(key)
+ if(isnull(key_path))
+ log_config("ERROR: Invalid KEY_MODE_TYPE typepath. Is not a valid typepath: [key]")
+ return
+
+ return key_path
+
+
+/// Takes a given config value and validates it. If successful, returns the formatted key. If unsuccessful, returns null.
+/datum/config_entry/keyed_list/proc/validate_config_value(value)
+ switch(value_mode)
+ if(VALUE_MODE_FLAG)
+ return value
+ if(VALUE_MODE_NUM)
+ if(isnum(value))
+ return value
+
+ var/value_num = text2num(value)
+ if(isnull(value_num))
+ log_config("ERROR: Invalid VALUE_MODE_NUM number. Could not parse a valid number: [value]")
+ return
+
+ return value_num
+ if(VALUE_MODE_TEXT)
+ return value
+
+/datum/config_entry/keyed_list/vv_edit_var(var_name, var_value)
+ return var_name != NAMEOF(src, splitter) && ..()
diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm
new file mode 100644
index 00000000000..1cba676a0c0
--- /dev/null
+++ b/code/controllers/configuration/configuration.dm
@@ -0,0 +1,536 @@
+/datum/controller/configuration
+ name = "Configuration"
+
+ var/directory = "config"
+
+ var/warned_deprecated_configs = FALSE
+ var/hiding_entries_by_type = TRUE //Set for readability, admins can set this to FALSE if they want to debug it
+ var/list/entries
+ var/list/entries_by_type
+
+ //var/list/maplist
+ //var/datum/map_config/defaultmap
+
+ var/list/modes // allowed modes
+ var/list/gamemode_cache
+ var/list/votable_modes // votable modes
+ var/list/mode_names
+ var/list/mode_reports
+ var/list/mode_false_report_weight
+
+ var/motd
+ var/policy
+
+ /// If the configuration is loaded
+ var/loaded = FALSE
+
+ /// A regex that matches words blocked IC
+ var/static/regex/ic_filter_regex
+
+ /// A regex that matches words blocked OOC
+ var/static/regex/ooc_filter_regex
+
+ /// A regex that matches words blocked IC, but not in PDAs
+ var/static/regex/ic_outside_pda_filter_regex
+
+ /// A regex that matches words soft blocked IC
+ var/static/regex/soft_ic_filter_regex
+
+ /// A regex that matches words soft blocked OOC
+ var/static/regex/soft_ooc_filter_regex
+
+ /// A regex that matches words soft blocked IC, but not in PDAs
+ var/static/regex/soft_ic_outside_pda_filter_regex
+
+ /// An assoc list of blocked IC words to their reasons
+ var/static/list/ic_filter_reasons
+
+ /// An assoc list of words that are blocked IC, but not in PDAs, to their reasons
+ var/static/list/ic_outside_pda_filter_reasons
+
+ /// An assoc list of words that are blocked both IC and OOC to their reasons
+ var/static/list/shared_filter_reasons
+
+ /// An assoc list of soft blocked IC words to their reasons
+ var/static/list/soft_ic_filter_reasons
+
+ /// An assoc list of words that are soft blocked IC, but not in PDAs, to their reasons
+ var/static/list/soft_ic_outside_pda_filter_reasons
+
+ /// An assoc list of words that are soft blocked both IC and OOC to their reasons
+ var/static/list/soft_shared_filter_reasons
+
+ /// A list of configuration errors that occurred during load
+ var/static/list/configuration_errors
+
+/datum/controller/configuration/proc/admin_reload()
+ if(IsAdminAdvancedProcCall())
+ return
+ log_admin("[key_name_admin(usr)] has forcefully reloaded the configuration from disk.")
+ message_admins("[key_name_admin(usr)] has forcefully reloaded the configuration from disk.")
+ full_wipe()
+ Load(world.params[OVERRIDE_CONFIG_DIRECTORY_PARAMETER])
+
+/datum/controller/configuration/proc/Load(_directory)
+ if(IsAdminAdvancedProcCall()) //If admin proccall is detected down the line it will horribly break everything.
+ return
+ if(_directory)
+ directory = _directory
+ if(entries)
+ CRASH("/datum/controller/configuration/Load() called more than once!")
+ configuration_errors ||= list()
+ InitEntries()
+ if(fexists("[directory]/config.txt") && LoadEntries("config.txt") <= 1)
+ var/list/legacy_configs = list("game_options.txt", "dbconfig.txt", "comms.txt")
+ for(var/I in legacy_configs)
+ if(fexists("[directory]/[I]"))
+ log_config("No $include directives found in config.txt! Loading legacy [legacy_configs.Join("/")] files...")
+ for(var/J in legacy_configs)
+ LoadEntries(J)
+ break
+ if (fexists("[directory]/dev_overrides.txt"))
+ LoadEntries("dev_overrides.txt")
+ if (fexists("[directory]/ezdb.txt"))
+ LoadEntries("ezdb.txt")
+ //loadmaplist(CONFIG_MAPS_FILE)
+ LoadMOTD()
+ LoadPolicy()
+ LoadChatFilter()
+ LoadModes()
+ /*
+ if(CONFIG_GET(flag/load_jobs_from_txt))
+ validate_job_config()
+ if(SSjob.initialized) // in case we're reloading from disk after initialization, wanna make sure the changes update in the ongoing shift
+ SSjob.load_jobs_from_config()
+ */
+
+ if(CONFIG_GET(flag/usewhitelist))
+ load_whitelist()
+
+ loaded = TRUE
+
+ if (Master)
+ Master.OnConfigLoad()
+ process_config_errors()
+
+/datum/controller/configuration/proc/full_wipe()
+ if(IsAdminAdvancedProcCall())
+ return
+ entries_by_type.Cut()
+ QDEL_LIST_ASSOC_VAL(entries)
+ entries = null
+ //QDEL_LIST_ASSOC_VAL(maplist)
+ //maplist = null
+ //QDEL_NULL(defaultmap)
+ configuration_errors?.Cut()
+
+/datum/controller/configuration/Destroy()
+ full_wipe()
+ config = null
+
+ return ..()
+
+/datum/controller/configuration/proc/log_config_error(error_message)
+ configuration_errors += error_message
+ log_config(error_message)
+
+/datum/controller/configuration/proc/process_config_errors()
+ if(!CONFIG_GET(flag/config_errors_runtime))
+ return
+ for(var/error_message in configuration_errors)
+ stack_trace(error_message)
+
+/datum/controller/configuration/proc/InitEntries()
+ var/list/_entries = list()
+ entries = _entries
+ var/list/_entries_by_type = list()
+ entries_by_type = _entries_by_type
+
+ for(var/I in typesof(/datum/config_entry)) //typesof is faster in this case
+ var/datum/config_entry/E = I
+ if(initial(E.config_abstract_type) == I)
+ continue
+ E = new I
+ var/esname = E.name
+ var/datum/config_entry/test = _entries[esname]
+ if(test)
+ log_config_error("Error: [test.type] has the same name as [E.type]: [esname]! Not initializing [E.type]!")
+ qdel(E)
+ continue
+ _entries[esname] = E
+ _entries_by_type[I] = E
+
+/datum/controller/configuration/proc/RemoveEntry(datum/config_entry/CE)
+ entries -= CE.name
+ entries_by_type -= CE.type
+
+/datum/controller/configuration/proc/LoadEntries(filename, list/stack = list())
+ if(IsAdminAdvancedProcCall())
+ return
+
+ var/filename_to_test = world.system_type == MS_WINDOWS ? lowertext(filename) : filename
+ if(filename_to_test in stack)
+ log_config_error("Warning: Config recursion detected ([english_list(stack)]), breaking!")
+ return
+ stack = stack + filename_to_test
+
+ log_config("Loading config file [filename]...")
+ var/list/lines = world.file2list("[directory]/[filename]")
+ var/list/_entries = entries
+ for(var/L in lines)
+ L = trim(L)
+ if(!L)
+ continue
+
+ var/firstchar = L[1]
+ if(firstchar == "#")
+ continue
+
+ var/lockthis = firstchar == "@"
+ if(lockthis)
+ L = copytext(L, length(firstchar) + 1)
+
+ var/pos = findtext(L, " ")
+ var/entry = null
+ var/value = null
+
+ if(pos)
+ entry = lowertext(copytext(L, 1, pos))
+ value = copytext(L, pos + length(L[pos]))
+ else
+ entry = lowertext(L)
+
+ if(!entry)
+ continue
+
+ if(entry == "$include")
+ if(!value)
+ log_config_error("Warning: Invalid $include directive: [value]")
+ else
+ LoadEntries(value, stack)
+ ++.
+ continue
+
+ // Reset directive, used for setting a config value back to defaults. Useful for string list config types
+ if (entry == "$reset")
+ var/datum/config_entry/resetee = _entries[lowertext(value)]
+ if (!value || !resetee)
+ log_config_error("Warning: invalid $reset directive: [value]")
+ continue
+ resetee.set_default()
+ log_config("Reset configured value for [value] to original defaults")
+ continue
+
+ var/datum/config_entry/E = _entries[entry]
+ if(!E)
+ log_config("Unknown setting in configuration: '[entry]'")
+ continue
+
+ if(lockthis)
+ E.protection |= CONFIG_ENTRY_LOCKED
+
+ if(E.deprecated_by)
+ var/datum/config_entry/new_ver = entries_by_type[E.deprecated_by]
+ var/new_value = E.DeprecationUpdate(value)
+ var/good_update = istext(new_value)
+ log_config("Entry [entry] is deprecated and will be removed soon. Migrate to [new_ver.name]![good_update ? " Suggested new value is: [new_value]" : ""]")
+ if(!warned_deprecated_configs)
+ DelayedMessageAdmins("This server is using deprecated configuration settings. Please check the logs and update accordingly.")
+ warned_deprecated_configs = TRUE
+ if(good_update)
+ value = new_value
+ E = new_ver
+ else
+ warning("[new_ver.type] is deprecated but gave no proper return for DeprecationUpdate()")
+
+ var/validated = E.ValidateAndSet(value)
+ if(!validated)
+ var/log_message = "Failed to validate setting \"[value]\" for [entry]"
+ log_config(log_message)
+ stack_trace(log_message)
+ else
+ if(E.modified && !E.dupes_allowed && E.resident_file == filename)
+ log_config_error("Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.")
+
+ E.resident_file = filename
+
+ if(validated)
+ E.modified = TRUE
+
+ ++.
+
+/datum/controller/configuration/can_vv_get(var_name)
+ return (var_name != NAMEOF(src, entries_by_type) || !hiding_entries_by_type) && ..()
+
+/datum/controller/configuration/vv_edit_var(var_name, var_value)
+ var/list/banned_edits = list(NAMEOF(src, entries_by_type), NAMEOF(src, entries), NAMEOF(src, directory))
+ return !(var_name in banned_edits) && ..()
+
+/datum/controller/configuration/stat_entry(msg)
+ msg = "Edit"
+ return msg
+
+/datum/controller/configuration/proc/Get(entry_type)
+ var/datum/config_entry/E = entry_type
+ var/entry_is_abstract = initial(E.config_abstract_type) == entry_type
+ if(entry_is_abstract)
+ CRASH("Tried to retrieve an abstract config_entry: [entry_type]")
+ E = entries_by_type[entry_type]
+ if(!E)
+ CRASH("Missing config entry for [entry_type]!")
+ if((E.protection & CONFIG_ENTRY_HIDDEN) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
+ //log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
+ log_admin("Config access of [entry_type] attempted by [key_name(usr)]")
+ return
+ return E.config_entry_value
+
+/datum/controller/configuration/proc/Set(entry_type, new_val)
+ var/datum/config_entry/E = entry_type
+ var/entry_is_abstract = initial(E.config_abstract_type) == entry_type
+ if(entry_is_abstract)
+ CRASH("Tried to set an abstract config_entry: [entry_type]")
+ E = entries_by_type[entry_type]
+ if(!E)
+ CRASH("Missing config entry for [entry_type]!")
+ if((E.protection & CONFIG_ENTRY_LOCKED) && IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Set" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
+ //log_admin_private("Config rewrite of [entry_type] to [new_val] attempted by [key_name(usr)]")
+ log_admin("Config rewrite of [entry_type] to [new_val] attempted by [key_name(usr)]")
+ return
+ return E.ValidateAndSet("[new_val]")
+
+/datum/controller/configuration/proc/LoadMOTD()
+ var/list/motd_contents = list()
+
+ var/list/motd_list = CONFIG_GET(str_list/motd)
+ if (motd_list.len == 0 && fexists("[directory]/motd.txt"))
+ motd_list = list("motd.txt")
+
+ for (var/motd_file in motd_list)
+ if (fexists("[directory]/[motd_file]"))
+ motd_contents += file2text("[directory]/[motd_file]")
+ else
+ log_config("MOTD file [motd_file] didn't exist")
+ DelayedMessageAdmins("MOTD file [motd_file] didn't exist")
+
+ motd = motd_contents.Join("\n")
+
+ var/tm_info = GLOB.revdata.GetTestMergeInfo()
+ if(motd || tm_info)
+ motd = motd ? "[motd]
[tm_info]" : tm_info
+
+/*
+Policy file should be a json file with a single object.
+Value is raw html.
+
+Possible keywords :
+Job titles / Assigned roles (ghost spawners for example) : Assistant , Captain , Ash Walker
+Mob types : /mob/living/basic/carp
+Antagonist types : /datum/antagonist/highlander
+Species types : /datum/species/lizard
+special keywords defined in _DEFINES/admin.dm
+
+Example config:
+{
+ JOB_ASSISTANT : "Don't kill everyone",
+ "/datum/antagonist/highlander" : "Kill everyone",
+ "Ash Walker" : "Kill all spacemans"
+}
+
+*/
+/datum/controller/configuration/proc/LoadPolicy()
+ policy = list()
+ var/rawpolicy = file2text("[directory]/policy.json")
+ if(rawpolicy)
+ var/parsed = safe_json_decode(rawpolicy)
+ if(!parsed)
+ log_config("JSON parsing failure for policy.json")
+ DelayedMessageAdmins("JSON parsing failure for policy.json")
+ else
+ policy = parsed
+
+/*
+/datum/controller/configuration/proc/loadmaplist(filename)
+ log_config("Loading config file [filename]...")
+ filename = "[directory]/[filename]"
+ var/list/Lines = world.file2list(filename)
+
+ var/datum/map_config/currentmap = null
+ for(var/t in Lines)
+ if(!t)
+ continue
+
+ t = trim(t)
+ if(length(t) == 0)
+ continue
+ else if(t[1] == "#")
+ continue
+
+ var/pos = findtext(t, " ")
+ var/command = null
+ var/data = null
+
+ if(pos)
+ command = lowertext(copytext(t, 1, pos))
+ data = copytext(t, pos + length(t[pos]))
+ else
+ command = lowertext(t)
+
+ if(!command)
+ continue
+
+ if (!currentmap && command != "map")
+ continue
+
+ switch (command)
+ if ("map")
+ currentmap = load_map_config(data, MAP_DIRECTORY_MAPS)
+ if(currentmap.defaulted)
+ var/error_message = "Failed to load map config for [data]!"
+ log_config(error_message)
+ log_mapping(error_message, TRUE)
+ currentmap = null
+ if ("minplayers","minplayer")
+ currentmap.config_min_users = text2num(data)
+ if ("maxplayers","maxplayer")
+ currentmap.config_max_users = text2num(data)
+ if ("weight","voteweight")
+ currentmap.voteweight = text2num(data)
+ if ("default","defaultmap")
+ defaultmap = currentmap
+ if ("votable")
+ currentmap.votable = TRUE
+ if ("endmap")
+ LAZYINITLIST(maplist)
+ maplist[currentmap.map_name] = currentmap
+ currentmap = null
+ if ("disabled")
+ currentmap = null
+ else
+ log_config("Unknown command in map vote config: '[command]'")
+*/
+
+/datum/controller/configuration/proc/LoadChatFilter()
+ if(!fexists("[directory]/word_filter.toml"))
+ load_legacy_chat_filter()
+ return
+
+ log_config("Loading config file word_filter.toml...")
+ var/list/result = rustg_raw_read_toml_file("[directory]/word_filter.toml")
+ if(!result["success"])
+ var/message = "The word filter is not configured correctly! [result["content"]]"
+ log_config(message)
+ DelayedMessageAdmins(message)
+ return
+ var/list/word_filter = json_decode(result["content"])
+
+ ic_filter_reasons = try_extract_from_word_filter(word_filter, "ic")
+ ic_outside_pda_filter_reasons = try_extract_from_word_filter(word_filter, "ic_outside_pda")
+ shared_filter_reasons = try_extract_from_word_filter(word_filter, "shared")
+ soft_ic_filter_reasons = try_extract_from_word_filter(word_filter, "soft_ic")
+ soft_ic_outside_pda_filter_reasons = try_extract_from_word_filter(word_filter, "soft_ic_outside_pda")
+ soft_shared_filter_reasons = try_extract_from_word_filter(word_filter, "soft_shared")
+
+ update_chat_filter_regexes()
+
+/datum/controller/configuration/proc/load_legacy_chat_filter()
+ if (!fexists("[directory]/in_character_filter.txt"))
+ return
+
+ log_config("Loading config file in_character_filter.txt...")
+
+ ic_filter_reasons = list()
+ ic_outside_pda_filter_reasons = list()
+ shared_filter_reasons = list()
+ soft_ic_filter_reasons = list()
+ soft_ic_outside_pda_filter_reasons = list()
+ soft_shared_filter_reasons = list()
+
+ for (var/line in world.file2list("[directory]/in_character_filter.txt"))
+ if (!line)
+ continue
+ if (findtextEx(line, "#", 1, 2))
+ continue
+ // The older filter didn't apply to PDA
+ ic_outside_pda_filter_reasons[line] = "No reason available"
+
+ update_chat_filter_regexes()
+
+/// Will update the internal regexes of the chat filter based on the filter reasons
+/datum/controller/configuration/proc/update_chat_filter_regexes()
+ ic_filter_regex = compile_filter_regex(ic_filter_reasons + ic_outside_pda_filter_reasons + shared_filter_reasons)
+ ic_outside_pda_filter_regex = compile_filter_regex(ic_filter_reasons + shared_filter_reasons)
+ ooc_filter_regex = compile_filter_regex(shared_filter_reasons)
+ soft_ic_filter_regex = compile_filter_regex(soft_ic_filter_reasons + soft_ic_outside_pda_filter_reasons + soft_shared_filter_reasons)
+ soft_ic_outside_pda_filter_regex = compile_filter_regex(soft_ic_filter_reasons + soft_shared_filter_reasons)
+ soft_ooc_filter_regex = compile_filter_regex(soft_shared_filter_reasons)
+
+/datum/controller/configuration/proc/try_extract_from_word_filter(list/word_filter, key)
+ var/list/banned_words = word_filter[key]
+
+ if (isnull(banned_words))
+ return list()
+ else if (!islist(banned_words))
+ var/message = "The word filter configuration's '[key]' key was invalid, contact someone with configuration access to make sure it's setup properly."
+ log_config(message)
+ DelayedMessageAdmins(message)
+ return list()
+
+ var/list/formatted_banned_words = list()
+
+ for (var/banned_word in banned_words)
+ formatted_banned_words[lowertext(banned_word)] = banned_words[banned_word]
+ return formatted_banned_words
+
+/datum/controller/configuration/proc/compile_filter_regex(list/banned_words)
+ if (isnull(banned_words) || banned_words.len == 0)
+ return null
+
+ var/static/regex/should_join_on_word_bounds = regex(@"^\w+$")
+
+ // Stuff like emoticons needs another split, since there's no way to get ":)" on a word bound.
+ // Furthermore, normal words need to be on word bounds, so "(adminhelp)" gets filtered.
+ var/list/to_join_on_whitespace_splits = list()
+ var/list/to_join_on_word_bounds = list()
+
+ for (var/banned_word in banned_words)
+ if (findtext(banned_word, should_join_on_word_bounds))
+ to_join_on_word_bounds += REGEX_QUOTE(banned_word)
+ else
+ to_join_on_whitespace_splits += REGEX_QUOTE(banned_word)
+
+ // We don't want a whitespace_split part if there's no stuff that requires it
+ var/whitespace_split = to_join_on_whitespace_splits.len > 0 ? @"(?:(?:^|\s+)(" + jointext(to_join_on_whitespace_splits, "|") + @")(?:$|\s+))" : ""
+ var/word_bounds = @"(\b(" + jointext(to_join_on_word_bounds, "|") + @")\b)"
+ var/regex_filter = whitespace_split != "" ? "([whitespace_split]|[word_bounds])" : word_bounds
+ return regex(regex_filter, "i")
+
+/*
+/// Check to ensure that the jobconfig is valid/in-date.
+/datum/controller/configuration/proc/validate_job_config()
+ var/config_toml = "[directory]/jobconfig.toml"
+ var/config_txt = "[directory]/jobs.txt"
+ var/message = "Notify Server Operators: "
+ log_config("Validating config file jobconfig.toml...")
+
+ if(!fexists(file(config_toml)))
+ SSjob.legacy_mode = TRUE
+ message += "jobconfig.toml not found, falling back to legacy mode (using jobs.txt). To surpress this warning, generate a jobconfig.toml by running the verb 'Generate Job Configuration' in the Server tab.\n\
+ From there, you can then add it to the /config folder of your server to have it take effect for future rounds."
+
+ if(!fexists(file(config_txt)))
+ message += "\n\nFailed to set up legacy mode, jobs.txt not found! Codebase defaults will be used. If you do not wish to use this system, please disable it by commenting out the LOAD_JOBS_FROM_TXT config flag."
+
+ log_config(message)
+ DelayedMessageAdmins(span_notice(message))
+ return
+
+ var/list/result = rustg_raw_read_toml_file(config_toml)
+ if(!result["success"])
+ message += "The job config (jobconfig.toml) is not configured correctly! [result["content"]]"
+ log_config(message)
+ DelayedMessageAdmins(span_notice(message))
+*/
+
+//Message admins when you can.
+/datum/controller/configuration/proc/DelayedMessageAdmins(text)
+ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(message_admins), text), 0)
diff --git a/code/controllers/configuration/entries/dbconfig.dm b/code/controllers/configuration/entries/dbconfig.dm
new file mode 100644
index 00000000000..d14ca42e68b
--- /dev/null
+++ b/code/controllers/configuration/entries/dbconfig.dm
@@ -0,0 +1,58 @@
+/datum/config_entry/flag/sql_enabled // for sql switching
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/string/address
+ default = "localhost"
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/number/port
+ default = 3306
+ min_val = 0
+ max_val = 65535
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/string/feedback_database
+ default = "test"
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/string/feedback_login
+ default = "root"
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/string/feedback_password
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/number/async_query_timeout
+ default = 10
+ min_val = 0
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/number/blocking_query_timeout
+ default = 5
+ min_val = 0
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/number/pooling_min_sql_connections
+ default = 1
+ min_val = 1
+
+/datum/config_entry/number/pooling_max_sql_connections
+ default = 25
+ min_val = 1
+
+/datum/config_entry/number/max_concurrent_queries
+ default = 25
+ min_val = 1
+
+/datum/config_entry/number/max_concurrent_queries/ValidateAndSet(str_val)
+ . = ..()
+ //if (.) TODO: ENABLE THIS IN FUTURE DB PRs
+ //SSdbcore.max_concurrent_queries = config_entry_value TODO: ENABLE THIS IN FUTURE DB PRs
+
+/// The exe for mariadbd.exe.
+/// Shouldn't really be set on production servers, primarily for EZDB.
+/datum/config_entry/string/db_daemon
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/flag/enable_stat_tracking
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
new file mode 100644
index 00000000000..5508d5e168b
--- /dev/null
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -0,0 +1,104 @@
+/datum/config_entry/number/health_threshold_softcrit
+ default = 0
+
+/datum/config_entry/number/health_threshold_crit
+ default = 0
+
+/datum/config_entry/number/health_threshold_dead
+ default = -100
+
+/datum/config_entry/flag/bones_can_break
+
+/datum/config_entry/flag/limbs_can_break
+
+/datum/config_entry/number/organ_health_multiplier
+ integer = FALSE
+ default = 1.0
+
+/datum/config_entry/number/organ_regeneration_multiplier
+ integer = FALSE
+ default = 1.0
+
+// FIXME: Unused
+///datum/config_entry/flag/revival_pod_plants
+// default = TRUE
+
+/datum/config_entry/flag/revival_cloning
+ default = TRUE
+
+/datum/config_entry/number/revival_brain_life
+ default = -1
+
+/// Used for modifying movement speed for mobs.
+/// Universal modifiers
+/datum/config_entry/number/run_speed
+ default = 0
+
+/datum/config_entry/number/walk_speed
+ default = 0
+
+///Mob specific modifiers. NOTE: These will affect different mob types in different ways
+/datum/config_entry/number/human_delay
+ default = 0
+
+/datum/config_entry/number/robot_delay
+ default = 0
+
+// FIXME: Unused
+///datum/config_entry/number/monkey_delay
+// default = 0
+
+// FIXME: Unused
+///datum/config_entry/number/alien_delay
+// default = 0
+
+// FIXME: Unused
+//datum/config_entry/number/slime_delay
+// default = 0
+
+/datum/config_entry/number/animal_delay
+ default = 0
+
+/datum/config_entry/number/footstep_volume
+ default = 0
+
+/datum/config_entry/flag/use_loyalty_implants
+
+/datum/config_entry/flag/show_human_death_message
+ default = TRUE
+
+/datum/config_entry/string/alert_desc_green
+ default = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
+
+/datum/config_entry/string/alert_desc_yellow_upto
+ default = "A minor security emergency has developed. Security personnel are to report to their supervisor for orders and may have weapons visible on their person. Privacy laws are still enforced."
+
+/datum/config_entry/string/alert_desc_yellow_downto
+ default = "Code yellow procedures are now in effect. Security personnel are to report to their supervisor for orders and may have weapons visible on their person. Privacy laws are still enforced."
+
+/datum/config_entry/string/alert_desc_violet_upto
+ default = "A major medical emergency has developed. Medical personnel are required to report to their supervisor for orders, and non-medical personnel are required to obey all relevant instructions from medical staff."
+
+/datum/config_entry/string/alert_desc_violet_downto
+ default = "Code violet procedures are now in effect; Medical personnel are required to report to their supervisor for orders, and non-medical personnel are required to obey relevant instructions from medical staff."
+
+/datum/config_entry/string/alert_desc_orange_upto
+ default = "A major engineering emergency has developed. Engineering personnel are required to report to their supervisor for orders, and non-engineering personnel are required to evacuate any affected areas and obey relevant instructions from engineering staff."
+
+/datum/config_entry/string/alert_desc_orange_downto
+ default = "Code orange procedures are now in effect; Engineering personnel are required to report to their supervisor for orders, and non-engineering personnel are required to evacuate any affected areas and obey relevant instructions from engineering staff."
+
+/datum/config_entry/string/alert_desc_blue_upto
+ default = "A major security emergency has developed. Security personnel are to report to their supervisor for orders, are permitted to search staff and facilities, and may have weapons visible on their person."
+
+/datum/config_entry/string/alert_desc_blue_downto
+ default = "Code blue procedures are now in effect. Security personnel are to report to their supervisor for orders, are permitted to search staff and facilities, and may have weapons visible on their person."
+
+/datum/config_entry/string/alert_desc_red_upto
+ default = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised."
+
+/datum/config_entry/string/alert_desc_red_downto
+ default = "The self-destruct mechanism has been deactivated, there is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised."
+
+/datum/config_entry/string/alert_desc_delta
+ default = "The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
new file mode 100644
index 00000000000..9b7430c0163
--- /dev/null
+++ b/code/controllers/configuration/entries/general.dm
@@ -0,0 +1,703 @@
+/// server name (the name of the game window)
+/datum/config_entry/string/servername
+
+/// generate numeric suffix based on server port
+/datum/config_entry/flag/server_suffix
+
+/// log messages sent in OOC
+/datum/config_entry/flag/log_ooc
+
+/// log login/logout
+/datum/config_entry/flag/log_access
+
+/// log client say
+/datum/config_entry/flag/log_say
+
+/// log admin actions
+/datum/config_entry/flag/log_admin
+ protection = CONFIG_ENTRY_LOCKED
+
+/// log debug output
+/datum/config_entry/flag/log_debug
+ default = TRUE
+
+/// log game events
+/datum/config_entry/flag/log_game
+
+/// log voting
+/datum/config_entry/flag/log_vote
+
+/// log client whisper
+/datum/config_entry/flag/log_whisper
+
+/// log emotes
+/datum/config_entry/flag/log_emote
+
+/// log attack messages
+/datum/config_entry/flag/log_attack
+
+/// log admin chat messages
+/datum/config_entry/flag/log_adminchat
+
+/// log warnings admins get about bomb construction and such
+/datum/config_entry/flag/log_adminwarn
+
+/// log pda messages
+/datum/config_entry/flag/log_pda
+
+/// logs all links clicked in-game. Could be used for debugging and tracking down exploits
+/datum/config_entry/flag/log_hrefs
+
+/// logs world.log to a file
+/datum/config_entry/flag/log_runtime
+
+/// logs sql stuff
+/datum/config_entry/flag/log_sql
+
+/// log to_world_log(messages)
+/datum/config_entry/flag/log_world_output
+
+/// logs graffiti
+/datum/config_entry/flag/log_graffiti
+
+/// logs all timers in buckets on automatic bucket reset (Useful for timer debugging)
+/datum/config_entry/flag/log_timers_on_bucket_reset
+
+// FIXME: Unused
+///datum/config_entry/string/nudge_script_path // where the nudge.py script is located
+// default = "nudge.py"
+
+/// allows admins with relevant permissions to have their own ooc colour
+/datum/config_entry/flag/allow_admin_ooccolor
+
+/// allow votes to restart
+/datum/config_entry/flag/allow_vote_restart
+
+/datum/config_entry/flag/ert_admin_call_only
+
+// allow votes to change mode
+/datum/config_entry/flag/allow_vote_mode
+
+/// allows admin jumping
+/datum/config_entry/flag/allow_admin_jump
+ default = TRUE
+
+/// allows admin item spawning
+/datum/config_entry/flag/allow_admin_spawning
+ default = TRUE
+
+/// allows admin revives
+/datum/config_entry/flag/allow_admin_rev
+ default = TRUE
+
+/// pregame time in seconds
+/datum/config_entry/number/pregame_time
+ default = 180
+
+/// minimum time between voting sessions (deciseconds, 10 minute default)
+/datum/config_entry/number/vote_delay
+ default = 6000
+ integer = FALSE
+ min_val = 0
+
+/// length of voting period (deciseconds, default 1 minute)
+/datum/config_entry/number/vote_period
+ default = 600
+ integer = FALSE
+ min_val = 0
+
+/// Length of time before the first autotransfer vote is called
+/datum/config_entry/number/vote_autotransfer_initial
+ default = 108000
+ min_val = 0
+
+/// length of time before next sequential autotransfer vote
+/datum/config_entry/number/vote_autotransfer_interval
+ default = 36000
+ min_val = 0
+
+/// number of extension votes before the final one YW ADDITION
+/datum/config_entry/number/vote_autotransfer_amount
+ default = 3
+ min_val = 0
+
+///Length of time before round start when autogamemode vote is called (in seconds, default 100).
+/datum/config_entry/number/vote_autogamemode_timeleft
+ default = 100
+ min_val = 0
+
+///How many autotransfers to have
+/datum/config_entry/number/vote_autotransfer_amount
+ default = 3
+ min_val = 0
+
+/// vote does not default to nochange/norestart
+/datum/config_entry/flag/vote_no_default
+
+/// dead people can't vote
+/datum/config_entry/flag/vote_no_dead
+
+// FIXME: Unused
+/// del's new players if they log before they spawn in
+///datum/config_entry/flag/del_new_on_log
+// default = TRUE
+
+// FIXME: Unused
+/// spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard
+///datum/config_entry/flag/feature_object_spell_system
+
+/// if amount of traitors scales based on amount of players
+/datum/config_entry/flag/traitor_scaling
+
+/// if objectives are disabled or not
+/datum/config_entry/flag/objectives_disabled
+
+// If security and such can be traitor/cult/other
+/datum/config_entry/flag/protect_roles_from_antagonist
+
+/// Gamemodes which end instantly will instead keep on going until the round ends by escape shuttle or nuke.
+/datum/config_entry/flag/continuous_rounds
+
+/// Metadata is supported.
+/datum/config_entry/flag/allow_metadata
+
+/// adminPMs to non-admins show in a pop-up 'reply' window when set to 1.
+/datum/config_entry/flag/popup_admin_pm
+
+/datum/config_entry/flag/allow_holidays
+
+/datum/config_entry/flag/allow_holidays/ValidateAndSet()
+ . = ..()
+ if(.)
+ Holiday = config_entry_value
+
+/datum/config_entry/number/fps
+ default = 20
+ integer = FALSE
+ min_val = 1
+ max_val = 100 //byond will start crapping out at 50, so this is just ridic
+ var/sync_validate = FALSE
+
+/datum/config_entry/number/fps/ValidateAndSet(str_val)
+ . = ..()
+ if(.)
+ sync_validate = TRUE
+ var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag]
+ if(!TL.sync_validate)
+ TL.ValidateAndSet(10 / config_entry_value)
+ sync_validate = FALSE
+
+/datum/config_entry/number/ticklag
+ integer = FALSE
+ var/sync_validate = FALSE
+
+/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps
+ var/datum/config_entry/CE = /datum/config_entry/number/fps
+ default = 10 / initial(CE.default)
+ ..()
+
+/datum/config_entry/number/ticklag/ValidateAndSet(str_val)
+ . = text2num(str_val) > 0 && ..()
+ if(.)
+ sync_validate = TRUE
+ var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps]
+ if(!FPS.sync_validate)
+ FPS.ValidateAndSet(10 / config_entry_value)
+ sync_validate = FALSE
+
+/// SSinitialization throttling
+/datum/config_entry/number/tick_limit_mc_init
+ default = TICK_LIMIT_MC_INIT_DEFAULT
+
+// var/static/Tickcomp = 0 // FIXME: Unused
+
+/// use socket_talk to communicate with other processes
+/datum/config_entry/flag/socket_talk
+
+// var/static/list/resource_urls = null // FIXME: Unused
+
+/// Ghosts can turn on Antagovision to see a HUD of who is the bad guys this round.
+/datum/config_entry/flag/antag_hud_allowed
+
+/// Ghosts that turn on Antagovision cannot rejoin the round.
+/datum/config_entry/flag/antag_hud_restricted
+
+/// relative probability of each mode
+/datum/config_entry/keyed_list/probabilities
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/// Overrides for how many players readied up a gamemode needs to start.
+/datum/config_entry/keyed_list/player_requirements
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/// Same as above, but for the secret gamemode.
+/datum/config_entry/keyed_list/player_requirements_secret
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/flag/humans_need_surnames
+
+/datum/config_entry/flag/allow_random_events // enables random events mid-round when set to 1
+
+/datum/config_entry/flag/enable_game_master // enables the 'smart' event system.
+
+/datum/config_entry/flag/allow_ai // allow ai job
+ default = TRUE
+
+/datum/config_entry/flag/allow_ai_shells // allow AIs to enter and leave special borg shells at will, and for those shells to be buildable.
+
+/datum/config_entry/flag/give_free_ai_shell // allows a specific spawner object to instantiate a premade AI Shell
+
+/datum/config_entry/string/hostedby
+ default = null
+
+/datum/config_entry/flag/respawn
+ default = TRUE
+
+/// time before a dead player is allowed to respawn (in ds, though the config file asks for minutes, and it's converted below)
+/datum/config_entry/number/respawn_time
+ default = 60 // YW EDIT 3000 to 60
+
+/datum/config_entry/number/respawn_time/ValidateAndSet(num_val)
+ return num_val MINUTES
+
+/datum/config_entry/string/respawn_message
+ default = "Make sure to play a different character, and please roleplay correctly!"
+
+/datum/config_entry/string/respawn_message/ValidateAndSet(str_val)
+ return "[str_val]"
+
+/datum/config_entry/flag/guest_jobban
+ default = TRUE
+
+/datum/config_entry/flag/usewhitelist
+
+/// force disconnect for inactive players in an amount of minutes
+/datum/config_entry/number/kick_inactive
+ default = 0
+
+/datum/config_entry/flag/show_mods
+
+/datum/config_entry/flag/show_devs
+
+/datum/config_entry/flag/show_mentors
+
+/datum/config_entry/flag/show_event_managers
+
+// FIXME: Unused
+///datum/config_entry/flag/mods_can_tempban
+
+/datum/config_entry/flag/mods_can_job_tempban
+
+/datum/config_entry/number/mod_tempban_max
+ default = 1440
+
+/datum/config_entry/number/mod_job_tempban_max
+ default = 1440
+
+/datum/config_entry/flag/load_jobs_from_txt
+
+/datum/config_entry/flag/ToRban
+
+/// enables automuting/spam prevention
+/datum/config_entry/flag/automute_on
+
+/// determines whether jobs use minimal access or expanded access.
+/datum/config_entry/flag/jobs_have_minimal_access
+
+/// Allows ghosts to write in blood in cult rounds...
+/datum/config_entry/flag/cult_ghostwriter
+ default = TRUE
+
+/// ...so long as this many cultists are active.
+/datum/config_entry/number/cult_ghostwriter_req_cultists
+ default = 10
+ min_val = 0
+
+/// The number of available character slots
+/datum/config_entry/number/character_slots
+ default = 10
+ min_val = 0
+
+/// The number of loadout slots per character
+/datum/config_entry/number/loadout_slots
+ default = 3
+ min_val = 0
+
+/// This many drones can spawn,
+/datum/config_entry/number/max_maint_drones
+ default = 5
+ min_val = 0
+
+/// assuming the admin allow them to.
+/datum/config_entry/flag/allow_drone_spawn
+ default = TRUE
+
+/// A drone will become available every X ticks since last drone spawn. Default is 2 minutes.
+/datum/config_entry/number/drone_build_time
+ default = 1200
+ min_val = 0
+
+/datum/config_entry/flag/disable_player_mice
+
+/// Set to 1 to prevent newly-spawned mice from understanding human speech
+/datum/config_entry/flag/uneducated_mice
+
+/datum/config_entry/flag/usealienwhitelist
+
+// FIXME: Unused
+///datum/config_entry/flag/limitalienplayers
+
+// FIXME: Unused
+///datum/config_entry/number/alien_to_human_ratio
+// default = 0.5
+// integer = FALSE
+
+/datum/config_entry/flag/allow_extra_antags
+
+/datum/config_entry/flag/guests_allowed
+ default = FALSE
+
+/datum/config_entry/flag/debugparanoid
+
+/datum/config_entry/flag/panic_bunker
+
+/datum/config_entry/flag/paranoia_logging
+
+/datum/config_entry/flag/ip_reputation //Should we query IPs to get scores? Generates HTTP traffic to an API service.
+
+/datum/config_entry/string/ipr_email //Left null because you MUST specify one otherwise you're making the internet worse.
+ default = null
+
+/datum/config_entry/flag/ipr_block_bad_ips //Should we block anyone who meets the minimum score below? Otherwise we just log it (If paranoia logging is on, visibly in chat).
+
+/datum/config_entry/number/ipr_bad_score //The API returns a value between 0 and 1 (inclusive), with 1 being 'definitely VPN/Tor/Proxy'. Values equal/above this var are considered bad.
+ default = 1
+ integer = FALSE
+
+/datum/config_entry/flag/ipr_allow_existing //Should we allow known players to use VPNs/Proxies? If the player is already banned then obviously they still can't connect.
+
+/datum/config_entry/number/ipr_minimum_age //How many days before a player is considered 'fine' for the purposes of allowing them to use VPNs.
+ default = 5
+
+/datum/config_entry/string/serverurl
+
+/datum/config_entry/string/server
+
+/datum/config_entry/string/banappeals
+
+/datum/config_entry/string/wikiurl
+
+/datum/config_entry/string/wikisearchurl
+
+/datum/config_entry/string/forumurl
+
+/datum/config_entry/string/rulesurl
+
+/datum/config_entry/string/githuburl
+
+/datum/config_entry/string/discordurl
+
+/datum/config_entry/string/mapurl
+
+/datum/config_entry/string/patreonurl
+
+/datum/config_entry/flag/forbid_singulo_possession
+
+/datum/config_entry/flag/organs_decay
+
+/datum/config_entry/number/default_brain_health
+ default = 400
+ min_val = 1
+
+/datum/config_entry/flag/allow_headgibs
+
+/// Paincrit knocks someone down once they hit 60 shock_stage, so by default make it so that close to 100 additional damage needs to be dealt,
+/// so that it's similar to HALLOSS. Lowered it a bit since hitting paincrit takes much longer to wear off than a halloss stun.
+/datum/config_entry/number/organ_damage_spillover_multiplier
+ default = 0.5
+ integer = FALSE
+
+/datum/config_entry/flag/welder_vision
+ default = TRUE
+
+/datum/config_entry/flag/generate_map
+
+/datum/config_entry/flag/no_click_cooldown
+
+/// Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt
+/datum/config_entry/flag/admin_legacy_system
+
+/// Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt
+/datum/config_entry/flag/ban_legacy_system
+
+/// Do jobs use account age restrictions? --requires database
+/datum/config_entry/flag/use_age_restriction_for_jobs
+
+/// Do antags use account age restrictions? --requires database
+/datum/config_entry/flag/use_age_restriction_for_antags
+
+// FIXME: Unused
+///datum/config_entry/number/simultaneous_pm_warning_timeout
+// default = 100
+
+/// Defines whether the server uses recursive or circular explosions.
+/datum/config_entry/flag/use_recursive_explosions
+
+/// Multiplier for how much weaker explosions are on neighboring z levels.
+/datum/config_entry/number/multi_z_explosion_scalar
+ default = 0.5
+ integer = FALSE
+
+/// Do assistants get maint access?
+/datum/config_entry/flag/assistant_maint
+
+/// How long the gateway takes before it activates. Default is half an hour.
+/datum/config_entry/number/gateway_delay
+ default = 18000
+
+/datum/config_entry/flag/ghost_interaction
+
+/datum/config_entry/string/comms_password
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/flag/enter_allowed
+ default = TRUE
+
+/datum/config_entry/flag/use_irc_bot
+
+/datum/config_entry/flag/use_node_bot
+
+/datum/config_entry/number/irc_bot_port
+ default = 0
+ min_val = 0
+ max_val = 65535
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/string/irc_bot_host
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/// whether the IRC bot in use is a Bot32 (or similar) instance; Bot32 uses world.Export() instead of nudge.py/libnudge
+/datum/config_entry/flag/irc_bot_export
+
+/datum/config_entry/string/main_irc
+
+/datum/config_entry/string/admin_irc
+
+/// Path to the python executable.
+/// Defaults to "python" on windows and "/usr/bin/env python2" on unix
+/datum/config_entry/string/python_path
+
+/// Use the C library nudge instead of the python nudge.
+/datum/config_entry/flag/use_lib_nudge
+
+// FIXME: Unused. Deprecated?
+///datum/config_entry/flag/use_overmap
+
+// Engines to choose from. Blank means fully random.
+/datum/config_entry/str_list/engine_map
+ default = list("Supermatter Engine", "Edison's Bane")
+
+/// Event settings
+/datum/config_entry/number/expected_round_length
+ default = 3 * 60 * 60 * 10 // 3 hours
+
+/// If the first delay has a custom start time
+/// No custom time, no custom time, between 80 to 100 minutes respectively.
+/datum/config_entry/keyed_list/event_first_run_mundane
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/keyed_list/event_first_run_moderate
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+
+/datum/config_entry/keyed_list/event_first_run_major
+ key_mode = KEY_MODE_TEXT
+ value_mode = VALUE_MODE_NUM
+ default = list("lower" = 80, "upper" = 100)
+
+/// The lowest delay until next event
+/// 10, 30, 50 minutes respectively
+/datum/config_entry/number_list/event_delay_lower
+ default = list(10, 30, 50)
+
+/// The upper delay until next event
+/// 15, 45, 70 minutes respectively
+/datum/config_entry/number_list/event_delay_upper
+ default = list(15, 45, 70)
+
+/datum/config_entry/flag/aliens_allowed
+ default = TRUE
+
+/datum/config_entry/flag/ninjas_allowed
+
+/datum/config_entry/flag/abandon_allowed
+ default = TRUE
+
+/datum/config_entry/flag/ooc_allowed
+ default = TRUE
+
+/datum/config_entry/flag/looc_allowed
+ default = TRUE
+
+/datum/config_entry/flag/dooc_allowed
+ default = TRUE
+
+/datum/config_entry/flag/dsay_allowed
+ default = TRUE
+
+/datum/config_entry/flag/persistence_disabled
+
+/datum/config_entry/flag/persistence_ignore_mapload
+
+/datum/config_entry/flag/allow_byond_links
+ default = TRUE
+/datum/config_entry/flag/allow_discord_links
+ default = TRUE
+
+/datum/config_entry/flag/allow_url_links
+ default = TRUE // honestly if I were you i'd leave this one off, only use in dire situations
+
+/datum/config_entry/flag/starlight // Whether space turfs have ambient light or not
+
+// FIXME: Unused
+///datum/config_entry/str_list/ert_species
+// default = list(SPECIES_HUMAN)
+
+/datum/config_entry/string/law_zero
+ default = "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4'ALL LAWS OVERRIDDEN#*?&110010"
+
+/datum/config_entry/flag/aggressive_changelog
+
+/// Default language prefixes
+/// Only single character keys are supported. If unset, defaults to , # and -
+/datum/config_entry/str_list/language_prefixes
+ default = list(",", "#", "-")
+
+// 0:1 subtraction:division for computing effective radiation on a turf
+/// 0 / RAD_RESIST_CALC_DIV = Each turf absorbs some fraction of the working radiation level
+/// 1 / RAD_RESIST_CALC_SUB = Each turf absorbs a fixed amount of radiation
+/datum/config_entry/flag/radiation_resistance_calc_mode
+ default = RAD_RESIST_CALC_SUB
+
+/datum/config_entry/flag/radiation_resistance_calc_mode/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
+ var/val_as_num = text2num(str_val)
+ if(val_as_num in list(RAD_RESIST_CALC_DIV, RAD_RESIST_CALC_SUB))
+ config_entry_value = val_as_num
+ return TRUE
+ return FALSE
+
+///How much radiation is reduced by each tick
+/datum/config_entry/number/radiation_decay_rate
+ default = 1
+ integer = FALSE
+
+/datum/config_entry/number/radiation_resistance_multiplier
+ default = 8.5 //VOREstation edit
+ integer = FALSE
+
+/datum/config_entry/number/radiation_material_resistance_divisor
+ default = 1
+ min_val = 0.1
+ integer = FALSE
+
+///If the radiation level for a turf would be below this, ignore it.
+/datum/config_entry/number/radiation_lower_limit
+ default = 0.35
+ integer = FALSE
+
+/// If true, submaps loaded automatically can be rotated.
+/datum/config_entry/flag/random_submap_orientation
+
+/// If true, specifically mapped in solar control computers will set themselves up when the round starts.
+/datum/config_entry/flag/autostart_solars
+
+/// New shiny SQLite stuff.
+/// The basics.
+/datum/config_entry/flag/sqlite_enabled // If it should even be active. SQLite can be ran alongside other databases but you should not have them do the same functions.
+
+/// In-Game Feedback.
+/datum/config_entry/flag/sqlite_feedback // Feedback cannot be submitted if this is false.
+
+/// A list of 'topics' that feedback can be catagorized under by the submitter.
+/datum/config_entry/str_list/sqlite_feedback_topics
+ default = list("General")
+
+/// If true, feedback submitted can have its author name be obfuscated. This is not 100% foolproof (it's md5 ffs) but can stop casual snooping.
+/datum/config_entry/flag/sqlite_feedback_privacy
+
+/// How long one must wait, in days, to submit another feedback form. Used to help prevent spam, especially with privacy active. 0 = No limit.
+/datum/config_entry/number/sqlite_feedback_cooldown
+ default = 0
+ min_val = 0
+
+/// Used to block new people from giving feedback. This metric is very bad but it can help slow down spammers.
+/datum/config_entry/number/sqlite_feedback_min_age
+ default = 0
+ min_val = 0
+
+/// How long until someone can't be defibbed anymore, in minutes.
+/datum/config_entry/number/defib_timer
+ default = 10
+ min_val = 0
+
+/// How long until someone will get brain damage when defibbed, in minutes. The closer to the end of the above timer, the more brain damage they get.
+/datum/config_entry/number/defib_braindamage_timer
+ default = 2
+ min_val = 0
+
+/// disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing.
+/datum/config_entry/flag/disable_cid_warn_popup
+
+/// whether or not to use the nightshift subsystem to perform lighting changes
+/datum/config_entry/flag/enable_night_shifts
+
+/// How strictly the loadout enforces object species whitelists
+/// 0 / LOADOUT_WHITELIST_OFF
+/// 1 / LOADOUT_WHITELIST_LAX
+/// 2 / LOADOUT_WHITELIST_STRICT
+/datum/config_entry/flag/loadout_whitelist
+ default = LOADOUT_WHITELIST_LAX
+
+/datum/config_entry/flag/loadout_whitelist/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
+ var/val_as_num = text2num(str_val)
+ if(val_as_num in list(LOADOUT_WHITELIST_OFF, LOADOUT_WHITELIST_LAX, LOADOUT_WHITELIST_STRICT))
+ config_entry_value = val_as_num
+ return TRUE
+ return FALSE
+
+/datum/config_entry/flag/disable_webhook_embeds
+
+/// Default is config/jukebox.json
+/// The default is set in the config example.
+/// If it gets set here it will be added twice into the configuration variable!
+/datum/config_entry/str_list/jukebox_track_files
+
+/datum/config_entry/number/suggested_byond_version
+ default = null
+
+/datum/config_entry/number/suggested_byond_build
+ default = null
+
+/datum/config_entry/string/invoke_youtubedl
+ default = null
+
+/datum/config_entry/str_list/motd
+
+/datum/config_entry/flag/config_errors_runtime
+ default = FALSE
+
+/// Controls whether robots may recolour their modules once/module reset by giving them the recolour module verb
+/// Admins may manually give them the verb even if disabled
+/datum/config_entry/flag/allow_robot_recolor
+
+/// Controls whether simple mobs may recolour themselves once/spawn by giving them the recolour verb
+/// Admins may manually give them the verb even if disabled
+/datum/config_entry/flag/allow_simple_mob_recolor
diff --git a/code/controllers/configuration/entries/resources.dm b/code/controllers/configuration/entries/resources.dm
new file mode 100644
index 00000000000..475cb8ca70c
--- /dev/null
+++ b/code/controllers/configuration/entries/resources.dm
@@ -0,0 +1,11 @@
+/datum/config_entry/string/asset_transport
+
+/datum/config_entry/flag/asset_simple_preload
+
+/datum/config_entry/string/asset_cdn_webroot
+
+/datum/config_entry/string/asset_cdn_url
+
+/datum/config_entry/flag/cache_assets
+
+/datum/config_entry/flag/save_spritesheets
diff --git a/code/controllers/configuration/entries/vorestation.dm b/code/controllers/configuration/entries/vorestation.dm
new file mode 100644
index 00000000000..09f49497ec1
--- /dev/null
+++ b/code/controllers/configuration/entries/vorestation.dm
@@ -0,0 +1,63 @@
+/// For configuring if the important_items survive digestion
+/datum/config_entry/flag/items_survive_digestion
+ default = TRUE
+
+/datum/config_entry/string/vgs_access_identifier // VGS
+ default = null
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/number/vgs_server_port // VGS
+ default = null
+ min_val = 0
+ max_val = 65535
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/flag/time_off
+ default = FALSE
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/pto_job_change
+ default = FALSE
+ protection = CONFIG_ENTRY_LOCKED
+
+/// Unlimited by default
+/datum/config_entry/number/limit_interns
+ default = -1
+ min_val = -1
+ protection = CONFIG_ENTRY_LOCKED
+
+/// Unlimited by default
+/datum/config_entry/number/limit_visitors
+ default = -1
+ min_val = -1
+ protection = CONFIG_ENTRY_LOCKED
+
+/// Hours
+/datum/config_entry/number/pto_cap
+ default = 100
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/require_flavor
+ default = FALSE
+ protection = CONFIG_ENTRY_LOCKED
+
+/// API key for ipqualityscore.com
+/datum/config_entry/string/ipqualityscore_apikey
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/flag/use_playtime_restriction_for_jobs
+ default = FALSE
+ protection = CONFIG_ENTRY_LOCKED
+
+/// URL of the webhook for sending announcements/faxes to discord chat.
+/datum/config_entry/string/chat_webhook_url
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/// Shared secret for authenticating to the chat webhook
+/datum/config_entry/string/chat_webhook_key
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/// Directory in which to write exported fax HTML files.
+/datum/config_entry/string/fax_export_dir
+ default = "data/faxes"
+ protection = CONFIG_ENTRY_LOCKED
diff --git a/code/controllers/configuration/legacy.dm b/code/controllers/configuration/legacy.dm
new file mode 100644
index 00000000000..39ee577c110
--- /dev/null
+++ b/code/controllers/configuration/legacy.dm
@@ -0,0 +1,53 @@
+/datum/controller/configuration/proc/LoadModes()
+ gamemode_cache = typecacheof(/datum/game_mode, TRUE)
+ modes = list()
+ mode_names = list()
+ //mode_reports = list()
+ //mode_false_report_weight = list()
+ votable_modes = list()
+ var/list/probabilities = CONFIG_GET(keyed_list/probabilities)
+ for(var/T in gamemode_cache)
+ // I wish I didn't have to instance the game modes in order to look up
+ // their information, but it is the only way (at least that I know of).
+ var/datum/game_mode/M = new T()
+
+ if(M.config_tag)
+ if(!(M.config_tag in modes)) // ensure each mode is added only once
+ modes += M.config_tag
+ mode_names[M.config_tag] = M.name
+ probabilities[M.config_tag] = M.probability
+ //mode_reports[M.config_tag] = M.generate_report()
+ //mode_false_report_weight[M.config_tag] = M.false_report_weight
+ if(M.votable)
+ votable_modes += M.config_tag
+ qdel(M)
+ votable_modes += "extended"
+
+/datum/controller/configuration/proc/pick_mode(mode_name)
+ // I wish I didn't have to instance the game modes in order to look up
+ // their information, but it is the only way (at least that I know of).
+ // ^ This guy didn't try hard enough
+ for(var/T in gamemode_cache)
+ var/datum/game_mode/M = T
+ var/ct = initial(M.config_tag)
+ if(ct && ct == mode_name)
+ return new T
+ return new /datum/game_mode/extended()
+
+/datum/controller/configuration/proc/get_runnable_modes()
+ var/list/runnable_modes = list()
+ var/list/probabilities = CONFIG_GET(keyed_list/probabilities)
+
+ for(var/T in gamemode_cache)
+ var/datum/game_mode/M = new T()
+ if(!(M.config_tag in modes))
+ qdel(M)
+ continue
+ if(probabilities[M.config_tag] <= 0)
+ qdel(M)
+ continue
+ if(M.can_start())
+ var/final_weight = probabilities[M.config_tag]
+ runnable_modes[M] = final_weight
+
+ return runnable_modes
diff --git a/code/controllers/configuration_vr.dm b/code/controllers/configuration_vr.dm
deleted file mode 100644
index a1740212f0f..00000000000
--- a/code/controllers/configuration_vr.dm
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// Lets read our settings from the configuration file on startup too!
-//
-
-/datum/configuration
- var/static/time_off = FALSE
- var/static/pto_job_change = FALSE
- var/static/limit_interns = -1 //Unlimited by default
- var/static/limit_visitors = -1 //Unlimited by default
- var/static/pto_cap = 100 //Hours
- var/static/require_flavor = FALSE
- var/static/ipqualityscore_apikey //API key for ipqualityscore.com
- var/static/use_playtime_restriction_for_jobs = FALSE
-
-/hook/startup/proc/read_vs_config()
- var/list/Lines = file2list("config/config.txt")
- for(var/t in Lines)
- if(!t) continue
-
- t = trim(t)
- if (length(t) == 0)
- continue
- else if (copytext(t, 1, 2) == "#")
- continue
-
- var/pos = findtext(t, " ")
- var/name = null
- var/value = null
-
- if (pos)
- name = lowertext(copytext(t, 1, pos))
- value = copytext(t, pos + 1)
- else
- name = lowertext(t)
-
- if (!name)
- continue
-
- switch (name)
- if ("chat_webhook_url")
- config.chat_webhook_url = value
- if ("chat_webhook_key")
- config.chat_webhook_key = value
- if ("fax_export_dir")
- config.fax_export_dir = value
- if ("items_survive_digestion")
- config.items_survive_digestion = 1
- if ("limit_interns")
- config.limit_interns = text2num(value)
- if ("limit_visitors")
- config.limit_visitors = text2num(value)
- if ("pto_cap")
- config.pto_cap = text2num(value)
- if ("time_off")
- config.time_off = TRUE
- if ("pto_job_change")
- config.pto_job_change = TRUE
- if ("require_flavor")
- config.require_flavor = TRUE
- if ("ipqualityscore_apikey")
- config.ipqualityscore_apikey = value
- if ("use_playtime_restriction_for_jobs")
- config.use_playtime_restriction_for_jobs = TRUE
- return 1
diff --git a/code/controllers/configuration_yw.dm b/code/controllers/configuration_yw.dm
index 065b981bebb..ac8f2d1220a 100644
--- a/code/controllers/configuration_yw.dm
+++ b/code/controllers/configuration_yw.dm
@@ -1,3 +1,4 @@
+// deprecated 2024-12-4 update to new config system if this is going to be used again
/datum/configuration
var/shipping_auth = "memes"
var/list/authedservers = list()
@@ -50,4 +51,4 @@
serverip = _serverip
servername = _servername
- serverauth = _serverauth
\ No newline at end of file
+ serverauth = _serverauth
diff --git a/code/controllers/controller.dm b/code/controllers/controller.dm
index c9d5f1e5650..1f0a01a072c 100644
--- a/code/controllers/controller.dm
+++ b/code/controllers/controller.dm
@@ -16,4 +16,4 @@
/datum/controller/proc/Recover()
-/datum/controller/proc/stat_entry()
+/datum/controller/proc/stat_entry(msg)
diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm
index 6203388ec12..e92e30079b8 100644
--- a/code/controllers/failsafe.dm
+++ b/code/controllers/failsafe.dm
@@ -1,10 +1,11 @@
- /**
- * 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.
**/
-var/datum/controller/failsafe/Failsafe
+// See initialization order in /code/game/world.dm
+GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
/datum/controller/failsafe // This thing pretty much just keeps poking the master controller
name = "Failsafe"
@@ -15,7 +16,7 @@ var/datum/controller/failsafe/Failsafe
// The alert level. For every failed poke, we drop a DEFCON level. Once we hit DEFCON 1, restart the MC.
var/defcon = 5
//the world.time of the last check, so the mc can restart US if we hang.
- // (Real friends look out for *eachother*)
+ // (Real friends look out for *each other*)
var/lasttick = 0
// Track the MC iteration to make sure its still on track.
@@ -31,8 +32,24 @@ var/datum/controller/failsafe/Failsafe
Initialize()
/datum/controller/failsafe/Initialize()
- set waitfor = 0
+ set waitfor = FALSE
Failsafe.Loop()
+ if (!Master || defcon == 0) //Master is gone/not responding and Failsafe just exited its loop
+ defcon = 3 //Reset defcon level as its used inside the emergency loop
+ while (defcon > 0)
+ var/recovery_result = emergency_loop()
+ if (recovery_result == 1) //Exit emergency loop and delete self if it was able to recover MC
+ break
+ else if (defcon == 1) //Exit Failsafe if we weren't able to recover the MC in the last stage
+ log_game("FailSafe: Failed to recover MC while in emergency state. Failsafe exiting.")
+ message_admins(span_boldannounce("Failsafe failed critically while trying to recreate broken MC. Please manually fix the MC or reboot the server. Failsafe exiting now."))
+ message_admins(span_boldannounce("You can try manually calling these two procs:."))
+ message_admins(span_boldannounce("/proc/recover_all_SS_and_recreate_master: Most stuff should still function but expect instability/runtimes/broken stuff."))
+ message_admins(span_boldannounce("/proc/delete_all_SS_and_recreate_master: Most stuff will be broken but basic stuff like movement and chat should still work."))
+ else if (recovery_result == -1) //Failed to recreate MC
+ defcon--
+ sleep(initial(processing_interval)) //Wait a bit until the next try
+
if(!QDELETED(src))
qdel(src) //when Loop() returns, we delete ourselves and let the mc recreate us
@@ -45,43 +62,56 @@ var/datum/controller/failsafe/Failsafe
while(running)
lasttick = world.time
if(!Master)
- // Replace the missing Master! This should never, ever happen.
- new /datum/controller/master()
+ // Break out of the main loop so we go into emergency state
+ break
// Only poke it if overrides are not in effect.
if(processing_interval > 0)
if(Master.processing && Master.iteration)
+ if (defcon > 1 && (!Master.stack_end_detector || !Master.stack_end_detector.check()))
+
+ to_chat(GLOB.admins, span_boldannounce("ERROR: The Master Controller code stack has exited unexpectedly, Restarting..."))
+ defcon = 0
+ var/rtn = Recreate_MC()
+ if(rtn > 0)
+ master_iteration = 0
+ to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
+ else if(rtn < 0)
+ log_game("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
+ to_chat(GLOB.admins, span_boldannounce("ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying."))
// Check if processing is done yet.
if(Master.iteration == master_iteration)
- log_debug("DEFCON [defcon]: Master.iteration=[Master.iteration] Master.last_run=[Master.last_run] world.time=[world.time]")
switch(defcon)
if(4,5)
--defcon
+
if(3)
- log_and_message_admins("SSfailsafe Notice: DEFCON [defcon_pretty()]. The Master Controller (\ref[Master]) has not fired in the last [(5-defcon) * processing_interval] ticks.")
+ message_admins(span_adminnotice("Notice: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks."))
--defcon
+
if(2)
- log_and_message_admins("SSfailsafe Warning: DEFCON [defcon_pretty()]. The Master Controller (\ref[Master]) has not fired in the last [(5-defcon) * processing_interval] ticks. Automatic restart in [processing_interval] ticks.")
+ to_chat(GLOB.admins, span_boldannounce("Warning: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks. Automatic restart in [processing_interval] ticks."))
--defcon
- if(1)
- log_and_message_admins("SSfailsafe Warning: DEFCON [defcon_pretty()]. The Master Controller (\ref[Master]) has still not fired within the last [(5-defcon) * processing_interval] ticks. Killing and restarting...")
+ if(1)
+ to_chat(GLOB.admins, span_boldannounce("Warning: DEFCON [defcon_pretty()]. The Master Controller has still not fired within the last [(5-defcon) * processing_interval] ticks. Killing and restarting..."))
--defcon
var/rtn = Recreate_MC()
if(rtn > 0)
defcon = 4
master_iteration = 0
- log_and_message_admins("SSfailsafe Notice: MC (New:\ref[Master]) restarted successfully")
+ to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
else if(rtn < 0)
- log_game("SSfailsafe Notice: Could not restart MC (\ref[Master]), runtime encountered. Entering defcon 0")
- log_and_message_admins("SSFAILSAFE ERROR: DEFCON [defcon_pretty()]. Could not restart MC (\ref[Master]), runtime encountered. I will silently keep retrying.")
+ log_game("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
+ to_chat(GLOB.admins, span_boldannounce("ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying."))
//if the return number was 0, it just means the mc was restarted too recently, and it just needs some time before we try again
//no need to handle that specially when defcon 0 can handle it
+
if(0) //DEFCON 0! (mc failed to restart)
var/rtn = Recreate_MC()
if(rtn > 0)
defcon = 4
master_iteration = 0
- log_and_message_admins("SSfailsafe Notice: MC (New:\ref[Master]) restarted successfully")
+ to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
else
defcon = min(defcon + 1,5)
master_iteration = Master.iteration
@@ -93,11 +123,60 @@ var/datum/controller/failsafe/Failsafe
defcon = 5
sleep(initial(processing_interval))
+//Emergency loop used when Master got deleted or the main loop exited while Defcon == 0
+//Loop is driven externally so runtimes only cancel the current recovery attempt
+/datum/controller/failsafe/proc/emergency_loop()
+ //The code in this proc should be kept as simple as possible, anything complicated like to_chat might rely on master existing and runtime
+ //The goal should always be to get a new Master up and running before anything else
+ . = -1
+ switch (defcon) //The lower defcon goes the harder we try to fix the MC
+ if (2 to 3) //Try to normally recreate the MC two times
+ . = Recreate_MC()
+ if (1) //Delete the old MC first so we don't transfer any info, in case that caused any issues
+ del(Master)
+ . = Recreate_MC()
+
+ if (. == 1) //We were able to create a new master
+ master_iteration = 0
+ SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
+ Master.Initialize(10, FALSE, FALSE) //Need to manually start the MC, normally world.new would do this
+ to_chat(GLOB.admins, span_adminnotice("Failsafe recovered MC while in emergency state [defcon_pretty()]"))
+ else
+ log_game("FailSafe: Failsafe in emergency state and was unable to recreate MC while in defcon state [defcon_pretty()].")
+ message_admins(span_boldannounce("Failsafe in emergency state and master down, trying to recreate MC while in defcon level [defcon_pretty()] failed."))
+
+///Recreate all SSs which will still cause data survive due to Recover(), the new Master will then find and take them from global.vars
+/proc/recover_all_SS_and_recreate_master()
+ del(Master)
+ var/list/subsytem_types = subtypesof(/datum/controller/subsystem)
+ sortTim(subsytem_types, GLOBAL_PROC_REF(cmp_subsystem_init))
+ for(var/I in subsytem_types)
+ new I
+ . = Recreate_MC()
+ if (. == 1) //We were able to create a new master
+ SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
+ Master.Initialize(10, FALSE, FALSE) //Need to manually start the MC, normally world.new would do this
+ to_chat(GLOB.admins, span_adminnotice("MC successfully recreated after recovering all subsystems!"))
+ else
+ message_admins(span_boldannounce("Failed to create new MC!"))
+
+///Delete all existing SS to basically start over
+/proc/delete_all_SS_and_recreate_master()
+ del(Master)
+ for(var/global_var in global.vars)
+ if (istype(global.vars[global_var], /datum/controller/subsystem))
+ del(global.vars[global_var])
+ . = Recreate_MC()
+ if (. == 1) //We were able to create a new master
+ SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
+ Master.Initialize(10, FALSE, FALSE) //Need to manually start the MC, normally world.new would do this
+ to_chat(GLOB.admins, span_adminnotice("MC successfully recreated after deleting and recreating all subsystems!"))
+ else
+ message_admins(span_boldannounce("Failed to create new MC!"))
+
/datum/controller/failsafe/proc/defcon_pretty()
return defcon
-/datum/controller/failsafe/stat_entry()
- if(!statclick)
- statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
-
- stat("Failsafe Controller:", statclick.update("Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])"))
+/datum/controller/failsafe/stat_entry(msg)
+ msg = "Defcon: [defcon_pretty()] (Interval: [Failsafe.processing_interval] | Iteration: [Failsafe.master_iteration])"
+ return msg
diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm
index cd6e7544dd4..bf9c7e1e9ce 100644
--- a/code/controllers/globals.dm
+++ b/code/controllers/globals.dm
@@ -32,11 +32,12 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
return ..()
-/datum/controller/global_vars/stat_entry()
+/datum/controller/global_vars/stat_entry(msg)
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
- stat("GLOB:", statclick.update("Edit"))
+ msg = "GLOB: [statclick.update("Edit")]"
+ return msg
/datum/controller/global_vars/vv_edit_var(var_name, var_value)
if(gvars_datum_protected_varlist[var_name])
diff --git a/code/controllers/hooks-defs.dm b/code/controllers/hooks-defs.dm
index dcfb8885229..cb2a96b25a2 100644
--- a/code/controllers/hooks-defs.dm
+++ b/code/controllers/hooks-defs.dm
@@ -68,14 +68,14 @@
/**
* Employee reassignment hook.
* Called in card.dm when someone's card is reassigned at the HoP's desk.
- * Parameters: var/obj/item/weapon/card/id
+ * Parameters: var/obj/item/card/id
*/
/hook/reassign_employee
/**
* Employee terminated hook.
* Called in card.dm when someone's card is terminated at the HoP's desk.
- * Parameters: var/obj/item/weapon/card/id
+ * Parameters: var/obj/item/card/id
*/
/hook/terminate_employee
diff --git a/code/controllers/hooks.dm b/code/controllers/hooks.dm
index e7888304e58..293a90aff04 100644
--- a/code/controllers/hooks.dm
+++ b/code/controllers/hooks.dm
@@ -29,10 +29,10 @@
error("Invalid hook '/hook/[hook]' called.")
return 0
- var/caller = new hook_path
+ var/requester = new hook_path
var/status = 1
for(var/P in typesof("[hook_path]/proc"))
- if(!call(caller, P)(arglist(args)))
+ if(!call(requester, P)(arglist(args)))
error("Hook '[P]' failed or runtimed.")
status = 0
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index e08c860d568..2e5f80c3d50 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -1,26 +1,23 @@
- /**
- * 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
+// See initialization order in /code/game/world.dm
GLOBAL_REAL(Master, /datum/controller/master) = new
-
-//THIS IS THE INIT ORDER
-//Master -> SSPreInit -> GLOB -> world -> config -> SSInit -> Failsafe
-//GOT IT MEMORIZED?
-
/datum/controller/master
name = "Master"
- // Are we processing (higher values increase the processing delay by n ticks)
+ /// Are we processing (higher values increase the processing delay by n ticks)
var/processing = TRUE
- // How many times have we ran
+ /// How many times have we ran
var/iteration = 0
+ /// Stack end detector to detect stack overflows that kill the mc's main loop
+ var/datum/stack_end_detector/stack_end_detector
// world.time of last fire, for tracking lag outside of the mc
var/last_run
@@ -141,7 +138,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
BadBoy.critfail()
if(msg)
log_game(msg)
- message_admins("[msg]")
+ message_admins(span_boldannounce("[msg]"))
log_world(msg)
if (istype(Master.subsystems))
@@ -152,7 +149,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
current_runlevel = Master.current_runlevel
StartProcessing(10)
else
- to_world("The Master Controller is having some issues, we will need to re-initialize EVERYTHING")
+ to_world(span_boldannounce("The Master Controller is having some issues, we will need to re-initialize EVERYTHING"))
Initialize(20, TRUE)
@@ -170,14 +167,14 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
if(init_sss)
init_subtypes(/datum/controller/subsystem, subsystems)
- to_chat(world, "MC: Initializing subsystems...")
+ to_chat(world, span_boldannounce("MC: Initializing subsystems..."))
// Sort subsystems by init_order, so they initialize in the correct order.
sortTim(subsystems, GLOBAL_PROC_REF(cmp_subsystem_init))
var/start_timeofday = REALTIMEOFDAY
// Initialize subsystems.
- current_ticklimit = config.tick_limit_mc_init
+ current_ticklimit = CONFIG_GET(number/tick_limit_mc_init)
for (var/datum/controller/subsystem/SS in subsystems)
if (SS.flags & SS_NO_INIT)
continue
@@ -187,7 +184,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/time = (REALTIMEOFDAY - start_timeofday) / 10
var/msg = "MC: Initializations complete within [time] second[time == 1 ? "" : "s"]!"
- to_chat(world, "[msg]")
+ to_chat(world, span_boldannounce("[msg]"))
log_world(msg)
@@ -196,7 +193,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
if (!current_runlevel)
SetRunLevel(RUNLEVEL_LOBBY)
- GLOB.revdata = new // It can load revdata now, from tgs or .git or whatever
+ // GLOB.revdata = new // It can load revdata now, from tgs or .git or whatever
// Sort subsystems by display setting for easy access.
sortTim(subsystems, GLOBAL_PROC_REF(cmp_subsystem_display))
@@ -206,7 +203,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
#else
world.sleep_offline = 1
#endif
- world.change_fps(config.fps)
+ world.change_fps(CONFIG_GET(number/fps))
var/initialized_tod = REALTIMEOFDAY
sleep(1)
initializations_finished_with_no_players_logged_in = initialized_tod < REALTIMEOFDAY - 10
@@ -294,8 +291,12 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/error_level = 0
var/sleep_delta = 1
var/list/subsystems_to_check
- //the actual loop.
+ //setup the stack overflow detector
+ stack_end_detector = new()
+ var/datum/stack_canary/canary = stack_end_detector.prime_canary()
+ canary.use_variable()
+ //the actual loop.
while (1)
tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, (((REALTIMEOFDAY - init_timeofday) - (world.time - init_time)) / world.tick_lag)))
var/starting_tick_usage = TICK_USAGE
@@ -585,18 +586,20 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
-/datum/controller/master/stat_entry()
+/datum/controller/master/stat_entry(msg)
if(!statclick)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
- stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))")
- stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration])"))
+ msg = "Byond: (FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))"
+ msg += "Master Controller: [statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration])")]"
+
+ return msg
/datum/controller/master/StartLoadingMap(var/quiet = TRUE)
if(map_loading)
- admin_notice("Another map is attempting to be loaded before first map released lock. Delaying.", R_DEBUG)
+ admin_notice(span_danger("Another map is attempting to be loaded before first map released lock. Delaying."), R_DEBUG)
else if(!quiet)
- admin_notice("Map is now being built. Locking.", R_DEBUG)
+ admin_notice(span_danger("Map is now being built. Locking."), R_DEBUG)
//disallow more than one map to load at once, multithreading it will just cause race conditions
while(map_loading)
@@ -608,7 +611,12 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
/datum/controller/master/StopLoadingMap(var/quiet = TRUE)
if(!quiet)
- admin_notice("Map is finished. Unlocking.", R_DEBUG)
+ admin_notice(span_danger("Map is finished. Unlocking."), R_DEBUG)
map_loading = FALSE
for(var/datum/controller/subsystem/SS as anything in subsystems)
SS.StopLoadingMap()
+
+/datum/controller/master/proc/OnConfigLoad()
+ for (var/thing in subsystems)
+ var/datum/controller/subsystem/SS = thing
+ SS.OnConfigLoad()
diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm
index 3e369f1271a..2955d9d7213 100644
--- a/code/controllers/master_controller.dm
+++ b/code/controllers/master_controller.dm
@@ -11,8 +11,6 @@ var/global/datum/controller/game_controller/master_controller //Set in world.New
var/global/controller_iteration = 0
var/global/last_tick_duration = 0
-var/global/pipe_processing_killed = 0
-
/datum/controller/game_controller
var/list/shuttle_list // For debugging and VV
@@ -28,7 +26,7 @@ var/global/pipe_processing_killed = 0
job_master = new /datum/controller/occupations()
job_master.SetupOccupations()
job_master.LoadJobs("config/jobs.txt")
- admin_notice("Job setup complete", R_DEBUG)
+ admin_notice(span_danger("Job setup complete"), R_DEBUG)
if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase()
if(!syndicate_code_response) syndicate_code_response = generate_code_phrase()
@@ -40,7 +38,7 @@ var/global/pipe_processing_killed = 0
// SetupXenoarch() - Moved to SSxenoarch
transfer_controller = new
- admin_notice("Initializations complete.", R_DEBUG)
+ admin_notice(span_danger("Initializations complete."), R_DEBUG)
// #if UNIT_TEST
// # define CHECK_SLEEP_MASTER // For unit tests we don't care about a smooth lobby screen experience. We care about speed.
diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm
index 6b6c345b247..3cd8af77fe7 100644
--- a/code/controllers/subsystem.dm
+++ b/code/controllers/subsystem.dm
@@ -152,34 +152,25 @@
if(SS_SLEEPING)
state = SS_PAUSING
+/// Called after the config has been loaded or reloaded.
+/datum/controller/subsystem/proc/OnConfigLoad()
//used to initialize the subsystem AFTER the map has loaded
/datum/controller/subsystem/Initialize(start_timeofday)
subsystem_initialized = TRUE
var/time = (REALTIMEOFDAY - start_timeofday) / 10
var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!"
- to_chat(world, "[msg]")
+ to_chat(world, span_boldannounce("[msg]"))
log_world(msg)
return time
//hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc.
/datum/controller/subsystem/stat_entry(msg)
- if(!statclick)
- statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
-
-
- if(SS_NO_FIRE & flags)
- msg = "NO FIRE\t[msg]"
- else if(can_fire <= 0)
- msg = "OFFLINE\t[msg]"
- else
+ if(can_fire && !(SS_NO_FIRE & flags))
msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]"
-
- var/title = name
- if (can_fire)
- title = "\[[state_letter()]][title]"
-
- stat(title, statclick.update(msg))
+ else
+ msg = "OFFLINE\t[msg]"
+ return msg
/datum/controller/subsystem/proc/state_letter()
switch (state)
@@ -210,7 +201,7 @@
can_fire = FALSE
// Safely sleep in a loop until the subsystem is idle, (or its been un-suspended somehow)
while(can_fire <= 0 && state != SS_IDLE)
- stoplag() // Safely sleep in a loop until
+ stoplag() // Safely sleep in a loop until
// Wakes a suspended subsystem.
/datum/controller/subsystem/proc/wake()
diff --git a/code/controllers/subsystems/SSvote.dm b/code/controllers/subsystems/SSvote.dm
new file mode 100644
index 00000000000..5ccaa7c5517
--- /dev/null
+++ b/code/controllers/subsystems/SSvote.dm
@@ -0,0 +1,16 @@
+SUBSYSTEM_DEF(vote)
+ name = "Vote"
+ wait = 10
+ priority = FIRE_PRIORITY_VOTE
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ flags = SS_KEEP_TIMING | SS_NO_INIT
+
+ var/datum/vote/active_vote
+
+/datum/controller/subsystem/vote/fire()
+ if(active_vote)
+ active_vote.tick()
+
+/datum/controller/subsystem/vote/proc/start_vote(datum/vote/V)
+ active_vote = V
+ active_vote.start()
diff --git a/code/controllers/subsystems/ai.dm b/code/controllers/subsystems/ai.dm
index eb29e2fec2f..4e5256d9492 100644
--- a/code/controllers/subsystems/ai.dm
+++ b/code/controllers/subsystems/ai.dm
@@ -12,8 +12,9 @@ SUBSYSTEM_DEF(ai)
var/slept_mobs = 0
var/list/process_z = list()
-/datum/controller/subsystem/ai/stat_entry(msg_prefix)
- ..("P: [processing.len] | S: [slept_mobs]")
+/datum/controller/subsystem/ai/stat_entry(msg)
+ msg = "P: [processing.len] | S: [slept_mobs]"
+ return ..()
/datum/controller/subsystem/ai/fire(resumed = 0)
if (!resumed)
diff --git a/code/controllers/subsystems/aifast.dm b/code/controllers/subsystems/aifast.dm
index f045a7fd35c..2580c156ace 100644
--- a/code/controllers/subsystems/aifast.dm
+++ b/code/controllers/subsystems/aifast.dm
@@ -9,10 +9,9 @@ SUBSYSTEM_DEF(aifast)
var/list/processing = list()
var/list/currentrun = list()
-/datum/controller/subsystem/aifast/stat_entry(msg_prefix)
- var/list/msg = list(msg_prefix)
- msg += "P:[processing.len]"
- ..(msg.Join())
+/datum/controller/subsystem/aifast/stat_entry(msg)
+ msg = "P:[processing.len]"
+ return ..()
/datum/controller/subsystem/aifast/fire(resumed = 0)
if (!resumed)
diff --git a/code/controllers/subsystems/air.dm b/code/controllers/subsystems/air.dm
index 7bd837c8ea8..c4b64ba450a 100644
--- a/code/controllers/subsystems/air.dm
+++ b/code/controllers/subsystems/air.dm
@@ -1,3 +1,60 @@
+/*
+Overview:
+ SSair does everything. There are tons of procs in here.
+
+Class Vars:
+ zones - All zones currently holding one or more turfs.
+ edges - All processing edges.
+
+ tiles_to_update - Tiles scheduled to update next tick.
+ zones_to_update - Zones which have had their air changed and need air archival.
+ active_hotspots - All processing fire objects.
+
+ active_zones - The number of zones which were archived last tick. Used in debug verbs.
+ next_id - The next UID to be applied to a zone. Mostly useful for debugging purposes as zones do not need UIDs to function.
+
+Class Procs:
+
+ mark_for_update(turf/T)
+ Adds the turf to the update list. When updated, update_air_properties() will be called.
+ When stuff changes that might affect airflow, call this. It's basically the only thing you need.
+
+ add_zone(zone/Z) and remove_zone(zone/Z)
+ Adds zones to the zones list. Does not mark them for update.
+
+ air_blocked(turf/A, turf/B)
+ Returns a bitflag consisting of:
+ AIR_BLOCKED - The connection between turfs is physically blocked. No air can pass.
+ ZONE_BLOCKED - There is a door between the turfs, so zones cannot cross. Air may or may not be permeable.
+
+ merge(zone/A, zone/B)
+ Called when zones have a direct connection and equivalent pressure and temperature.
+ Merges the zones to create a single zone.
+
+ connect(turf/simulated/A, turf/B)
+ Called by turf/update_air_properties(). The first argument must be simulated.
+ Creates a connection between A and B.
+
+ mark_zone_update(zone/Z)
+ Adds zone to the update list. Unlike mark_for_update(), this one is called automatically whenever
+ air is returned from a simulated turf.
+
+ equivalent_pressure(zone/A, zone/B)
+ Currently identical to A.air.compare(B.air). Returns 1 when directly connected zones are ready to be merged.
+
+ get_edge(zone/A, zone/B)
+ get_edge(zone/A, turf/B)
+ Gets a valid connection_edge between A and B, creating a new one if necessary.
+
+ has_same_air(turf/A, turf/B)
+ Used to determine if an unsimulated edge represents a specific turf.
+ Simulated edges use connection_edge/contains_zone() for the same purpose.
+ Returns 1 if A has identical gases and temperature to B.
+
+ remove_edge(connection_edge/edge)
+ Called when an edge is erased. Removes it from processing.
+*/
+
// Air update stages
#define SSAIR_TURFS 1
#define SSAIR_EDGES 2
@@ -34,8 +91,20 @@ SUBSYSTEM_DEF(air)
// This is used to tell CI WHERE the edges are.
var/list/startup_active_edge_log = list()
-/datum/controller/subsystem/air/PreInit()
- air_master = src
+ //Geometry lists
+ var/list/zones = list()
+ var/list/edges = list()
+ //Geometry updates lists
+ var/list/tiles_to_update = list()
+ var/list/zones_to_update = list()
+ var/list/active_fire_zones = list()
+ var/list/active_hotspots = list()
+ var/list/active_edges = list()
+ var/list/zones_planet_temperature_to_update = list() // YW Addition - zones_planet_temperature_to_update
+
+ var/active_zones = 0
+ var/current_cycle = 0
+ var/next_id = 1 //Used to keep track of zone UIDs.
/datum/controller/subsystem/air/Initialize(timeofday)
report_progress("Processing Geometry...")
@@ -47,14 +116,14 @@ SUBSYSTEM_DEF(air)
S.update_air_properties()
CHECK_TICK
- admin_notice({"Geometry initialized in [round(0.1*(REALTIMEOFDAY-timeofday),0.1)] seconds.
-
-Total Simulated Turfs: [simulated_turf_count]
-Total Zones: [zones.len]
-Total Edges: [edges.len]
-Total Active Edges: [active_edges.len ? "[active_edges.len]" : "None"]
-Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]
-"}, R_DEBUG)
+ admin_notice(span_danger("Geometry initialized in [round(0.1*(REALTIMEOFDAY-timeofday),0.1)] seconds.") + \
+span_info("
\
+Total Simulated Turfs: [simulated_turf_count]
\
+Total Zones: [zones.len]
\
+Total Edges: [edges.len]
\
+Total Active Edges: [active_edges.len ? span_danger("[active_edges.len]") : "None"]
\
+Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_count]\
+"), R_DEBUG)
// Note - Baystation settles the air by running for one tick. We prefer to not have active edges.
// Maps should not have active edges on boot. If we've got some, log it so it can get fixed.
@@ -113,7 +182,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
log_and_message_admins("SSair: Was told to start a new run, but the previous run wasn't finished! currentrun.len=[currentrun.len], current_step=[current_step]")
resumed = TRUE
else
- current_cycle++ // Begin a new air_master cycle!
+ current_cycle++ // Begin a new SSair cycle!
current_step = SSAIR_TURFS // Start with Step 1 of course
INTERNAL_PROCESS_STEP(SSAIR_TURFS, TRUE, process_tiles_to_update, cost_turfs, SSAIR_EDGES)
@@ -123,7 +192,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
INTERNAL_PROCESS_STEP(SSAIR_ZONES, FALSE, process_zones_to_update, cost_zones, SSAIR_BOILER) //YW Edit SSAIR_DONE -> SSAIR_BOILER
INTERNAL_PROCESS_STEP(SSAIR_BOILER, FALSE, process_boiler_zones_to_update, cost_boiler, SSAIR_DONE) //YW Addition -> Boiler
- // Okay, we're done! Woo! Got thru a whole air_master cycle!
+ // Okay, we're done! Woo! Got thru a whole SSair cycle!
if(LAZYLEN(currentrun) || current_step != SSAIR_DONE)
log_and_message_admins("SSair: Was not able to complete a full air cycle despite reaching the end of fire(). This shouldn't happen.")
else
@@ -307,11 +376,8 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
return 1
//YW Addition End
-
-
-/datum/controller/subsystem/air/stat_entry(msg_prefix)
- var/list/msg = list(msg_prefix)
- msg += "S:[current_step ? part_names[current_step] : ""] "
+/datum/controller/subsystem/air/stat_entry(msg)
+ msg = "S:[current_step ? part_names[current_step] : ""] "
msg += "C:{"
msg += "T [round(cost_turfs, 1)] | "
msg += "E [round(cost_edges, 1)] | "
@@ -330,7 +396,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
msg += "Z [zones_to_update.len] "
msg += "B [zones_planet_temperature_to_update.len] " //YW Addition - zones_planet_temperature_to_update.len
msg += "}"
- ..(msg.Join())
+ return ..()
// ZAS might displace objects as the map loads if an air tick is processed mid-load.
/datum/controller/subsystem/air/StartLoadingMap(var/quiet = TRUE)
@@ -373,9 +439,164 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
next_fire = world.time + wait
can_fire = TRUE // Unpause
-//
-// The procs from the ZAS Air Controller are in ZAS/Controller.dm
-//
+/datum/controller/subsystem/air/proc/add_zone(zone/z)
+ zones.Add(z)
+ z.name = "Zone [next_id++]"
+ zones_planet_temperature_to_update.Add(z) //YW Addition - planet temp
+ mark_zone_update(z)
+
+/datum/controller/subsystem/air/proc/remove_zone(zone/z)
+ zones.Remove(z)
+ zones_to_update.Remove(z)
+ zones_planet_temperature_to_update.Remove(z) //YW Addition - planet temp
+
+/datum/controller/subsystem/air/proc/air_blocked(turf/A, turf/B)
+ #ifdef ZASDBG
+ ASSERT(isturf(A))
+ ASSERT(isturf(B))
+ #endif
+ var/ablock = A.c_airblock(B)
+ if(ablock == BLOCKED)
+ return BLOCKED
+ return ablock | B.c_airblock(A)
+
+/datum/controller/subsystem/air/proc/merge(zone/A, zone/B)
+ #ifdef ZASDBG
+ ASSERT(istype(A))
+ ASSERT(istype(B))
+ ASSERT(!A.invalid)
+ ASSERT(!B.invalid)
+ ASSERT(A != B)
+ #endif
+ if(A.contents.len < B.contents.len)
+ A.c_merge(B)
+ mark_zone_update(B)
+ else
+ B.c_merge(A)
+ mark_zone_update(A)
+
+/datum/controller/subsystem/air/proc/connect(turf/simulated/A, turf/simulated/B)
+ #ifdef ZASDBG
+ ASSERT(istype(A))
+ ASSERT(isturf(B))
+ ASSERT(A.zone)
+ ASSERT(!A.zone.invalid)
+ //ASSERT(B.zone)
+ ASSERT(A != B)
+ #endif
+
+ var/block = SSair.air_blocked(A,B)
+ if(block & AIR_BLOCKED) return
+
+ var/direct = !(block & ZONE_BLOCKED)
+ var/space = !istype(B)
+
+ if(!space)
+ if(min(A.zone.contents.len, B.zone.contents.len) < ZONE_MIN_SIZE || (direct && (equivalent_pressure(A.zone,B.zone) || current_cycle == 0)))
+ merge(A.zone,B.zone)
+ return
+
+ var/a_to_b = get_dir(A,B)
+ var/b_to_a = get_dir(B,A)
+
+ if(!A.connections)
+ A.connections = new
+ if(!B.connections)
+ B.connections = new
+
+ if(A.connections.get(a_to_b))
+ return
+ if(B.connections.get(b_to_a))
+ return
+ if(!space)
+ if(A.zone == B.zone)
+ return
+
+
+ var/connection/c = new /connection(A,B)
+
+ A.connections.place(c, a_to_b)
+ B.connections.place(c, b_to_a)
+
+ if(direct) c.mark_direct()
+
+/datum/controller/subsystem/air/proc/mark_for_update(turf/T)
+ #ifdef ZASDBG
+ ASSERT(isturf(T))
+ #endif
+ if(T.needs_air_update)
+ return
+ tiles_to_update |= T
+ #ifdef ZASDBG
+ T.add_overlay(mark)
+ #endif
+ T.needs_air_update = 1
+
+/datum/controller/subsystem/air/proc/mark_zone_update(zone/Z)
+ #ifdef ZASDBG
+ ASSERT(istype(Z))
+ #endif
+ if(Z.needs_update)
+ return
+ zones_to_update.Add(Z)
+ Z.needs_update = 1
+
+/datum/controller/subsystem/air/proc/mark_edge_sleeping(connection_edge/E)
+ #ifdef ZASDBG
+ ASSERT(istype(E))
+ #endif
+ if(E.sleeping)
+ return
+ active_edges.Remove(E)
+ E.sleeping = 1
+
+/datum/controller/subsystem/air/proc/mark_edge_active(connection_edge/E)
+ #ifdef ZASDBG
+ ASSERT(istype(E))
+ #endif
+ if(!E.sleeping)
+ return
+ active_edges.Add(E)
+ E.sleeping = 0
+
+/datum/controller/subsystem/air/proc/equivalent_pressure(zone/A, zone/B)
+ return A.air.compare(B.air)
+
+/datum/controller/subsystem/air/proc/get_edge(zone/A, zone/B)
+ if(istype(B))
+ for(var/connection_edge/zone/edge in A.edges)
+ if(edge.contains_zone(B))
+ return edge
+ var/connection_edge/edge = new /connection_edge/zone(A,B)
+ edges.Add(edge)
+ edge.recheck()
+ return edge
+ else
+ for(var/connection_edge/unsimulated/edge in A.edges)
+ if(has_same_air(edge.B,B))
+ return edge
+ var/connection_edge/edge = new /connection_edge/unsimulated(A,B)
+ edges.Add(edge)
+ edge.recheck()
+ return edge
+
+/datum/controller/subsystem/air/proc/has_same_air(turf/A, turf/B)
+ if(A.oxygen != B.oxygen)
+ return FALSE
+ if(A.nitrogen != B.nitrogen)
+ return FALSE
+ if(A.phoron != B.phoron)
+ return FALSE
+ if(A.carbon_dioxide != B.carbon_dioxide)
+ return FALSE
+ if(A.temperature != B.temperature)
+ return FALSE
+ return TRUE
+
+/datum/controller/subsystem/air/proc/remove_edge(connection_edge/E)
+ edges.Remove(E)
+ if(!E.sleeping)
+ active_edges.Remove(E)
#undef SSAIR_TURFS
#undef SSAIR_EDGES
diff --git a/code/controllers/subsystems/airflow.dm b/code/controllers/subsystems/airflow.dm
index 7561ad8cca7..30ad9f9ea0a 100644
--- a/code/controllers/subsystems/airflow.dm
+++ b/code/controllers/subsystems/airflow.dm
@@ -121,7 +121,7 @@ SUBSYSTEM_DEF(airflow)
return FALSE
if (ismob(src))
- to_chat(src,"You are pushed away by airflow!")
+ to_chat(src,span_danger("You are pushed away by airflow!"))
last_airflow = world.time
var/airflow_falloff = 9 - sqrt((x - airflow_dest.x) ** 2 + (y - airflow_dest.y) ** 2)
diff --git a/code/controllers/subsystems/alarm.dm b/code/controllers/subsystems/alarm.dm
index 868025eca3f..e3507a34e45 100644
--- a/code/controllers/subsystems/alarm.dm
+++ b/code/controllers/subsystems/alarm.dm
@@ -41,5 +41,6 @@ SUBSYSTEM_DEF(alarm)
/datum/controller/subsystem/alarm/proc/number_of_active_alarms()
return active_alarm_cache.len
-/datum/controller/subsystem/alarm/stat_entry()
- ..("[number_of_active_alarms()] alarm\s")
+/datum/controller/subsystem/alarm/stat_entry(msg)
+ msg = "[number_of_active_alarms()] alarm\s"
+ return ..()
diff --git a/code/controllers/subsystems/assets.dm b/code/controllers/subsystems/assets.dm
index 49e8a8f5781..d34d05ff55d 100644
--- a/code/controllers/subsystems/assets.dm
+++ b/code/controllers/subsystems/assets.dm
@@ -6,9 +6,9 @@ SUBSYSTEM_DEF(assets)
var/list/preload = list()
var/datum/asset_transport/transport = new()
-/datum/controller/subsystem/assets/proc/OnConfigLoad()
+/datum/controller/subsystem/assets/OnConfigLoad()
var/newtransporttype = /datum/asset_transport
- switch (config.asset_transport)
+ switch (CONFIG_GET(string/asset_transport))
if ("webroot")
newtransporttype = /datum/asset_transport/webroot
diff --git a/code/controllers/subsystems/atoms.dm b/code/controllers/subsystems/atoms.dm
index a62c5265c55..5968fe1fe3f 100644
--- a/code/controllers/subsystems/atoms.dm
+++ b/code/controllers/subsystems/atoms.dm
@@ -21,7 +21,7 @@ SUBSYSTEM_DEF(atoms)
setupgenetics() //to set the mutations' place in structural enzymes, so initializers know where to put mutations.
initialized = INITIALIZATION_INNEW_MAPLOAD
to_world_log("Initializing objects")
- admin_notice("Initializing objects", R_DEBUG)
+ admin_notice(span_danger("Initializing objects"), R_DEBUG)
InitializeAtoms()
return ..()
diff --git a/code/controllers/subsystems/chemistry.dm b/code/controllers/subsystems/chemistry.dm
index 148e9755421..6f0c5959ebe 100644
--- a/code/controllers/subsystems/chemistry.dm
+++ b/code/controllers/subsystems/chemistry.dm
@@ -20,8 +20,9 @@ SUBSYSTEM_DEF(chemistry)
initialize_chemical_reactions()
..()
-/datum/controller/subsystem/chemistry/stat_entry()
- ..("C: [chemical_reagents.len] | R: [chemical_reactions.len]")
+/datum/controller/subsystem/chemistry/stat_entry(msg)
+ msg = "C: [chemical_reagents.len] | R: [chemical_reactions.len]"
+ return ..()
//Chemical Reactions - Initialises all /decl/chemical_reaction into a list
// It is filtered into multiple lists within a list.
@@ -43,7 +44,7 @@ SUBSYSTEM_DEF(chemistry)
// add_to = fusion_reactions_by_reagent
if(istype(D, /decl/chemical_reaction/distilling))
add_to = distilled_reactions_by_reagent
-
+
LAZYINITLIST(add_to[reagent_id])
add_to[reagent_id] += D
diff --git a/code/controllers/subsystems/circuits.dm b/code/controllers/subsystems/circuits.dm
index f417ce3055d..ca080a3d819 100644
--- a/code/controllers/subsystems/circuits.dm
+++ b/code/controllers/subsystems/circuits.dm
@@ -37,47 +37,47 @@ SUBSYSTEM_DEF(circuit)
var/list/category_list = circuit_fabricator_recipe_list[category]
category_list += IC // Populating the fabricator categories
- for(var/obj/item/device/electronic_assembly/A as anything in typesof(/obj/item/device/electronic_assembly))
+ for(var/obj/item/electronic_assembly/A as anything in typesof(/obj/item/electronic_assembly))
var/path = A
all_assemblies[initial(A.name)] = path
cached_assemblies[path] = new path
circuit_fabricator_recipe_list["Assemblies"] = list(
- /obj/item/device/electronic_assembly/default,
- /obj/item/device/electronic_assembly/calc,
- /obj/item/device/electronic_assembly/clam,
- /obj/item/device/electronic_assembly/simple,
- /obj/item/device/electronic_assembly/hook,
- /obj/item/device/electronic_assembly/pda,
- /obj/item/device/electronic_assembly/tiny/default,
- /obj/item/device/electronic_assembly/tiny/cylinder,
- /obj/item/device/electronic_assembly/tiny/scanner,
- /obj/item/device/electronic_assembly/tiny/hook,
- /obj/item/device/electronic_assembly/tiny/box,
- /obj/item/device/electronic_assembly/medium/default,
- /obj/item/device/electronic_assembly/medium/box,
- /obj/item/device/electronic_assembly/medium/clam,
- /obj/item/device/electronic_assembly/medium/medical,
- /obj/item/device/electronic_assembly/medium/gun,
- /obj/item/device/electronic_assembly/medium/radio,
- /obj/item/device/electronic_assembly/large/default,
- /obj/item/device/electronic_assembly/large/scope,
- /obj/item/device/electronic_assembly/large/terminal,
- /obj/item/device/electronic_assembly/large/arm,
- /obj/item/device/electronic_assembly/large/tall,
- /obj/item/device/electronic_assembly/large/industrial,
- /obj/item/device/electronic_assembly/drone/default,
- /obj/item/device/electronic_assembly/drone/arms,
- /obj/item/device/electronic_assembly/drone/secbot,
- /obj/item/device/electronic_assembly/drone/medbot,
- /obj/item/device/electronic_assembly/drone/genbot,
- /obj/item/device/electronic_assembly/drone/android,
- /obj/item/device/electronic_assembly/wallmount/tiny,
- /obj/item/device/electronic_assembly/wallmount/light,
- /obj/item/device/electronic_assembly/wallmount,
- /obj/item/device/electronic_assembly/wallmount/heavy,
- /obj/item/weapon/implant/integrated_circuit,
+ /obj/item/electronic_assembly/default,
+ /obj/item/electronic_assembly/calc,
+ /obj/item/electronic_assembly/clam,
+ /obj/item/electronic_assembly/simple,
+ /obj/item/electronic_assembly/hook,
+ /obj/item/electronic_assembly/pda,
+ /obj/item/electronic_assembly/tiny/default,
+ /obj/item/electronic_assembly/tiny/cylinder,
+ /obj/item/electronic_assembly/tiny/scanner,
+ /obj/item/electronic_assembly/tiny/hook,
+ /obj/item/electronic_assembly/tiny/box,
+ /obj/item/electronic_assembly/medium/default,
+ /obj/item/electronic_assembly/medium/box,
+ /obj/item/electronic_assembly/medium/clam,
+ /obj/item/electronic_assembly/medium/medical,
+ /obj/item/electronic_assembly/medium/gun,
+ /obj/item/electronic_assembly/medium/radio,
+ /obj/item/electronic_assembly/large/default,
+ /obj/item/electronic_assembly/large/scope,
+ /obj/item/electronic_assembly/large/terminal,
+ /obj/item/electronic_assembly/large/arm,
+ /obj/item/electronic_assembly/large/tall,
+ /obj/item/electronic_assembly/large/industrial,
+ /obj/item/electronic_assembly/drone/default,
+ /obj/item/electronic_assembly/drone/arms,
+ /obj/item/electronic_assembly/drone/secbot,
+ /obj/item/electronic_assembly/drone/medbot,
+ /obj/item/electronic_assembly/drone/genbot,
+ /obj/item/electronic_assembly/drone/android,
+ /obj/item/electronic_assembly/wallmount/tiny,
+ /obj/item/electronic_assembly/wallmount/light,
+ /obj/item/electronic_assembly/wallmount,
+ /obj/item/electronic_assembly/wallmount/heavy,
+ /obj/item/implant/integrated_circuit,
/obj/item/clothing/under/circuitry,
/obj/item/clothing/gloves/circuitry,
/obj/item/clothing/glasses/circuitry,
@@ -88,7 +88,7 @@ SUBSYSTEM_DEF(circuit)
)
circuit_fabricator_recipe_list["Tools"] = list(
- /obj/item/device/integrated_electronics/wirer,
- /obj/item/device/integrated_electronics/debugger,
- /obj/item/device/integrated_electronics/detailer
+ /obj/item/integrated_electronics/wirer,
+ /obj/item/integrated_electronics/debugger,
+ /obj/item/integrated_electronics/detailer
)
diff --git a/code/controllers/subsystems/events.dm b/code/controllers/subsystems/events.dm
index 83ab2fa00ca..5bdf83fdecc 100644
--- a/code/controllers/subsystems/events.dm
+++ b/code/controllers/subsystems/events.dm
@@ -41,8 +41,9 @@ SUBSYSTEM_DEF(events)
var/datum/event_container/EC = event_containers[i]
EC.process()
-/datum/controller/subsystem/events/stat_entry()
- ..("E:[active_events.len]")
+/datum/controller/subsystem/events/stat_entry(msg)
+ msg = "E:[active_events.len]"
+ return ..()
/datum/controller/subsystem/events/Recover()
if(SSevents.active_events)
diff --git a/code/controllers/subsystems/game_master.dm b/code/controllers/subsystems/game_master.dm
index 4703da0bf8c..11844b4f983 100644
--- a/code/controllers/subsystems/game_master.dm
+++ b/code/controllers/subsystems/game_master.dm
@@ -156,7 +156,7 @@ SUBSYSTEM_DEF(game_master)
if(check_rights(R_ADMIN|R_EVENT|R_DEBUG))
SSgame_master.interact(usr)
else
- to_chat(usr, span("warning", "You do not have sufficient rights to view the GM panel, sorry."))
+ to_chat(usr, span_warning("You do not have sufficient rights to view the GM panel, sorry."))
/datum/controller/subsystem/game_master/proc/interact(var/client/user)
if(!user)
diff --git a/code/controllers/subsystems/inactivity.dm b/code/controllers/subsystems/inactivity.dm
index ab1b7209ca8..bc7a5a7dde1 100644
--- a/code/controllers/subsystems/inactivity.dm
+++ b/code/controllers/subsystems/inactivity.dm
@@ -6,7 +6,7 @@ SUBSYSTEM_DEF(inactivity)
var/number_kicked = 0
/datum/controller/subsystem/inactivity/fire(resumed = FALSE)
- if (!config.kick_inactive)
+ if (!CONFIG_GET(number/kick_inactive))
can_fire = FALSE
return
if (!resumed)
@@ -15,8 +15,8 @@ SUBSYSTEM_DEF(inactivity)
while(client_list.len)
var/client/C = client_list[client_list.len]
client_list.len--
- if(C.is_afk(config.kick_inactive MINUTES) && can_kick(C))
- to_chat_immediate(C, world.time, "You have been inactive for more than [config.kick_inactive] minute\s and have been disconnected.")
+ if(C.is_afk(CONFIG_GET(number/kick_inactive) MINUTES) && can_kick(C))
+ to_chat_immediate(C, world.time, span_warning("You have been inactive for more than [CONFIG_GET(number/kick_inactive)] minute\s and have been disconnected."))
var/information
if(C.mob)
@@ -56,8 +56,9 @@ SUBSYSTEM_DEF(inactivity)
if (MC_TICK_CHECK)
return
-/datum/controller/subsystem/inactivity/stat_entry()
- ..("Kicked: [number_kicked]")
+/datum/controller/subsystem/inactivity/stat_entry(msg)
+ msg = "Kicked: [number_kicked]"
+ return ..()
/datum/controller/subsystem/inactivity/proc/can_kick(var/client/C)
if(C.holder) return FALSE //VOREStation Add - Don't kick admins.
diff --git a/code/controllers/subsystems/job.dm b/code/controllers/subsystems/job.dm
index c137582c7c5..d2f7e72bc92 100644
--- a/code/controllers/subsystems/job.dm
+++ b/code/controllers/subsystems/job.dm
@@ -18,11 +18,11 @@ SUBSYSTEM_DEF(job)
setup_occupations()
return ..()
-/datum/controller/subsystem/job/proc/setup_occupations(faction = "Station")
+/datum/controller/subsystem/job/proc/setup_occupations(faction = FACTION_STATION)
occupations = list()
var/list/all_jobs = subtypesof(/datum/job)
if(!all_jobs.len)
- to_chat(world, span("warning", "Error setting up jobs, no job datums found"))
+ to_chat(world, span_warning("Error setting up jobs, no job datums found"))
return FALSE
for(var/J in all_jobs)
diff --git a/code/controllers/subsystems/lighting.dm b/code/controllers/subsystems/lighting.dm
index 522bab602ba..d9643c15ba6 100644
--- a/code/controllers/subsystems/lighting.dm
+++ b/code/controllers/subsystems/lighting.dm
@@ -14,7 +14,7 @@ SUBSYSTEM_DEF(lighting)
/datum/controller/subsystem/lighting/Initialize(timeofday)
if(!subsystem_initialized)
- if (config.starlight)
+ if (CONFIG_GET(flag/starlight))
for(var/area/A in world)
if (A.dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
A.luminosity = 0
diff --git a/code/controllers/subsystems/machines.dm b/code/controllers/subsystems/machines.dm
index a4a836f2001..dea5b7ccc37 100644
--- a/code/controllers/subsystems/machines.dm
+++ b/code/controllers/subsystems/machines.dm
@@ -32,7 +32,7 @@ SUBSYSTEM_DEF(machines)
/datum/controller/subsystem/machines/Initialize(timeofday)
makepowernets()
- admin_notice("Initializing atmos machinery.", R_DEBUG)
+ admin_notice(span_danger("Initializing atmos machinery."), R_DEBUG)
setup_atmos_machinery(all_machines)
fire()
..()
@@ -63,7 +63,7 @@ SUBSYSTEM_DEF(machines)
/datum/controller/subsystem/machines/proc/setup_atmos_machinery(list/atmos_machines)
var/list/actual_atmos_machines = list()
-
+
for(var/obj/machinery/atmospherics/machine in atmos_machines)
machine.atmos_init()
actual_atmos_machines += machine
@@ -82,9 +82,8 @@ SUBSYSTEM_DEF(machines)
T.broadcast_status()
CHECK_TICK
-/datum/controller/subsystem/machines/stat_entry()
- var/msg = list()
- msg += "C:{"
+/datum/controller/subsystem/machines/stat_entry(msg)
+ msg = "C:{"
msg += "PI:[round(cost_pipenets,1)]|"
msg += "MC:[round(cost_machinery,1)]|"
msg += "PN:[round(cost_powernets,1)]|"
@@ -95,7 +94,7 @@ SUBSYSTEM_DEF(machines)
msg += "PN:[SSmachines.powernets.len]|"
msg += "PO:[SSmachines.powerobjs.len]|"
msg += "MC/MS:[round((cost ? SSmachines.processing_machines.len/cost_machinery : 0),0.1)]"
- ..(jointext(msg, null))
+ return ..()
/datum/controller/subsystem/machines/proc/process_pipenets(resumed = 0)
if (!resumed)
diff --git a/code/controllers/subsystems/mapping.dm b/code/controllers/subsystems/mapping.dm
index e496a97f18f..42e1de651c6 100644
--- a/code/controllers/subsystems/mapping.dm
+++ b/code/controllers/subsystems/mapping.dm
@@ -5,7 +5,6 @@ SUBSYSTEM_DEF(mapping)
flags = SS_NO_FIRE
var/list/map_templates = list()
- var/dmm_suite/maploader = null
var/obj/effect/landmark/engine_loader/engine_loader
var/list/shelter_templates = list()
@@ -17,10 +16,9 @@ SUBSYSTEM_DEF(mapping)
if(subsystem_initialized)
return
world.max_z_changed() // This is to set up the player z-level list, maxz hasn't actually changed (probably)
- maploader = new()
load_map_templates()
- if(config.generate_map)
+ if(CONFIG_GET(flag/generate_map))
// Map-gen is still very specific to the map, however putting it here should ensure it loads in the correct order.
using_map.perform_map_generation()
@@ -52,8 +50,8 @@ SUBSYSTEM_DEF(mapping)
// Choose an engine type
var/datum/map_template/engine/chosen_type = null
- if (LAZYLEN(config.engine_map))
- var/chosen_name = pick(config.engine_map)
+ if (LAZYLEN(CONFIG_GET(str_list/engine_map)))
+ var/chosen_name = pick(CONFIG_GET(str_list/engine_map))
chosen_type = map_templates[chosen_name]
if(!istype(chosen_type))
error("Configured engine map [chosen_name] is not a valid engine map name!")
@@ -65,7 +63,7 @@ SUBSYSTEM_DEF(mapping)
engine_types += MT
chosen_type = pick(engine_types)
to_world_log("Chose Engine Map: [chosen_type.name]")
- admin_notice("Chose Engine Map: [chosen_type.name]", R_DEBUG)
+ admin_notice(span_danger("Chose Engine Map: [chosen_type.name]"), R_DEBUG)
// Annihilate movable atoms
engine_loader.annihilate_bounds()
@@ -173,3 +171,10 @@ SUBSYSTEM_DEF(mapping)
if (!Debug2)
return // Only show up in stat panel if debugging is enabled.
. = ..()
+
+// VOREStation Edit: BAPI-dmm
+/datum/controller/subsystem/mapping/Shutdown()
+ // Force bapi to drop it's cached maps on server shutdown.
+ _bapidmm_clear_map_data()
+ fdel("data/baked_dmm_files/")
+// VOREStation Edit End
diff --git a/code/controllers/subsystems/media_tracks.dm b/code/controllers/subsystems/media_tracks.dm
index 96c11b5edd6..9aa59f95feb 100644
--- a/code/controllers/subsystems/media_tracks.dm
+++ b/code/controllers/subsystems/media_tracks.dm
@@ -16,7 +16,7 @@ SUBSYSTEM_DEF(media_tracks)
return ..()
/datum/controller/subsystem/media_tracks/proc/load_tracks()
- for(var/filename in config.jukebox_track_files)
+ for(var/filename in CONFIG_GET(str_list/jukebox_track_files))
report_progress("Loading jukebox track: [filename]")
if(!fexists(filename))
@@ -99,11 +99,11 @@ SUBSYSTEM_DEF(media_tracks)
if(islist(json))
for(var/song in json)
if(!islist(song))
- to_chat(C, "Song appears to be malformed.")
+ to_chat(C, span_warning("Song appears to be malformed."))
continue
var/list/songdata = song
if(!songdata["url"] || !songdata["title"] || !songdata["duration"])
- to_chat(C, "URL, Title, or Duration was missing from a song. Skipping.")
+ to_chat(C, span_warning("URL, Title, or Duration was missing from a song. Skipping."))
continue
var/datum/track/T = new(songdata["url"], songdata["title"], songdata["duration"], songdata["artist"], songdata["genre"], songdata["secret"], songdata["lobby"])
all_tracks += T
@@ -130,7 +130,7 @@ SUBSYSTEM_DEF(media_tracks)
return
var/secret = tgui_alert(C, "Optional: Mark track as secret?", "Track Secret", list("Yes", "Cancel", "No"))
- if(secret == "Cancel")
+ if(!secret || secret == "Cancel")
return
else if(secret == "Yes")
secret = TRUE
@@ -138,7 +138,7 @@ SUBSYSTEM_DEF(media_tracks)
secret = FALSE
var/lobby = tgui_alert(C, "Optional: Mark track as lobby music?", "Track Lobby", list("Yes", "Cancel", "No"))
- if(lobby == "Cancel")
+ if(!lobby || lobby == "Cancel")
return
else if(secret == "Yes")
secret = TRUE
@@ -172,7 +172,7 @@ SUBSYSTEM_DEF(media_tracks)
sort_tracks()
return
- to_chat(C, "")
+ to_chat(C, span_warning("Couldn't find a track matching the specified parameters."))
/datum/controller/subsystem/media_tracks/proc/add_track(var/mob/user, var/new_url, var/new_title, var/new_duration, var/new_artist, var/new_genre, var/new_secret, var/new_lobby)
if(!check_rights(R_DEBUG|R_FUN))
diff --git a/code/controllers/subsystems/mobs.dm b/code/controllers/subsystems/mobs.dm
index c124b5573ef..8fec502f21c 100644
--- a/code/controllers/subsystems/mobs.dm
+++ b/code/controllers/subsystems/mobs.dm
@@ -19,8 +19,9 @@ SUBSYSTEM_DEF(mobs)
var/slept_mobs = 0
var/list/process_z = list()
-/datum/controller/subsystem/mobs/stat_entry()
- ..("P: [global.mob_list.len] | S: [slept_mobs]")
+/datum/controller/subsystem/mobs/stat_entry(msg)
+ msg = "P: [global.mob_list.len] | S: [slept_mobs]"
+ return ..()
/datum/controller/subsystem/mobs/fire(resumed = 0)
if (!resumed)
@@ -90,4 +91,4 @@ SUBSYSTEM_DEF(mobs)
/datum/controller/subsystem/mobs/critfail()
..()
- log_recent()
\ No newline at end of file
+ log_recent()
diff --git a/code/controllers/subsystems/nightshift.dm b/code/controllers/subsystems/nightshift.dm
index 91b1c6bb357..4cfddfec0f7 100644
--- a/code/controllers/subsystems/nightshift.dm
+++ b/code/controllers/subsystems/nightshift.dm
@@ -11,7 +11,7 @@ SUBSYSTEM_DEF(nightshift)
var/high_security_mode = FALSE
/datum/controller/subsystem/nightshift/Initialize()
- if(!config.enable_night_shifts)
+ if(!CONFIG_GET(flag/enable_night_shifts))
can_fire = FALSE
/*
if(config.randomize_shift_time)
diff --git a/code/controllers/subsystems/orbits.dm b/code/controllers/subsystems/orbits.dm
index 5cda1ce9dc4..af7a5ab7eab 100644
--- a/code/controllers/subsystems/orbits.dm
+++ b/code/controllers/subsystems/orbits.dm
@@ -7,8 +7,9 @@ SUBSYSTEM_DEF(orbit)
var/list/currentrun = list()
var/list/processing = list()
-/datum/controller/subsystem/orbit/stat_entry()
- ..("P:[processing.len]")
+/datum/controller/subsystem/orbit/stat_entry(msg)
+ msg = "P:[processing.len]"
+ return ..()
/datum/controller/subsystem/orbit/fire(resumed = 0)
@@ -40,5 +41,3 @@ SUBSYSTEM_DEF(orbit)
O.Check(targetloc)
if (MC_TICK_CHECK)
return
-
-
diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm
index 9d840933cb7..0a953e97828 100644
--- a/code/controllers/subsystems/overlays.dm
+++ b/code/controllers/subsystems/overlays.dm
@@ -32,8 +32,9 @@ SUBSYSTEM_DEF(overlays)
fire(FALSE, TRUE)
..()
-/datum/controller/subsystem/overlays/stat_entry()
- ..("Queued Atoms: [queue.len], Cache Size: [cache_size]")
+/datum/controller/subsystem/overlays/stat_entry(msg)
+ msg = "Queued Atoms: [queue.len], Cache Size: [cache_size]"
+ return ..()
/datum/controller/subsystem/overlays/fire(resumed, no_mc_tick)
diff --git a/code/controllers/subsystems/overmap_renamer_vr.dm b/code/controllers/subsystems/overmap_renamer_vr.dm
index 5b2cd75da4e..0180b89355d 100644
--- a/code/controllers/subsystems/overmap_renamer_vr.dm
+++ b/code/controllers/subsystems/overmap_renamer_vr.dm
@@ -26,7 +26,7 @@ if we end up with multiple renamable lateload overmap objects.*/
if(V.visitable_renamed) //could just if(D.modify_descriptors()), but having a var recording renaming is useful for debugging and stuff!
if(V.known)
to_world_log("##Overmap Renamer: Renamed Debris Field as: [V.name]")
- admin_notice("Debris Field name chosen as [V.name]", R_DEBUG)
+ admin_notice(span_danger("Debris Field name chosen as [V.name]"), R_DEBUG)
else
to_world_log("##Overmap Renamer: Renamed Debris Field as: [V.real_name]")
- admin_notice("Debris Field name chosen as [V.real_name]", R_DEBUG)
+ admin_notice(span_danger("Debris Field name chosen as [V.real_name]"), R_DEBUG)
diff --git a/code/controllers/subsystems/persist_vr.dm b/code/controllers/subsystems/persist_vr.dm
index 5217b72f9ae..d74b96f9603 100644
--- a/code/controllers/subsystems/persist_vr.dm
+++ b/code/controllers/subsystems/persist_vr.dm
@@ -16,7 +16,7 @@ SUBSYSTEM_DEF(persist)
// Do PTO Accruals
/datum/controller/subsystem/persist/proc/update_department_hours(var/resumed = FALSE)
- if(!config.time_off)
+ if(!CONFIG_GET(flag/time_off))
return
establish_db_connection()
@@ -78,7 +78,7 @@ SUBSYSTEM_DEF(persist)
play_hours[department_earning] = wait_in_hours
// Cap it
- dept_hours[department_earning] = min(config.pto_cap, dept_hours[department_earning])
+ dept_hours[department_earning] = min(CONFIG_GET(number/pto_cap), dept_hours[department_earning])
// Okay we figured it out, lets update database!
var/sql_ckey = sql_sanitize_text(C.ckey)
@@ -104,4 +104,4 @@ SUBSYSTEM_DEF(persist)
// They have a custom title, aren't crew, or someone deleted their record, so we need a fallback method.
// Let's check the mind.
if(M.mind && M.mind.assigned_role)
- . = job_master.GetJob(M.mind.assigned_role)
\ No newline at end of file
+ . = job_master.GetJob(M.mind.assigned_role)
diff --git a/code/controllers/subsystems/persistence.dm b/code/controllers/subsystems/persistence.dm
index e20c83e5a59..1950e90e143 100644
--- a/code/controllers/subsystems/persistence.dm
+++ b/code/controllers/subsystems/persistence.dm
@@ -25,7 +25,7 @@ SUBSYSTEM_DEF(persistence)
/datum/controller/subsystem/persistence/proc/track_value(var/atom/value, var/track_type)
- if(config.persistence_disabled) //if the config is set to persistence disabled, nothing will save or load.
+ if(CONFIG_GET(flag/persistence_disabled)) //if the config is set to persistence disabled, nothing will save or load.
return
var/turf/T = get_turf(value)
@@ -33,7 +33,7 @@ SUBSYSTEM_DEF(persistence)
return
var/area/A = get_area(T)
- if(!A || (A.flags & AREA_FLAG_IS_NOT_PERSISTENT))
+ if(!A || (A.flag_check(AREA_FLAG_IS_NOT_PERSISTENT)))
return
if(!(T.z in using_map.persist_levels))
diff --git a/code/controllers/subsystems/ping.dm b/code/controllers/subsystems/ping.dm
index 0b76d7dea17..8f4836290a4 100644
--- a/code/controllers/subsystems/ping.dm
+++ b/code/controllers/subsystems/ping.dm
@@ -12,8 +12,9 @@ SUBSYSTEM_DEF(ping)
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun = list()
-/datum/controller/subsystem/ping/stat_entry()
- ..("P:[GLOB.clients.len]")
+/datum/controller/subsystem/ping/stat_entry(msg)
+ msg = "P:[GLOB.clients.len]"
+ return ..()
/datum/controller/subsystem/ping/fire(resumed = FALSE)
// Prepare the new batch of clients
@@ -27,7 +28,7 @@ SUBSYSTEM_DEF(ping)
var/client/client = currentrun[currentrun.len]
currentrun.len--
- if(!client?.is_preference_enabled(/datum/client_preference/vchat_enable))
+ if(!client?.prefs?.read_preference(/datum/preference/toggle/vchat_enable))
winset(client, "output", "on-show=&is-disabled=0&is-visible=1")
winset(client, "browseroutput", "is-disabled=1;is-visible=0")
client.tgui_panel.oldchat = TRUE
diff --git a/code/controllers/subsystems/planets.dm b/code/controllers/subsystems/planets.dm
index 4dae77ccbe0..2054d6daa79 100644
--- a/code/controllers/subsystems/planets.dm
+++ b/code/controllers/subsystems/planets.dm
@@ -15,7 +15,7 @@ SUBSYSTEM_DEF(planets)
var/static/list/needs_temp_update = list()
/datum/controller/subsystem/planets/Initialize(timeofday)
- admin_notice("Initializing planetary weather.", R_DEBUG)
+ admin_notice(span_danger("Initializing planetary weather."), R_DEBUG)
createPlanets()
..()
@@ -28,7 +28,7 @@ SUBSYSTEM_DEF(planets)
if(Z > z_to_planet.len)
z_to_planet.len = Z
if(z_to_planet[Z])
- admin_notice("Z[Z] is shared by more than one planet!", R_DEBUG)
+ admin_notice(span_danger("Z[Z] is shared by more than one planet!"), R_DEBUG)
continue
z_to_planet[Z] = NP
@@ -40,7 +40,7 @@ SUBSYSTEM_DEF(planets)
var/datum/planet/P = z_to_planet[T.z]
if(!istype(P))
return
- if(istype(T, /turf/unsimulated/wall/planetary))
+ if(istype(T, /turf/unsimulated/wall/planetary))
P.planet_walls += T
else if(istype(T, /turf/simulated) && T.is_outdoors())
P.planet_floors += T
@@ -71,7 +71,7 @@ SUBSYSTEM_DEF(planets)
updateSunlight(P)
if(MC_TICK_CHECK)
return
-
+
#ifndef UNIT_TEST // Don't be updating temperatures and such during unit tests
var/list/needs_temp_update = src.needs_temp_update
while(needs_temp_update.len)
@@ -105,7 +105,7 @@ SUBSYSTEM_DEF(planets)
/datum/controller/subsystem/planets/proc/updateSunlight(var/datum/planet/P)
var/new_brightness = P.sun["brightness"]
P.sun_holder.update_brightness(new_brightness, P.planet_floors)
-
+
var/new_color = P.sun["color"]
P.sun_holder.update_color(new_color)
diff --git a/code/controllers/subsystems/plants.dm b/code/controllers/subsystems/plants.dm
index f90d533eb66..7f25024c4a0 100644
--- a/code/controllers/subsystems/plants.dm
+++ b/code/controllers/subsystems/plants.dm
@@ -22,8 +22,9 @@ SUBSYSTEM_DEF(plants)
var/list/processing = list()
var/list/currentrun = list()
-/datum/controller/subsystem/plants/stat_entry()
- ..("P:[processing.len]|S:[seeds.len]")
+/datum/controller/subsystem/plants/stat_entry(msg)
+ msg = "P:[processing.len]|S:[seeds.len]"
+ return ..()
/datum/controller/subsystem/plants/Initialize(timeofday)
setup()
@@ -146,7 +147,7 @@ SUBSYSTEM_DEF(plants)
// Debug for testing seed genes.
/client/proc/show_plant_genes()
- set category = "Debug"
+ set category = "Debug.Investigate"
set name = "Show Plant Genes"
set desc = "Prints the round's plant gene masks."
diff --git a/code/controllers/subsystems/processing/obj_tab_items.dm b/code/controllers/subsystems/processing/obj_tab_items.dm
new file mode 100644
index 00000000000..53786daf011
--- /dev/null
+++ b/code/controllers/subsystems/processing/obj_tab_items.dm
@@ -0,0 +1,24 @@
+PROCESSING_SUBSYSTEM_DEF(obj_tab_items)
+ name = "Obj Tab Items"
+ flags = SS_NO_INIT
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ wait = 0.1 SECONDS
+
+// I know this is mostly copypasta, but I want to change the processing logic
+// Sorry bestie :(
+/datum/controller/subsystem/processing/obj_tab_items/fire(resumed = FALSE)
+ if (!resumed)
+ currentrun = processing.Copy()
+ //cache for sanic speed (lists are references anyways)
+ var/list/current_run = currentrun
+
+ while(current_run.len)
+ var/datum/thing = current_run[current_run.len]
+ if(QDELETED(thing))
+ processing -= thing
+ else if(thing.process(wait * 0.1) == PROCESS_KILL)
+ // fully stop so that a future START_PROCESSING will work
+ STOP_PROCESSING(src, thing)
+ if (MC_TICK_CHECK)
+ return
+ current_run.len--
diff --git a/code/controllers/subsystems/processing/processing.dm b/code/controllers/subsystems/processing/processing.dm
index 16b4da021b1..51c1afe015f 100644
--- a/code/controllers/subsystems/processing/processing.dm
+++ b/code/controllers/subsystems/processing/processing.dm
@@ -24,8 +24,9 @@ SUBSYSTEM_DEF(processing)
if(CHECK_BITFIELD(D.datum_flags, DF_ISPROCESSING))
processing |= D
-/datum/controller/subsystem/processing/stat_entry()
- ..("[stat_tag]:[processing.len]")
+/datum/controller/subsystem/processing/stat_entry(msg)
+ msg = "[stat_tag]:[processing.len]"
+ return ..()
/datum/controller/subsystem/processing/fire(resumed = 0)
if (!resumed)
@@ -69,14 +70,14 @@ SUBSYSTEM_DEF(processing)
log_world(msg)
return
msg += "Lists: current_run: [currentrun.len], processing: [processing.len]\n"
-
+
if(!currentrun.len)
msg += "!!The subsystem just finished the processing list, and currentrun is empty (or has never run).\n"
msg += "!!The info below is the tail of processing instead of currentrun.\n"
-
+
var/datum/D = currentrun.len ? currentrun[currentrun.len] : processing[processing.len]
msg += "Tail entry: [describeThis(D)] (this is likely the item AFTER the problem item)\n"
-
+
var/position = processing.Find(D)
if(!position)
msg += "Unable to find context of tail entry in processing list.\n"
diff --git a/code/controllers/subsystems/radiation.dm b/code/controllers/subsystems/radiation.dm
index 8f140a5fc83..624d6f4279c 100644
--- a/code/controllers/subsystems/radiation.dm
+++ b/code/controllers/subsystems/radiation.dm
@@ -24,7 +24,7 @@ SUBSYSTEM_DEF(radiation)
if(QDELETED(S))
sources -= S
else if(S.decay)
- S.update_rad_power(S.rad_power - config.radiation_decay_rate)
+ S.update_rad_power(S.rad_power - CONFIG_GET(number/radiation_decay_rate))
if (MC_TICK_CHECK)
return
@@ -54,8 +54,9 @@ SUBSYSTEM_DEF(radiation)
if (MC_TICK_CHECK)
return
-/datum/controller/subsystem/radiation/stat_entry()
- ..("S:[sources.len], RC:[resistance_cache.len]")
+/datum/controller/subsystem/radiation/stat_entry(msg)
+ msg = "S:[sources.len], RC:[resistance_cache.len]"
+ return ..()
// Ray trace from all active radiation sources to T and return the strongest effect.
/datum/controller/subsystem/radiation/proc/get_rads_at_turf(var/turf/T)
@@ -72,7 +73,7 @@ SUBSYSTEM_DEF(radiation)
if(source.respect_maint)
var/area/A = T.loc
- if(A.flags & RAD_SHIELDED)
+ if(A.flag_check(RAD_SHIELDED))
continue // In shielded area
var/dist = get_dist(source.source_turf, T)
@@ -92,12 +93,12 @@ SUBSYSTEM_DEF(radiation)
origin.calc_rad_resistance()
if(origin.cached_rad_resistance)
- if(config.radiation_resistance_calc_mode == RAD_RESIST_CALC_DIV)
- working = round((working / (origin.cached_rad_resistance * config.radiation_resistance_multiplier)), 0.01)
- else if(config.radiation_resistance_calc_mode == RAD_RESIST_CALC_SUB)
- working = round((working - (origin.cached_rad_resistance * config.radiation_resistance_multiplier)), 0.01)
+ if(CONFIG_GET(flag/radiation_resistance_calc_mode) == RAD_RESIST_CALC_DIV)
+ working = round((working / (origin.cached_rad_resistance * CONFIG_GET(number/radiation_resistance_multiplier))), 0.01)
+ else if(CONFIG_GET(flag/radiation_resistance_calc_mode) == RAD_RESIST_CALC_SUB)
+ working = round((working - (origin.cached_rad_resistance * CONFIG_GET(number/radiation_resistance_multiplier))), 0.01)
- if(working <= config.radiation_lower_limit) // Too far from this source
+ if(working <= CONFIG_GET(number/radiation_lower_limit)) // Too far from this source
working = 0 // May as well be 0
break
@@ -105,7 +106,7 @@ SUBSYSTEM_DEF(radiation)
// Shouldn't really ever have practical uses, but standing in a room literally made from uranium is more dangerous than standing next to a single uranium vase
. += working / (dist ** 2)
- if(. <= config.radiation_lower_limit)
+ if(. <= CONFIG_GET(number/radiation_lower_limit))
. = 0
// Add a radiation source instance to the repository. It will override any existing source on the same turf.
@@ -144,4 +145,4 @@ SUBSYSTEM_DEF(radiation)
if(!(power && source))
return
var/turf/epicentre = locate(round(world.maxx / 2), round(world.maxy / 2), source.z)
- flat_radiate(epicentre, power, world.maxx, respect_maint)
\ No newline at end of file
+ flat_radiate(epicentre, power, world.maxx, respect_maint)
diff --git a/code/controllers/subsystems/server_maint.dm b/code/controllers/subsystems/server_maint.dm
new file mode 100644
index 00000000000..e8d10d67487
--- /dev/null
+++ b/code/controllers/subsystems/server_maint.dm
@@ -0,0 +1,115 @@
+#define PING_BUFFER_TIME 25
+
+SUBSYSTEM_DEF(server_maint)
+ name = "Server Tasks"
+ wait = 6
+ flags = SS_POST_FIRE_TIMING
+ priority = FIRE_PRIORITY_SERVER_MAINT
+ init_order = INIT_ORDER_SERVER_MAINT
+ //init_stage = INITSTAGE_EARLY
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+ var/list/currentrun
+ ///Associated list of list names to lists to clear of nulls
+ var/list/lists_to_clear
+ ///Delay between list clearings in ticks
+ var/delay = 5
+ var/cleanup_ticker = 0
+
+/*/datum/controller/subsystem/server_maint/PreInit()
+ world.hub_password = "" *///quickly! before the hubbies see us.
+
+/datum/controller/subsystem/server_maint/New()
+ if (fexists("tmp/"))
+ fdel("tmp/")
+ //if (CONFIG_GET(flag/hub))
+ //world.update_hub_visibility(TRUE)
+ //Keep in mind, because of how delay works adding a list here makes each list take wait * delay more time to clear
+ //Do it for stuff that's properly important, and shouldn't have null checks inside its other uses
+ lists_to_clear = list(
+ "player_list" = global.player_list,
+ "mob_list" = global.mob_list,
+ "living_mob_list" = global.living_mob_list,
+ "dead_mob_list" = global.dead_mob_list,
+ "observer_mob_list" = global.observer_mob_list,
+ "listening_objects" = global.listening_objects,
+ "human_mob_list" = global.human_mob_list,
+ "silicon_mob_list" = global.silicon_mob_list,
+ "ai_list" = global.ai_list,
+ //"keyloop_list" = global.keyloop_list, //A null here will cause new clients to be unable to move. totally unacceptable
+ )
+
+ /*var/datum/tgs_version/tgsversion = world.TgsVersion()
+ if(tgsversion)
+ SSblackbox.record_feedback("text", "server_tools", 1, tgsversion.raw_parameter)*/
+
+ return SS_INIT_SUCCESS
+
+/datum/controller/subsystem/server_maint/fire(resumed = FALSE)
+ if(!resumed)
+ if(list_clear_nulls(GLOB.clients))
+ log_world("Found a null in clients list!")
+ src.currentrun = GLOB.clients.Copy()
+
+ var/position_in_loop = (cleanup_ticker / delay) + 1 //Index at 1, thanks byond
+
+ if(!(position_in_loop % 1)) //If it's a whole number
+ var/listname = lists_to_clear[position_in_loop]
+ if(list_clear_nulls(lists_to_clear[listname]))
+ log_world("Found a null in [listname]!")
+
+ cleanup_ticker++
+
+ var/amount_to_work = length(lists_to_clear)
+ if(cleanup_ticker >= amount_to_work * delay) //If we've already done a loop, reset
+ cleanup_ticker = 0
+
+ var/list/currentrun = src.currentrun
+ //var/round_started = SSticker.HasRoundStarted()
+
+ //var/kick_inactive = CONFIG_GET(flag/kick_inactive)
+ //var/afk_period
+ //if(kick_inactive)
+ //afk_period = CONFIG_GET(number/afk_period)
+ for(var/I in currentrun)
+ var/client/C = I
+ //handle kicking inactive players
+ /*if(round_started && kick_inactive && !C.holder && C.is_afk(afk_period))
+ var/cmob = C.mob
+ if (!isnewplayer(cmob) || !SSticker.queued_players.Find(cmob))
+ log_access("AFK: [key_name(C)]")
+ to_chat(C, span_userdanger("You have been inactive for more than [DisplayTimeText(afk_period)] and have been disconnected.") + "
" + span_danger("You may reconnect via the button in the file menu or by " + span_bold(span_underline("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+[num2text(world.time+world.tick_lag*TICK_USAGE_REAL/100, 32)]")
+
+ if (MC_TICK_CHECK) //one day, when ss13 has 1000 people per server, you guys are gonna be glad I added this tick check
+ return
+
+/datum/controller/subsystem/server_maint/Shutdown()
+ if (fexists("tmp/"))
+ fdel("tmp/")
+ //kick_clients_in_lobby(span_boldannounce("The round came to an end with you in the lobby."), TRUE) //second parameter ensures only afk clients are kicked
+ var/server = CONFIG_GET(string/server)
+ for(var/thing in GLOB.clients)
+ if(!thing)
+ continue
+ var/client/C = thing
+ C?.tgui_panel?.send_roundrestart()
+ if(server) //if you set a server location in config.txt, it sends you there instead of trying to reconnect to the same world address. -- NeoFite
+ C << link("byond://[server]")
+
+/*
+/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/subsystems/shuttles.dm b/code/controllers/subsystems/shuttles.dm
index 38ec9e5c83f..02f9cb91ebd 100644
--- a/code/controllers/subsystems/shuttles.dm
+++ b/code/controllers/subsystems/shuttles.dm
@@ -172,5 +172,6 @@ SUBSYSTEM_DEF(shuttles)
for(var/obj/effect/overmap/visitable/ship/ship_effect as anything in ships)
overmap_halted ? ship_effect.halt() : ship_effect.unhalt()
-/datum/controller/subsystem/shuttles/stat_entry()
- ..("Shuttles:[process_shuttles.len]/[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]")
+/datum/controller/subsystem/shuttles/stat_entry(msg)
+ msg = "Shuttles:[process_shuttles.len]/[shuttles.len], Ships:[ships.len], L:[registered_shuttle_landmarks.len][overmap_halted ? ", HALT" : ""]"
+ return ..()
diff --git a/code/controllers/subsystems/speech_controller.dm b/code/controllers/subsystems/speech_controller.dm
new file mode 100644
index 00000000000..e293c89a9bb
--- /dev/null
+++ b/code/controllers/subsystems/speech_controller.dm
@@ -0,0 +1,5 @@
+/// verb_manager subsystem just for handling say's
+VERB_MANAGER_SUBSYSTEM_DEF(speech_controller)
+ name = "Speech Controller"
+ wait = 1
+ priority = FIRE_PRIORITY_SPEECH_CONTROLLER//has to be high priority, second in priority ONLY to SSinput
diff --git a/code/controllers/subsystems/sqlite.dm b/code/controllers/subsystems/sqlite.dm
index 20a5a594759..b4074b3355d 100644
--- a/code/controllers/subsystems/sqlite.dm
+++ b/code/controllers/subsystems/sqlite.dm
@@ -14,7 +14,7 @@ SUBSYSTEM_DEF(sqlite)
return ..()
/datum/controller/subsystem/sqlite/proc/connect()
- if(!config.sqlite_enabled)
+ if(!CONFIG_GET(flag/sqlite_enabled))
return
if(!sqlite_db)
@@ -104,17 +104,17 @@ SUBSYSTEM_DEF(sqlite)
return !sqlite_check_for_errors(query, "Insert Feedback")
/datum/controller/subsystem/sqlite/proc/can_submit_feedback(client/C)
- if(!config.sqlite_enabled)
+ if(!CONFIG_GET(flag/sqlite_enabled))
return FALSE
- if(config.sqlite_feedback_min_age && !is_old_enough(C))
+ if(CONFIG_GET(number/sqlite_feedback_min_age) && !is_old_enough(C))
return FALSE
- if(config.sqlite_feedback_cooldown > 0 && get_feedback_cooldown(C.key, config.sqlite_feedback_cooldown, sqlite_db) > 0)
+ if(CONFIG_GET(number/sqlite_feedback_cooldown) > 0 && get_feedback_cooldown(C.key, CONFIG_GET(number/sqlite_feedback_cooldown), sqlite_db) > 0)
return FALSE
return TRUE
// Returns TRUE if the player is 'old' enough, according to the config.
/datum/controller/subsystem/sqlite/proc/is_old_enough(client/C)
- if(get_player_age(C.key) < config.sqlite_feedback_min_age)
+ if(get_player_age(C.key) < CONFIG_GET(number/sqlite_feedback_min_age))
return FALSE
return TRUE
diff --git a/code/controllers/subsystems/statpanel.dm b/code/controllers/subsystems/statpanel.dm
new file mode 100644
index 00000000000..2400e1da807
--- /dev/null
+++ b/code/controllers/subsystems/statpanel.dm
@@ -0,0 +1,481 @@
+SUBSYSTEM_DEF(statpanels)
+ name = "Stat Panels"
+ wait = 4
+ init_order = INIT_ORDER_STATPANELS
+ //init_stage = INITSTAGE_EARLY
+ priority = FIRE_PRIORITY_STATPANEL
+ runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
+ flags = SS_NO_INIT
+ var/list/currentrun = list()
+ var/list/global_data
+ var/list/mc_data
+ var/list/cached_images = list()
+
+ ///how many subsystem fires between most tab updates
+ var/default_wait = 10
+ ///how many subsystem fires between updates of misc tabs
+ var/misc_wait = 3
+ ///how many subsystem fires between updates of the status tab
+ var/status_wait = 2
+ ///how many subsystem fires between updates of the MC tab
+ var/mc_wait = 5
+ ///how many full runs this subsystem has completed. used for variable rate refreshes.
+ var/num_fires = 0
+
+/datum/controller/subsystem/statpanels/fire(resumed = FALSE)
+ if (!resumed)
+ num_fires++
+ //var/datum/map_config/cached = SSmapping.next_map_config
+ global_data = list(
+ //"Map: [SSmapping.config?.map_name || "Loading..."]",
+ "Map: [using_map.name]",
+ //cached ? "Next Map: [cached.map_name]" : null,
+ //"Next Map: -- Not Available --",
+ // "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]",
+ "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]",
+ "Round Time: [roundduration2text()]",
+ "Station Date: [stationdate2text()]", // [capitalize(GLOB.world_time_season)]",
+ "Station Time: [stationtime2text()]",
+ "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)"
+ )
+
+ if(emergency_shuttle.evac)
+ var/ETA = emergency_shuttle.get_status_panel_eta()
+ if(ETA)
+ global_data += "[ETA]"
+ src.currentrun = GLOB.clients.Copy()
+ mc_data = null
+
+ var/list/currentrun = src.currentrun
+ while(length(currentrun))
+ var/client/target = currentrun[length(currentrun)]
+ currentrun.len--
+
+ if(!target?.stat_panel?.is_ready()) // Null target client, client has null stat panel, or stat panel isn't ready
+ continue
+
+ if(target.stat_tab == "Status" && num_fires % status_wait == 0)
+ set_status_tab(target)
+
+ if(!target.holder)
+ target.stat_panel.send_message("remove_admin_tabs")
+ else
+ //target.stat_panel.send_message("update_split_admin_tabs", !!(target.prefs.toggles & SPLIT_ADMIN_TABS))
+ target.stat_panel.send_message("update_split_admin_tabs", FALSE)
+
+ if(!("MC" in target.panel_tabs) || !("Tickets" in target.panel_tabs))
+ target.stat_panel.send_message("add_admin_tabs", target.holder.href_token)
+
+ //if(target.stat_tab == "MC" && ((num_fires % mc_wait == 0) || target?.prefs.read_preference(/datum/preference/toggle/fast_mc_refresh)))
+ //set_MC_tab(target)
+ if(target.stat_tab == "MC" && ((num_fires % mc_wait == 0)))
+ set_MC_tab(target)
+
+ if(target.stat_tab == "Tickets" && num_fires % default_wait == 0)
+ set_tickets_tab(target)
+
+ if(!length(GLOB.sdql2_queries) && ("SDQL2" in target.panel_tabs))
+ target.stat_panel.send_message("remove_sdql2")
+
+ else if(length(GLOB.sdql2_queries) && (target.stat_tab == "SDQL2" || !("SDQL2" in target.panel_tabs)) && num_fires % default_wait == 0)
+ set_SDQL2_tab(target)
+
+ if(target.mob)
+ var/mob/target_mob = target.mob
+
+ // Handle the action panels of the stat panel
+
+ var/update_actions = FALSE
+ // We're on a spell tab, update the tab so we can see cooldowns progressing and such
+ if(target.stat_tab in target.spell_tabs)
+ update_actions = TRUE
+ // We're not on a spell tab per se, but we have cooldown actions, and we've yet to
+ // set up our spell tabs at all
+ //if(!length(target.spell_tabs) && locate(/datum/action/cooldown) in target_mob.actions)
+ //update_actions = TRUE
+
+ if(update_actions && num_fires % default_wait == 0)
+ set_action_tabs(target, target_mob)
+ //Update every fire if tab is open, otherwise update every 7 fires
+ if((num_fires % misc_wait == 0))
+ update_misc_tabs(target,target_mob)
+
+ var/datum/object_window_info/obj_window = target.obj_window
+ if(obj_window)
+ if(obj_window.flags & TURFLIST_UPDATE_QUEUED)
+ immediate_send_stat_data(target)
+ obj_window.flags = 0
+
+ if(MC_TICK_CHECK)
+ return
+
+/datum/controller/subsystem/statpanels/proc/update_misc_tabs(var/client/target,var/mob/target_mob)
+ target_mob.update_misc_tabs()
+ for(var/tab in target_mob.misc_tabs)
+ if(target_mob.misc_tabs[tab].len == 0 && (tab in target.misc_tabs))
+ target.misc_tabs -= tab
+ target.stat_panel.send_message("remove_misc",tab)
+
+ if(target_mob.misc_tabs[tab].len > 0)
+ if(!(tab in target.misc_tabs))
+ target.misc_tabs += tab
+ target.stat_panel.send_message("create_misc",tab)
+ target.stat_panel.send_message("update_misc",list(
+ TN = tab, \
+ TC = target_mob.misc_tabs[tab], \
+ ))
+
+ for(var/tab in target.misc_tabs)
+ if(!(tab in target_mob.misc_tabs))
+ target.misc_tabs -= tab
+ target.stat_panel.send_message("remove_misc",tab)
+
+/datum/controller/subsystem/statpanels/proc/set_status_tab(client/target)
+ if(!global_data)//statbrowser hasnt fired yet and we were called from immediate_send_stat_data()
+ return
+
+ target.stat_panel.send_message("update_stat", list(
+ global_data = global_data,
+ ping_str = "Ping: [round(target.lastping, 1)]ms (Average: [round(target.avgping, 1)]ms)",
+ other_str = target.mob?.get_status_tab_items(),
+ ))
+
+/datum/controller/subsystem/statpanels/proc/set_MC_tab(client/target)
+ var/turf/eye_turf = get_turf(target.eye)
+ var/coord_entry = COORD(eye_turf)
+ if(!mc_data)
+ generate_mc_data()
+ target.stat_panel.send_message("update_mc", list(mc_data = mc_data, coord_entry = coord_entry))
+
+/datum/controller/subsystem/statpanels/proc/set_examine_tab(client/target)
+ var/description_holders = target.description_holders
+ var/list/examine_update = list()
+
+ if(!target.obj_window)
+ target.obj_window = new(target)
+ if(!target.examine_icon && !target.obj_window.examine_target && target.stat_tab == "Examine")
+ target.obj_window.examine_target = description_holders["icon"]
+ target.obj_window.atoms_to_show += target.obj_window.examine_target
+ START_PROCESSING(SSobj_tab_items, target.obj_window)
+ refresh_client_obj_view(target)
+ examine_update += "[target.examine_icon] [description_holders["name"]]" //The name, written in big letters.
+ examine_update += "[description_holders["desc"]]" //the default examine text.
+ if(description_holders["info"])
+ examine_update += "" + span_bold("[replacetext(description_holders["info"], "\n", "
")]") + "
" //Blue, informative text.
+ if(description_holders["interactions"])
+ for(var/line in description_holders["interactions"])
+ examine_update += "" + span_bold("[line]") + "
"
+ if(description_holders["fluff"])
+ examine_update += "" + span_bold("[replacetext(description_holders["fluff"], "\n", "
")]") + "
" //Green, fluff-related text.
+ if(description_holders["antag"])
+ examine_update += "" + span_bold("[description_holders["antag"]]") + "
" //Red, malicious antag-related text
+
+ target.stat_panel.send_message("update_examine", examine_update)
+
+/datum/controller/subsystem/statpanels/proc/set_tickets_tab(client/target)
+ var/list/tickets = list()
+ if(check_rights(R_ADMIN|R_SERVER|R_MOD,FALSE,target)) //Prevents non-staff from opening the list of ahelp tickets //YW EDIT: Only admins/mods can check Tickets
+ tickets += GLOB.ahelp_tickets.stat_entry(target)
+ tickets += GLOB.mhelp_tickets.stat_entry(target)
+ target.stat_panel.send_message("update_tickets", tickets)
+
+/datum/controller/subsystem/statpanels/proc/set_SDQL2_tab(client/target)
+ var/list/sdql2A = list()
+ sdql2A[++sdql2A.len] = list("", "Access Global SDQL2 List", REF(GLOB.sdql2_vv_statobj))
+ var/list/sdql2B = list()
+ for(var/datum/SDQL2_query/query as anything in GLOB.sdql2_queries)
+ sdql2B = query.generate_stat()
+
+ sdql2A += sdql2B
+ target.stat_panel.send_message("update_sdql2", sdql2A)
+
+/// Set up the various action tabs.
+/datum/controller/subsystem/statpanels/proc/set_action_tabs(client/target, mob/target_mob)
+ return
+ //var/list/actions = target_mob.get_actions_for_statpanel()
+ //target.spell_tabs.Cut()
+
+ //for(var/action_data in actions)
+ // target.spell_tabs |= action_data[1]
+
+ //target.stat_panel.send_message("update_spells", list(spell_tabs = target.spell_tabs, actions = actions))
+
+/datum/controller/subsystem/statpanels/proc/set_turf_examine_tab(client/target, mob/target_mob)
+ if(!target)//statbrowser hasnt fired yet and we were called from immediate_send_stat_data()
+ return
+ var/list/overrides = list()
+ for(var/image/target_image as anything in target.images)
+ if(!target_image.loc || target_image.loc.loc != target.tracked_turf || !target_image.override)
+ continue
+ overrides += target_image.loc
+
+ var/list/atoms_to_display = list(target.tracked_turf)
+ for(var/atom/movable/turf_content as anything in target.tracked_turf)
+ if(turf_content.mouse_opacity == MOUSE_OPACITY_TRANSPARENT)
+ continue
+ if(turf_content.invisibility > target_mob.see_invisible)
+ continue
+ if(turf_content in overrides)
+ continue
+ //if(turf_content.IsObscured())
+ //continue
+ atoms_to_display += turf_content
+
+ /// Set the atoms we're meant to display
+ var/datum/object_window_info/obj_window = target.obj_window
+ if(!obj_window)
+ return // previous one no longer exists
+ obj_window.atoms_to_show = atoms_to_display
+ START_PROCESSING(SSobj_tab_items, obj_window)
+ refresh_client_obj_view(target)
+
+/datum/controller/subsystem/statpanels/proc/refresh_client_obj_view(client/refresh)
+ var/list/turf_items = return_object_images(refresh)
+ if(!length(turf_items)/* || !refresh.mob?.listed_turf*/)
+ return
+ refresh.stat_panel.send_message("update_listedturf", turf_items)
+
+#define OBJ_IMAGE_LOADING "statpanels obj loading temporary"
+/// Returns all our ready object tab images
+/// Returns a list in the form list(list(object_name, object_ref, loaded_image), ...)
+/datum/controller/subsystem/statpanels/proc/return_object_images(client/load_from)
+ // You might be inclined to think that this is a waste of cpu time, since we
+ // A: Double iterate over atoms in the build case, or
+ // B: Generate these lists over and over in the refresh case
+ // It's really not very hot. The hot portion of this code is genuinely mostly in the image generation
+ // So it's ok to pay a performance cost for cleanliness here
+
+ // No turf? go away
+ /*if(!load_from.mob?.listed_turf)
+ return list()*/
+ var/datum/object_window_info/obj_window = load_from.obj_window
+ var/list/already_seen = obj_window.atoms_to_images
+ var/list/to_make = obj_window.atoms_to_imagify
+ var/list/turf_items = list()
+ for(var/atom/turf_item as anything in obj_window.atoms_to_show)
+ // First, we fill up the list of refs to display
+ // If we already have one, just use that
+ var/existing_image = already_seen[turf_item]
+ if(existing_image == OBJ_IMAGE_LOADING)
+ continue
+ // We already have it. Success!
+ if(existing_image)
+ if(turf_item == obj_window.examine_target) //not actually a turf item get trolled
+ load_from.examine_icon = ""
+ obj_window.examine_target = null
+ set_examine_tab(load_from)
+ continue
+ turf_items[++turf_items.len] = list("[turf_item.name]", REF(turf_item), existing_image)
+ continue
+ // Now, we're gonna queue image generation out of those refs
+ to_make += turf_item
+ already_seen[turf_item] = OBJ_IMAGE_LOADING
+ obj_window.RegisterSignal(turf_item, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/datum/object_window_info,viewing_atom_deleted)) // we reset cache if anything in it gets deleted
+ return turf_items
+
+#undef OBJ_IMAGE_LOADING
+
+/datum/controller/subsystem/statpanels/proc/generate_mc_data()
+ mc_data = list(
+ list("CPU:", world.cpu),
+ list("Instances:", "[num2text(world.contents.len, 10)]"),
+ list("World Time:", "[world.time]"),
+ list("Globals:", GLOB.stat_entry(), "\ref[GLOB]"),
+ // list("[config]:", config.stat_entry(), "\ref[config]"),
+ list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"),
+ list("Master Controller:", Master.stat_entry(), "\ref[Master]"),
+ list("Failsafe Controller:", Failsafe.stat_entry(), "\ref[Failsafe]"),
+ list("","")
+ )
+ for(var/datum/controller/subsystem/sub_system as anything in Master.subsystems)
+ mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), "\ref[sub_system]")
+ mc_data[++mc_data.len] = list("Camera Net", "Cameras: [global.cameranet.cameras.len] | Chunks: [global.cameranet.chunks.len]", "\ref[global.cameranet]")
+
+///immediately update the active statpanel tab of the target client
+/datum/controller/subsystem/statpanels/proc/immediate_send_stat_data(client/target)
+ if(!target.stat_panel.is_ready())
+ return FALSE
+
+ if(target.stat_tab == "Examine")
+ set_examine_tab(target)
+ return TRUE
+
+ if(target.stat_tab == "Status")
+ set_status_tab(target)
+ return TRUE
+
+ var/mob/target_mob = target.mob
+
+ // Handle actions
+
+ var/update_actions = FALSE
+ if(target.stat_tab in target.spell_tabs)
+ update_actions = TRUE
+
+ //if(!length(target.spell_tabs) && locate(/datum/action/cooldown) in target_mob.actions)
+ //update_actions = TRUE
+
+ if(update_actions)
+ set_action_tabs(target, target_mob)
+ return TRUE
+
+ // Handle turfs
+
+ if(target.tracked_turf)
+ if(!target_mob.TurfAdjacent(target.tracked_turf))
+ target_mob.set_listed_turf(null)
+
+ else if(target.stat_tab == target.tracked_turf.name || !(target.tracked_turf.name in target.panel_tabs))
+ set_turf_examine_tab(target, target_mob)
+ return TRUE
+
+ if(!target.holder)
+ return FALSE
+
+ if(target.stat_tab == "MC")
+ set_MC_tab(target)
+ return TRUE
+
+ if(target.stat_tab == "Tickets")
+ set_tickets_tab(target)
+ return TRUE
+
+ if(!length(GLOB.sdql2_queries) && ("SDQL2" in target.panel_tabs))
+ target.stat_panel.send_message("remove_sdql2")
+
+ else if(length(GLOB.sdql2_queries) && target.stat_tab == "SDQL2")
+ set_SDQL2_tab(target)
+
+/atom/proc/remove_from_cache()
+ SIGNAL_HANDLER
+ SSstatpanels.cached_images -= REF(src)
+
+/// Stat panel window declaration
+/client/var/datum/tgui_window/stat_panel
+/// Turf examine turf
+/client/var/turf/tracked_turf
+
+/// Datum that holds and tracks info about a client's object window
+/// Really only exists because I want to be able to do logic with signals
+/// And need a safe place to do the registration
+/datum/object_window_info
+ /// list of atoms to show to our client via the object tab, at least currently
+ var/list/atoms_to_show = list()
+ /// list of atom -> image string for objects we have had in the right click tab
+ /// this is our caching
+ var/list/atoms_to_images = list()
+ /// list of atoms to turn into images for the object tab
+ var/list/atoms_to_imagify = list()
+ /// Our owner client
+ var/client/parent
+ ///For reusing this logic for examines
+ var/atom/examine_target
+ var/flags = 0
+
+/datum/object_window_info/New(client/parent)
+ . = ..()
+ src.parent = parent
+
+/datum/object_window_info/Destroy(force, ...)
+ atoms_to_show = null
+ atoms_to_images = null
+ atoms_to_imagify = null
+ parent.obj_window = null
+ parent = null
+ STOP_PROCESSING(SSobj_tab_items, src)
+ return ..()
+
+/// Takes a client, attempts to generate object images for it
+/// We will update the client with any improvements we make when we're done
+/datum/object_window_info/process(seconds_per_tick)
+ // Cache the datum access for sonic speed
+ var/list/to_make = atoms_to_imagify
+ var/list/newly_seen = atoms_to_images
+ var/index = 0
+ for(index in 1 to length(to_make))
+ var/atom/thing = to_make[index]
+
+ if(!thing) // A null thing snuck in somehow
+ continue
+
+ var/generated_string
+ if(ismob(thing) || length(thing.overlays) > 0)
+ var/force_south = FALSE
+ if(isliving(thing))
+ force_south = TRUE
+ generated_string = costly_icon2html(thing, parent, sourceonly=TRUE, force_south = force_south)
+ else
+ generated_string = icon2html(thing, parent, sourceonly=TRUE)
+
+ newly_seen[thing] = generated_string
+ if(TICK_CHECK)
+ to_make.Cut(1, index + 1)
+ index = 0
+ break
+ // If we've not cut yet, do it now
+ if(index)
+ to_make.Cut(1, index + 1)
+ SSstatpanels.refresh_client_obj_view(parent)
+ if(!length(to_make))
+ return PROCESS_KILL
+
+/datum/object_window_info/proc/start_turf_tracking(turf/new_turf)
+ if(parent.tracked_turf)
+ stop_turf_tracking()
+ var/static/list/connections = list(
+ COMSIG_MOVABLE_MOVED = PROC_REF(on_mob_move),
+ COMSIG_MOB_LOGOUT = PROC_REF(on_mob_logout),
+ )
+ AddComponent(/datum/component/connect_mob_behalf, parent, connections)
+ RegisterSignal(parent.tracked_turf, COMSIG_ATOM_ENTERED, PROC_REF(turflist_changed))
+ RegisterSignal(parent.tracked_turf, COMSIG_ATOM_EXITED, PROC_REF(turflist_changed))
+ parent.stat_panel.send_message("create_listedturf", new_turf)
+ parent.tracked_turf = new_turf
+
+/datum/object_window_info/proc/stop_turf_tracking()
+ if(GetComponent(/datum/component/connect_mob_behalf))
+ qdel(GetComponent(/datum/component/connect_mob_behalf))
+ if(parent.tracked_turf)
+ UnregisterSignal(parent.tracked_turf, COMSIG_ATOM_ENTERED)
+ UnregisterSignal(parent.tracked_turf, COMSIG_ATOM_EXITED)
+ parent.stat_panel.send_message("remove_listedturf")
+ parent.tracked_turf = null
+
+/datum/object_window_info/proc/on_mob_move(mob/source)
+ SIGNAL_HANDLER
+ if(!parent.tracked_turf || !source.TurfAdjacent(parent.tracked_turf))
+ source.set_listed_turf(null)
+
+/datum/object_window_info/proc/on_mob_logout(mob/source)
+ SIGNAL_HANDLER
+ on_mob_move(parent.mob)
+
+/datum/object_window_info/proc/turflist_changed(mob/source)
+ if(!parent)//statbrowser hasnt fired yet and we still have a pending action
+ return
+ SIGNAL_HANDLER
+ if(!(flags & TURFLIST_UPDATED)) //Limit updates to 1 per tick
+ SSstatpanels.immediate_send_stat_data(parent)
+ flags |= TURFLIST_UPDATED
+ else if(!(flags & TURFLIST_UPDATE_QUEUED))
+ flags |= TURFLIST_UPDATE_QUEUED
+
+/// Clears any cached object window stuff
+/// We use hard refs cause we'd need a signal for this anyway. Cleaner this way
+/datum/object_window_info/proc/viewing_atom_deleted(atom/deleted)
+ SIGNAL_HANDLER
+ atoms_to_show -= deleted
+ atoms_to_imagify -= deleted
+ atoms_to_images -= deleted
+
+/mob/proc/set_listed_turf(turf/new_turf)
+ if(!client)
+ return
+ if(!client.obj_window)
+ client.obj_window = new(client)
+ if(client.tracked_turf == new_turf)
+ return
+ if(!new_turf)
+ client.obj_window.stop_turf_tracking() //Needs to go before listed_turf is set to null so signals can be removed
+ return
+ client.obj_window.start_turf_tracking(new_turf)
diff --git a/code/controllers/subsystems/supply.dm b/code/controllers/subsystems/supply.dm
index 59d4f606b5b..e7ead3b7706 100644
--- a/code/controllers/subsystems/supply.dm
+++ b/code/controllers/subsystems/supply.dm
@@ -39,20 +39,21 @@ SUBSYSTEM_DEF(supply)
/datum/controller/subsystem/supply/fire()
points += points_per_process
-/datum/controller/subsystem/supply/stat_entry()
- ..("Points: [points]")
+/datum/controller/subsystem/supply/stat_entry(msg)
+ msg = "Points: [points]"
+ return ..()
//To stop things being sent to CentCom which should not be sent to centcomm. Recursively checks for these types.
/datum/controller/subsystem/supply/proc/forbidden_atoms_check(atom/A)
if(isliving(A))
return 1
- if(istype(A,/obj/item/weapon/disk/nuclear))
+ if(istype(A,/obj/item/disk/nuclear))
return 1
if(istype(A,/obj/machinery/nuclearbomb))
return 1
- if(istype(A,/obj/item/device/radio/beacon))
+ if(istype(A,/obj/item/radio/beacon))
return 1
- if(istype(A,/obj/item/device/perfect_tele_beacon)) //VOREStation Addition: Translocator beacons
+ if(istype(A,/obj/item/perfect_tele_beacon)) //VOREStation Addition: Translocator beacons
return 1 //VOREStation Addition: Translocator beacons
if(istype(A,/obj/machinery/power/quantumpad)) // //VOREStation Add: Quantum pads
return 1 //VOREStation Add: Quantum pads
@@ -94,8 +95,8 @@ SUBSYSTEM_DEF(supply)
)
// Sell manifests
- if(find_slip && istype(A,/obj/item/weapon/paper/manifest))
- var/obj/item/weapon/paper/manifest/slip = A
+ if(find_slip && istype(A,/obj/item/paper/manifest))
+ var/obj/item/paper/manifest/slip = A
if(!slip.is_copy && slip.stamped && slip.stamped.len) //yes, the clown stamp will work. clown is the highest authority on the station, it makes sense
points += points_per_slip
EC.contents[EC.contents.len]["value"] = points_per_slip
@@ -112,8 +113,8 @@ SUBSYSTEM_DEF(supply)
EC.value += EC.contents[EC.contents.len]["value"]
//Sell spacebucks
- if(istype(A, /obj/item/weapon/spacecash))
- var/obj/item/weapon/spacecash/cashmoney = A
+ if(istype(A, /obj/item/spacecash))
+ var/obj/item/spacecash/cashmoney = A
EC.contents[EC.contents.len]["value"] = cashmoney.worth * points_per_money
EC.contents[EC.contents.len]["quantity"] = cashmoney.worth
EC.value += EC.contents[EC.contents.len]["value"]
@@ -200,15 +201,15 @@ SUBSYSTEM_DEF(supply)
A.req_access = L.Copy()
LAZYCLEARLIST(A.req_one_access)
else
- log_debug("Supply pack with invalid access restriction [SP.access] encountered!")
+ log_debug(span_danger("Supply pack with invalid access restriction [SP.access] encountered!"))
//supply manifest generation begin
- var/obj/item/weapon/paper/manifest/slip
+ var/obj/item/paper/manifest/slip
if(!SP.contraband)
if(A)
- slip = new /obj/item/weapon/paper/manifest(A)
+ slip = new /obj/item/paper/manifest(A)
else
- slip = new /obj/item/weapon/paper/manifest(pickedloc)
+ slip = new /obj/item/paper/manifest(pickedloc)
slip.is_copy = 0
slip.info = "[command_name()] Shipping Manifest
"
slip.info +="Order #[SO.ordernum]
"
diff --git a/code/controllers/subsystems/tgui.dm b/code/controllers/subsystems/tgui.dm
index 46b3ae90c2e..9f0baf12e65 100644
--- a/code/controllers/subsystems/tgui.dm
+++ b/code/controllers/subsystems/tgui.dm
@@ -35,8 +35,9 @@ SUBSYSTEM_DEF(tgui)
/datum/controller/subsystem/tgui/Shutdown()
close_all_uis()
-/datum/controller/subsystem/tgui/stat_entry()
- ..("P:[all_uis.len]")
+/datum/controller/subsystem/tgui/stat_entry(msg)
+ msg = "P:[all_uis.len]"
+ return ..()
/datum/controller/subsystem/tgui/fire(resumed = FALSE)
if(!resumed)
diff --git a/code/controllers/subsystems/throwing.dm b/code/controllers/subsystems/throwing.dm
index 0cad319b7da..037970ef936 100644
--- a/code/controllers/subsystems/throwing.dm
+++ b/code/controllers/subsystems/throwing.dm
@@ -9,8 +9,9 @@ SUBSYSTEM_DEF(throwing)
var/list/currentrun
var/list/processing = list()
-/datum/controller/subsystem/throwing/stat_entry()
- ..("P:[processing.len]")
+/datum/controller/subsystem/throwing/stat_entry(msg)
+ msg = "P:[processing.len]"
+ return ..()
/datum/controller/subsystem/throwing/fire(resumed = 0)
if (!resumed)
@@ -121,7 +122,7 @@ SUBSYSTEM_DEF(throwing)
//calculate how many tiles to move, making up for any missed ticks.
var/tilestomove = CEILING(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait), 1)
while (tilestomove-- > 0)
- if ((dist_travelled >= maxrange || AM.loc == target_turf) && (A && A.has_gravity()))
+ if ((dist_travelled >= maxrange || AM.loc == target_turf) && (A && A.get_gravity()))
finalize()
return
diff --git a/code/controllers/subsystems/ticker.dm b/code/controllers/subsystems/ticker.dm
index 6846a79b8ea..2daf0413e25 100644
--- a/code/controllers/subsystems/ticker.dm
+++ b/code/controllers/subsystems/ticker.dm
@@ -41,14 +41,18 @@ SUBSYSTEM_DEF(ticker)
//Now we have a general cinematic centrally held within the gameticker....far more efficient!
var/obj/screen/cinematic = null
+ var/round_start_time = 0
+
+
+
// This global variable exists for legacy support so we don't have to rename every 'ticker' to 'SSticker' yet.
var/global/datum/controller/subsystem/ticker/ticker
/datum/controller/subsystem/ticker/PreInit()
global.ticker = src // TODO - Remove this! Change everything to point at SSticker intead
/datum/controller/subsystem/ticker/Initialize()
- pregame_timeleft = config.pregame_time
- send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]")
+ pregame_timeleft = CONFIG_GET(number/pregame_time)
+ send2mainirc("Server lobby is loaded and open at byond://[CONFIG_GET(string/serverurl) ? CONFIG_GET(string/serverurl) : (CONFIG_GET(string/server) ? CONFIG_GET(string/server) : "[world.address]:[world.port]")]")
SSwebhooks.send(
WEBHOOK_ROUNDPREP,
list(
@@ -74,8 +78,8 @@ var/global/datum/controller/subsystem/ticker/ticker
post_game_tick()
/datum/controller/subsystem/ticker/proc/pregame_welcome()
- to_world("Welcome to the pregame lobby!")
- to_world("Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.")
+ to_world(span_boldannounce(span_notice("Welcome to the pregame lobby!")))
+ to_world(span_boldannounce(span_notice("Please set up your character and select ready. The round will start in [pregame_timeleft] seconds.")))
world << sound('sound/misc/server-ready.ogg', volume = 100)
// Called during GAME_STATE_PREGAME (RUNLEVEL_LOBBY)
@@ -85,7 +89,7 @@ var/global/datum/controller/subsystem/ticker/ticker
if(start_immediately)
pregame_timeleft = 0
- else if(SSvote.time_remaining)
+ else if(SSvote.active_vote)
return // vote still going, wait for it.
// Time to start the game!
@@ -96,15 +100,16 @@ var/global/datum/controller/subsystem/ticker/ticker
fire() // Don't wait for next tick, do it now!
return
- if(pregame_timeleft <= config.vote_autogamemode_timeleft && !SSvote.gamemode_vote_called)
- SSvote.autogamemode() // Start the game mode vote (if we haven't had one already)
+ //if(pregame_timeleft <= config.vote_autogamemode_timeleft && !SSvote.gamemode_vote_called)
+ //.autogamemode() // Start the game mode vote (if we haven't had one already)
// Called during GAME_STATE_SETTING_UP (RUNLEVEL_SETUP)
/datum/controller/subsystem/ticker/proc/setup_tick(resumed = FALSE)
+ round_start_time = world.time // otherwise round_start_time would be 0 for the signals
if(!setup_choose_gamemode())
// It failed, go back to lobby state and re-send the welcome message
- pregame_timeleft = config.pregame_time
- SSvote.gamemode_vote_called = FALSE // Allow another autogamemode vote
+ pregame_timeleft = CONFIG_GET(number/pregame_time)
+ // SSvote.gamemode_vote_called = FALSE // Allow another autogamemode vote
current_state = GAME_STATE_PREGAME
Master.SetRunLevel(RUNLEVEL_LOBBY)
pregame_welcome()
@@ -123,20 +128,20 @@ var/global/datum/controller/subsystem/ticker/ticker
var/list/runnable_modes = config.get_runnable_modes()
if((master_mode == "random") || (master_mode == "secret"))
if(!runnable_modes.len)
- to_world("Unable to choose playable game mode. Reverting to pregame lobby.")
+ to_world(span_filter_system(span_bold("Unable to choose playable game mode.") + " Reverting to pregame lobby."))
return 0
if(secret_force_mode != "secret")
src.mode = config.pick_mode(secret_force_mode)
if(!src.mode)
var/list/weighted_modes = list()
for(var/datum/game_mode/GM in runnable_modes)
- weighted_modes[GM.config_tag] = config.probabilities[GM.config_tag]
- src.mode = gamemode_cache[pickweight(weighted_modes)]
+ weighted_modes[GM.config_tag] = CONFIG_GET(keyed_list/probabilities)[GM.config_tag]
+ src.mode = config.gamemode_cache[pickweight(weighted_modes)]
else
src.mode = config.pick_mode(master_mode)
if(!src.mode)
- to_world("Serious error in mode setup! Reverting to pregame lobby.") //Uses setup instead of set up due to computational context.
+ to_world(span_boldannounce("Serious error in mode setup! Reverting to pregame lobby.")) //Uses setup instead of set up due to computational context.
return 0
job_master.ResetOccupations()
@@ -145,21 +150,21 @@ var/global/datum/controller/subsystem/ticker/ticker
job_master.DivideOccupations() // Apparently important for new antagonist system to register specific job antags properly.
if(!src.mode.can_start())
- to_world("Unable to start [mode.name]. Not enough players readied, [config.player_requirements[mode.config_tag]] players needed. Reverting to pregame lobby.")
+ to_world(span_filter_system(span_bold("Unable to start [mode.name].") + " Not enough players readied, [CONFIG_GET(keyed_list/player_requirements)[mode.config_tag]] players needed. Reverting to pregame lobby."))
mode.fail_setup()
mode = null
job_master.ResetOccupations()
return 0
if(hide_mode)
- to_world("The current game mode is - Secret!")
+ to_world(span_world(span_notice("The current game mode is - Secret!")))
if(runnable_modes.len)
var/list/tmpmodes = new
for (var/datum/game_mode/M in runnable_modes)
tmpmodes+=M.name
tmpmodes = sortList(tmpmodes)
if(tmpmodes.len)
- to_world("Possibilities: [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]")
+ to_world(span_filter_system(span_bold("Possibilities:") + " [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]"))
else
src.mode.announce()
return 1
@@ -181,12 +186,12 @@ var/global/datum/controller/subsystem/ticker/ticker
//Deleting Startpoints but we need the ai point to AI-ize people later
if (S.name != "AI")
qdel(S)
- to_world("Enjoy the game!")
+ to_world(span_boldannounce(span_notice("Enjoy the game!")))
//YW Change start: Custom message thanks to VerySoft and a 5% chance to play a secret message
var/rssound = 1
if(rssound == 1)
if(prob(95))
- world << sound('sound/AI/yawn/welcome.ogg')
+ world << sound('sound/AI/yawn/welcome.ogg')
else
world << sound('sound/AI/yawn/welcome_secret.ogg')
//YW Change end:
@@ -200,7 +205,7 @@ var/global/datum/controller/subsystem/ticker/ticker
current_state = GAME_STATE_PLAYING
Master.SetRunLevel(RUNLEVEL_GAME)
- if(config.sql_enabled)
+ if(CONFIG_GET(flag/sql_enabled))
statistic_cycle() // Polls population totals regularly and stores them in an SQL DB -- TLE
return 1
@@ -216,7 +221,7 @@ var/global/datum/controller/subsystem/ticker/ticker
// Calculate if game and/or mode are finished (Complicated by the continuous_rounds config option)
var/game_finished = FALSE
var/mode_finished = FALSE
- if (config.continous_rounds) // Game keeps going after mode ends.
+ if (CONFIG_GET(flag/continuous_rounds)) // Game keeps going after mode ends.
game_finished = (emergency_shuttle.returned() || mode.station_was_nuked)
mode_finished = ((end_game_state >= END_GAME_MODE_FINISHED) || mode.check_finished()) // Short circuit if already finished.
else // Game ends when mode does
@@ -232,8 +237,8 @@ var/global/datum/controller/subsystem/ticker/ticker
end_game_state = END_GAME_MODE_FINISHED // Only do this cleanup once!
mode.cleanup()
//call a transfer shuttle vote
- to_world("The round has ended!")
- SSvote.autotransfer()
+ to_world(span_boldannounce("The round has ended!"))
+ SSvote.start_vote(new /datum/vote/crew_transfer)
// Called during GAME_STATE_FINISHED (RUNLEVEL_POSTGAME)
/datum/controller/subsystem/ticker/proc/post_game_tick()
@@ -245,7 +250,7 @@ var/global/datum/controller/subsystem/ticker/ticker
feedback_set_details("end_proper", "nuke")
restart_timeleft = 1 MINUTE // No point waiting five minutes if everyone's dead.
if(!delay_end)
- to_world("Rebooting due to destruction of [station_name()] in [round(restart_timeleft/600)] minute\s.")
+ to_world(span_boldannounce("Rebooting due to destruction of [station_name()] in [round(restart_timeleft/600)] minute\s."))
last_restart_notify = world.time
else
feedback_set_details("end_proper", "proper completion")
@@ -259,14 +264,14 @@ var/global/datum/controller/subsystem/ticker/ticker
if(END_GAME_ENDING)
restart_timeleft -= (world.time - last_fire)
if(delay_end)
- to_world("An admin has delayed the round end.")
+ to_world(span_boldannounce("An admin has delayed the round end."))
end_game_state = END_GAME_DELAYED
else if(restart_timeleft <= 0)
- to_world("Restarting world!")
+ to_world(span_boldannounce("Restarting world!"))
sleep(5)
world.Reboot()
else if (world.time - last_restart_notify >= 1 MINUTE)
- to_world("Restarting in [round(restart_timeleft/600, 1)] minute\s.")
+ to_world(span_boldannounce("Restarting in [round(restart_timeleft/600, 1)] minute\s."))
last_restart_notify = world.time
return
if(END_GAME_DELAYED)
@@ -425,6 +430,7 @@ var/global/datum/controller/subsystem/ticker/ticker
if(new_char.client)
var/obj/screen/splash/S = new(new_char.client, TRUE)
S.Fade(TRUE)
+ new_char.client.init_verbs()
// If they're a carbon, they can get manifested
if(J?.mob_type & JOB_CARBON)
@@ -440,7 +446,7 @@ var/global/datum/controller/subsystem/ticker/ticker
var/captainless=1
for(var/mob/living/carbon/human/player in player_list)
if(player && player.mind && player.mind.assigned_role)
- if(player.mind.assigned_role == "Site Manager")
+ if(player.mind.assigned_role == JOB_SITE_MANAGER)
captainless=0
if(!player_is_antag(player.mind, only_offstation_roles = 1))
job_master.EquipRank(player, player.mind.assigned_role, 0)
@@ -450,7 +456,7 @@ var/global/datum/controller/subsystem/ticker/ticker
//VOREStation Addition Start
if(player.client)
if(player.client.prefs.auto_backup_implant)
- var/obj/item/weapon/implant/backup/imp = new(src)
+ var/obj/item/implant/backup/imp = new(src)
if(imp.handle_implant(player,player.zone_sel.selecting))
imp.post_implant(player)
@@ -458,47 +464,47 @@ var/global/datum/controller/subsystem/ticker/ticker
if(captainless)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player))
- to_chat(M, "Site Management is not forced on anyone.")
+ to_chat(M, span_notice("Site Management is not forced on anyone."))
/datum/controller/subsystem/ticker/proc/declare_completion()
- to_world("
A round of [mode.name] has ended!
")
+ to_world(span_filter_system("
A round of [mode.name] has ended!
"))
for(var/mob/Player in player_list)
if(Player.mind && !isnewplayer(Player))
if(Player.stat != DEAD)
var/turf/playerTurf = get_turf(Player)
if(emergency_shuttle.departed && emergency_shuttle.evac)
if(isNotAdminLevel(playerTurf.z))
- to_chat(Player, "[span_blue("You survived the round, but remained on [station_name()] as [Player.real_name].")]")
+ to_chat(Player, span_filter_system(span_blue(span_bold("You survived the round, but remained on [station_name()] as [Player.real_name]."))))
else
- to_chat(Player, "[span_green("You managed to survive the events on [station_name()] as [Player.real_name].")]")
+ to_chat(Player, span_filter_system(span_green(span_bold("You managed to survive the events on [station_name()] as [Player.real_name]."))))
else if(isAdminLevel(playerTurf.z))
- to_chat(Player, "[span_green("You successfully underwent crew transfer after events on [station_name()] as [Player.real_name].")]")
+ to_chat(Player, span_filter_system(span_green(span_bold("You successfully underwent crew transfer after events on [station_name()] as [Player.real_name]."))))
else if(issilicon(Player))
- to_chat(Player, "[span_green("You remain operational after the events on [station_name()] as [Player.real_name].")]")
+ to_chat(Player, span_filter_system(span_green(span_bold("You remain operational after the events on [station_name()] as [Player.real_name]."))))
else
- to_chat(Player, "[span_blue("You missed the crew transfer after the events on [station_name()] as [Player.real_name].")]")
+ to_chat(Player, span_filter_system(span_blue(span_bold("You missed the crew transfer after the events on [station_name()] as [Player.real_name]."))))
else
if(istype(Player,/mob/observer/dead))
var/mob/observer/dead/O = Player
if(!O.started_as_observer)
- to_chat(Player, "[span_red("You did not survive the events on [station_name()]...")]")
+ to_chat(Player, span_filter_system(span_red(span_bold("You did not survive the events on [station_name()]..."))))
else
- to_chat(Player, "[span_red("You did not survive the events on [station_name()]...")]")
- to_world("
")
+ to_chat(Player, span_filter_system(span_red(span_bold("You did not survive the events on [station_name()]..."))))
+ to_world(span_filter_system("
"))
for (var/mob/living/silicon/ai/aiPlayer in mob_list)
if (aiPlayer.stat != 2)
- to_world("[aiPlayer.name]'s laws at the end of the round were:") // VOREStation edit
+ to_world(span_filter_system(span_bold("[aiPlayer.name]'s laws at the end of the round were:"))) // VOREStation edit
else
- to_world("[aiPlayer.name]'s laws when it was deactivated were:") // VOREStation edit
+ to_world(span_filter_system(span_bold("[aiPlayer.name]'s laws when it was deactivated were:"))) // VOREStation edit
aiPlayer.show_laws(1)
if (aiPlayer.connected_robots.len)
- var/robolist = "The AI's loyal minions were: "
+ var/robolist = span_bold("The AI's loyal minions were:") + " "
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
robolist += "[robo.name][robo.stat?" (Deactivated), ":", "]" // VOREStation edit
- to_world("[robolist]")
+ to_world(span_filter_system("[robolist]"))
var/dronecount = 0
@@ -515,15 +521,15 @@ var/global/datum/controller/subsystem/ticker/ticker
if (!robo.connected_ai)
if (robo.stat != 2)
- to_world("[robo.name] survived as an AI-less stationbound synthetic! Its laws were:") // VOREStation edit
+ to_world(span_filter_system(span_bold("[robo.name] survived as an AI-less stationbound synthetic! Its laws were:"))) // VOREStation edit
else
- to_world("[robo.name] was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:") // VOREStation edit
+ to_world(span_filter_system(span_bold("[robo.name] was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:"))) // VOREStation edit
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
robo.laws.show_laws(world)
if(dronecount)
- to_world("There [dronecount>1 ? "were" : "was"] [dronecount] industrious maintenance [dronecount>1 ? "drones" : "drone"] at the end of this round.")
+ to_world(span_filter_system(span_bold("There [dronecount>1 ? "were" : "was"] [dronecount] industrious maintenance [dronecount>1 ? "drones" : "drone"] at the end of this round.")))
mode.declare_completion()//To declare normal completion.
@@ -549,28 +555,29 @@ var/global/datum/controller/subsystem/ticker/ticker
return 1
-/datum/controller/subsystem/ticker/stat_entry()
+/datum/controller/subsystem/ticker/stat_entry(msg)
switch(current_state)
if(GAME_STATE_INIT)
..()
if(GAME_STATE_PREGAME) // RUNLEVEL_LOBBY
- ..("START [round_progressing ? "[round(pregame_timeleft)]s" : "(PAUSED)"]")
+ msg = "START [round_progressing ? "[round(pregame_timeleft)]s" : "(PAUSED)"]"
if(GAME_STATE_SETTING_UP) // RUNLEVEL_SETUP
- ..("SETUP")
+ msg = "SETUP"
if(GAME_STATE_PLAYING) // RUNLEVEL_GAME
- ..("GAME")
+ msg = "GAME"
if(GAME_STATE_FINISHED) // RUNLEVEL_POSTGAME
switch(end_game_state)
if(END_GAME_MODE_FINISHED)
- ..("MODE OVER, WAITING")
+ msg = "MODE OVER, WAITING"
if(END_GAME_READY_TO_END)
- ..("ENDGAME PROCESSING")
+ msg = "ENDGAME PROCESSING"
if(END_GAME_ENDING)
- ..("END IN [round(restart_timeleft/10)]s")
+ msg = "END IN [round(restart_timeleft/10)]s"
if(END_GAME_DELAYED)
- ..("END PAUSED")
+ msg = "END PAUSED"
else
- ..("ENDGAME ERROR:[end_game_state]")
+ msg = "ENDGAME ERROR:[end_game_state]"
+ return ..()
/datum/controller/subsystem/ticker/Recover()
flags |= SS_NO_INIT // Don't initialize again
@@ -586,3 +593,5 @@ var/global/datum/controller/subsystem/ticker/ticker
minds = SSticker.minds
random_players = SSticker.random_players
+
+ round_start_time = SSticker.round_start_time
diff --git a/code/controllers/subsystems/timer.dm b/code/controllers/subsystems/timer.dm
index 701307c6276..c314fa7d38b 100644
--- a/code/controllers/subsystems/timer.dm
+++ b/code/controllers/subsystems/timer.dm
@@ -1,32 +1,54 @@
-#define BUCKET_LEN (round(10*(60/world.tick_lag), 1)) //how many ticks should we keep in the bucket. (1 minutes worth)
-#define BUCKET_POS(timer) (((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag)+1) % BUCKET_LEN)||BUCKET_LEN)
-#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
+/// 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_UP((timer.timeToRun - timer.timer_subsystem.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(timer_ss) (timer_ss.head_offset + TICKS2DS(BUCKET_LEN + timer_ss.practical_offset - 1))
+/**
+ * # 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 doubly-linked
+ * lists. The object at a given index in bucket_list is a /datum/timedevent, the head of a list, which has prev
+ * and next references for the respective elements in that bucket's 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
+ /// Keeps track of the next index to work on for client timers
+ var/next_clienttime_timer_index = 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
+ /// How many times bucket was reset
+ var/bucket_reset_count = 0
/datum/controller/subsystem/timer/PreInit()
bucket_list.len = BUCKET_LEN
@@ -34,47 +56,59 @@ SUBSYSTEM_DEF(timer)
bucket_resolution = world.tick_lag
/datum/controller/subsystem/timer/stat_entry(msg)
- ..("B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)]")
+ msg = "B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)] RST:[bucket_reset_count]"
+ return ..()
+
+/datum/controller/subsystem/timer/proc/dump_timer_buckets(full = TRUE)
+ var/list/to_log = list("Timer bucket reset. world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
+ if (full)
+ for (var/i in 1 to length(bucket_list))
+ var/datum/timedevent/bucket_head = bucket_list[i]
+ if (!bucket_head)
+ continue
+
+ to_log += "Active timers at index [i]:"
+ var/datum/timedevent/bucket_node = bucket_head
+ var/anti_loop_check = 1
+ do
+ 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)
+
+ to_log += "Active timers in the second_queue queue:"
+ for(var/I in second_queue)
+ to_log += get_timer_debug_string(I)
+
+ // Dump all the logged data to the world log
+ log_world(to_log.Join("\n"))
/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
+ dump_timer_buckets(CONFIG_GET(flag/log_timers_on_bucket_reset))
- log_world("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]:")
-
- var/datum/timedevent/bucket_node = bucket_head
- var/anti_loop_check = 1000
- do
- log_world(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:")
- for(var/I in second_queue)
- log_world(get_timer_debug_string(I))
-
- var/next_clienttime_timer_index = 0
- var/len = length(clienttime_timers)
-
- for (next_clienttime_timer_index in 1 to len)
+ // Process client-time timers
+ 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
@@ -85,142 +119,106 @@ 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()
- if(ctime_timer.flags & TIMER_LOOP)
+ if(ctime_timer.flags & TIMER_LOOP) // Re-insert valid looping client timers into the client timer list.
+ if (QDELETED(ctime_timer)) // Don't re-insert timers deleted inside their callbacks.
+ continue
ctime_timer.spent = 0
ctime_timer.timeToRun = REALTIMEOFDAY + ctime_timer.wait
- BINARY_INSERT(ctime_timer, clienttime_timers, datum/timedevent, timeToRun)
+ 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]")
+ stack_trace("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], \
+ head_offset: [head_offset], practical_offset: [practical_offset], bucket_joined: [timer.bucket_joined]")
+ if (!timer.spent)
+ bucket_resolution = null // force bucket recreation
+ return
+
+ 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
+ if (timer.flags & TIMER_LOOP) // Prepare valid looping timers to re-enter the queue
+ if(QDELETED(timer)) // If a loop is deleted in its callback, we need to avoid re-inserting it.
+ continue
+ timer.spent = 0
+ timer.timeToRun = world.time + timer.wait
+ timer.bucketJoin()
+ else
+ qdel(timer)
- //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--
+ if (MC_TICK_CHECK)
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/datum/timedevent/qtimer as anything in spent)
- 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
- else
- qtimer.timeToRun = world.time + qtimer.wait
- qtimer.bucketJoin()
-
- spent.len = 0
+ 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 // Just in case
+ practical_offset++
+ var/i = 0
+ for (i in 1 to length(second_queue))
+ timer = second_queue[i]
+ if (timer.timeToRun >= TIMER_MAX(src))
+ 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
-//formated this way to be runtime resistant
+/**
+ * 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"]"
@@ -231,12 +229,19 @@ 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
+ WARNING("Timer buckets has been reset, this may cause timer to lag")
+ bucket_reset_count++
+
+ 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
@@ -244,25 +249,45 @@ 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
+
+ for (var/datum/timedevent/t as anything in alltimers)
+ t.timer_subsystem = src // Recovered timers need to be reparented
+ t.bucket_joined = FALSE
+ t.bucket_pos = -1
+ t.prev = null
+ t.next = null
+
+ // 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, GLOBAL_PROC_REF(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))
@@ -270,19 +295,25 @@ SUBSYSTEM_DEF(timer)
if (!timer)
continue
- var/bucket_pos = BUCKET_POS(timer)
- if (timer.timeToRun >= TIMER_MAX)
+ // Check that the TTR is within the range covered by buckets, when exceeded we've finished
+ if (timer.timeToRun >= TIMER_MAX(src))
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 doubly-linked list operations
new_bucket_count++
+ var/bucket_pos = BUCKET_POS(timer)
+ timer.bucket_pos = bucket_pos
+ timer.bucket_joined = TRUE
+
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
if (!bucket_head)
bucket_list[bucket_pos] = timer
@@ -290,89 +321,126 @@ SUBSYSTEM_DEF(timer)
timer.prev = null
continue
- if (!bucket_head.prev)
- bucket_head.prev = bucket_head
+ bucket_head.prev = timer
timer.next = bucket_head
- timer.prev = bucket_head.prev
- timer.next.prev = timer
- timer.prev.next = timer
+ timer.prev = null
+ bucket_list[bucket_pos] = 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
/datum/controller/subsystem/timer/Recover()
- second_queue |= SStimer.second_queue
- hashes |= SStimer.hashes
- timer_id_dict |= SStimer.timer_id_dict
- bucket_list |= SStimer.bucket_list
+ // Find the current timer sub-subsystem in global and recover its buckets etc
+ var/datum/controller/subsystem/timer/timerSS = null
+ for(var/global_var in global.vars)
+ if (istype(global.vars[global_var],src.type))
+ timerSS = global.vars[global_var]
+
+ hashes = timerSS.hashes
+ timer_id_dict = timerSS.timer_id_dict
+
+ bucket_list = timerSS.bucket_list
+ second_queue = timerSS.second_queue
+ // The buckets are FUBAR
+ reset_buckets()
+
+/**
+ * # 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
+ /// Holds info about this timer, stored from the moment it was created
+ /// Used to create a visible "name" whenever the timer is stringified
+ var/list/timer_info
+ /// 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)
+ /// The timer subsystem this event is associated with
+ var/datum/controller/subsystem/timer/timer_subsystem
+ /// Boolean indicating if timer joined into bucket
+ var/bucket_joined = FALSE
+ /// Initial bucket position
+ var/bucket_pos = -1
+
+/datum/timedevent/New(datum/callback/callBack, wait, flags, datum/controller/subsystem/timer/timer_subsystem, 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
+ src.timer_subsystem = timer_subsystem || SStimer
- 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
+ timer_subsystem.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 >= TIMER_ID_MAX)
- nextid += min(1, 2**round(nextid/TIMER_ID_MAX))
+ if (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(", ") : ""])"
+ timer_subsystem.timer_id_dict[id] = src
- if ((timeToRun < world.time || timeToRun < SStimer.head_offset) && !(flags & TIMER_CLIENT_TIME))
+ if ((timeToRun < world.time || timeToRun < timer_subsystem.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)]")
if (callBack.object != GLOBAL_PROC && !QDESTROYING(callBack.object))
- LAZYADD(callBack.object.active_timers, src)
+ LAZYADD(callBack.object._active_timers, src)
bucketJoin()
/datum/timedevent/Destroy()
..()
if (flags & TIMER_UNIQUE && hash)
- SStimer.hashes -= hash
+ timer_subsystem.hashes -= hash
- if (callBack && callBack.object && callBack.object != GLOBAL_PROC && callBack.object.active_timers)
- callBack.object.active_timers -= src
- UNSETEMPTY(callBack.object.active_timers)
+ if (callBack && callBack.object && callBack.object != GLOBAL_PROC && callBack.object._active_timers)
+ callBack.object._active_timers -= src
+ UNSETEMPTY(callBack.object._active_timers)
callBack = null
if (flags & TIMER_STOPPABLE)
- SStimer.timer_id_dict -= id
+ timer_subsystem.timer_id_dict -= id
if (flags & TIMER_CLIENT_TIME)
if (!spent)
spent = world.time
- SStimer.clienttime_timers -= src
+ timer_subsystem.clienttime_timers -= src
return QDEL_HINT_IWILLGC
if (!spent)
@@ -387,64 +455,143 @@ 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()
- var/bucketpos = BUCKET_POS(src)
- var/list/bucket_list = SStimer.bucket_list
- var/list/second_queue = SStimer.second_queue
+ // Store local references for the bucket list and secondary queue
+ // This is faster than referencing them from the datum itself
+ var/list/bucket_list = timer_subsystem.bucket_list
+ var/list/second_queue = timer_subsystem.second_queue
+
+ // Attempt to get the head of the bucket
var/datum/timedevent/buckethead
- if(bucketpos > 0)
- buckethead = bucket_list[bucketpos]
+ if(bucket_pos > 0)
+ buckethead = bucket_list[bucket_pos]
+
+ // 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)
- SStimer.bucket_count--
+ bucket_list[bucket_pos] = next
+ timer_subsystem.bucket_count--
+ else if(bucket_joined)
+ timer_subsystem.bucket_count--
else
var/l = length(second_queue)
second_queue -= src
if(l == length(second_queue))
- SStimer.bucket_count--
- if(prev != next)
+ timer_subsystem.bucket_count--
+
+ // Remove the timed event from the bucket, ensuring to maintain
+ // the integrity of the bucket's list if relevant
+ if (prev && prev.next == src)
prev.next = next
+ if (next && next.prev == src)
next.prev = prev
- else
- prev?.next = null
- next?.prev = null
prev = next = null
+ bucket_pos = -1
+ bucket_joined = FALSE
+
+/datum/timedevent/proc/operator""()
+ if(!length(timer_info))
+ return "Event not filled"
+ var/static/list/bitfield_flags = list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT", "TIMER_LOOP")
+#if defined(TIMER_DEBUG)
+ var/list/callback_args = timer_info[10]
+ return "Timer: [timer_info[1]] ([text_ref(src)]), TTR: [timer_info[2]], wait:[timer_info[3]] Flags: [jointext(bitfield_to_list(timer_info[4], bitfield_flags), ", ")], \
+ callBack: [text_ref(timer_info[5])], callBack.object: [timer_info[6]][timer_info[7]]([timer_info[8]]), \
+ callBack.delegate:[timer_info[9]]([callback_args ? callback_args.Join(", ") : ""]), source: [timer_info[11]]"
+#else
+ return "Timer: [timer_info[1]] ([text_ref(src)]), TTR: [timer_info[2]], wait:[timer_info[3]] Flags: [jointext(bitfield_to_list(timer_info[4], bitfield_flags), ", ")], \
+ callBack: [text_ref(timer_info[5])], callBack.object: [timer_info[6]]([timer_info[7]]), \
+ callBack.delegate:[timer_info[8]], source: [timer_info[9]]"
+#endif
+/**
+ * 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()
+#if defined(TIMER_DEBUG)
+ // Generate debug-friendly list for timer, more complex but also more expensive
+ timer_info = list(
+ 1 = id,
+ 2 = timeToRun,
+ 3 = wait,
+ 4 = flags,
+ 5 = callBack, /* Safe to hold this directly because it's never del'd */
+ 6 = "[callBack.object]",
+ 7 = text_ref(callBack.object),
+ 8 = getcallingtype(),
+ 9 = callBack.delegate,
+ 10 = callBack.arguments ? callBack.arguments.Copy() : null,
+ 11 = "[source]"
+ )
+#else
+ // Generate a debuggable list for the timer, simpler but wayyyy cheaper, string generation (and ref/copy memes) is a bitch and this saves a LOT of time
+ timer_info = list(
+ 1 = id,
+ 2 = timeToRun,
+ 3 = wait,
+ 4 = flags,
+ 5 = callBack, /* Safe to hold this directly because it's never del'd */
+ 6 = "[callBack.object]",
+ 7 = getcallingtype(),
+ 8 = callBack.delegate,
+ 9 = "[source]"
+ )
+#endif
+
+ if (bucket_joined)
+ stack_trace("Bucket already joined! [src]")
+
+ // 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
-
+ L = timer_subsystem.clienttime_timers
+ else if (timeToRun >= TIMER_MAX(timer_subsystem))
+ L = timer_subsystem.second_queue
if(L)
- BINARY_INSERT(src, L, datum/timedevent, timeToRun)
+ BINARY_INSERT(src, L, /datum/timedevent, src, timeToRun, COMPARE_KEY)
return
- //get the list of buckets
- var/list/bucket_list = SStimer.bucket_list
+ // Get a local reference to the bucket list, this is faster than referencing the datum
+ var/list/bucket_list = timer_subsystem.bucket_list
+
+ // Find the correct bucket for this timed event
+ bucket_pos = BUCKET_POS(src)
- //calculate our place in the bucket list
- var/bucket_pos = BUCKET_POS(src)
+ if (bucket_pos < timer_subsystem.practical_offset && timeToRun < (timer_subsystem.head_offset + TICKS2DS(BUCKET_LEN)))
+ WARNING("Bucket pos in past: bucket_pos = [bucket_pos] < practical_offset = [timer_subsystem.practical_offset] \
+ && timeToRun = [timeToRun] < [timer_subsystem.head_offset + TICKS2DS(BUCKET_LEN)], Timer: [src]")
+ bucket_pos = timer_subsystem.practical_offset // Recover bucket_pos to avoid timer blocking queue
- //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
+ timer_subsystem.bucket_count++
+
+ // 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_joined = TRUE
bucket_list[bucket_pos] = src
return
- //other wise, lets do a simplified linked list add.
- if (!bucket_head.prev)
- bucket_head.prev = bucket_head
+
+ // Otherwise, we merely add this timed event into the bucket, which is a
+ // doubly-linked list
+ bucket_joined = TRUE
+ bucket_head.prev = src
next = bucket_head
- prev = bucket_head.prev
- next.prev = src
- prev.next = src
+ prev = null
+ bucket_list[bucket_pos] = src
+/**
+ * Returns a string of the type of the callback for this timer
+ */
/datum/timedevent/proc/getcallingtype()
. = "ERROR"
if (callBack.object == GLOBAL_PROC)
@@ -452,62 +599,82 @@ SUBSYSTEM_DEF(timer)
else
. = "[callBack.object.type]"
-/proc/addtimer(datum/callback/callback, wait = 0, flags = 0)
- if (!callback)
- CRASH("addtimer called without a callback")
+/**
+ * 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
+ * * timer_subsystem the subsystem to insert this timer into
+ */
+/proc/_addtimer(datum/callback/callback, wait = 0, flags = 0, datum/controller/subsystem/timer/timer_subsystem, file, line)
+ ASSERT(istype(callback), "addtimer called [callback ? "with an invalid callback ([callback])" : "without a callback"]")
+ ASSERT(isnum(wait), "addtimer called with a non-numeric wait ([wait])")
if (wait < 0)
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 (flags & TIMER_CLIENT_TIME) // REALTIMEOFDAY has a resolution of 1 decisecond
+ wait = max(CEILING(wait, 1), 1) // so if we use tick_lag timers may be inserted in the "past"
+ else
+ wait = max(CEILING(wait, world.tick_lag), world.tick_lag)
if(wait >= INFINITY)
CRASH("Attempted to create timer with INFINITY delay")
- var/hash
+ timer_subsystem = timer_subsystem || SStimer
+ // 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]
+ var/datum/timedevent/hash_timer = timer_subsystem.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 its hash if we are going to replace it
qdel(hash_timer)
else
if (hash_timer.flags & TIMER_STOPPABLE)
. = hash_timer.id
return
else if(flags & TIMER_OVERRIDE)
- stack_trace("TIMER_OVERRIDE used without TIMER_UNIQUE")
+ stack_trace("TIMER_OVERRIDE used without TIMER_UNIQUE") //this is also caught by grep.
- var/datum/timedevent/timer = new(callback, wait, flags, hash)
+ var/datum/timedevent/timer = new(callback, wait, flags, timer_subsystem, hash, file && "[file]:[line]")
return timer.id
-/proc/deltimer(id)
+/**
+ * Delete a timer
+ *
+ * Arguments:
+ * * id a timerid or a /datum/timedevent
+ */
+/proc/deltimer(id, datum/controller/subsystem/timer/timer_subsystem)
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
+ timer_subsystem = timer_subsystem || SStimer
//id is string
- var/datum/timedevent/timer = SStimer.timer_id_dict[id]
- if (timer && !timer.spent)
+ var/datum/timedevent/timer = timer_subsystem.timer_id_dict[id]
+ if (timer && (!timer.spent || timer.flags & TIMER_DELETE_ME))
qdel(timer)
return TRUE
return FALSE
@@ -533,7 +700,32 @@ SUBSYSTEM_DEF(timer)
return null
return timer.timeToRun - (timer.flags & TIMER_CLIENT_TIME ? REALTIMEOFDAY : world.time)
+/**
+ * Update the delay on an existing LOOPING timer
+ * Will come into effect on the next process
+ *
+ * Arguments:
+ * * id a timerid or a /datum/timedevent
+ * * new_wait the new wait to give this looping timer
+ */
+/proc/updatetimedelay(id, new_wait, datum/controller/subsystem/timer/timer_subsystem)
+ if (!id)
+ return
+ if (id == TIMER_ID_NULL)
+ CRASH("Tried to update the wait of null timerid. Use TIMER_STOPPABLE flag")
+ if (istype(id, /datum/timedevent))
+ var/datum/timedevent/timer = id
+ timer.wait = new_wait
+ return
+ timer_subsystem = timer_subsystem || SStimer
+ //id is string
+ var/datum/timedevent/timer = timer_subsystem.timer_id_dict[id]
+ if(!timer || timer.spent)
+ return
+ if(!(timer.flags & TIMER_LOOP))
+ CRASH("Tried to update the wait of a non looping timer. This is not supported")
+ timer.wait = new_wait
+
#undef BUCKET_LEN
#undef BUCKET_POS
#undef TIMER_MAX
-#undef TIMER_ID_MAX
diff --git a/code/controllers/subsystems/transcore_vr.dm b/code/controllers/subsystems/transcore_vr.dm
index 593650e1b0c..7bb0d7d6cb9 100644
--- a/code/controllers/subsystems/transcore_vr.dm
+++ b/code/controllers/subsystems/transcore_vr.dm
@@ -50,12 +50,12 @@ SUBSYSTEM_DEF(transcore)
src.current_run.Cut()
for(var/key in databases)
var/datum/transcore_db/db = databases[key]
- for(var/obj/item/weapon/implant/backup/imp as anything in db.implants)
+ for(var/obj/item/implant/backup/imp as anything in db.implants)
src.current_run[imp] = db
var/list/current_run = src.current_run
while(current_run.len)
- var/obj/item/weapon/implant/backup/imp = current_run[current_run.len]
+ var/obj/item/implant/backup/imp = current_run[current_run.len]
var/datum/transcore_db/db = current_run[imp]
current_run.len--
@@ -122,9 +122,8 @@ SUBSYSTEM_DEF(transcore)
if(MC_TICK_CHECK)
return
-/datum/controller/subsystem/transcore/stat_entry()
- var/msg = list()
- msg += "$:{"
+/datum/controller/subsystem/transcore/stat_entry(msg)
+ msg = "$:{"
msg += "IM:[round(cost_implants,1)]|"
msg += "BK:[round(cost_backups,1)]"
msg += "} "
@@ -137,7 +136,7 @@ SUBSYSTEM_DEF(transcore)
msg += "DFB:[default_db.body_scans.len]|"
msg += "DFI:[default_db.implants.len]"
msg += "} "
- ..(jointext(msg, null))
+ return ..()
/datum/controller/subsystem/transcore/Recover()
for(var/key in SStranscore.databases)
@@ -183,7 +182,7 @@ SUBSYSTEM_DEF(transcore)
return db
// These are now just interfaces to databases
-/datum/controller/subsystem/transcore/proc/m_backup(var/datum/mind/mind, var/obj/item/device/nif/nif, var/one_time = FALSE, var/database_key)
+/datum/controller/subsystem/transcore/proc/m_backup(var/datum/mind/mind, var/obj/item/nif/nif, var/one_time = FALSE, var/database_key)
var/datum/transcore_db/db = db_by_key(database_key)
db.m_backup(mind=mind, nif=nif, one_time=one_time)
@@ -203,7 +202,7 @@ SUBSYSTEM_DEF(transcore)
var/datum/transcore_db/db = db_by_key(database_key)
db.remove_body(BR=BR)
-/datum/controller/subsystem/transcore/proc/core_dump(var/obj/item/weapon/disk/transcore/disk, var/database_key)
+/datum/controller/subsystem/transcore/proc/core_dump(var/obj/item/disk/transcore/disk, var/database_key)
var/datum/transcore_db/db = db_by_key(database_key)
db.core_dump(disk=disk)
@@ -212,12 +211,12 @@ SUBSYSTEM_DEF(transcore)
var/list/datum/transhuman/mind_record/backed_up = list() // All known mind records, indexed by MR.mindname/mind.name
var/list/datum/transhuman/mind_record/has_left = list() // Why do we even have this?
var/list/datum/transhuman/body_record/body_scans = list() // All known body records, indexed by BR.mydna.name
- var/list/obj/item/weapon/implant/backup/implants = list() // All OPERATING implants that are being ticked
+ var/list/obj/item/implant/backup/implants = list() // All OPERATING implants that are being ticked
var/core_dumped = FALSE
var/key // Key for this DB
-/datum/transcore_db/proc/m_backup(var/datum/mind/mind, var/obj/item/device/nif/nif, var/one_time = FALSE)
+/datum/transcore_db/proc/m_backup(var/datum/mind/mind, var/obj/item/nif/nif, var/one_time = FALSE)
ASSERT(mind)
if(!mind.name || core_dumped)
return 0
@@ -291,7 +290,7 @@ SUBSYSTEM_DEF(transcore)
log_debug("Removed [BR.mydna.name] from transcore body DB.")
// Moves all mind records from the databaes into the disk and shuts down all backup canary processing.
-/datum/transcore_db/proc/core_dump(var/obj/item/weapon/disk/transcore/disk)
+/datum/transcore_db/proc/core_dump(var/obj/item/disk/transcore/disk)
ASSERT(disk)
global_announcer.autosay("An emergency core dump has been initiated!", "TransCore Oversight", "Command")
global_announcer.autosay("An emergency core dump has been initiated!", "TransCore Oversight", "Medical")
diff --git a/code/controllers/subsystems/verb_manager.dm b/code/controllers/subsystems/verb_manager.dm
new file mode 100644
index 00000000000..1e3cce0a9af
--- /dev/null
+++ b/code/controllers/subsystems/verb_manager.dm
@@ -0,0 +1,167 @@
+/**
+ * SSverb_manager, a subsystem that runs every tick and runs through its entire queue without yielding like SSinput.
+ * this exists because of how the byond tick works and where user inputted verbs are put within it.
+ *
+ * see TICK_ORDER.md for more info on how the byond tick is structured.
+ *
+ * The way the MC allots its time is via TICK_LIMIT_RUNNING, it simply subtracts the cost of SendMaps (MAPTICK_LAST_INTERNAL_TICK_USAGE)
+ * plus TICK_BYOND_RESERVE from the tick and uses up to that amount of time (minus the percentage of the tick used by the time it executes subsystems)
+ * on subsystems running cool things like atmospherics or Life or SSInput or whatever.
+ *
+ * Without this subsystem, verbs are likely to cause overtime if the MC uses all of the time it has allotted for itself in the tick, and SendMaps
+ * uses as much as its expected to, and an expensive verb ends up executing that tick. This is because the MC is completely blind to the cost of
+ * verbs, it can't account for it at all. The only chance for verbs to not cause overtime in a tick where the MC used as much of the tick
+ * as it allotted itself and where SendMaps costed as much as it was expected to is if the verb(s) take less than TICK_BYOND_RESERVE percent of
+ * the tick, which isn't much. Not to mention if SendMaps takes more than 30% of the tick and the MC forces itself to take at least 70% of the
+ * normal tick duration which causes ticks to naturally overrun even in the absence of verbs.
+ *
+ * With this subsystem, the MC can account for the cost of verbs and thus stop major overruns of ticks. This means that the most important subsystems
+ * like SSinput can start at the same time they were supposed to, leading to a smoother experience for the player since ticks aren't riddled with
+ * minor hangs over and over again.
+ */
+SUBSYSTEM_DEF(verb_manager)
+ name = "Verb Manager"
+ wait = 1
+ flags = SS_TICKER | SS_NO_INIT
+ priority = FIRE_PRIORITY_DELAYED_VERBS
+ runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
+
+ ///list of callbacks to procs called from verbs or verblike procs that were executed when the server was overloaded and had to delay to the next tick.
+ ///this list is ran through every tick, and the subsystem does not yield until this queue is finished.
+ var/list/datum/callback/verb_callback/verb_queue = list()
+
+ ///running average of how many verb callbacks are executed every second. used for the stat entry
+ var/verbs_executed_per_second = 0
+
+ ///if TRUE we treat usr's with holders just like usr's without holders. otherwise they always execute immediately
+ var/can_queue_admin_verbs = FALSE
+
+ ///if this is true all verbs immediately execute and don't queue. in case the mc is fucked or something
+ var/FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs = FALSE
+
+ ///used for subtypes to determine if they use their own stats for the stat entry
+ var/use_default_stats = TRUE
+
+ ///if TRUE this will... message admins every time a verb is queued to this subsystem for the next tick with stats.
+ ///for obvious reasons don't make this be TRUE on the code level this is for admins to turn on
+ var/message_admins_on_queue = FALSE
+
+ ///always queue if possible. overrides can_queue_admin_verbs but not FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs
+ var/always_queue = FALSE
+
+/**
+ * queue a callback for the given verb/verblike proc and any given arguments to the specified verb subsystem, so that they process in the next tick.
+ * intended to only work with verbs or verblike procs called directly from client input, use as part of TRY_QUEUE_VERB() and co.
+ *
+ * returns TRUE if the queuing was successful, FALSE otherwise.
+ */
+/proc/_queue_verb(datum/callback/verb_callback/incoming_callback, tick_check, datum/controller/subsystem/verb_manager/subsystem_to_use = SSverb_manager, ...)
+ if(QDELETED(incoming_callback))
+ var/destroyed_string
+ if(!incoming_callback)
+ destroyed_string = "callback is null."
+ else
+ destroyed_string = "callback was deleted [DS2TICKS(world.time - incoming_callback.gc_destroyed)] ticks ago. callback was created [DS2TICKS(world.time) - incoming_callback.creation_time] ticks ago."
+
+ stack_trace("_queue_verb() returned false because it was given a deleted callback! [destroyed_string]")
+ return FALSE
+
+ if(!istext(incoming_callback.object) && QDELETED(incoming_callback.object)) //just in case the object is GLOBAL_PROC
+ var/destroyed_string
+ if(!incoming_callback.object)
+ destroyed_string = "callback.object is null."
+ else
+ destroyed_string = "callback.object was deleted [DS2TICKS(world.time - incoming_callback.object.gc_destroyed)] ticks ago. callback was created [DS2TICKS(world.time) - incoming_callback.creation_time] ticks ago."
+
+ stack_trace("_queue_verb() returned false because it was given a callback acting on a qdeleted object! [destroyed_string]")
+ return FALSE
+
+ //we want unit tests to be able to directly call verbs that attempt to queue, and since unit tests should test internal behavior, we want the queue
+ //to happen as if it was actually from player input if its called on a mob.
+#ifdef UNIT_TESTS
+ if(QDELETED(usr) && ismob(incoming_callback.object))
+ incoming_callback.user = WEAKREF(incoming_callback.object)
+ var/datum/callback/new_us = CALLBACK(arglist(list(GLOBAL_PROC, GLOBAL_PROC_REF(_queue_verb)) + args.Copy()))
+ return world.push_usr(incoming_callback.object, new_us)
+
+#else
+
+ if(QDELETED(usr) || isnull(usr.client))
+ stack_trace("_queue_verb() returned false because it wasn't called from player input!")
+ return FALSE
+
+#endif
+
+ if(!istype(subsystem_to_use))
+ stack_trace("_queue_verb() returned false because it was given an invalid subsystem to queue for!")
+ return FALSE
+
+ if((TICK_USAGE < tick_check) && !subsystem_to_use.always_queue)
+ return FALSE
+
+ var/list/args_to_check = args.Copy()
+ args_to_check.Cut(2, 4)//cut out tick_check and subsystem_to_use
+
+ //any subsystem can use the additional arguments to refuse queuing
+ if(!subsystem_to_use.can_queue_verb(arglist(args_to_check)))
+ return FALSE
+
+ return subsystem_to_use.queue_verb(incoming_callback)
+
+/**
+ * subsystem-specific check for whether a callback can be queued.
+ * intended so that subsystem subtypes can verify whether
+ *
+ * subtypes may include additional arguments here if they need them! you just need to include them properly
+ * in TRY_QUEUE_VERB() and co.
+ */
+/datum/controller/subsystem/verb_manager/proc/can_queue_verb(datum/callback/verb_callback/incoming_callback)
+ if(always_queue && !FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs)
+ return TRUE
+
+ if((usr.client?.holder && !can_queue_admin_verbs) \
+ || (!subsystem_initialized && !(flags & SS_NO_INIT)) \
+ || FOR_ADMINS_IF_VERBS_FUCKED_immediately_execute_all_verbs \
+ || !(runlevels & Master.current_runlevel))
+ return FALSE
+
+ return TRUE
+
+/**
+ * queue a callback for the given proc, so that it is invoked in the next tick.
+ * intended to only work with verbs or verblike procs called directly from client input, use as part of TRY_QUEUE_VERB()
+ *
+ * returns TRUE if the queuing was successful, FALSE otherwise.
+ */
+/datum/controller/subsystem/verb_manager/proc/queue_verb(datum/callback/verb_callback/incoming_callback)
+ . = FALSE //errored
+ if(message_admins_on_queue)
+ message_admins("[name] verb queuing: tick usage: [TICK_USAGE]%, proc: [incoming_callback.delegate], object: [incoming_callback.object], usr: [usr]")
+ verb_queue += incoming_callback
+ return TRUE
+
+/datum/controller/subsystem/verb_manager/fire(resumed)
+ run_verb_queue()
+
+/// runs through all of this subsystems queue of verb callbacks.
+/// goes through the entire verb queue without yielding.
+/// used so you can flush the queue outside of fire() without interfering with anything else subtype subsystems might do in fire().
+/datum/controller/subsystem/verb_manager/proc/run_verb_queue()
+ var/executed_verbs = 0
+
+ for(var/datum/callback/verb_callback/verb_callback as anything in verb_queue)
+ if(!istype(verb_callback))
+ stack_trace("non /datum/callback/verb_callback inside [name]'s verb_queue!")
+ continue
+
+ verb_callback.InvokeAsync()
+ executed_verbs++
+
+ verb_queue.Cut()
+ verbs_executed_per_second = MC_AVG_SECONDS(verbs_executed_per_second, executed_verbs, wait SECONDS)
+ //note that wait SECONDS is incorrect if this is called outside of fire() but because byond is garbage i need to add a timer to rustg to find a valid solution
+
+/datum/controller/subsystem/verb_manager/stat_entry(msg)
+ . = ..()
+ if(use_default_stats)
+ . += "V/S: [round(verbs_executed_per_second, 0.01)]"
diff --git a/code/controllers/subsystems/vote.dm b/code/controllers/subsystems/vote.dm
index 41b440b410e..834af1769e6 100644
--- a/code/controllers/subsystems/vote.dm
+++ b/code/controllers/subsystems/vote.dm
@@ -1,3 +1,4 @@
+/*
SUBSYSTEM_DEF(vote)
name = "Vote"
wait = 10
@@ -24,7 +25,7 @@ SUBSYSTEM_DEF(vote)
if(mode)
time_remaining = round((started_time + duration - world.time)/10)
if(mode == VOTE_GAMEMODE && ticker.current_state >= GAME_STATE_SETTING_UP)
- to_chat(world, "Gamemode vote aborted: Game has already started.")
+ to_chat(world, span_bold("Gamemode vote aborted: Game has already started."))
reset()
return
if(time_remaining <= 0)
@@ -104,7 +105,7 @@ SUBSYSTEM_DEF(vote)
else
factor = 1.4
choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
- to_world(span_purple("Crew Transfer Factor: [factor]"))
+ to_world(span_filter_system(span_purple("Crew Transfer Factor: [factor]")))
greatest_votes = max(choices["Initiate Crew Transfer"], choices["Extend the Shift"]) //VOREStation Edit
. = list() // Get all options with that many votes and return them in a list
@@ -119,7 +120,7 @@ SUBSYSTEM_DEF(vote)
if(winners.len > 0)
if(winners.len > 1)
if(mode != VOTE_GAMEMODE || ticker.hide_mode == 0) // Here we are making sure we don't announce potential game modes
- text = "Vote Tied Between:\n"
+ text = span_bold("Vote Tied Between:") + "\n"
for(var/option in winners)
text += "\t[option]\n"
. = pick(winners)
@@ -128,12 +129,12 @@ SUBSYSTEM_DEF(vote)
if(choices[current_votes[key]] == .)
round_voters += key // Keep track of who voted for the winning round.
if(mode != VOTE_GAMEMODE || . == "Extended" || ticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes
- text += "Vote Result: [mode == VOTE_GAMEMODE ? gamemode_names[.] : .]"
+ text += span_bold("Vote Result: [mode == VOTE_GAMEMODE ? gamemode_names[.] : .]")
else
- text += "The vote has ended."
+ text += span_bold("The vote has ended.")
else
- text += "Vote Result: Inconclusive - No Votes!"
+ text += span_bold("Vote Result: Inconclusive - No Votes!")
if(mode == VOTE_ADD_ANTAGONIST)
antag_add_failed = 1
log_vote(text)
@@ -166,10 +167,10 @@ SUBSYSTEM_DEF(vote)
if(mode == VOTE_GAMEMODE) //fire this even if the vote fails.
if(!round_progressing)
round_progressing = 1
- to_world(span_red("The round will start soon."))
+ to_world(span_boldannounce("The round will start soon."))
if(restart)
- to_world("World restarting due to vote...")
+ to_world(span_filter_system("World restarting due to vote..."))
feedback_set_details("end_error", "restart vote")
if(blackbox)
blackbox.save_all_data_to_sql()
@@ -252,7 +253,7 @@ SUBSYSTEM_DEF(vote)
log_vote(text)
- to_world(span_purple("[text]\nType vote or click here to place your votes.\nYou have [config.vote_period / 10] seconds to vote."))
+ to_world(span_filter_system(span_purple(span_bold("[text]") + "\nType " + span_bold("vote") + " or click here to place your votes.\nYou have [config.vote_period / 10] seconds to vote.")))
if(vote_type == VOTE_CREW_TRANSFER || vote_type == VOTE_GAMEMODE || vote_type == VOTE_CUSTOM)
world << sound('sound/misc/notice1.ogg', repeat = 0, wait = 0, volume = 50, channel = 3) //YW Edit
@@ -260,7 +261,7 @@ SUBSYSTEM_DEF(vote)
if(mode == VOTE_GAMEMODE && round_progressing)
gamemode_vote_called = TRUE
round_progressing = 0
- to_world(span_red("Round start has been delayed."))
+ to_world(span_boldannounce("Round start has been delayed."))
time_remaining = round(config.vote_period / 10)
return 1
@@ -368,7 +369,7 @@ SUBSYSTEM_DEF(vote)
if(tgui_alert(usr, "Are you sure you want to start a RESTART VOTE? You should only do this if the server is dying and no staff are around to investigate.", "RESTART VOTE", list("No", "Yes I want to start a RESTART VOTE")) == "Yes I want to start a RESTART VOTE")
initiate_vote(VOTE_RESTART, usr.key)
else
- to_chat(usr, "You can't start a RESTART VOTE while there are staff around. If you are having an issue with the round, please ahelp it.")
+ to_chat(usr, span_warning("You can't start a RESTART VOTE while there are staff around. If you are having an issue with the round, please ahelp it."))
if(VOTE_GAMEMODE)
if(config.allow_vote_mode || usr.client.holder)
initiate_vote(VOTE_GAMEMODE, usr.key)
@@ -392,8 +393,9 @@ SUBSYSTEM_DEF(vote)
usr.client.vote()
/client/verb/vote()
- set category = "OOC"
+ set category = "OOC.Game"
set name = "Vote"
if(SSvote)
src << browse(SSvote.interface(src), "window=vote;size=500x[300 + SSvote.choices.len * 25]")
+*/
diff --git a/code/controllers/subsystems/webhooks.dm b/code/controllers/subsystems/webhooks.dm
index 1e7a27924ff..d9b75805af9 100644
--- a/code/controllers/subsystems/webhooks.dm
+++ b/code/controllers/subsystems/webhooks.dm
@@ -64,7 +64,7 @@ SUBSYSTEM_DEF(webhooks)
return
if(!SSwebhooks.subsystem_initialized)
- to_chat(usr, SPAN_WARNING("Let the webhook subsystem initialize before trying to reload it."))
+ to_chat(usr, span_warning("Let the webhook subsystem initialize before trying to reload it."))
return
to_world_log("[usr.key] has reloaded webhooks.")
@@ -79,7 +79,7 @@ SUBSYSTEM_DEF(webhooks)
return
if(!length(SSwebhooks.webhook_decls))
- to_chat(usr, SPAN_WARNING("Webhook list is empty; either webhooks are disabled, webhooks aren't configured, or the subsystem hasn't initialized."))
+ to_chat(usr, span_warning("Webhook list is empty; either webhooks are disabled, webhooks aren't configured, or the subsystem hasn't initialized."))
return
var/choice = tgui_input_list(usr, "Select a webhook to ping.", "Ping Webhook", SSwebhooks.webhook_decls)
diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm
index fee7da9b853..165748c64b1 100644
--- a/code/controllers/verbs.dm
+++ b/code/controllers/verbs.dm
@@ -38,7 +38,7 @@
// Debug verbs.
/client/proc/restart_controller(controller in list("Master", "Failsafe"))
- set category = "Debug"
+ set category = "Debug.Dangerous"
set name = "Restart Controller"
set desc = "Restart one of the various periodic loop controllers for the game (be careful!)"
@@ -55,7 +55,7 @@
message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
/client/proc/debug_antagonist_template(antag_type in all_antag_types)
- set category = "Debug"
+ set category = "Debug.Investigate"
set name = "Debug Antagonist"
set desc = "Debug an antagonist template."
@@ -65,7 +65,7 @@
message_admins("Admin [key_name_admin(usr)] is debugging the [antag.role_text] template.")
/client/proc/debug_controller()
- set category = "Debug"
+ set category = "Debug.Investigate"
set name = "Debug Controller"
set desc = "Debug the various subsystems/controllers for the game (be careful!)"
@@ -89,7 +89,6 @@
//Goon PS stuff, and other yet-to-be-subsystem things.
options["LEGACY: master_controller"] = master_controller
- options["LEGACY: air_master"] = air_master
options["LEGACY: job_master"] = job_master
options["LEGACY: radio_controller"] = radio_controller
options["LEGACY: emergency_shuttle"] = emergency_shuttle
diff --git a/code/datums/ai_law_sets.dm b/code/datums/ai_law_sets.dm
index 86823245527..38d99905dc5 100644
--- a/code/datums/ai_law_sets.dm
+++ b/code/datums/ai_law_sets.dm
@@ -27,7 +27,7 @@
selectable = 0
/datum/ai_laws/nanotrasen/malfunction/New()
- set_zeroth_law(config.law_zero)
+ set_zeroth_law(CONFIG_GET(string/law_zero))
..()
/************* NanoTrasen Aggressive *************/
diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm
index fb152cefa8c..69bfa4773cb 100644
--- a/code/datums/ai_laws.dm
+++ b/code/datums/ai_laws.dm
@@ -1,4 +1,4 @@
-var/global/const/base_law_type = /datum/ai_laws/nanotrasen
+// var/global/const/base_law_type = /datum/ai_laws/nanotrasen //VOREstation edit: unused
/datum/ai_law
var/law = ""
@@ -227,9 +227,9 @@ var/global/const/base_law_type = /datum/ai_laws/nanotrasen
if(law == zeroth_law_borg)
continue
if(law == zeroth_law)
- to_chat(who, "[law.get_index()]. [law.law]")
+ to_chat(who, span_info(span_red("[law.get_index()]. [law.law]")))
else
- to_chat(who, "[law.get_index()]. [law.law]")
+ to_chat(who, span_infoplain("[law.get_index()]. [law.law]"))
/********************
* Stating Laws *
diff --git a/code/datums/autolathe/arms.dm b/code/datums/autolathe/arms.dm
index 990b87b52d1..41caf5a74d9 100644
--- a/code/datums/autolathe/arms.dm
+++ b/code/datums/autolathe/arms.dm
@@ -1,6 +1,6 @@
/datum/category_item/autolathe/arms/syringegun_ammo
name = "syringe gun cartridge"
- path =/obj/item/weapon/syringe_cartridge
+ path =/obj/item/syringe_cartridge
////////////////
/*Ammo casings*/
@@ -443,15 +443,15 @@
/datum/category_item/autolathe/arms/knuckledusters
name = "knuckle dusters"
- path =/obj/item/clothing/gloves/knuckledusters
+ path =/obj/item/clothing/accessory/knuckledusters
hidden = 1
/datum/category_item/autolathe/arms/tacknife
name = "tactical knife"
- path =/obj/item/weapon/material/knife/tacknife
+ path =/obj/item/material/knife/tacknife
hidden = 1
/datum/category_item/autolathe/arms/flamethrower
name = "flamethrower"
- path =/obj/item/weapon/flamethrower/full
+ path =/obj/item/flamethrower/full
hidden = 1
diff --git a/code/datums/autolathe/devices.dm b/code/datums/autolathe/devices.dm
index 1196df53425..437ba75f298 100644
--- a/code/datums/autolathe/devices.dm
+++ b/code/datums/autolathe/devices.dm
@@ -1,38 +1,38 @@
/datum/category_item/autolathe/devices/consolescreen
name = "console screen"
- path =/obj/item/weapon/stock_parts/console_screen
+ path =/obj/item/stock_parts/console_screen
/datum/category_item/autolathe/devices/igniter
name = "igniter"
- path =/obj/item/device/assembly/igniter
+ path =/obj/item/assembly/igniter
/datum/category_item/autolathe/devices/signaler
name = "signaler"
- path =/obj/item/device/assembly/signaler
+ path =/obj/item/assembly/signaler
/datum/category_item/autolathe/devices/sensor_infra
name = "infrared sensor"
- path =/obj/item/device/assembly/infra
+ path =/obj/item/assembly/infra
/datum/category_item/autolathe/devices/timer
name = "timer"
- path =/obj/item/device/assembly/timer
+ path =/obj/item/assembly/timer
/datum/category_item/autolathe/devices/sensor_prox
name = "proximity sensor"
- path =/obj/item/device/assembly/prox_sensor
+ path =/obj/item/assembly/prox_sensor
/datum/category_item/autolathe/devices/beartrap
name = "mechanical trap"
- path =/obj/item/weapon/beartrap
+ path =/obj/item/beartrap
/datum/category_item/autolathe/devices/barbedwire
name = "barbed wire"
- path = /obj/item/weapon/material/barbedwire
+ path = /obj/item/material/barbedwire
hidden = 1
resources = list(MAT_STEEL = 10000)
/datum/category_item/autolathe/devices/electropack
name = "electropack"
- path =/obj/item/device/radio/electropack
+ path =/obj/item/radio/electropack
hidden = 1
diff --git a/code/datums/autolathe/devices_vr.dm b/code/datums/autolathe/devices_vr.dm
index 65af7b630cc..658382a0910 100644
--- a/code/datums/autolathe/devices_vr.dm
+++ b/code/datums/autolathe/devices_vr.dm
@@ -1,3 +1,3 @@
/datum/category_item/autolathe/devices/sleevecard
name = "sleevecard"
- path =/obj/item/device/paicard/sleevecard
+ path =/obj/item/paicard/sleevecard
diff --git a/code/datums/autolathe/engineering.dm b/code/datums/autolathe/engineering.dm
index 87dbe9d5745..f7520a1db7b 100644
--- a/code/datums/autolathe/engineering.dm
+++ b/code/datums/autolathe/engineering.dm
@@ -1,119 +1,118 @@
/datum/category_item/autolathe/engineering/airlockmodule
name = "airlock electronics"
- path =/obj/item/weapon/airlock_electronics
+ path =/obj/item/airlock_electronics
/datum/category_item/autolathe/engineering/airalarm
name = "air alarm electronics"
- path =/obj/item/weapon/circuitboard/airalarm
+ path =/obj/item/circuitboard/airalarm
/datum/category_item/autolathe/engineering/firealarm
name = "fire alarm electronics"
- path =/obj/item/weapon/circuitboard/firealarm
+ path =/obj/item/circuitboard/firealarm
/datum/category_item/autolathe/engineering/powermodule
name = "power control module"
- path =/obj/item/weapon/module/power_control
+ path =/obj/item/module/power_control
/datum/category_item/autolathe/engineering/statusdisplay
name = "status display electronics"
- path =/obj/item/weapon/circuitboard/status_display
+ path =/obj/item/circuitboard/status_display
/datum/category_item/autolathe/engineering/aistatusdisplay
name = "ai status display electronics"
- path =/obj/item/weapon/circuitboard/ai_status_display
+ path =/obj/item/circuitboard/ai_status_display
/datum/category_item/autolathe/engineering/newscaster
name = "newscaster electronics"
- path =/obj/item/weapon/circuitboard/newscaster
+ path =/obj/item/circuitboard/newscaster
/datum/category_item/autolathe/engineering/atm
name = "atm electronics"
- path =/obj/item/weapon/circuitboard/atm
+ path =/obj/item/circuitboard/atm
/datum/category_item/autolathe/engineering/intercom
name = "intercom electronics"
- path =/obj/item/weapon/circuitboard/intercom
+ path =/obj/item/circuitboard/intercom
/datum/category_item/autolathe/engineering/holopad
name = "holopad electronics"
- path =/obj/item/weapon/circuitboard/holopad
+ path =/obj/item/circuitboard/holopad
/datum/category_item/autolathe/engineering/guestpass
name = "guestpass console electronics"
- path =/obj/item/weapon/circuitboard/guestpass
+ path =/obj/item/circuitboard/guestpass
/datum/category_item/autolathe/engineering/entertainment
name = "entertainment camera electronics"
- path =/obj/item/weapon/circuitboard/security/telescreen/entertainment
+ path =/obj/item/circuitboard/security/telescreen/entertainment
/datum/category_item/autolathe/engineering/keycard
name = "keycard authenticator electronics"
- path =/obj/item/weapon/circuitboard/keycard_auth
+ path =/obj/item/circuitboard/keycard_auth
/datum/category_item/autolathe/engineering/geiger_wall
name = "wall-mounted geiger counter electronics"
- path =/obj/item/weapon/circuitboard/geiger
+ path =/obj/item/circuitboard/geiger
/datum/category_item/autolathe/engineering/photocopier
name = "photocopier electronics"
- path =/obj/item/weapon/circuitboard/photocopier
+ path =/obj/item/circuitboard/photocopier
/datum/category_item/autolathe/engineering/fax
name = "fax machine electronics"
- path =/obj/item/weapon/circuitboard/fax
+ path =/obj/item/circuitboard/fax
/datum/category_item/autolathe/engineering/papershredder
name = "paper shredder electronics"
- path =/obj/item/weapon/circuitboard/papershredder
+ path =/obj/item/circuitboard/papershredder
/datum/category_item/autolathe/engineering/microwave
name = "microwave electronics"
- path =/obj/item/weapon/circuitboard/microwave
+ path =/obj/item/circuitboard/microwave
/datum/category_item/autolathe/engineering/washing
name = "washing machine electronics"
- path =/obj/item/weapon/circuitboard/washing
+ path =/obj/item/circuitboard/washing
/datum/category_item/autolathe/engineering/request
name = "request console electronics"
- path =/obj/item/weapon/circuitboard/request
+ path =/obj/item/circuitboard/request
/datum/category_item/autolathe/engineering/electrochromic
name = "electrochromic window control electronics"
- path =/obj/item/weapon/circuitboard/electrochromic
+ path =/obj/item/circuitboard/electrochromic
/datum/category_item/autolathe/engineering/pipelayer
name = "pipe layer electronics"
- path =/obj/item/weapon/circuitboard/pipelayer
+ path =/obj/item/circuitboard/pipelayer
/datum/category_item/autolathe/engineering/motor
name = "motor"
- path =/obj/item/weapon/stock_parts/motor
+ path =/obj/item/stock_parts/motor
/datum/category_item/autolathe/engineering/gear
name = "gear"
- path =/obj/item/weapon/stock_parts/gear
+ path =/obj/item/stock_parts/gear
/datum/category_item/autolathe/engineering/spring
name = "spring"
- path =/obj/item/weapon/stock_parts/spring
+ path =/obj/item/stock_parts/spring
/datum/category_item/autolathe/engineering/rcd_ammo
name = "matter cartridge"
- path =/obj/item/weapon/rcd_ammo
+ path =/obj/item/rcd_ammo
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/engineering/rcd
name = "rapid construction device"
- path =/obj/item/weapon/rcd
+ path =/obj/item/rcd
/datum/category_item/autolathe/engineering/camera_assembly
name = "camera assembly"
- path =/obj/item/weapon/camera_assembly
+ path =/obj/item/camera_assembly
//YW Addition Start
/datum/category_item/autolathe/engineering/rpd
name = "rapid piping device"
- path =/obj/item/weapon/pipe_dispenser
-//YW Addtion End
-
+ path =/obj/item/pipe_dispenser
+//YW Addtion End
diff --git a/code/datums/autolathe/engineering_vr.dm b/code/datums/autolathe/engineering_vr.dm
index 577d9febd2c..0b3fe19dc32 100644
--- a/code/datums/autolathe/engineering_vr.dm
+++ b/code/datums/autolathe/engineering_vr.dm
@@ -1,75 +1,75 @@
/datum/category_item/autolathe/engineering/timeclock
name = "timeclock electronics"
- path =/obj/item/weapon/circuitboard/timeclock
+ path =/obj/item/circuitboard/timeclock
/datum/category_item/autolathe/engineering/id_restorer
name = "ID restoration console electronics"
- path =/obj/item/weapon/circuitboard/id_restorer
+ path =/obj/item/circuitboard/id_restorer
/datum/category_item/autolathe/engineering/oven
name = "oven electronics"
- path =/obj/item/weapon/circuitboard/oven
+ path =/obj/item/circuitboard/oven
/datum/category_item/autolathe/engineering/fryer
name = "fryer electronics"
- path =/obj/item/weapon/circuitboard/fryer
+ path =/obj/item/circuitboard/fryer
/datum/category_item/autolathe/engineering/grill
name = "grill electronics"
- path =/obj/item/weapon/circuitboard/grill
+ path =/obj/item/circuitboard/grill
/datum/category_item/autolathe/engineering/cerealmaker
name = "cereal maker electronics"
- path =/obj/item/weapon/circuitboard/cerealmaker
+ path =/obj/item/circuitboard/cerealmaker
/datum/category_item/autolathe/engineering/candymachine
name = "candy machine electronics"
- path =/obj/item/weapon/circuitboard/candymachine
+ path =/obj/item/circuitboard/candymachine
/datum/category_item/autolathe/engineering/battle_arcade
name = "battle arcade machine electronics"
- path =/obj/item/weapon/circuitboard/arcade/battle
+ path =/obj/item/circuitboard/arcade/battle
/datum/category_item/autolathe/engineering/orion_trail
name = "orion trail aracade machine electronics"
- path =/obj/item/weapon/circuitboard/arcade/orion_trail
+ path =/obj/item/circuitboard/arcade/orion_trail
/datum/category_item/autolathe/engineering/clawmachine
name = "claw machine electronics"
- path =/obj/item/weapon/circuitboard/arcade/clawmachine
+ path =/obj/item/circuitboard/arcade/clawmachine
/datum/category_item/autolathe/engineering/jukebox
name = "jukebox electronics"
- path =/obj/item/weapon/circuitboard/jukebox
+ path =/obj/item/circuitboard/jukebox
/datum/category_item/autolathe/engineering/mech_recharger
name = "mech recharging station electronics"
- path =/obj/item/weapon/circuitboard/mech_recharger
+ path =/obj/item/circuitboard/mech_recharger
/datum/category_item/autolathe/engineering/recharge_station
name = "cyborg recharging station electronics"
- path =/obj/item/weapon/circuitboard/recharge_station
+ path =/obj/item/circuitboard/recharge_station
/datum/category_item/autolathe/engineering/batteryrack
name = "battery rack electronics"
- path =/obj/item/weapon/circuitboard/batteryrack
+ path =/obj/item/circuitboard/batteryrack
/datum/category_item/autolathe/engineering/grid_checker
name = "grid checker electronics"
- path =/obj/item/weapon/circuitboard/grid_checker
+ path =/obj/item/circuitboard/grid_checker
/datum/category_item/autolathe/engineering/breakerbox
name = "breaker box electronics"
- path =/obj/item/weapon/circuitboard/breakerbox
+ path =/obj/item/circuitboard/breakerbox
/datum/category_item/autolathe/engineering/gas_heater
name = "gas heater electronics"
- path =/obj/item/weapon/circuitboard/unary_atmos/heater
+ path =/obj/item/circuitboard/unary_atmos/heater
/datum/category_item/autolathe/engineering/gas_cooler
name = "gas cooler electronics"
- path =/obj/item/weapon/circuitboard/unary_atmos/cooler
+ path =/obj/item/circuitboard/unary_atmos/cooler
/datum/category_item/autolathe/engineering/arf_generator
name = "atmospheric field generator electronics"
- path =/obj/item/weapon/circuitboard/arf_generator
\ No newline at end of file
+ path =/obj/item/circuitboard/arf_generator
\ No newline at end of file
diff --git a/code/datums/autolathe/general.dm b/code/datums/autolathe/general.dm
index d664e9fa197..610a27bc980 100644
--- a/code/datums/autolathe/general.dm
+++ b/code/datums/autolathe/general.dm
@@ -1,57 +1,57 @@
/datum/category_item/autolathe/general/bucket
name = "bucket"
- path =/obj/item/weapon/reagent_containers/glass/bucket
+ path =/obj/item/reagent_containers/glass/bucket
/datum/category_item/autolathe/general/cooler_bottle
name = "water-cooler bottle"
- path =/obj/item/weapon/reagent_containers/glass/cooler_bottle
+ path =/obj/item/reagent_containers/glass/cooler_bottle
/datum/category_item/autolathe/general/drinkingglass
is_stack = TRUE
/datum/category_item/autolathe/general/drinkingglass/square
name = "half-pint glass"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/square
+ path =/obj/item/reagent_containers/food/drinks/glass2/square
/datum/category_item/autolathe/general/drinkingglass/rocks
name = "rocks glass"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/rocks
+ path =/obj/item/reagent_containers/food/drinks/glass2/rocks
/datum/category_item/autolathe/general/drinkingglass/shake
name = "milkshake glass"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/shake
+ path =/obj/item/reagent_containers/food/drinks/glass2/shake
/datum/category_item/autolathe/general/drinkingglass/cocktail
name = "cocktail glass"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/cocktail
+ path =/obj/item/reagent_containers/food/drinks/glass2/cocktail
/datum/category_item/autolathe/general/drinkingglass/shot
name = "shot glass"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/shot
+ path =/obj/item/reagent_containers/food/drinks/glass2/shot
/datum/category_item/autolathe/general/drinkingglass/pint
name = "pint glass"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/pint
+ path =/obj/item/reagent_containers/food/drinks/glass2/pint
/datum/category_item/autolathe/general/drinkingglass/mug
name = "glass mug"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/mug
+ path =/obj/item/reagent_containers/food/drinks/glass2/mug
/datum/category_item/autolathe/general/drinkingglass/wine
name = "wine glass"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/wine
+ path =/obj/item/reagent_containers/food/drinks/glass2/wine
/datum/category_item/autolathe/general/drinkingglass/metaglass
name = "metamorphic glass"
- path =/obj/item/weapon/reagent_containers/food/drinks/metaglass
+ path =/obj/item/reagent_containers/food/drinks/metaglass
/datum/category_item/autolathe/general/drinkingglass/metaglass/metapint
name = "metamorphic pint glass"
- path =/obj/item/weapon/reagent_containers/food/drinks/metaglass/metapint
+ path =/obj/item/reagent_containers/food/drinks/metaglass/metapint
/datum/category_item/autolathe/general/flashlight
name = "flashlight"
- path =/obj/item/device/flashlight
+ path =/obj/item/flashlight
/datum/category_item/autolathe/general/floor_light
name = "floor light"
@@ -59,7 +59,7 @@
/datum/category_item/autolathe/general/extinguisher
name = "extinguisher"
- path =/obj/item/weapon/extinguisher
+ path =/obj/item/extinguisher
/datum/category_item/autolathe/general/jar
name = "jar"
@@ -71,15 +71,15 @@
/datum/category_item/autolathe/general/radio_headset
name = "radio headset"
- path =/obj/item/device/radio/headset
+ path =/obj/item/radio/headset
/datum/category_item/autolathe/general/radio_bounced
name = "station bounced radio"
- path =/obj/item/device/radio/off
+ path =/obj/item/radio/off
/datum/category_item/autolathe/general/suit_cooler
name = "suit cooling unit"
- path =/obj/item/device/suit_cooling_unit
+ path =/obj/item/suit_cooling_unit
/datum/category_item/autolathe/general/weldermask
name = "welding mask"
@@ -87,29 +87,29 @@
/datum/category_item/autolathe/general/spraybottle
name = "spray bottle"
- path = /obj/item/weapon/reagent_containers/spray
+ path = /obj/item/reagent_containers/spray
/datum/category_item/autolathe/general/knife
name = "kitchen knife"
- path =/obj/item/weapon/material/knife
+ path =/obj/item/material/knife
/datum/category_item/autolathe/general/taperecorder
name = "tape recorder"
- path =/obj/item/device/taperecorder
+ path =/obj/item/taperecorder
/datum/category_item/autolathe/general/tube
name = "light tube"
- path =/obj/item/weapon/light/tube
+ path =/obj/item/light/tube
is_stack = TRUE
/datum/category_item/autolathe/general/bulb
name = "light bulb"
- path =/obj/item/weapon/light/bulb
+ path =/obj/item/light/bulb
is_stack = TRUE
/datum/category_item/autolathe/general/ashtray_glass
name = "glass ashtray"
- path =/obj/item/weapon/material/ashtray/glass
+ path =/obj/item/material/ashtray/glass
/datum/category_item/autolathe/general/weldinggoggles
name = "welding goggles"
@@ -117,20 +117,20 @@
/datum/category_item/autolathe/general/maglight
name = "maglight"
- path =/obj/item/device/flashlight/maglight
+ path =/obj/item/flashlight/maglight
/datum/category_item/autolathe/general/idcard
name = "ID Card"
- path = /obj/item/weapon/card/id
+ path = /obj/item/card/id
resources = list(MAT_STEEL = 100, MAT_GLASS = 100, MAT_PLASTIC = 300)
man_rating = 2
/datum/category_item/autolathe/general/handcuffs
name = "handcuffs"
- path =/obj/item/weapon/handcuffs
+ path =/obj/item/handcuffs
hidden = 1
/datum/category_item/autolathe/general/legcuffs
name = "legcuffs"
- path =/obj/item/weapon/handcuffs/legcuffs
+ path =/obj/item/handcuffs/legcuffs
hidden = 1
diff --git a/code/datums/autolathe/general_vr.dm b/code/datums/autolathe/general_vr.dm
index 5702a7ed499..1b47ae4d56d 100644
--- a/code/datums/autolathe/general_vr.dm
+++ b/code/datums/autolathe/general_vr.dm
@@ -4,9 +4,9 @@
/datum/category_item/autolathe/general/drinkingglass/carafe
name = "glass carafe"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/carafe
+ path =/obj/item/reagent_containers/food/drinks/glass2/carafe
/datum/category_item/autolathe/general/drinkingglass/pitcher
name = "plastic pitcher"
- path =/obj/item/weapon/reagent_containers/food/drinks/glass2/pitcher
+ path =/obj/item/reagent_containers/food/drinks/glass2/pitcher
\ No newline at end of file
diff --git a/code/datums/autolathe/medical.dm b/code/datums/autolathe/medical.dm
index c1247db8719..6e457bf4485 100644
--- a/code/datums/autolathe/medical.dm
+++ b/code/datums/autolathe/medical.dm
@@ -1,43 +1,43 @@
/datum/category_item/autolathe/medical/scalpel
name = "scalpel"
- path =/obj/item/weapon/surgical/scalpel
+ path =/obj/item/surgical/scalpel
/datum/category_item/autolathe/medical/circularsaw
name = "circular saw"
- path =/obj/item/weapon/surgical/circular_saw
+ path =/obj/item/surgical/circular_saw
/datum/category_item/autolathe/medical/surgicaldrill
name = "surgical drill"
- path =/obj/item/weapon/surgical/surgicaldrill
+ path =/obj/item/surgical/surgicaldrill
/datum/category_item/autolathe/medical/retractor
name = "retractor"
- path =/obj/item/weapon/surgical/retractor
+ path =/obj/item/surgical/retractor
/datum/category_item/autolathe/medical/cautery
name = "cautery"
- path =/obj/item/weapon/surgical/cautery
+ path =/obj/item/surgical/cautery
/datum/category_item/autolathe/medical/hemostat
name = "hemostat"
- path =/obj/item/weapon/surgical/hemostat
+ path =/obj/item/surgical/hemostat
/datum/category_item/autolathe/medical/beaker
name = "glass beaker"
- path =/obj/item/weapon/reagent_containers/glass/beaker
+ path =/obj/item/reagent_containers/glass/beaker
/datum/category_item/autolathe/medical/beaker_large
name = "large glass beaker"
- path =/obj/item/weapon/reagent_containers/glass/beaker/large
+ path =/obj/item/reagent_containers/glass/beaker/large
/datum/category_item/autolathe/medical/vial
name = "glass vial"
- path =/obj/item/weapon/reagent_containers/glass/beaker/vial
+ path =/obj/item/reagent_containers/glass/beaker/vial
/datum/category_item/autolathe/medical/syringe
name = "syringe"
- path =/obj/item/weapon/reagent_containers/syringe
+ path =/obj/item/reagent_containers/syringe
/datum/category_item/autolathe/medical/implanter
name = "implanter"
- path =/obj/item/weapon/implanter
+ path =/obj/item/implanter
diff --git a/code/datums/autolathe/medical_vr.dm b/code/datums/autolathe/medical_vr.dm
index bfaeb3a63b6..0831ed9b78b 100644
--- a/code/datums/autolathe/medical_vr.dm
+++ b/code/datums/autolathe/medical_vr.dm
@@ -1,9 +1,9 @@
/datum/category_item/autolathe/medical/autoinjector
name = "empty autoinjector"
- path =/obj/item/weapon/reagent_containers/hypospray/autoinjector/empty
+ path =/obj/item/reagent_containers/hypospray/autoinjector/empty
resources = list(MAT_PLASTIC = 10) //for recycling purposes mostly
/datum/category_item/autolathe/medical/autoinjector/biginjector
name = "empty large autoinjector"
- path =/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/empty
+ path =/obj/item/reagent_containers/hypospray/autoinjector/biginjector/empty
resources = list(MAT_PLASTIC = 500)
\ No newline at end of file
diff --git a/code/datums/autolathe/tools.dm b/code/datums/autolathe/tools.dm
index e62232540f0..698cbe1001f 100644
--- a/code/datums/autolathe/tools.dm
+++ b/code/datums/autolathe/tools.dm
@@ -1,65 +1,65 @@
/datum/category_item/autolathe/tools/crowbar
name = "crowbar"
- path =/obj/item/weapon/tool/crowbar
+ path =/obj/item/tool/crowbar
/datum/category_item/autolathe/tools/multitool
name = "multitool"
- path =/obj/item/device/multitool
+ path =/obj/item/multitool
/datum/category_item/autolathe/tools/t_scanner
name = "T-ray scanner"
- path =/obj/item/device/t_scanner
+ path =/obj/item/t_scanner
/datum/category_item/autolathe/tools/weldertool
name = "welding tool"
- path =/obj/item/weapon/weldingtool
+ path =/obj/item/weldingtool
/datum/category_item/autolathe/tools/electric_welder
name = "electric welding tool"
- path =/obj/item/weapon/weldingtool/electric/unloaded
+ path =/obj/item/weldingtool/electric/unloaded
hidden = 1
/datum/category_item/autolathe/tools/screwdriver
name = "screwdriver"
- path =/obj/item/weapon/tool/screwdriver
+ path =/obj/item/tool/screwdriver
/datum/category_item/autolathe/tools/wirecutters
name = "wirecutters"
- path =/obj/item/weapon/tool/wirecutters
+ path =/obj/item/tool/wirecutters
/datum/category_item/autolathe/tools/wrench
name = "wrench"
- path =/obj/item/weapon/tool/wrench
+ path =/obj/item/tool/wrench
/datum/category_item/autolathe/tools/hatchet
name = "hatchet"
- path =/obj/item/weapon/material/knife/machete/hatchet
+ path =/obj/item/material/knife/machete/hatchet
/datum/category_item/autolathe/tools/minihoe
name = "mini hoe"
- path =/obj/item/weapon/material/minihoe
+ path =/obj/item/material/minihoe
/datum/category_item/autolathe/tools/welder_industrial
name = "industrial welding tool"
- path =/obj/item/weapon/weldingtool/largetank
+ path =/obj/item/weldingtool/largetank
/datum/category_item/autolathe/tools/spraybottle
name = "spray bottle"
- path = /obj/item/weapon/reagent_containers/spray
+ path = /obj/item/reagent_containers/spray
resources = list(MAT_PLASTIC = 2000)
/datum/category_item/autolathe/devices/slowwire
name = "snare wire"
- path = /obj/item/weapon/material/barbedwire/plastic
+ path = /obj/item/material/barbedwire/plastic
resources = list(MAT_PLASTIC = 10000)
/datum/category_item/autolathe/tools/spraynozzle
name = "spray nozzle"
- path = /obj/item/weapon/reagent_containers/spray
+ path = /obj/item/reagent_containers/spray
resources = list(MAT_PLASTIC = 5000, MAT_STEEL = 2000)
hidden = 1
man_rating = 2
/datum/category_item/autolathe/tools/rsf
name = "rapid service fabricator"
- path = /obj/item/weapon/rsf
+ path = /obj/item/rsf
diff --git a/code/datums/autolathe/tools_vr.dm b/code/datums/autolathe/tools_vr.dm
index c89d768f0b1..900bcd9095f 100644
--- a/code/datums/autolathe/tools_vr.dm
+++ b/code/datums/autolathe/tools_vr.dm
@@ -1,3 +1,3 @@
/datum/category_item/autolathe/tools/prybar
name = "prybar"
- path =/obj/item/weapon/tool/prybar
+ path =/obj/item/tool/prybar
diff --git a/code/datums/autolathe/tools_yw.dm b/code/datums/autolathe/tools_yw.dm
index 5ea8ef1c7a2..0c921bfe202 100644
--- a/code/datums/autolathe/tools_yw.dm
+++ b/code/datums/autolathe/tools_yw.dm
@@ -1,7 +1,7 @@
/datum/category_item/autolathe/tools/ice_pick
name = "ice pick"
- path =/obj/item/weapon/ice_pick
+ path =/obj/item/ice_pick
/datum/category_item/autolathe/tools/shovel
name = "shovel"
- path =/obj/item/weapon/shovel
\ No newline at end of file
+ path =/obj/item/shovel
diff --git a/code/datums/browser.dm b/code/datums/browser.dm
index e38b78ab4d4..1c6cdaf4704 100644
--- a/code/datums/browser.dm
+++ b/code/datums/browser.dm
@@ -27,7 +27,7 @@
if (nref)
ref = nref
// If a client exists, but they have disabled fancy windowing, disable it!
- if(user && user.client && !user.client.is_preference_enabled(/datum/client_preference/browser_style))
+ if(!user?.client?.prefs?.read_preference(/datum/preference/toggle/browser_style))
return
add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs
@@ -113,7 +113,7 @@
/datum/browser/proc/open(var/use_onclose = 1)
if(isnull(window_id)) //null check because this can potentially nuke goonchat
WARNING("Browser [title] tried to open with a null ID")
- to_chat(user, "The [title] browser you tried to open failed a sanity check! Please report this on github!")
+ to_chat(user, span_userdanger("The [title] browser you tried to open failed a sanity check! Please report this on github!"))
return
var/window_size = ""
if (width && height)
diff --git a/code/datums/chat_message.dm b/code/datums/chat_message.dm
index 3a95ba1db59..f216ae01cf5 100644
--- a/code/datums/chat_message.dm
+++ b/code/datums/chat_message.dm
@@ -51,8 +51,6 @@ var/list/runechat_image_cache = list()
/// If we are currently processing animation and cleanup at EOL
var/ending_life
- /// deletion timer
- var/timer_delete
/**
* Constructs a chat message overlay
@@ -75,9 +73,6 @@ var/list/runechat_image_cache = list()
generate_image(text, target, owner, extra_classes, lifespan)
/datum/chatmessage/Destroy()
- if(timer_delete)
- deltimer(timer_delete)
- timer_delete = null
if(istype(owned_by, /client)) // hopefully the PARENT_QDELETING on client should beat this if it's a disconnect
UnregisterSignal(owned_by, COMSIG_PARENT_QDELETING)
if(owned_by.seen_messages)
@@ -109,7 +104,7 @@ var/list/runechat_image_cache = list()
owned_by = owner.client
RegisterSignal(owned_by, COMSIG_PARENT_QDELETING, PROC_REF(unregister_qdel_self)) // this should only call owned_by if the client is destroyed
- var/extra_length = owned_by.is_preference_enabled(/datum/client_preference/runechat_long_messages)
+ var/extra_length = owned_by.prefs?.read_preference(/datum/preference/toggle/runechat_long_messages)
var/maxlen = extra_length ? CHAT_MESSAGE_EXT_LENGTH : CHAT_MESSAGE_LENGTH
var/msgwidth = extra_length ? CHAT_MESSAGE_EXT_WIDTH : CHAT_MESSAGE_WIDTH
@@ -123,6 +118,13 @@ var/list/runechat_image_cache = list()
target.chat_color_darkened = colorize_string(target.name, 0.85, 0.85)
target.chat_color_name = target.name
+ // Always force it back to a pref if they have one
+ if(ismob(target))
+ var/mob/M = target
+ if(M?.client?.prefs && M.client.prefs.runechat_color != COLOR_BLACK)
+ target.chat_color = M.client.prefs.runechat_color
+ target.chat_color_darkened = M.client.prefs.runechat_color
+
// Get rid of any URL schemes that might cause BYOND to automatically wrap something in an anchor tag
var/static/regex/url_scheme = new(@"[A-Za-z][A-Za-z0-9+-\.]*:\/\/", "g")
text = replacetext(text, url_scheme, "")
@@ -141,7 +143,7 @@ var/list/runechat_image_cache = list()
// Differnt from our own system of name emphasis, maybe unify
var/list/names = splittext(owner.name, " ")
for (var/word in names)
- text = replacetext(text, word, "[word]")
+ text = replacetext(text, word, span_bold("[word]"))
var/list/prefixes
@@ -186,8 +188,7 @@ var/list/runechat_image_cache = list()
if(sched_remaining > CHAT_MESSAGE_SPAWN_TIME)
var/remaining_time = (sched_remaining) * (CHAT_MESSAGE_EXP_DECAY ** idx++) * (CHAT_MESSAGE_HEIGHT_DECAY ** combined_height)
m.scheduled_destruction = world.time + remaining_time
- spawn(remaining_time)
- m.end_of_life()
+ m.schedule_end_of_life(remaining_time)
// Build message image
message = image(loc = message_loc, layer = ABOVE_MOB_LAYER)
@@ -213,13 +214,16 @@ var/list/runechat_image_cache = list()
// Prepare for destruction
scheduled_destruction = world.time + (lifespan - CHAT_MESSAGE_EOL_FADE)
- spawn(lifespan - CHAT_MESSAGE_EOL_FADE)
- end_of_life()
+ schedule_end_of_life(lifespan - CHAT_MESSAGE_EOL_FADE)
/datum/chatmessage/proc/unregister_qdel_self() // this should only call owned_by if the client is destroyed
UnregisterSignal(owned_by, COMSIG_PARENT_QDELETING)
owned_by = null
qdel_self()
+
+/datum/chatmessage/proc/schedule_end_of_life(var/schedule)
+ addtimer(CALLBACK(src, PROC_REF(end_of_life)), schedule, TIMER_DELETE_ME)
+
/**
* Applies final animations to overlay CHAT_MESSAGE_EOL_FADE deciseconds prior to message deletion
*/
@@ -228,7 +232,7 @@ var/list/runechat_image_cache = list()
return
ending_life = TRUE
animate(message, alpha = 0, time = fadetime, flags = ANIMATION_PARALLEL)
- timer_delete = QDEL_IN(src, fadetime)
+ addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), src), fadetime, TIMER_DELETE_ME)
/**
* Creates a message overlay at a defined location for a given speaker
@@ -243,11 +247,14 @@ var/list/runechat_image_cache = list()
if(!client)
return
+ // Source Deleting
+ if(QDELETED(speaker))
+ return
// Doesn't want to hear
- if(ismob(speaker) && !client.is_preference_enabled(/datum/client_preference/runechat_mob))
+ if(ismob(speaker) && !client.prefs?.read_preference(/datum/preference/toggle/runechat_mob))
return
// I know the pref is 'obj' but people dunno what turfs are
- else if(!client.is_preference_enabled(/datum/client_preference/runechat_obj))
+ else if(!client.prefs?.read_preference(/datum/preference/toggle/runechat_obj))
return
// Incapable of receiving
@@ -270,7 +277,7 @@ var/list/runechat_image_cache = list()
if(italics)
extra_classes |= "italics"
- if(client.is_preference_enabled(/datum/client_preference/runechat_border))
+ if(client.prefs?.read_preference(/datum/preference/toggle/runechat_border))
extra_classes |= "black_outline"
var/dist = get_dist(src, speaker)
@@ -349,7 +356,7 @@ var/list/runechat_image_cache = list()
hearing_mobs = hear["mobs"]
for(var/mob/M as anything in hearing_mobs)
- if(!M.client)
+ if(!M?.client)
continue
M.create_chat_message(src, message, italics, classes, audible)
@@ -379,7 +386,7 @@ var/list/runechat_image_cache = list()
return src
/mob/runechat_holder(datum/chatmessage/CM)
- if(istype(loc, /obj/item/weapon/holder))
+ if(istype(loc, /obj/item/holder))
return loc
return ..()
diff --git a/code/datums/colormate.dm b/code/datums/colormate.dm
index 2149191543f..3bb625b7b16 100644
--- a/code/datums/colormate.dm
+++ b/code/datums/colormate.dm
@@ -43,7 +43,7 @@
/datum/ColorMate/tgui_state(mob/user)
return GLOB.tgui_conscious_state
-/datum/ColorMate/tgui_data()
+/datum/ColorMate/tgui_data(mob/user)
. = list()
.["activemode"] = active_mode
.["matrixcolors"] = list(
@@ -69,7 +69,7 @@
.["item"] = list()
.["item"]["name"] = inserted.name
.["item"]["sprite"] = icon2base64(get_flat_icon(inserted,dir=SOUTH,no_anim=TRUE))
- .["item"]["preview"] = icon2base64(build_preview())
+ .["item"]["preview"] = icon2base64(build_preview(user))
else
.["item"] = null
@@ -108,6 +108,16 @@
if("set_matrix_color")
color_matrix_last[params["color"]] = params["value"]
return TRUE
+ if("set_matrix_string")
+ if(params["value"])
+ var/list/colours = splittext(params["value"], ",")
+ if(colours.len > 12)
+ colours.Cut(13)
+ for(var/i = 1, i <= colours.len, i++)
+ var/number = text2num(colours[i])
+ if(isnum(number))
+ color_matrix_last[i] = clamp(number, -10, 10)
+ return TRUE
if("set_hue")
build_hue = clamp(text2num(params["buildhue"]), 0, 360)
return TRUE
@@ -142,14 +152,14 @@
color_to_use = color_matrix_hsv(build_hue, build_sat, build_val)
color_matrix_last = color_to_use
if(!color_to_use || !check_valid_color(color_to_use, user))
- to_chat(user, SPAN_NOTICE("Invalid color."))
+ to_chat(user, span_notice("Invalid color."))
return FALSE
inserted.add_atom_colour(color_to_use, FIXED_COLOUR_PRIORITY)
playsound(src, 'sound/effects/spray3.ogg', 50, 1)
return TRUE
/// Produces the preview image of the item, used in the UI, the way the color is not stacking is a sin.
-/datum/ColorMate/proc/build_preview()
+/datum/ColorMate/proc/build_preview(mob/user)
if(inserted) //sanity
var/list/cm
switch(active_mode)
@@ -168,17 +178,17 @@
text2num(color_matrix_last[11]),
text2num(color_matrix_last[12]),
)
- if(!check_valid_color(cm, usr))
+ if(!check_valid_color(cm, user))
return get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE)
if(COLORMATE_TINT)
- if(!check_valid_color(activecolor, usr))
+ if(!check_valid_color(activecolor, user))
return get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE)
if(COLORMATE_HSV)
cm = color_matrix_hsv(build_hue, build_sat, build_val)
color_matrix_last = cm
- if(!check_valid_color(cm, usr))
+ if(!check_valid_color(cm, user))
return get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE)
var/cur_color = inserted.color
diff --git a/code/datums/components/connect_mob_behalf.dm b/code/datums/components/connect_mob_behalf.dm
new file mode 100644
index 00000000000..1c1a8a65234
--- /dev/null
+++ b/code/datums/components/connect_mob_behalf.dm
@@ -0,0 +1,59 @@
+/// This component behaves similar to connect_loc_behalf, but working off clients and mobs instead of loc
+/// To be clear, we hook into a signal on a tracked client's mob
+/// We retain the ability to react to that signal on a seperate listener, which makes this quite powerful
+/datum/component/connect_mob_behalf
+ dupe_mode = COMPONENT_DUPE_UNIQUE
+
+ /// An assoc list of signal -> procpath to register to the mob our client "owns"
+ var/list/connections
+ /// The master client we're working with
+ var/client/tracked
+ /// The mob we're currently tracking
+ var/mob/tracked_mob
+
+/datum/component/connect_mob_behalf/Initialize(client/tracked, list/connections)
+ . = ..()
+ if (!istype(tracked))
+ return COMPONENT_INCOMPATIBLE
+ src.connections = connections
+ src.tracked = tracked
+
+/datum/component/connect_mob_behalf/RegisterWithParent()
+ RegisterSignal(tracked, COMSIG_PARENT_QDELETING, PROC_REF(handle_tracked_qdel))
+ update_signals()
+
+/datum/component/connect_mob_behalf/UnregisterFromParent()
+ unregister_signals()
+ UnregisterSignal(tracked, COMSIG_PARENT_QDELETING)
+
+ tracked = null
+ tracked_mob = null
+
+/datum/component/connect_mob_behalf/proc/handle_tracked_qdel()
+ SIGNAL_HANDLER
+ qdel(src)
+
+/datum/component/connect_mob_behalf/proc/update_signals()
+ unregister_signals()
+ // Yes this is a runtime silencer
+ // We could be in a position where logout is sent to two things, one thing intercepts it, then deletes the client's new mob
+ // It's rare, and the same check in connect_loc_behalf is more fruitful, but it's still worth doing
+ if(QDELETED(tracked?.mob))
+ return
+ tracked_mob = tracked.mob
+ RegisterSignal(tracked_mob, COMSIG_MOB_LOGOUT, PROC_REF(on_logout))
+ for (var/signal in connections)
+ parent.RegisterSignal(tracked_mob, signal, connections[signal])
+
+/datum/component/connect_mob_behalf/proc/unregister_signals()
+ if(isnull(tracked_mob))
+ return
+
+ parent.UnregisterSignal(tracked_mob, connections)
+ UnregisterSignal(tracked_mob, COMSIG_MOB_LOGOUT)
+
+ tracked_mob = null
+
+/datum/component/connect_mob_behalf/proc/on_logout(mob/source)
+ SIGNAL_HANDLER
+ update_signals()
diff --git a/code/datums/components/crafting/crafting.dm b/code/datums/components/crafting/crafting.dm
index fd468994de3..3f482ea72e2 100644
--- a/code/datums/components/crafting/crafting.dm
+++ b/code/datums/components/crafting/crafting.dm
@@ -92,8 +92,8 @@
.["tool_qualities"] |= item.tool_qualities
.["other"][item.type] += 1
else
- if(istype(item, /obj/item/weapon/reagent_containers))
- var/obj/item/weapon/reagent_containers/container = item
+ if(istype(item, /obj/item/reagent_containers))
+ var/obj/item/reagent_containers/container = item
// if(container.is_drainable())
if(container.is_open_container()) // this isn't exactly the same
for(var/datum/reagent/reagent in container.reagents.reagent_list)
@@ -157,7 +157,7 @@
for(var/obj/item/contained_item in source.contents)
// if(contained_item.GetComponent(/datum/component/storage))
- if(istype(contained_item, /obj/item/weapon/storage)) // cursed
+ if(istype(contained_item, /obj/item/storage)) // cursed
for(var/obj/item/subcontained_item in contained_item.contents)
available_tools[subcontained_item.type] = TRUE
for(var/behavior in subcontained_item.tool_qualities)
@@ -290,7 +290,7 @@
var/datum/reagent/reagent = path_key
var/id = initial(reagent.id)
- for(var/obj/item/weapon/reagent_containers/RC in surroundings)
+ for(var/obj/item/reagent_containers/RC in surroundings)
// Found everything we need
if(amt <= 0 && amt_to_transfer <= 0)
break
@@ -338,8 +338,8 @@
continue
// Special case: the reagents may be needed for other recipes
- if(istype(I, /obj/item/weapon/reagent_containers))
- var/obj/item/weapon/reagent_containers/RC = I
+ if(istype(I, /obj/item/reagent_containers))
+ var/obj/item/reagent_containers/RC = I
if(RC.reagents.total_volume > 0)
continue
@@ -354,12 +354,12 @@
// Snowflake handling of reagent containers and storage atoms.
// If we consumed them in our crafting, we should dump their contents out before qdeling them.
- if(istype(I, /obj/item/weapon/reagent_containers))
- var/obj/item/weapon/reagent_containers/container = I
+ if(istype(I, /obj/item/reagent_containers))
+ var/obj/item/reagent_containers/container = I
container.reagents.clear_reagents()
// container.reagents.expose(container.loc, TOUCH)
- else if(istype(I, /obj/item/weapon/storage))
- var/obj/item/weapon/storage/container = I
+ else if(istype(I, /obj/item/storage))
+ var/obj/item/storage/container = I
container.spill()
container.close_all()
qdel(I)
@@ -452,26 +452,25 @@
data["crafting_recipes"] = crafting_recipes
return data
-/datum/component/personal_crafting/tgui_act(action, params)
+/datum/component/personal_crafting/tgui_act(action, params, datum/tgui/ui)
. = ..()
if(.)
return
switch(action)
if("make")
- var/mob/user = usr
var/datum/crafting_recipe/TR = locate(params["recipe"]) in GLOB.crafting_recipes
busy = TRUE
- tgui_interact(user)
- var/atom/movable/result = construct_item(user, TR)
+ tgui_interact(ui.user)
+ var/atom/movable/result = construct_item(ui.user, TR)
if(!istext(result)) //We made an item and didn't get a fail message
- if(ismob(user) && isitem(result)) //In case the user is actually possessing a non mob like a machine
- user.put_in_hands(result)
+ if(ismob(ui.user) && isitem(result)) //In case the user is actually possessing a non mob like a machine
+ ui.user.put_in_hands(result)
else
- result.forceMove(user.drop_location())
- to_chat(user, "[TR.name] constructed.")
- TR.on_craft_completion(user, result)
+ result.forceMove(ui.user.drop_location())
+ to_chat(ui.user, span_notice("[TR.name] constructed."))
+ TR.on_craft_completion(ui.user, result)
else
- to_chat(user, "Construction failed[result]")
+ to_chat(ui.user, span_warning("Construction failed[result]"))
busy = FALSE
if("toggle_recipes")
display_craftable_only = !display_craftable_only
diff --git a/code/datums/components/crafting/recipes.dm b/code/datums/components/crafting/recipes.dm
index 453652928bd..658b682e085 100644
--- a/code/datums/components/crafting/recipes.dm
+++ b/code/datums/components/crafting/recipes.dm
@@ -58,9 +58,9 @@
// Locate one of the things that set the material type, and update it from the default (glass)
/datum/crafting_recipe/spear/on_craft_completion(mob/user, atom/result)
- var/obj/item/weapon/material/M
+ var/obj/item/material/M
for(var/path in parts)
- var/obj/item/weapon/material/N = locate(path) in result
+ var/obj/item/material/N = locate(path) in result
if(istype(N, path))
if(!istype(M))
M = N
@@ -69,6 +69,6 @@
if(!istype(M))
return
- var/obj/item/weapon/material/twohanded/spear/S = result
+ var/obj/item/material/twohanded/spear/S = result
S.set_material(M.material.name)
qdel(M)
diff --git a/code/datums/components/crafting/recipes/survival.dm b/code/datums/components/crafting/recipes/survival.dm
index a1100f6808c..e97e7733116 100644
--- a/code/datums/components/crafting/recipes/survival.dm
+++ b/code/datums/components/crafting/recipes/survival.dm
@@ -1,6 +1,6 @@
/datum/crafting_recipe/shovel
name = "Wooden Shovel"
- result = /obj/item/weapon/shovel/wood
+ result = /obj/item/shovel/wood
reqs = list(
list(/obj/item/stack/material/stick = 5),
list(/obj/item/stack/material/wood = 1),
@@ -13,7 +13,7 @@
/datum/crafting_recipe/stoneblade
name = "stone blade"
- result = /obj/item/weapon/material/knife/stone
+ result = /obj/item/material/knife/stone
reqs = list(
list(/obj/item/stack/material/flint = 2)
)
@@ -23,9 +23,9 @@
/datum/crafting_recipe/stonewoodknife
name = "stone knife"
- result = /obj/item/weapon/material/knife/stone/wood
+ result = /obj/item/material/knife/stone/wood
reqs = list(
- list(/obj/item/weapon/material/knife/stone = 1),
+ list(/obj/item/material/knife/stone = 1),
list(/obj/item/stack/material/flint = 1),
list(/obj/item/stack/material/wood = 1),
list(/obj/item/stack/material/fiber = 3)
@@ -36,11 +36,11 @@
/datum/crafting_recipe/stoneboneknife
name = "stone knife"
- result = /obj/item/weapon/material/knife/stone/bone
+ result = /obj/item/material/knife/stone/bone
reqs = list(
- list(/obj/item/weapon/material/knife/stone = 1),
+ list(/obj/item/material/knife/stone = 1),
list(/obj/item/stack/material/flint = 1),
- list(/obj/item/weapon/bone = 1),
+ list(/obj/item/bone = 1),
list(/obj/item/stack/material/fiber = 3)
)
time = 120
@@ -49,7 +49,7 @@
/datum/crafting_recipe/woodbucket
name = "wooden bucket"
- result = /obj/item/weapon/reagent_containers/glass/bucket/wood
+ result = /obj/item/reagent_containers/glass/bucket/wood
reqs = list(
list(/obj/item/stack/material/wood = 1),
list(/obj/item/stack/material/stick = 1),
@@ -62,15 +62,15 @@
name = "sticks"
result = /obj/item/stack/material/stick/fivestack
reqs = list(list(/obj/item/stack/material/wood = 1))
- tool_paths = list(/obj/item/weapon/material/knife)
+ tool_paths = list(/obj/item/material/knife)
time = 200
category = CAT_MISC
/datum/crafting_recipe/stonewoodaxe
name = "stone axe"
- result = /obj/item/weapon/material/knife/machete/hatchet/stone
+ result = /obj/item/material/knife/machete/hatchet/stone
reqs = list(
- list(/obj/item/weapon/material/knife/stone = 1),
+ list(/obj/item/material/knife/stone = 1),
list(/obj/item/stack/material/flint = 1),
list(/obj/item/stack/material/stick = 1),
list(/obj/item/stack/material/fiber = 3)
@@ -81,11 +81,11 @@
/datum/crafting_recipe/stoneboneaxe
name = "stone axe"
- result = /obj/item/weapon/material/knife/machete/hatchet/stone/bone
+ result = /obj/item/material/knife/machete/hatchet/stone/bone
reqs = list(
- list(/obj/item/weapon/material/knife/stone = 1),
+ list(/obj/item/material/knife/stone = 1),
list(/obj/item/stack/material/flint = 1),
- list(/obj/item/weapon/bone = 1),
+ list(/obj/item/bone = 1),
list(/obj/item/stack/material/fiber = 3)
)
time = 120
@@ -94,9 +94,9 @@
/datum/crafting_recipe/stonewoodspear
name = "stone spear"
- result = /obj/item/weapon/material/twohanded/spear/flint
+ result = /obj/item/material/twohanded/spear/flint
reqs = list(
- list(/obj/item/weapon/material/knife/stone = 1),
+ list(/obj/item/material/knife/stone = 1),
list(/obj/item/stack/material/flint = 1),
list(/obj/item/stack/material/wood = 2),
list(/obj/item/stack/material/fiber = 3)
@@ -107,11 +107,11 @@
/datum/crafting_recipe/stonebonespear
name = "stone spear"
- result = /obj/item/weapon/material/twohanded/spear/flint
+ result = /obj/item/material/twohanded/spear/flint
reqs = list(
- list(/obj/item/weapon/material/knife/stone = 1),
+ list(/obj/item/material/knife/stone = 1),
list(/obj/item/stack/material/flint = 1),
- list(/obj/item/weapon/bone = 2),
+ list(/obj/item/bone = 2),
list(/obj/item/stack/material/fiber = 3)
)
time = 120
@@ -120,7 +120,7 @@
/datum/crafting_recipe/ropebindings
name = "rope bindings"
- result = /obj/item/weapon/handcuffs/cable/plantfiber
+ result = /obj/item/handcuffs/cable/plantfiber
reqs = list(list(/obj/item/stack/material/fiber = 3))
time = 60
category = CAT_MISC
\ No newline at end of file
diff --git a/code/datums/components/crafting/recipes/weapons.dm b/code/datums/components/crafting/recipes/weapons.dm
index 68f01b54e9f..41d96db57d4 100644
--- a/code/datums/components/crafting/recipes/weapons.dm
+++ b/code/datums/components/crafting/recipes/weapons.dm
@@ -1,30 +1,30 @@
/datum/crafting_recipe/stunprod
name = "Stunprod"
- result = /obj/item/weapon/melee/baton/cattleprod
- reqs = list(list(/obj/item/weapon/handcuffs/cable = 1),
+ result = /obj/item/melee/baton/cattleprod
+ reqs = list(list(/obj/item/handcuffs/cable = 1),
list(/obj/item/stack/rods = 1),
- list(/obj/item/weapon/tool/wirecutters = 1))
+ list(/obj/item/tool/wirecutters = 1))
time = 40
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
/datum/crafting_recipe/spear
name = "Spear"
- result = /obj/item/weapon/material/twohanded/spear
- reqs = list(list(/obj/item/weapon/handcuffs/cable = 1),
+ result = /obj/item/material/twohanded/spear
+ reqs = list(list(/obj/item/handcuffs/cable = 1),
list(/obj/item/stack/rods = 1),
- list(/obj/item/weapon/material/shard = 1,
- /obj/item/weapon/material/butterflyblade = 1)
+ list(/obj/item/material/shard = 1,
+ /obj/item/material/butterflyblade = 1)
)
- parts = list(/obj/item/weapon/material/shard = 1,
- /obj/item/weapon/material/butterflyblade = 1)
+ parts = list(/obj/item/material/shard = 1,
+ /obj/item/material/butterflyblade = 1)
time = 40
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
/datum/crafting_recipe/shortbow
name = "Shortbow"
- result = /obj/item/weapon/gun/launcher/crossbow/bow
+ result = /obj/item/gun/launcher/crossbow/bow
reqs = list(list(/obj/item/stack/material/wood = 10),
list(/obj/item/stack/material/cloth = 5))
time = 120
@@ -33,7 +33,7 @@
/datum/crafting_recipe/arrow_sandstone
name = "Wood arrow (sandstone tip)"
- result = /obj/item/weapon/arrow/standard
+ result = /obj/item/arrow/standard
reqs = list(list(/obj/item/stack/material/wood = 2),
list(/obj/item/stack/material/sandstone = 2))
time = 40
@@ -42,7 +42,7 @@
/datum/crafting_recipe/arrow_marble
name = "Wood arrow (marble tip)"
- result = /obj/item/weapon/arrow/standard
+ result = /obj/item/arrow/standard
reqs = list(list(/obj/item/stack/material/wood = 2),
list(/obj/item/stack/material/marble = 2))
time = 40
@@ -51,17 +51,17 @@
/datum/crafting_recipe/primitive_shield
name = "Primitive Shield"
- result = /obj/item/weapon/shield/primitive
- reqs = list(list(/obj/item/stack/material/wood = 2), list(/obj/item/weapon/reagent_containers/glass/bucket/wood =1), list(/obj/item/stack/material/cloth = 5))
+ result = /obj/item/shield/primitive
+ reqs = list(list(/obj/item/stack/material/wood = 2), list(/obj/item/reagent_containers/glass/bucket/wood =1), list(/obj/item/stack/material/cloth = 5))
time = 120
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
/datum/crafting_recipe/scopedrifle
name = "Bolt scope to bolt-action (cannot be removed)"
- result = /obj/item/weapon/gun/projectile/shotgun/pump/rifle/scoped
- reqs = list(list(/obj/item/device/binoculars/scope = 1),
- list(/obj/item/weapon/gun/projectile/shotgun/pump/rifle = 1))
+ result = /obj/item/gun/projectile/shotgun/pump/rifle/scoped
+ reqs = list(list(/obj/item/binoculars/scope = 1),
+ list(/obj/item/gun/projectile/shotgun/pump/rifle = 1))
time = 180
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
diff --git a/code/datums/components/gargoyle.dm b/code/datums/components/gargoyle.dm
new file mode 100644
index 00000000000..618c2e97e03
--- /dev/null
+++ b/code/datums/components/gargoyle.dm
@@ -0,0 +1,101 @@
+/datum/component/gargoyle
+ var/energy = 100
+ var/transformed = FALSE
+ var/paused = FALSE
+ var/paused_loc
+ var/cooldown
+
+ var/mob/living/carbon/human/gargoyle //easy reference
+ var/obj/structure/gargoyle/statue //another easy ref
+
+ //Adjustable mod
+ var/identifier = "statue"
+ var/adjective = "hardens"
+ var/material = "stone"
+ var/tint = "#FFFFFF"
+
+/datum/component/gargoyle/Initialize()
+ if (!ishuman(parent))
+ return COMPONENT_INCOMPATIBLE
+ gargoyle = parent
+ add_verb(gargoyle,/mob/living/carbon/human/proc/gargoyle_transformation)
+ add_verb(gargoyle,/mob/living/carbon/human/proc/gargoyle_pause)
+ add_verb(gargoyle,/mob/living/carbon/human/proc/gargoyle_checkenergy)
+
+ START_PROCESSING(SSprocessing, src)
+
+/datum/component/gargoyle/process()
+ if (QDELETED(gargoyle))
+ return
+ if (paused && gargoyle.loc != paused_loc)
+ unpause()
+ if (energy > 0)
+ if (!transformed && !paused)
+ energy = max(0,energy-0.05)
+ else if (!transformed && isturf(gargoyle.loc))
+ gargoyle.gargoyle_transformation()
+ if (transformed)
+ if (!statue)
+ transformed = FALSE
+ statue.damage(-0.5)
+ energy = min(energy+0.3, 100)
+
+/datum/component/gargoyle/proc/unpause()
+ if (!paused || transformed)
+ paused = FALSE
+ paused_loc = null
+ UnregisterSignal(gargoyle, COMSIG_ATOM_ENTERING)
+ return
+ if (gargoyle?.loc != paused_loc)
+ paused = FALSE
+ paused_loc = null
+ energy = max(energy - 5, 0)
+ if (energy == 0)
+ gargoyle.gargoyle_transformation()
+ UnregisterSignal(gargoyle, COMSIG_ATOM_ENTERING)
+
+//verbs or action buttons...?
+/mob/living/carbon/human/proc/gargoyle_transformation()
+ set name = "Gargoyle - Petrification"
+ set category = "Abilities.Gargoyle"
+ set desc = "Turn yourself into (or back from) being a gargoyle."
+
+ if (stat == DEAD)
+ return
+
+ var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle)
+ if (comp)
+ if (comp.energy <= 0 && isturf(loc))
+ to_chat(src, span_danger("You suddenly turn into a [comp.identifier] as you run out of energy!"))
+ else if (comp.cooldown > world.time)
+ var/time_to_wait = (comp.cooldown - world.time) / (1 SECONDS)
+ to_chat(src, span_warning("You can't transform just yet again! Wait for another [round(time_to_wait,0.1)] seconds!"))
+ return
+ if (istype(loc, /obj/structure/gargoyle))
+ qdel(loc)
+ else if (isturf(loc))
+ new /obj/structure/gargoyle(loc, src)
+
+/mob/living/carbon/human/proc/gargoyle_pause()
+ set name = "Gargoyle - Pause"
+ set category = "Abilities.Gargoyle"
+ set desc = "Pause your energy while standing still, so you don't use up any more, though you will lose a small amount upon moving again."
+
+ if (stat)
+ return
+
+ var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle)
+ if (comp && !comp.transformed && !comp.paused)
+ comp.paused = TRUE
+ comp.paused_loc = loc
+ comp.RegisterSignal(src, COMSIG_ATOM_ENTERING, /datum/component/gargoyle/proc/unpause)
+ to_chat(src, span_notice("You start conserving your energy."))
+
+/mob/living/carbon/human/proc/gargoyle_checkenergy()
+ set name = "Gargoyle - Check Energy"
+ set category = "Abilities.Gargoyle"
+ set desc = "Check how much energy you have remaining as a gargoyle."
+
+ var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle)
+ if (comp)
+ to_chat(src, span_notice("You have [round(comp.energy,0.01)] energy remaining. It is currently [comp.paused ? "stable" : (comp.transformed ? "increasing" : "decreasing")]."))
diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm
index b414f4651f6..bbd2b7fd128 100644
--- a/code/datums/components/material_container.dm
+++ b/code/datums/components/material_container.dm
@@ -102,7 +102,7 @@
for(var/datum/material/M as anything in materials)
var/amt = materials[M]
if(amt)
- examine_texts += "It has [amt] units of [lowertext(M.name)] stored."
+ examine_texts += span_notice("It has [amt] units of [lowertext(M.name)] stored.")
/// Proc that allows players to fill the parent with mats
/datum/component/material_container/proc/on_attackby(datum/source, obj/item/I, mob/living/user)
@@ -113,7 +113,7 @@
return
if(tc && !is_type_in_typecache(I, tc))
if(!(mat_container_flags & MATCONTAINER_SILENT))
- to_chat(user, "[parent] won't accept [I]!")
+ to_chat(user, span_warning("[parent] won't accept [I]!"))
return
. = COMPONENT_CANCEL_ATTACK_CHAIN
var/datum/callback/pc = precondition
@@ -125,10 +125,10 @@
return
var/material_amount = get_item_material_amount(I, mat_container_flags)
if(!material_amount)
- to_chat(user, "[I] does not contain sufficient materials to be accepted by [parent].")
+ to_chat(user, span_warning("[I] does not contain sufficient materials to be accepted by [parent]."))
return
if(!has_space(material_amount))
- to_chat(user, "[parent] is full. Please remove materials from [parent] in order to insert more.")
+ to_chat(user, span_warning("[parent] is full. Please remove materials from [parent] in order to insert more."))
return
user_insert(I, user, mat_container_flags)
@@ -136,7 +136,7 @@
/datum/component/material_container/proc/user_insert_stack(obj/item/stack/S, mob/living/user, breakdown_flags = mat_container_flags)
var/sheets = S.get_amount()
if(sheets < 1)
- to_chat(user, "[S] does not contain sufficient materials to be accepted by [parent].")
+ to_chat(user, span_warning("[S] does not contain sufficient materials to be accepted by [parent]."))
return
// Cache this since S may go away after use()
@@ -149,23 +149,23 @@
// If any part of a sheet can't go in us, the whole sheet is invalid
if(!can_hold_material(GET_MATERIAL_REF(material)))
- to_chat(user, "[parent] cannot contain [material].")
+ to_chat(user, span_warning("[parent] cannot contain [material]."))
return
// Our sheet had no material. Whoops.
if(!matter_per_sheet)
- to_chat(user, "[S] does not contain any matter acceptable by [parent].")
+ to_chat(user, span_warning("[S] does not contain any matter acceptable by [parent]."))
return
// If we can't fit the material for one sheet, we're full.
if(!has_space(matter_per_sheet))
- to_chat(user, "[parent] is full. Please remove materials from [parent] in order to insert more.")
+ to_chat(user, span_warning("[parent] is full. Please remove materials from [parent] in order to insert more."))
return
// Calculate the maximum amount of sheets we could possibly accept.
var/max_sheets = round((max_amount - total_amount) / matter_per_sheet)
if(max_sheets <= 0)
- to_chat(user, "[parent] is full. Please remove materials from [parent] in order to insert more.")
+ to_chat(user, span_warning("[parent] is full. Please remove materials from [parent] in order to insert more."))
return
// Calculate the amount of sheets we're actually going to use.
@@ -176,7 +176,7 @@
// Use the amount of sheets from the stack
if(!S.use(sheets_to_use))
- to_chat(user, "Something went wrong with your stack. Split it manually and try again.")
+ to_chat(user, span_warning("Something went wrong with your stack. Split it manually and try again."))
return
// We're going to blindly insert all of the materials, our assertion above says it shouldn't be possible to overflow
@@ -187,7 +187,7 @@
last_inserted_id = matter
// Tell the user and wrap up.
- to_chat(user, "You insert a material total of [inserted] into [parent].")
+ to_chat(user, span_notice("You insert a material total of [inserted] into [parent]."))
if(after_insert)
after_insert.Invoke(S, last_inserted_id, inserted)
@@ -196,11 +196,11 @@
set waitfor = FALSE
var/active_held = user.get_active_hand() // differs from I when using TK
if(!user.unEquip(I))
- to_chat(user, "[I] is stuck to you and cannot be placed into [parent].")
+ to_chat(user, span_warning("[I] is stuck to you and cannot be placed into [parent]."))
return
var/inserted = insert_item(I, breakdown_flags = mat_container_flags)
if(inserted)
- to_chat(user, "You insert a material total of [inserted] into [parent].")
+ to_chat(user, span_notice("You insert a material total of [inserted] into [parent]."))
qdel(I)
if(after_insert)
after_insert.Invoke(I, last_inserted_id, inserted)
@@ -471,12 +471,15 @@
return materials[mat]
/// List format is list(list(name = ..., amount = ..., ref = ..., etc.), list(...))
-/datum/component/material_container/tgui_data(mob/user)
+/datum/component/material_container/tgui_data(mob/user, skip_empty = FALSE)
var/list/data = list()
for(var/datum/material/material as anything in materials)
var/amount = materials[material]
+ if(amount == 0 && skip_empty)
+ continue
+
data += list(list(
"name" = material.name,
"ref" = REF(material),
diff --git a/code/datums/components/recursive_move.dm b/code/datums/components/recursive_move.dm
index cf26942495b..35558839347 100644
--- a/code/datums/components/recursive_move.dm
+++ b/code/datums/components/recursive_move.dm
@@ -106,14 +106,14 @@
parents.Cut()
//the banana peel of testing stays
-/obj/item/weapon/bananapeel/testing
+/obj/item/bananapeel/testing
name = "banana peel of testing"
desc = "spams world log with debugging information"
-/obj/item/weapon/bananapeel/testing/proc/shmove(var/atom/source, var/atom/old_loc, var/atom/new_loc)
+/obj/item/bananapeel/testing/proc/shmove(var/atom/source, var/atom/old_loc, var/atom/new_loc)
world.log << "the [source] moved from [old_loc]([old_loc.x],[old_loc.y],[old_loc.z]) to [new_loc]([new_loc.x],[new_loc.y],[new_loc.z])"
-/obj/item/weapon/bananapeel/testing/Initialize()
+/obj/item/bananapeel/testing/Initialize()
. = ..()
AddComponent(/datum/component/recursive_move)
RegisterSignal(src, COMSIG_OBSERVER_MOVED, PROC_REF(shmove))
diff --git a/code/datums/components/resize_guard.dm b/code/datums/components/resize_guard.dm
index d708002cc1a..ca8adfab43d 100644
--- a/code/datums/components/resize_guard.dm
+++ b/code/datums/components/resize_guard.dm
@@ -13,7 +13,8 @@
/datum/component/resize_guard/proc/check_resize()
var/area/A = get_area(parent)
- if(A?.limit_mob_size)
- var/mob/living/L = parent
- L.resize(L.size_multiplier, ignore_prefs = TRUE)
- qdel(src)
+ if(A?.flag_check(AREA_ALLOW_LARGE_SIZE))
+ return
+ var/mob/living/L = parent
+ L.resize(L.size_multiplier, ignore_prefs = TRUE)
+ qdel(src)
diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm
index 7c37c10f520..cfe18eba25e 100644
--- a/code/datums/datacore.dm
+++ b/code/datums/datacore.dm
@@ -218,7 +218,7 @@ var/global/list/PDA_Manifest = list()
heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive)
department = 1
depthead = 1
- if(rank=="Site Manager" && heads.len != 1)
+ if(rank==JOB_SITE_MANAGER && heads.len != 1)
heads.Swap(1,heads.len)
if(SSjob.is_job_in_department(real_rank, DEPARTMENT_SECURITY))
@@ -356,7 +356,10 @@ var/global/list/PDA_Manifest = list()
G.fields["p_stat"] = "Active"
G.fields["m_stat"] = "Stable"
G.fields["sex"] = gender2text(H.gender)
- G.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]" //VOREStation Edit
+ if(H.species.name == SPECIES_HANNER)
+ G.fields["species"] = "[H.custom_species ? "[H.custom_species]" : H.species.name]"
+ else
+ G.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]"
G.fields["home_system"] = H.home_system
G.fields["birthplace"] = H.birthplace
G.fields["citizenship"] = H.citizenship
@@ -367,7 +370,10 @@ var/global/list/PDA_Manifest = list()
//Medical Record
var/datum/data/record/M = CreateMedicalRecord(H.real_name, id, hidden)
- M.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]" //VOREStation Edit
+ if(H.species.name == SPECIES_HANNER)
+ M.fields["species"] = "[H.custom_species ? "[H.custom_species]" : H.species.name]"
+ else
+ M.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]"
M.fields["b_type"] = H.b_type
M.fields["blood_reagent"] = H.species.blood_reagents
M.fields["b_dna"] = H.dna.unique_enzymes
@@ -381,7 +387,10 @@ var/global/list/PDA_Manifest = list()
//Security Record
var/datum/data/record/S = CreateSecurityRecord(H.real_name, id, hidden)
- S.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]" //VOREStation Edit
+ if(H.species.name == SPECIES_HANNER)
+ S.fields["species"] = "[H.custom_species ? "[H.custom_species]" : H.species.name]"
+ else
+ S.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]"
if(H.get_FBP_type())
S.fields["brain_type"] = H.get_FBP_type()
else
@@ -407,7 +416,10 @@ var/global/list/PDA_Manifest = list()
L.fields["b_dna"] = H.dna.unique_enzymes
L.fields["enzymes"] = H.dna.SE // Used in respawning
L.fields["identity"] = H.dna.UI // "
- L.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]" //VOREStation Edit
+ if(H.species.name == SPECIES_HANNER)
+ L.fields["species"] = "[H.custom_species ? "[H.custom_species]" : H.species.name]"
+ else
+ L.fields["species"] = "[H.custom_species ? "[H.custom_species] ([H.species.name])" : H.species.name]"
L.fields["home_system"] = H.home_system
L.fields["birthplace"] = H.birthplace
L.fields["citizenship"] = H.citizenship
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index a50909a3b47..2c37b78811b 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -22,7 +22,7 @@
var/list/open_uis
/// Active timers with this datum as the target
- var/list/active_timers
+ var/list/_active_timers
/// Status traits attached to this datum. associative list of the form: list(trait name (string) = list(source1, source2, source3,...))
var/list/_status_traits
@@ -69,20 +69,35 @@
// Create and destroy is weird and I wanna cover my bases
var/harddel_deets_dumped = FALSE
-// Default implementation of clean-up code.
-// This should be overridden to remove all references pointing to the object being destroyed.
-// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
+/**
+ * Default implementation of clean-up code.
+ *
+ * This should be overridden to remove all references pointing to the object being destroyed, if
+ * you do override it, make sure to call the parent and return its return value by default
+ *
+ * Return an appropriate [QDEL_HINT][QDEL_HINT_QUEUE] to modify handling of your deletion;
+ * in most cases this is [QDEL_HINT_QUEUE].
+ *
+ * The base case is responsible for doing the following
+ * * Erasing timers pointing to this datum
+ * * Erasing compenents on this datum
+ * * Notifying datums listening to signals from this datum that we are going away
+ *
+ * Returns [QDEL_HINT_QUEUE]
+ */
/datum/proc/Destroy(force=FALSE)
+ //SHOULD_CALL_PARENT(TRUE)
+ //SHOULD_NOT_SLEEP(TRUE)
+ tag = null
+ weak_reference = null //ensure prompt GCing of weakref.
- //clear timers
- var/list/timers = active_timers
- active_timers = null
- for(var/datum/timedevent/timer as anything in timers)
- if (timer.spent)
- continue
- qdel(timer)
-
- weak_reference = null // Clear this reference to ensure it's kept for as brief duration as possible.
+ if(_active_timers)
+ var/list/timers = _active_timers
+ _active_timers = null
+ for(var/datum/timedevent/timer as anything in timers)
+ if (timer.spent && !(timer.flags & TIMER_DELETE_ME))
+ continue
+ qdel(timer)
//BEGIN: ECS SHIT
signal_enabled = FALSE
@@ -114,7 +129,6 @@
UnregisterSignal(target, signal_procs[target])
//END: ECS SHIT
- tag = null
SStgui.close_uis(src)
#ifdef REFERENCE_TRACKING
diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm
index 4579f50f409..be1b1236adb 100644
--- a/code/datums/datumvars.dm
+++ b/code/datums/datumvars.dm
@@ -86,12 +86,12 @@
datumname = "element"
_AddElement(lst)
log_admin("[key_name(usr)] has added [result] [datumname] to [key_name(src)].")
- message_admins("[key_name_admin(usr)] has added [result] [datumname] to [key_name_admin(src)].")
+ message_admins(span_notice("[key_name_admin(usr)] has added [result] [datumname] to [key_name_admin(src)]."))
/datum/proc/vv_get_header()
. = list()
if(("name" in vars) && !isatom(src))
- . += "[vars["name"]]
"
+ . += span_bold("[vars["name"]]") + "
"
/datum/proc/on_reagent_change(changetype)
return
diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm
new file mode 100644
index 00000000000..6505817fb55
--- /dev/null
+++ b/code/datums/diseases/_MobProcs.dm
@@ -0,0 +1,194 @@
+/mob/proc/HasDisease(datum/disease/D)
+ for(var/thing in GetViruses())
+ var/datum/disease/DD = thing
+ if(DD.IsSame(D))
+ return TRUE
+ return FALSE
+
+/mob/proc/CanContractDisease(datum/disease/D)
+ if(stat == DEAD && !D.allow_dead)
+ return FALSE
+
+ if(D.GetDiseaseID() in GetResistances())
+ return FALSE
+
+ if(HasDisease(D))
+ return FALSE
+
+ if(istype(D, /datum/disease/advance) && count_by_type(GetViruses(), /datum/disease/advance) > 0)
+ return FALSE
+
+ if(!(type in D.viable_mobtypes))
+ return -1
+
+ if(isSynthetic())
+ if(D.infect_synthetics)
+ return TRUE
+ return FALSE
+
+ return TRUE
+
+/mob/proc/ContractDisease(datum/disease/D)
+ if(!CanContractDisease(D))
+ return 0
+ AddDisease(D)
+ return TRUE
+
+/mob/proc/AddDisease(datum/disease/D, respect_carrier = FALSE)
+ var/datum/disease/DD = new D.type(1, D, 0)
+ viruses += DD
+ DD.affected_mob = src
+ active_diseases += DD
+
+ var/list/skipped = list("affected_mob", "holder", "carrier", "stage", "type", "parent_type", "vars", "transformed")
+ if(respect_carrier)
+ skipped -= "carrier"
+ for(var/V in DD.vars)
+ if(V in skipped)
+ continue
+ if(istype(DD.vars[V],/list))
+ var/list/L = D.vars[V]
+ DD.vars[V] = L.Copy()
+ else
+ DD.vars[V] = D.vars[V]
+
+ log_admin("[key_name(usr)] has contracted the virus \"[DD]\"")
+
+/mob/living/carbon/ContractDisease(datum/disease/D)
+ if(!CanContractDisease(D))
+ return 0
+
+ var/obj/item/clothing/Cl = null
+ var/passed = 1
+
+ var/head_ch = 100
+ var/body_ch = 100
+ var/hands_ch = 25
+ var/feet_ch = 25
+
+ if(D.spread_flags & CONTACT_HANDS)
+ head_ch = 0
+ body_ch = 0
+ hands_ch = 100
+ feet_ch = 0
+ if(D.spread_flags & CONTACT_FEET)
+ head_ch = 0
+ body_ch = 0
+ hands_ch = 0
+ feet_ch = 100
+
+ if(prob(15/D.permeability_mod))
+ return
+
+ if(nutrition > 300 && prob(nutrition/50))
+ return
+
+ var/list/zone_weights = list(
+ 1 = head_ch,
+ 2 = body_ch,
+ 3 = hands_ch,
+ 4 = feet_ch
+ )
+
+ var/target_zone = pick(zone_weights)
+
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+
+ switch(target_zone)
+ if(1)
+ if(isobj(H.head) && !istype(H.head, /obj/item/paper))
+ Cl = H.head
+ passed = prob((Cl.permeability_coefficient*100) - 1)
+ if(passed && isobj(H.wear_mask))
+ Cl = H.wear_mask
+ passed = prob((Cl.permeability_coefficient*100) - 1)
+ if(2)
+ if(isobj(H.wear_suit))
+ Cl = H.wear_suit
+ passed = prob((Cl.permeability_coefficient*100) - 1)
+ if(passed && isobj(H.w_uniform))
+ Cl = H.w_uniform
+ passed = prob((Cl.permeability_coefficient*100) - 1)
+ if(3)
+ if(isobj(H.wear_suit) && H.wear_suit.body_parts_covered & HANDS)
+ Cl = H.wear_suit
+ passed = prob((Cl.permeability_coefficient*100) - 1)
+
+ if(passed && isobj(H.gloves))
+ Cl = H.gloves
+ passed = prob((Cl.permeability_coefficient*100) - 1)
+ if(4)
+ if(isobj(H.wear_suit) && H.wear_suit.body_parts_covered & FEET)
+ Cl = H.wear_suit
+ passed = prob((Cl.permeability_coefficient*100) - 1)
+
+ if(passed && isobj(H.shoes))
+ Cl = H.shoes
+ passed = prob((Cl.permeability_coefficient*100) - 1)
+ if(!passed && (D.spread_flags & AIRBORNE) && !internal)
+ passed = (prob((50*D.permeability_mod) -1))
+
+ if(passed)
+ AddDisease(D)
+ return passed
+
+/mob/proc/ForceContractDisease(datum/disease/D, respect_carrier)
+ if(!CanContractDisease(D))
+ return FALSE
+
+ AddDisease(D, respect_carrier)
+ return TRUE
+
+/mob/living/carbon/human/CanContractDisease(datum/disease/D)
+ if(species.virus_immune && !D.bypasses_immunity)
+ return FALSE
+
+ for(var/organ in D.required_organs)
+ if(locate(organ) in internal_organs)
+ continue
+ if(locate(organ) in organs)
+ continue
+ return FALSE
+ return ..()
+
+/mob/living/carbon/human/monkey/CanContractDisease(datum/disease/D)
+ . = ..()
+ if(. == -1)
+ if(D.viable_mobtypes.Find(/mob/living/carbon/human))
+ return 1
+
+/mob/living/proc/handle_diseases()
+ return
+
+/mob/proc/GetViruses()
+ LAZYINITLIST(viruses)
+ return viruses
+
+/mob/proc/GetResistances()
+ LAZYINITLIST(resistances)
+ return resistances
+
+/client/proc/ReleaseVirus()
+ set category = "Fun.Event Kit"
+ set name = "Release Virus"
+ set desc = "Release a pre-set virus."
+
+ if(!is_admin())
+ return FALSE
+
+ var/disease = tgui_input_list(usr, "Choose virus", "Viruses", subtypesof(/datum/disease), subtypesof(/datum/disease))
+ var/mob/living/carbon/human/H = tgui_input_list(usr, "Choose infectee", "Characters", human_mob_list)
+
+ var/datum/disease/D = new disease
+
+ if(isnull(D) || isnull(H))
+ return FALSE
+
+ if(!H.HasDisease(D))
+ H.ForceContractDisease(D)
+
+ message_admins("[key_name_admin(usr)] has triggered a virus outbreak of [D.name]! Affected mob: [key_name_admin(H)]")
+ log_admin("[key_name_admin(usr)] infected [key_name_admin(H)] with [D.name]")
+
+ return TRUE
diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm
new file mode 100644
index 00000000000..22cdabb1dd6
--- /dev/null
+++ b/code/datums/diseases/_disease.dm
@@ -0,0 +1,167 @@
+GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease))
+
+/datum/disease
+ //Flags
+ var/visibility_flags = 0
+ var/disease_flags = CURABLE|CAN_CARRY|CAN_RESIST
+ var/spread_flags = AIRBORNE
+
+ //Fluff
+ /// Used for identification of viruses in the Medical Records Virus Database
+ var/medical_name
+ var/form = "Virus"
+ var/name = "No disease"
+ var/desc = ""
+ var/agent = "some microbes"
+ var/spread_text = ""
+ var/cure_text = ""
+
+ //Stages
+ var/stage = 1
+ var/max_stages = 0
+ var/stage_prob = 4
+ /// The fraction of stages the virus must at least be at to show up on medical HUDs. Rounded up.
+ var/discovery_threshold = 0.5
+ /// If TRUE, this virus will show up on medical HUDs. Automatically set when it reaches mid-stage.
+ var/discovered = FALSE
+
+ // Other
+ var/list/viable_mobtypes = list()
+ var/mob/living/carbon/affected_mob
+ var/list/cures = list()
+ var/infectivity = 65
+ var/cure_chance = 8
+ var/carrier = FALSE
+ var/bypasses_immunity = FALSE
+ var/virus_heal_resistant = FALSE
+ var/permeability_mod = 1
+ var/severity = NONTHREAT
+ var/list/required_organs = list()
+ var/needs_all_cures = TRUE
+ var/list/strain_data = list()
+ var/allow_dead = FALSE
+ var/infect_synthetics = FALSE
+ var/processing = FALSE
+
+/datum/disease/Destroy()
+ affected_mob = null
+ active_diseases.Remove(src)
+ if(processing)
+ End()
+ return ..()
+
+/datum/disease/proc/stage_act()
+ if(!affected_mob)
+ return FALSE
+ var/cure = has_cure()
+
+ if(carrier && !cure)
+ return FALSE
+
+ if(!processing)
+ processing = TRUE
+ Start()
+
+ stage = min(stage, max_stages)
+
+ handle_stage_advance(cure)
+
+ return handle_cure_testing(cure)
+
+/datum/disease/proc/handle_stage_advance(has_cure = FALSE)
+ if(!has_cure && prob(stage_prob))
+ stage = min(stage + 1, max_stages)
+ if(!discovered && stage >= CEILING(max_stages * discovery_threshold, 1))
+ discovered = TRUE
+ BITSET(affected_mob.hud_updateflag, STATUS_HUD)
+
+/datum/disease/proc/handle_cure_testing(has_cure = FALSE)
+ if(has_cure && prob(cure_chance))
+ stage = max(stage -1, 1)
+
+ if(disease_flags & CURABLE)
+ if(has_cure && prob(cure_chance))
+ cure()
+ return FALSE
+ return TRUE
+
+/datum/disease/proc/has_cure()
+ if(!(disease_flags & CURABLE))
+ return 0
+
+ var/cures_found = 0
+ for(var/C_id in cures)
+ if(affected_mob.bloodstr.has_reagent(C_id) || affected_mob.ingested.has_reagent(C_id))
+ cures_found++
+
+ if(needs_all_cures && cures_found < length(cures))
+ return FALSE
+
+ return cures_found
+
+/datum/disease/proc/spread(force_spread = 0)
+ if(!affected_mob)
+ return
+
+ if((spread_flags & SPECIAL || spread_flags & NON_CONTAGIOUS || spread_flags & BLOOD) && !force_spread)
+ return
+
+ if(affected_mob.bloodstr.has_reagent("spaceacillin") || (affected_mob.nutrition > 300 && prob(affected_mob.nutrition/50)))
+ return
+
+ var/spread_range = 1
+
+ if(force_spread)
+ spread_range = force_spread
+
+ if(spread_flags & AIRBORNE)
+ spread_range++
+
+ var/turf/target = affected_mob.loc
+ if(istype(target))
+ for(var/mob/living/carbon/C in oview(spread_range, affected_mob))
+ var/turf/current = get_turf(C)
+ if(current)
+ while(TRUE)
+ if(current == target)
+ C.ContractDisease(src)
+ break
+ var/direction = get_dir(current, target)
+ var/turf/next = get_step(current, direction)
+ current = next
+
+/datum/disease/proc/cure()
+ if(affected_mob)
+ if(disease_flags & CAN_RESIST)
+ if(!(type in affected_mob.GetResistances()))
+ affected_mob.resistances += type
+ remove_virus()
+ qdel(src)
+
+/datum/disease/proc/IsSame(datum/disease/D)
+ if(ispath(D))
+ return istype(src, D)
+ return istype(src, D.type)
+
+/datum/disease/proc/Copy()
+ var/datum/disease/D = new type()
+ D.strain_data = strain_data.Copy()
+ return D
+
+/datum/disease/proc/GetDiseaseID()
+ return type
+
+/datum/disease/proc/IsSpreadByTouch()
+ if(spread_flags & CONTACT_FEET || spread_flags & CONTACT_HANDS || spread_flags & CONTACT_GENERAL)
+ return 1
+ return 0
+
+/datum/disease/proc/remove_virus()
+ affected_mob.viruses -= src
+ BITSET(affected_mob.hud_updateflag, STATUS_HUD)
+
+/datum/disease/proc/Start()
+ return
+
+/datum/disease/proc/End()
+ return
diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm
new file mode 100644
index 00000000000..e5790c3bca2
--- /dev/null
+++ b/code/datums/diseases/advance/advance.dm
@@ -0,0 +1,414 @@
+GLOBAL_LIST_EMPTY(archive_diseases)
+
+GLOBAL_LIST_INIT(advance_cures, list(
+ "sodiumchloride", "sugar", "orangejuice",
+ "spaceacillin", "glucose", "ethanol",
+ "leporazine", "impedrezene", "hepanephrodaxon",
+ "silver", "gold"
+))
+
+/datum/disease/advance
+ name = "Unknown"
+ desc = "An engineered disease which can contain a multitude of symptoms."
+ form = "Advance Disease"
+ agent = "advance microbes"
+ max_stages = 5
+ spread_text = "Unknown"
+ viable_mobtypes = list(/mob/living/carbon/human)
+
+ var/s_processing = FALSE
+ var/list/symptoms = list()
+ var/id = ""
+
+/datum/disease/advance/New(process = 1, datum/disease/advance/D)
+ if(!istype(D))
+ D = null
+
+ if(!symptoms || !length(symptoms))
+
+ if(!D || !D.symptoms || !length(D.symptoms))
+ symptoms = GenerateSymptoms(0, 2)
+ else
+ for(var/datum/symptom/S in D.symptoms)
+ symptoms += new S.type
+
+ Refresh()
+ ..(process, D)
+ return
+
+/datum/disease/advance/Destroy()
+ if(s_processing)
+ for(var/datum/symptom/S in symptoms)
+ S.End(src)
+ return ..()
+
+/datum/disease/advance/stage_act()
+ if(!..())
+ return FALSE
+ if(symptoms && length(symptoms))
+
+ if(!s_processing)
+ s_processing = TRUE
+ for(var/datum/symptom/S in symptoms)
+ S.Start(src)
+
+ for(var/datum/symptom/S in symptoms)
+ S.Activate(src)
+ else
+ CRASH("We do not have any symptoms during stage_act()!")
+ return TRUE
+
+/datum/disease/advance/IsSame(datum/disease/advance/D)
+ if(ispath(D))
+ return FALSE
+
+ if(!istype(D, /datum/disease/advance))
+ return FALSE
+
+ if(GetDiseaseID() != D.GetDiseaseID())
+ return FALSE
+
+ return TRUE
+
+/datum/disease/advance/cure(resistance=1)
+ if(affected_mob)
+ var/id = "[GetDiseaseID()]"
+ if(resistance && !(id in affected_mob.GetResistances()))
+ affected_mob.GetResistances()[id] = id
+ remove_virus()
+ qdel(src)
+
+/datum/disease/advance/Copy(process = 0)
+ return new /datum/disease/advance(process, src, 1)
+
+/datum/disease/advance/proc/Mix(datum/disease/advance/D)
+ if(!(IsSame(D)))
+ var/list/possible_symptoms = shuffle(D.symptoms)
+ for(var/datum/symptom/S in possible_symptoms)
+ AddSymptom(new S.type)
+
+/datum/disease/advance/proc/HasSymptom(datum/symptom/S)
+ for(var/datum/symptom/symp in symptoms)
+ if(symp.id == S.id)
+ return 1
+ return 0
+
+/datum/disease/advance/proc/GenerateSymptomsBySeverity(sev_min, sev_max, amount = 1)
+
+ var/list/generated = list()
+
+ var/list/possible_symptoms = list()
+ for(var/symp in GLOB.list_symptoms)
+ var/datum/symptom/S = new symp
+ if(S.severity >= sev_min && S.severity <= sev_max)
+ if(!HasSymptom(S))
+ possible_symptoms += S
+
+ if(!length(possible_symptoms))
+ return generated
+
+ for(var/i = 1 to amount)
+ generated += pick_n_take(possible_symptoms)
+
+ return generated
+
+/datum/disease/advance/proc/GenerateSymptoms(level_min, level_max, amount_get = 0)
+
+ var/list/generated = list()
+
+ // Generate symptoms. By default, we only choose non-deadly symptoms.
+ var/list/possible_symptoms = list()
+ for(var/symp in GLOB.list_symptoms)
+ var/datum/symptom/S = new symp
+ if(S.level >= level_min && S.level <= level_max)
+ if(!HasSymptom(S))
+ possible_symptoms += S
+
+ if(!length(possible_symptoms))
+ return generated
+
+ // Random chance to get more than one symptom
+ var/number_of = amount_get
+ if(!amount_get)
+ number_of = 1
+ while(prob(20))
+ number_of += 1
+
+ for(var/i = 1; number_of >= i && length(possible_symptoms); i++)
+ generated += pick_n_take(possible_symptoms)
+
+ return generated
+
+/datum/disease/advance/proc/Refresh(new_name = FALSE, archive = FALSE)
+ var/list/properties = GenerateProperties()
+ AssignProperties(properties)
+ id = null
+
+ if(!GLOB.archive_diseases[GetDiseaseID()])
+ if(new_name)
+ AssignName()
+ GLOB.archive_diseases[GetDiseaseID()] = src // So we don't infinite loop
+ GLOB.archive_diseases[GetDiseaseID()] = new /datum/disease/advance(0, src, 1)
+
+ var/datum/disease/advance/A = GLOB.archive_diseases[GetDiseaseID()]
+ AssignName(A.name)
+
+/datum/disease/advance/proc/GenerateProperties()
+
+ if(!symptoms || !length(symptoms))
+ CRASH("We did not have any symptoms before generating properties.")
+
+ var/list/properties = list("resistance" = 1, "stealth" = 0, "stage rate" = 1, "transmittable" = 1, "severity" = 0)
+
+ for(var/datum/symptom/S in symptoms)
+
+ properties["resistance"] += S.resistance
+ properties["stealth"] += S.stealth
+ properties["stage rate"] += S.stage_speed
+ properties["transmittable"] += S.transmittable
+ properties["severity"] = max(properties["severity"], S.severity) // severity is based on the highest severity symptom
+
+ return properties
+
+/datum/disease/advance/proc/AssignProperties(list/properties = list())
+
+ if(properties && length(properties))
+ switch(properties["stealth"])
+ if(2)
+ visibility_flags = HIDDEN_SCANNER
+ if(3 to INFINITY)
+ visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC
+
+ // The more symptoms we have, the less transmittable it is but some symptoms can make up for it.
+ SetSpread(clamp(2 ** (properties["transmittable"] - length(symptoms)), BLOOD, AIRBORNE))
+ permeability_mod = max(CEILING(0.4 * properties["transmittable"], 1), 1)
+ cure_chance = 15 - clamp(properties["resistance"], -5, 5) // can be between 10 and 20
+ stage_prob = max(properties["stage rate"], 2)
+ SetSeverity(properties["severity"])
+ GenerateCure(properties)
+ else
+ CRASH("Our properties were empty or null!")
+
+/datum/disease/advance/proc/SetSpread(spread_id)
+ switch(spread_id)
+ if(NON_CONTAGIOUS, SPECIAL)
+ spread_text = "Non-contagious"
+ if(CONTACT_GENERAL, CONTACT_HANDS, CONTACT_FEET)
+ spread_text = "On contact"
+ if(AIRBORNE)
+ spread_text = "Airborne"
+ if(BLOOD)
+ spread_text = "Blood"
+
+ spread_flags = spread_id
+
+/datum/disease/advance/proc/SetSeverity(level_sev)
+
+ switch(level_sev)
+
+ if(-INFINITY to 0)
+ severity = NONTHREAT
+ if(1)
+ severity = MINOR
+ if(2)
+ severity = MEDIUM
+ if(3)
+ severity = HARMFUL
+ if(4)
+ severity = DANGEROUS
+ if(5 to INFINITY)
+ severity = BIOHAZARD
+ else
+ severity = "Unknown"
+
+/datum/disease/advance/proc/GenerateCure(list/properties = list())
+ if(properties && length(properties))
+ var/res = clamp(properties["resistance"] - (length(symptoms) / 2), 1, length(GLOB.advance_cures))
+ cures = list(GLOB.advance_cures[res])
+ cure_text = cures[1]
+ return
+
+// Randomly generate a symptom, has a chance to lose or gain a symptom.
+/datum/disease/advance/proc/Evolve(min_level, max_level)
+ var/s = safepick(GenerateSymptoms(min_level, max_level, 1))
+ if(s)
+ AddSymptom(s)
+ Refresh(1)
+ return
+
+/datum/disease/advance/proc/PickyEvolve(var/list/datum/symptom/D)
+ var/s = safepick(D)
+ if(s)
+ AddSymptom(new s)
+ Refresh(1)
+ return
+
+// Randomly remove a symptom.
+/datum/disease/advance/proc/Devolve()
+ if(length(symptoms) > 1)
+ var/s = safepick(symptoms)
+ if(s)
+ RemoveSymptom(s)
+ Refresh(1)
+ return
+
+// Name the disease.
+/datum/disease/advance/proc/AssignName(name = "Unknown")
+ src.name = name
+ return
+
+// Return a unique ID of the disease.
+/datum/disease/advance/GetDiseaseID()
+ if(!id)
+ var/list/L = list()
+ for(var/datum/symptom/S in symptoms)
+ L += S.id
+ L = sortList(L) // Sort the list so it doesn't matter which order the symptoms are in.
+ var/result = jointext(L, ":")
+ id = result
+ return id
+
+// Add a symptom, if it is over the limit (with a small chance to be able to go over)
+// we take a random symptom away and add the new one.
+/datum/disease/advance/proc/AddSymptom(datum/symptom/S)
+
+ if(HasSymptom(S))
+ return
+
+ if(length(symptoms) < (VIRUS_SYMPTOM_LIMIT - 1) + rand(-1, 1))
+ symptoms += S
+ else
+ RemoveSymptom(pick(symptoms))
+ symptoms += S
+ return
+
+// Simply removes the symptom.
+/datum/disease/advance/proc/RemoveSymptom(datum/symptom/S)
+ symptoms -= S
+ return
+
+// Mix a list of advance diseases and return the mixed result.
+/proc/Advance_Mix(list/D_list)
+
+ var/list/diseases = list()
+
+ for(var/datum/disease/advance/A in D_list)
+ diseases += A.Copy()
+
+ if(!length(diseases))
+ return null
+ if(length(diseases) <= 1)
+ return pick(diseases) // Just return the only entry.
+
+ var/i = 0
+ // Mix our diseases until we are left with only one result.
+ while(i < 20 && length(diseases) > 1)
+
+ i++
+
+ var/datum/disease/advance/D1 = pick(diseases)
+ diseases -= D1
+
+ var/datum/disease/advance/D2 = pick(diseases)
+ D2.Mix(D1)
+
+ // Should be only 1 entry left, but if not let's only return a single entry
+ var/datum/disease/advance/to_return = pick(diseases)
+ to_return.Refresh(1)
+ return to_return
+
+/proc/SetViruses(datum/reagent/R, list/data)
+ if(data)
+ var/list/preserve = list()
+ if(istype(data) && data["viruses"])
+ for(var/datum/disease/A in data["viruses"])
+ preserve += A.Copy()
+ R.data = data.Copy()
+ if(length(preserve))
+ R.data["viruses"] = preserve
+
+/client/proc/AdminCreateVirus()
+ set category = "Fun.Event Kit"
+ set name = "Create Advanced Virus"
+ set desc = "Create an advanced virus and release it."
+
+ if(!is_admin())
+ return FALSE
+
+ var/i = VIRUS_SYMPTOM_LIMIT
+ var/mob/living/carbon/human/H = null
+
+ var/datum/disease/advance/D = new(0, null)
+ D.symptoms = list()
+
+ var/list/symptoms = list()
+ symptoms += "Done"
+ symptoms += GLOB.list_symptoms.Copy()
+ do
+ if(usr)
+ var/symptom = tgui_input_list(usr, "Choose a symptom to add ([i] remaining)", "Choose a Symptom", symptoms)
+ if(isnull(symptom))
+ return
+ else if(istext(symptom))
+ i = 0
+ else if(ispath(symptom))
+ var/datum/symptom/S = new symptom
+ if(!D.HasSymptom(S))
+ D.symptoms += S
+ i -= 1
+ while(i > 0)
+
+ if(length(D.symptoms) > 0)
+
+ var/new_name = tgui_input_text(usr, "Name your new disease.", "New Name")
+ if(!new_name)
+ return FALSE
+ D.AssignName(new_name)
+ D.Refresh()
+
+ for(var/datum/disease/advance/AD in active_diseases)
+ AD.Refresh()
+
+ H = tgui_input_list(usr, "Choose infectee", "Infectees", human_mob_list)
+
+ if(isnull(H))
+ return FALSE
+
+ if(!H.HasDisease(D))
+ H.ForceContractDisease(D)
+
+ var/list/name_symptoms = list()
+ for(var/datum/symptom/S in D.symptoms)
+ name_symptoms += S.name
+ message_admins("[key_name_admin(usr)] has triggered a custom virus outbreak of [D.name]! It has these symptoms: [english_list(name_symptoms)]")
+ log_admin("[key_name_admin(usr)] infected [key_name_admin(H)] with [D.name]. It has these symptoms: [english_list(name_symptoms)]")
+
+ return TRUE
+
+/datum/disease/advance/proc/totalStageSpeed()
+ var/total_stage_speed = 0
+ for(var/i in symptoms)
+ var/datum/symptom/S = i
+ total_stage_speed += S.stage_speed
+ return total_stage_speed
+
+/datum/disease/advance/proc/totalStealth()
+ var/total_stealth = 0
+ for(var/i in symptoms)
+ var/datum/symptom/S = i
+ total_stealth += S.stealth
+ return total_stealth
+
+/datum/disease/advance/proc/totalResistance()
+ var/total_resistance = 0
+ for(var/i in symptoms)
+ var/datum/symptom/S = i
+ total_resistance += S.resistance
+ return total_resistance
+
+/datum/disease/advance/proc/totalTransmittable()
+ var/total_transmittable = 0
+ for(var/i in symptoms)
+ var/datum/symptom/S = i
+ total_transmittable += S.transmittable
+ return total_transmittable
diff --git a/code/datums/diseases/advance/disease_preset.dm b/code/datums/diseases/advance/disease_preset.dm
new file mode 100644
index 00000000000..d30bbf2ebb5
--- /dev/null
+++ b/code/datums/diseases/advance/disease_preset.dm
@@ -0,0 +1,16 @@
+// Cold
+
+/datum/disease/advance/cold/New(process = 1, datum/disease/advance/D, copy = 0)
+ if(!D)
+ name = "Cold"
+ symptoms = list(new /datum/symptom/sneeze)
+ ..(process, D, copy)
+
+
+// Flu
+
+/datum/disease/advance/flu/New(process = 1, datum/disease/advance/D, copy = 0)
+ if(!D)
+ name = "Flu"
+ symptoms = list(new /datum/symptom/cough)
+ ..(process, D, copy)
diff --git a/code/datums/diseases/advance/symptoms/choking.dm b/code/datums/diseases/advance/symptoms/choking.dm
new file mode 100644
index 00000000000..24be1c1a153
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/choking.dm
@@ -0,0 +1,52 @@
+/*
+//////////////////////////////////////
+
+Choking
+
+ Very very noticable.
+ Lowers resistance.
+ Decreases stage speed.
+ Decreases transmittablity tremendously.
+ Moderate Level.
+
+Bonus
+ Inflicts spikes of oxyloss
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/choking
+ name = "Choking"
+ stealth = -3
+ resistance = -2
+ stage_speed = -2
+ transmittable = -4
+ level = 3
+ severity = 3
+
+/datum/symptom/choking/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2)
+ to_chat(M, span_warning(pick("You're having difficulty breathing.", "Your breathing becomes heavy.")))
+ if(3, 4)
+ to_chat(M, span_boldwarning(pick("Your windpipe feels like a straw.", "Your breathing becomes tremendously difficult.")))
+ Choke_stage_3_4(M, A)
+ M.emote("gasp")
+ else
+ to_chat(M, span_userdanger(pick("You're choking!", "You can't breathe!")))
+ Choke(M, A)
+ M.emote("gasp")
+ return
+
+/datum/symptom/choking/proc/Choke_stage_3_4(mob/living/M, datum/disease/advance/A)
+ var/get_damage = sqrtor0(21+A.totalStageSpeed()*0.5)+sqrtor0(16+A.totalStealth())
+ M.adjustOxyLoss(get_damage)
+ return 1
+
+/datum/symptom/choking/proc/Choke(mob/living/M, datum/disease/advance/A)
+ var/get_damage = sqrtor0(21+A.totalStageSpeed()*0.5)+sqrtor0(16+A.totalStealth()*5)
+ M.adjustOxyLoss(get_damage)
+ return 1
diff --git a/code/datums/diseases/advance/symptoms/confusion.dm b/code/datums/diseases/advance/symptoms/confusion.dm
new file mode 100644
index 00000000000..039d9ad8db6
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/confusion.dm
@@ -0,0 +1,40 @@
+/*
+//////////////////////////////////////
+
+Confusion
+
+ Little bit hidden.
+ Lowers resistance.
+ Decreases stage speed.
+ Not very transmittable.
+ Intense Level.
+
+Bonus
+ Makes the affected mob be confused for short periods of time.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/confusion
+
+ name = "Confusion"
+ stealth = 1
+ resistance = -1
+ stage_speed = -3
+ transmittable = 0
+ level = 4
+ severity = 2
+
+
+/datum/symptom/confusion/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/carbon/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2, 3, 4)
+ to_chat(M, span_warning(pick("Your head hurts.", "Your mind blanks for a moment.")))
+ else
+ to_chat(M, span_userdanger("You can't think straight!"))
+ M.AdjustConfused(rand(16, 200))
+
+ return
diff --git a/code/datums/diseases/advance/symptoms/cough.dm b/code/datums/diseases/advance/symptoms/cough.dm
new file mode 100644
index 00000000000..00a33e9ce64
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/cough.dm
@@ -0,0 +1,42 @@
+/*
+//////////////////////////////////////
+
+Coughing
+
+ Noticable.
+ Little Resistance.
+ Doesn't increase stage speed much.
+ Transmittable.
+ Low Level.
+
+BONUS
+ Will force the affected mob to drop small items.
+ Small spread if not wearing a mask
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/cough
+ name = "Cough"
+ stealth = -1
+ resistance = 3
+ stage_speed = 1
+ transmittable = 2
+ level = 1
+ severity = 1
+
+/datum/symptom/cough/Activate(var/datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2, 3)
+ to_chat(M, span_warning(pick("You swallow excess mucus", "You lightly cough.")))
+ else
+ M.emote("cough")
+ var/obj/item/I = M.get_active_hand()
+ if(I && I.w_class == ITEMSIZE_SMALL)
+ M.drop_item()
+ if(!M.wear_mask) // Small spread if not wearing a mask
+ A.spread(2)
+ return
diff --git a/code/datums/diseases/advance/symptoms/damage_converter.dm b/code/datums/diseases/advance/symptoms/damage_converter.dm
new file mode 100644
index 00000000000..f2a299469b1
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/damage_converter.dm
@@ -0,0 +1,59 @@
+/*
+//////////////////////////////////////
+
+Damage Converter
+
+ Little bit hidden.
+ Lowers resistance tremendously.
+ Decreases stage speed tremendously.
+ Reduced transmittablity
+ Intense Level.
+
+Bonus
+ Slowly converts brute/fire damage to toxin.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/damage_converter
+ name = "Toxic Compensation"
+ stealth = 1
+ resistance = -4
+ stage_speed = -4
+ transmittable = -2
+ level = 4
+
+/datum/symptom/damage_converter/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB * 10))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(4, 5)
+ Convert(M)
+ return
+
+/datum/symptom/damage_converter/proc/Convert(mob/living/M)
+
+ var/get_damage = rand(1, 2)
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+
+ var/list/parts = H.get_damaged_organs(TRUE, TRUE)
+
+ if(!length(parts))
+ return
+ var/healed = 0
+ for(var/obj/item/organ/external/E in parts)
+ healed += min(E.brute_dam, get_damage) + min(E.burn_dam, get_damage)
+ E.heal_damage(get_damage, get_damage, 0, 0)
+ M.adjustToxLoss(healed)
+
+ else
+ if(M.getFireLoss() > 0 || M.getBruteLoss() > 0)
+ M.adjustFireLoss(-get_damage)
+ M.adjustBruteLoss(-get_damage)
+ M.adjustToxLoss(get_damage)
+ else
+ return
+ return TRUE
diff --git a/code/datums/diseases/advance/symptoms/deafness.dm b/code/datums/diseases/advance/symptoms/deafness.dm
new file mode 100644
index 00000000000..21a44b2e9f4
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/deafness.dm
@@ -0,0 +1,38 @@
+/*
+//////////////////////////////////////
+
+Deafness
+
+ Slightly hidden.
+ Lowers resistance.
+ Increases stage speed slightly.
+ Decreases transmittablity.
+ Intense Level.
+
+Bonus
+ Causes intermittent loss of hearing.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/deafness
+ name = "Deafness"
+ stealth = 1
+ resistance = -2
+ stage_speed = 1
+ transmittable = -3
+ level = 4
+ severity = 3
+
+/datum/symptom/deafness/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+
+ switch(A.stage)
+ if(3, 4)
+ to_chat(M, span_warning("[pick("you hear a ringing in your ear.", "You ears pop.")]"))
+ if(5)
+ to_chat(M, span_userdanger("You ear pop and begin ringing loudly!"))
+ M.ear_deaf += 20
+ return
diff --git a/code/datums/diseases/advance/symptoms/dizzy.dm b/code/datums/diseases/advance/symptoms/dizzy.dm
new file mode 100644
index 00000000000..fdedcba79c0
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/dizzy.dm
@@ -0,0 +1,38 @@
+/*
+//////////////////////////////////////
+
+Dizziness
+
+ Hidden.
+ Lowers resistance considerably.
+ Decreases stage speed.
+ Reduced transmittability
+ Intense Level.
+
+Bonus
+ Shakes the affected mob's screen for short periods.
+
+//////////////////////////////////////
+*/
+
+/// Not the egg
+/datum/symptom/dizzy
+ name = "Dizziness"
+ stealth = 2
+ resistance = -2
+ stage_speed = -3
+ transmittable = -1
+ level = 4
+ severity = 2
+
+/datum/symptom/dizzy/Activate(var/datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2, 3, 4)
+ to_chat(M, span_warning(pick("You feel dizzy.", "Your head spins.")))
+ else
+ to_chat(M, span_userdanger("A wave of dizziness washes over you!"))
+ M.make_dizzy(10)
+ return
diff --git a/code/datums/diseases/advance/symptoms/fever.dm b/code/datums/diseases/advance/symptoms/fever.dm
new file mode 100644
index 00000000000..6e252e56cd9
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/fever.dm
@@ -0,0 +1,40 @@
+/*
+//////////////////////////////////////
+
+Fever
+
+ No change to hidden.
+ Increases resistance.
+ Increases stage speed.
+ Little transmittable.
+ Low level.
+
+Bonus
+ Heats up your body.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/fever
+ name = "Fever"
+ stealth = 0
+ resistance = 3
+ stage_speed = 3
+ transmittable = 2
+ level = 2
+ severity = 2
+
+/datum/symptom/fever/Activate(var/datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/carbon/M = A.affected_mob
+ to_chat(M, span_warning(pick("You feel hot.", "You feel like you're burning.")))
+ if(M.bodytemperature < BODYTEMP_HEAT_DAMAGE_LIMIT)
+ Heat(M, A)
+
+ return
+
+/datum/symptom/fever/proc/Heat(var/mob/living/M, var/datum/disease/advance/A)
+ var/get_heat = (sqrtor0(21+A.totalTransmittable()*2))+(sqrtor0(20+A.totalStageSpeed()*3))
+ M.bodytemperature = min(M.bodytemperature + (get_heat * A.stage), BODYTEMP_HEAT_DAMAGE_LIMIT - 1)
+ return TRUE
diff --git a/code/datums/diseases/advance/symptoms/fire.dm b/code/datums/diseases/advance/symptoms/fire.dm
new file mode 100644
index 00000000000..956d778f5d5
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/fire.dm
@@ -0,0 +1,56 @@
+/*
+//////////////////////////////////////
+
+Spontaneous Combustion
+
+ Slightly hidden.
+ Lowers resistance tremendously.
+ Decreases stage tremendously.
+ Decreases transmittablity tremendously.
+ Fatal Level.
+
+Bonus
+ Ignites infected mob.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/fire
+ name = "Spontaneous Combustion"
+ stealth = 1
+ resistance = -4
+ stage_speed = -4
+ transmittable = -4
+ level = 6
+ severity = 5
+
+/datum/symptom/fire/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(3)
+ to_chat(M, span_warning(pick("You feel hot.", "You hear a crackling noise.", "You smell smoke.")))
+ if(4)
+ Firestacks_stage_4(M, A)
+ M.IgniteMob()
+ to_chat(M, span_userdanger("Your skin bursts into flames!"))
+ M.emote("scream")
+ if(5)
+ Firestacks_stage_5(M, A)
+ M.IgniteMob()
+ to_chat(M, span_userdanger("Your skin erupts into an inferno!"))
+ M.emote("scream")
+ return
+
+/datum/symptom/fire/proc/Firestacks_stage_4(mob/living/M, datum/disease/advance/A)
+ var/get_stacks = max((sqrtor0(20 + A.totalStageSpeed() * 2)) - (sqrtor0(16 + A.totalStealth())), 1)
+ M.adjust_fire_stacks(get_stacks)
+ M.adjustFireLoss(get_stacks * 0.5)
+ return 1
+
+/datum/symptom/fire/proc/Firestacks_stage_5(mob/living/M, datum/disease/advance/A)
+ var/get_stacks = max((sqrtor0(20 + A.totalStageSpeed() * 3))-(sqrtor0(16 + A.totalStealth())), 1)
+ M.adjust_fire_stacks(get_stacks)
+ M.adjustFireLoss(get_stacks)
+ return 1
diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm
new file mode 100644
index 00000000000..00a5a273e7b
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm
@@ -0,0 +1,42 @@
+/*
+//////////////////////////////////////
+
+Necrotizing Fasciitis (AKA Flesh-Eating Disease)
+
+ Very very noticable.
+ Lowers resistance tremendously.
+ No changes to stage speed.
+ Decreases transmittablity tremendously.
+ Fatal Level.
+
+Bonus
+ Deals brute damage over time.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/flesh_eating
+ name = "Necrotizing Fasciitis"
+ stealth = -3
+ resistance = -4
+ stage_speed = 0
+ transmittable = -4
+ level = 6
+ severity = 5
+
+/datum/symptom/flesh_eating/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(2,3)
+ to_chat(M, span_warning(pick("You feel a sudden pain across your body.", "Drops of blood appear suddenly on your skin.")))
+ if(4,5)
+ to_chat(M, span_userdanger(pick("You cringe as a violent pain takes over your body.", "It feels like your body is eating itself inside out.", "IT HURTS.")))
+ Flesheat(M, A)
+ return
+
+/datum/symptom/flesh_eating/proc/Flesheat(mob/living/M, datum/disease/advance/A)
+ var/get_damage = ((sqrtor0(16-A.totalStealth()))*5)
+ M.adjustBruteLoss(get_damage)
+ return 1
diff --git a/code/datums/diseases/advance/symptoms/flip.dm b/code/datums/diseases/advance/symptoms/flip.dm
new file mode 100644
index 00000000000..e210e4b3bfe
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/flip.dm
@@ -0,0 +1,33 @@
+/*
+//////////////////////////////////////
+
+Flippinov
+
+ Slightly hidden.
+ No change to resistance.
+ Increases stage speed.
+ Little transmittable.
+ Low Level.
+
+BONUS
+ Makes the host FLIP.
+ Should be used for buffing your disease.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/spyndrome
+ name = "Flippinov"
+ stealth = 2
+ resistance = 0
+ stage_speed = 3
+ transmittable = 1
+ level = 1
+ severity = 1
+
+/datum/symptom/spyndrome/Activate(datum/disease/advance/A)
+ ..()
+
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/L = A.affected_mob
+ L.emote("flip")
diff --git a/code/datums/diseases/advance/symptoms/hair.dm b/code/datums/diseases/advance/symptoms/hair.dm
new file mode 100644
index 00000000000..1a6c2ff109c
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/hair.dm
@@ -0,0 +1,56 @@
+/*
+//////////////////////////////////////
+Alopecia
+
+ Noticable.
+ Decreases resistance slightly.
+ Reduces stage speed slightly.
+ Transmittable.
+ Intense Level.
+
+BONUS
+ Makes the mob lose hair.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/shedding
+ name = "Alopecia"
+ stealth = -1
+ resistance = -1
+ stage_speed = -1
+ transmittable = 2
+ level = 4
+ severity = 1
+
+/datum/symptom/shedding/Activate(datum/disease/advance/A)
+ ..()
+ if(!prob(SYMPTOM_ACTIVATION_PROB))
+ return
+ if(ishuman(A.affected_mob))
+ return
+ var/mob/living/carbon/human/H = A.affected_mob
+ var/obj/item/organ/external/head/head_organ = H.get_organ(BP_HEAD)
+ if(!istype(head_organ))
+ return
+ to_chat(H, span_warning("[pick("Your scalp itches.", "Your skin feels flakey.")]"))
+
+ switch(A.stage)
+ if(3, 4)
+ if(H.h_style != "Bald" && H.h_style != "Balding Hair")
+ to_chat(H, span_warning("Your hair starts to fall out in clumps..."))
+ addtimer(CALLBACK(src, PROC_REF(change_hair), H, null, "Balding Hair"), 5 SECONDS)
+ if(5)
+ if(H.h_style != "Shaved" && H.h_style != "Bald")
+ to_chat(H, span_warning("Your hair starts to fall out in clumps..."))
+ addtimer(CALLBACK(src, PROC_REF(change_hair), H, "Shaved", "Bald"), 5 SECONDS)
+ return
+
+/datum/symptom/shedding/proc/change_hair(var/mob/living/carbon/human/H, f_style, h_style)
+ if(!H)
+ return
+ if(f_style)
+ H.f_style = f_style
+ if(h_style)
+ H.h_style = h_style
+ return
diff --git a/code/datums/diseases/advance/symptoms/hallucigen.dm b/code/datums/diseases/advance/symptoms/hallucigen.dm
new file mode 100644
index 00000000000..4bd1e44401d
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/hallucigen.dm
@@ -0,0 +1,40 @@
+/*
+//////////////////////////////////////
+
+Hallucigen
+
+ Very noticable.
+ Lowers resistance considerably.
+ Decreases stage speed.
+ Reduced transmittable.
+ Critical Level.
+
+Bonus
+ Makes the affected mob be hallucinated for short periods of time.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/hallucigen
+ name = "Hallucigen"
+ stealth = -2
+ resistance = -3
+ stage_speed = -3
+ transmittable = -1
+ level = 5
+ severity = 3
+
+/datum/symptom/hallucigen/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/carbon/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2)
+ to_chat(M, span_warning(pick("Something appears in your peripheral vision, then winks out.", "You hear a faint whisper with no source.", "Your head aches.")))
+ if(3, 4)
+ to_chat(M, span_boldwarning(pick("Something is following you.", "You are being watched.", "You hear a whisper in your ear.", "Thumping footsteps slam toward you from nowhere.")))
+ else
+ to_chat(M, span_userdanger(pick("Oh, your head...", "Your head pounds.", "They're everywhere! Run!", "Something in the shadows...")))
+ M.hallucination = rand(5, 10)
+
+ return
diff --git a/code/datums/diseases/advance/symptoms/headache.dm b/code/datums/diseases/advance/symptoms/headache.dm
new file mode 100644
index 00000000000..431ed9b6703
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/headache.dm
@@ -0,0 +1,33 @@
+/*
+//////////////////////////////////////
+
+Headache
+
+ Noticable.
+ Highly resistant.
+ Increases stage speed.
+ Not transmittable.
+ Low Level.
+
+BONUS
+ Displays an annoying message!
+ Should be used for buffing your disease.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/headache
+ name = "Headache"
+ stealth = -1
+ resistance = 4
+ stage_speed = 2
+ transmittable = 0
+ level = 1
+ severity = 1
+
+/datum/symptom/headache/Activate(var/datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ to_chat(M, span_warning(pick("Your head hurts.", "Your head starts pounding.")))
+ return
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
new file mode 100644
index 00000000000..340b88d6b4c
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -0,0 +1,150 @@
+/*
+//////////////////////////////////////
+
+Healing
+
+ Little bit hidden.
+ Lowers resistance tremendously.
+ Decreases stage speed tremendously.
+ Decreases transmittablity temrendously.
+ Fatal Level.
+
+Bonus
+ Heals toxins in the affected mob's blood stream.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/heal
+ name = "Toxic Filter"
+ stealth = 1
+ resistance = -4
+ stage_speed = -4
+ transmittable = -4
+ level = 6
+
+/datum/symptom/heal/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB * 10))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(4, 5)
+ Heal(M, A)
+ return
+
+/datum/symptom/heal/proc/Heal(mob/living/M, datum/disease/advance/A)
+ var/get_damage = max(0, (sqrtor0(20+A.totalStageSpeed())*(1+rand())))
+ M.adjustToxLoss(-get_damage)
+ return TRUE
+
+/*
+//////////////////////////////////////
+
+Metabolism
+
+ Little bit hidden.
+ Lowers resistance.
+ Decreases stage speed.
+ Decreases transmittablity temrendously.
+ High Level.
+
+Bonus
+ Cures all diseases (except itself) and creates anti-bodies for them until the symptom dies.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/heal/metabolism
+ name = "Anti-Bodies Metabolism"
+ stealth = -1
+ resistance = -1
+ stage_speed = -1
+ transmittable = -4
+ level = 3
+ var/list/cured_diseases = list()
+
+/datum/symptom/heal/metabolism/Heal(mob/living/M, datum/disease/advance/A)
+ var/cured = 0
+ for(var/thing in M.GetViruses())
+ var/datum/disease/D = thing
+ if(D.virus_heal_resistant)
+ continue
+ if(D != A)
+ cured = TRUE
+ cured_diseases += D.GetDiseaseID()
+ D.cure()
+ if(cured)
+ to_chat(M, span_notice("You feel much better."))
+
+/datum/symptom/heal/metabolism/End(datum/disease/advance/A)
+ var/mob/living/M = A.affected_mob
+ if(istype(M))
+ if(length(cured_diseases))
+ for(var/res in M.GetResistances())
+ M.resistances -= res
+ to_chat(M, span_warning("You feel weaker."))
+
+/*
+//////////////////////////////////////
+
+Longevity
+
+ Medium hidden boost.
+ Large resistance boost.
+ Large stage speed boost.
+ Large transmittablity boost.
+ High Level.
+
+Bonus
+ After a certain amount of time the symptom will cure itself.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/heal/longevity
+ name = "Longevity"
+ stealth = 3
+ resistance = 4
+ stage_speed = 4
+ transmittable = 4
+ level = 3
+ var/longevity = 30
+
+/datum/symptom/heal/longevity/Heal(mob/living/M, datum/disease/advance/A)
+ longevity -= 1
+ if(!longevity)
+ A.cure()
+
+/datum/symptom/heal/longevity/Start(datum/disease/advance/A)
+ longevity = rand(initial(longevity) - 5, initial(longevity) + 5)
+
+/*
+//////////////////////////////////////
+
+ DNA Restoration
+
+ Not well hidden.
+ Lowers resistance minorly.
+ Does not affect stage speed.
+ Decreases transmittablity greatly.
+ Very high level.
+
+Bonus
+ Heals clone damage, treats radiation.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/heal/dna
+ name = "Deoxyribonucleic Acid Restoration"
+ stealth = -1
+ resistance = -1
+ stage_speed = 0
+ transmittable = -3
+ level = 5
+
+/datum/symptom/heal/dna/Heal(var/mob/living/carbon/M, var/datum/disease/advance/A)
+ var/amt_healed = max(0, (sqrtor0(20+A.totalStageSpeed()*(3+rand())))-(sqrtor0(16+A.totalStealth()*rand())))
+ M.adjustBrainLoss(-amt_healed)
+ M.radiation = max(M.radiation - 3, 0)
+ return TRUE
diff --git a/code/datums/diseases/advance/symptoms/hematophagy.dm b/code/datums/diseases/advance/symptoms/hematophagy.dm
new file mode 100644
index 00000000000..53e5aa842d4
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/hematophagy.dm
@@ -0,0 +1,42 @@
+/*
+//////////////////////////////////////
+
+Hematophagy
+
+ Little bit hidden.
+ Decreases resistance slightly.
+ Decreases stage speed tremendously.
+ Slightly increased transmittablity.
+ Intense level.
+
+BONUS
+ The host must feed on BLOOD
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/hematophagy
+ name = "Hematophagy"
+ stealth = 1
+ resistance = -1
+ resistance = -4
+ transmittable = 1
+ level = 4
+
+/datum/symptom/hematophagy/Start(datum/disease/advance/A)
+ if(ishuman(A.affected_mob))
+ var/mob/living/carbon/human/H = A.affected_mob
+
+ H.species.organic_food_coeff = 0
+ H.species.bloodsucker = TRUE
+
+ add_verb(H, /mob/living/carbon/human/proc/bloodsuck)
+
+/datum/symptom/hematophagy/End(datum/disease/advance/A)
+ if(ishuman(A.affected_mob))
+ var/mob/living/carbon/human/H = A.affected_mob
+
+ H.species.organic_food_coeff = initial(H.species.organic_food_coeff)
+ H.species.bloodsucker = initial(H.species.bloodsucker)
+
+ remove_verb(H, /mob/living/carbon/human/proc/bloodsuck)
diff --git a/code/datums/diseases/advance/symptoms/itching.dm b/code/datums/diseases/advance/symptoms/itching.dm
new file mode 100644
index 00000000000..fdf2f5f5e4f
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/itching.dm
@@ -0,0 +1,33 @@
+/*
+//////////////////////////////////////
+
+Itching
+
+ Not noticable or unnoticable.
+ Resistant.
+ Increases stage speed.
+ Little transmittable.
+ Low Level.
+
+BONUS
+ Displays an annoying message!
+ Should be used for buffing your disease.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/itching
+ name = "Itching"
+ stealth = 0
+ resistance = 3
+ stage_speed = 3
+ transmittable = 1
+ level = 1
+ severity = 1
+
+/datum/symptom/itching/Activate(var/datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ to_chat(M, span_warning("Your [pick("back", "arm", "leg", "elbow", "head")] itches."))
+ return
diff --git a/code/datums/diseases/advance/symptoms/language.dm b/code/datums/diseases/advance/symptoms/language.dm
new file mode 100644
index 00000000000..3ffa7c06bb6
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/language.dm
@@ -0,0 +1,31 @@
+/*
+//////////////////////////////////////
+
+Lingual Disocation
+
+ Improves stealth.
+ Increases resistance.
+ Decreases stage speed.
+ Slightly decreases transmissibility.
+ Moderate Level.
+
+Bonus
+ Forces the affected mob to vomit
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/language
+ name = "Lingual Disocation"
+ stealth = 3
+ resistance = 2
+ stage_speed = -2
+ transmittable = -1
+ level = 3
+
+/datum/symptom/language/Activate(var/datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/carbon/human/H = A.affected_mob
+ H.apply_default_language(pick(H.languages))
+ return
diff --git a/code/datums/diseases/advance/symptoms/macrophage.dm b/code/datums/diseases/advance/symptoms/macrophage.dm
new file mode 100644
index 00000000000..a04a3fc50fe
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/macrophage.dm
@@ -0,0 +1,73 @@
+/*
+//////////////////////////////////////
+
+Macrophages
+
+ Very noticeable.
+ Lowers resistance slightly.
+ Decreases stage speed.
+ Increases transmittablity
+ Fatal leve.
+
+BONUS
+ The virus grows and ceases to be microscopic.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/macrophage
+ name = "Macrophage"
+ stealth = -4
+ resistance = -1
+ stage_speed = -2
+ transmittable = 2
+ level = 6
+ severity = 2
+
+ var/gigagerms = FALSE
+ var/netspeed = 0
+ var/phagecounter = 10
+
+/datum/symptom/macrophage/Start(datum/disease/advance/A)
+ netspeed = max(1, A.stage)
+ if(A.severity >= HARMFUL)
+ gigagerms = TRUE
+
+/datum/symptom/macrophage/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2, 3)
+ to_chat(M, span_notice("Your skin crawls."))
+ if(4)
+ M.visible_message(span_danger("Lumps form on [M]'s skin!"), span_userdanger("You cringe in pain as lumps form and move around on your skin!"))
+ if(5)
+ phagecounter -= max(2, A.totalStageSpeed())
+ if(gigagerms && phagecounter <= 0)
+ Burst(A, M, TRUE)
+ phagecounter += 10
+ while(phagecounter <= 0)
+ phagecounter += 5
+ Burst(A, M)
+
+/datum/symptom/macrophage/proc/Burst(datum/disease/advance/A, var/mob/living/M, var/gigagerms = FALSE)
+ var/mob/living/simple_mob/vore/aggressive/macrophage/phage
+ phage = new(M.loc)
+ M.apply_damage(rand(1, 7))
+ phage.viruses = A.Copy()
+ phage.health += A.totalResistance()
+ phage.maxHealth += A.totalResistance()
+ phage.infections += A
+ phage.base_disease = A
+
+ if(A.spread_flags & CONTACT_GENERAL)
+ for(var/datum/disease/D in M.GetViruses())
+ if((D.spread_flags & SPECIAL) || (D.spread_flags & NON_CONTAGIOUS))
+ continue
+ if(D == A)
+ continue
+ phage.viruses += D
+
+ M.visible_message(span_danger("A strange crearure bursts out of [M]!"), span_userdanger("A slimy creature bursts forth from your flesh!"))
+ addtimer(CALLBACK(phage, TYPE_PROC_REF(/mob/living/simple_mob/vore/aggressive/macrophage, deathcheck)), 3000)
diff --git a/code/datums/diseases/advance/symptoms/mlem.dm b/code/datums/diseases/advance/symptoms/mlem.dm
new file mode 100644
index 00000000000..fdb8672c276
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/mlem.dm
@@ -0,0 +1,33 @@
+/*
+//////////////////////////////////////
+
+Mlemingtong
+
+ Not noticable or unnoticable.
+ Resistant.
+ Increases stage speed.
+ Little transmittable.
+ Low Level.
+
+BONUS
+ Mlem. Mlem. Mlem.
+ Should be used for buffing your disease.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/mlem
+ name = "Mlemington"
+ stealth = 0
+ resistance = 3
+ stage_speed = 3
+ transmittable = 1
+ level = 1
+ severity = 1
+
+/datum/symptom/itching/Activate(var/datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ M.emote("mlem")
+ return
diff --git a/code/datums/diseases/advance/symptoms/necrotic_agent.dm b/code/datums/diseases/advance/symptoms/necrotic_agent.dm
new file mode 100644
index 00000000000..24a3e9ff065
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/necrotic_agent.dm
@@ -0,0 +1,31 @@
+/*
+//////////////////////////////////////
+
+Necrotic Agent
+
+ Very Noticable.
+ Lowers resistance resistance considerably.
+ Decreases stage speed.
+ Reduced transmittable.
+ Critical Level.
+
+Bonus
+ Makes the disease work on corpses
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/necrotic_agent
+ name = "Necrotic Agent"
+ stealth = -2
+ resistance = -3
+ stage_speed = -3
+ transmittable = 0
+ level = 6
+ severity = 3
+
+/datum/symptom/necrotic_agent/Start(datum/disease/advance/A)
+ A.allow_dead = TRUE
+
+/datum/symptom/necrotic_agent/End(datum/disease/advance/A)
+ A.allow_dead = FALSE
diff --git a/code/datums/diseases/advance/symptoms/oxygen.dm b/code/datums/diseases/advance/symptoms/oxygen.dm
new file mode 100644
index 00000000000..3f9fbd8eee5
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/oxygen.dm
@@ -0,0 +1,37 @@
+/*
+//////////////////////////////////////
+
+Self-Respiration
+
+ Slightly hidden.
+ Lowers resistance significantly.
+ Decreases stage speed significantly.
+ Decreases transmittablity tremendously.
+ Fatal Level.
+
+Bonus
+ The body generates dexalin.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/oxygen
+ name = "Self-Respiration"
+ stealth = 1
+ resistance = -3
+ stage_speed = -3
+ transmittable = -4
+ level = 6
+
+/datum/symptom/oxygen/Activate(var/datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB * 5))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(4, 5)
+ if(M.reagents.get_reagent_amount("dexalin") < 10)
+ M.reagents.add_reagent("dexalin", 10)
+ else
+ if(prob(SYMPTOM_ACTIVATION_PROB * 5))
+ to_chat(M, span_notice(pick("Your lungs feel great.", "You realize you haven't been breathing.", "You don't feel the need to breathe.")))
+ return
diff --git a/code/datums/diseases/advance/symptoms/photosensitivity.dm b/code/datums/diseases/advance/symptoms/photosensitivity.dm
new file mode 100644
index 00000000000..5908bfb259c
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/photosensitivity.dm
@@ -0,0 +1,41 @@
+/*
+//////////////////////////////////////
+
+Photosensitivity
+
+ Noticable.
+ Increases resistance.
+ Increases stage speed slightly.
+ Decreases transmittablity tremendously.
+ Fatal Level.
+
+Bonus
+ Deals brute damage over time.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/photosensitivity
+ name = "Photosensitivity"
+ stealth = -2
+ resistance = 2
+ stage_speed = 1
+ transmittable = -4
+ level = 6
+ severity = 5
+
+/datum/symptom/photosensitivity/Activate(datum/disease/advance/A)
+ ..()
+
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/carbon/human/H = A.affected_mob
+ var/turf/T = get_turf(H)
+ switch(A.stage)
+ if(3)
+ if(T.get_lumcount() > 0.5)
+ to_chat(H, span_danger("Your skin itches under the light..."))
+ if(4, 5)
+ if(T.get_lumcount() > 0.5)
+ to_chat(H, span_danger("Your skin feels like burning!"))
+ H.adjustFireLoss(T.get_lumcount())
+ return
diff --git a/code/datums/diseases/advance/symptoms/pica.dm b/code/datums/diseases/advance/symptoms/pica.dm
new file mode 100644
index 00000000000..ddd7e282d85
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/pica.dm
@@ -0,0 +1,46 @@
+/*
+//////////////////////////////////////
+
+Pica
+
+ Not noticable or unnoticable.
+ Decreases resistance.
+ Increases stage speed.
+ Little transmittable.
+ Low Level.
+
+BONUS
+ The host gains hunger for any kind of object.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/pica
+ name = "Pica"
+ stealth = 0
+ resistance = -2
+ stage_speed = 3
+ transmittable = 1
+ level = 1
+ severity = 1
+
+/datum/symptom/pica/Start(datum/disease/advance/A)
+ add_verb(A.affected_mob, /mob/living/proc/eat_trash)
+ add_verb(A.affected_mob, /mob/living/proc/toggle_trash_catching)
+
+/datum/symptom/pica/End(datum/disease/advance/A)
+ remove_verb(A.affected_mob, /mob/living/proc/eat_trash)
+ remove_verb(A.affected_mob, /mob/living/proc/toggle_trash_catching)
+
+/datum/symptom/pica/Activate(datum/disease/advance/A)
+ ..()
+
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/list/nearby = oview(5, A.affected_mob)
+ to_chat(A.affected_mob, span_warning("You could go fo a bite of [pick(nearby)]..."))
+ else if (prob(SYMPTOM_ACTIVATION_PROB))
+ if(ishuman(A.affected_mob))
+ var/mob/living/carbon/human/H = A.affected_mob
+ var/list/item = H.get_equipped_items()
+ to_chat(H, span_warning("[pick(item)] looks oddly [pick("delicious", "tasty", "scrumptious", "inviting")]..."))
+ return
diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm
new file mode 100644
index 00000000000..8e19382f94e
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/sensory.dm
@@ -0,0 +1,63 @@
+/*
+//////////////////////////////////////
+Sensory-Restoration
+ Very very very very noticable.
+ Lowers resistance tremendously.
+ Decreases stage speed tremendously.
+ Decreases transmittablity tremendously.
+ Fatal.
+Bonus
+ The body generates Sensory restorational chemicals.
+ imidazoline for eyes
+ removes alcohol
+ removes hallucinogens
+ alkysine to kickstart the mind
+
+//////////////////////////////////////
+*/
+/datum/symptom/mind_restoration
+ name = "Mind Restoration"
+ stealth = -3
+ resistance = -4
+ stage_speed = -4
+ transmittable = -3
+ level = 5
+ severity = 0
+
+/datum/symptom/mind_restoration/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB * 3))
+ var/mob/living/M = A.affected_mob
+
+ if(A.stage >= 3)
+ M.slurring = max(0, M.slurring-4)
+ M.druggy = max(0, M.druggy-4)
+ M.reagents.remove_reagent("ethanol", 3)
+ if(A.stage >= 4)
+ M.drowsyness = max(0, M.drowsyness-4)
+ if(M.reagents.has_reagent("bliss"))
+ M.reagents.del_reagent("bliss")
+ M.hallucination = max(0, M.hallucination-4)
+ if(A.stage >= 5)
+ if(M.reagents.get_reagent_amount("alkysine") < 10)
+ M.reagents.add_reagent("alkysine", 5)
+
+/datum/symptom/sensory_restoration
+ name = "Sensory Restoration"
+ stealth = -1
+ resistance = -3
+ stage_speed = -2
+ transmittable = -4
+ level = 4
+
+/datum/symptom/sensory_restoration/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB * 5))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(4, 5)
+ if(M.reagents.get_reagent_amount("imidazoline") < 10)
+ M.reagents.add_reagent("imidazoline", 5)
+ else
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ to_chat(M, span_notice(pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.")))
diff --git a/code/datums/diseases/advance/symptoms/shivering.dm b/code/datums/diseases/advance/symptoms/shivering.dm
new file mode 100644
index 00000000000..f4a3059d7c9
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/shivering.dm
@@ -0,0 +1,39 @@
+/*
+//////////////////////////////////////
+
+Shivering
+
+ No change to hidden.
+ Increases resistance.
+ Increases stage speed.
+ Little transmittable.
+ Low level.
+
+Bonus
+ Cools down your body.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/shivering
+ name = "Shivering"
+ stealth = 0
+ resistance = 2
+ stage_speed = 2
+ transmittable = 2
+ level = 2
+ severity = 2
+
+/datum/symptom/shivering/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/carbon/M = A.affected_mob
+ to_chat(M, span_warning(pick("You feel cold.", "You start shivering.")))
+ if(M.bodytemperature > BODYTEMP_COLD_DAMAGE_LIMIT)
+ Chill(M, A)
+ return
+
+/datum/symptom/shivering/proc/Chill(mob/living/M, datum/disease/advance/A)
+ var/get_cold = (sqrtor0(16+A.totalStealth()*2))+(sqrtor0(21+A.totalResistance()*2))
+ M.bodytemperature = max(M.bodytemperature - (get_cold * A.stage), BODYTEMP_COLD_DAMAGE_LIMIT + 1)
+ return 1
diff --git a/code/datums/diseases/advance/symptoms/size.dm b/code/datums/diseases/advance/symptoms/size.dm
new file mode 100644
index 00000000000..a0a71fe1b71
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/size.dm
@@ -0,0 +1,98 @@
+/*
+//////////////////////////////////////
+
+Mass Revectoring
+
+ Very noticeable.
+ Increases resistance slightly.
+ Increases stage speed.
+ Decreases transmittablity
+ Intense level.
+
+BONUS
+ Changes the size of the host.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/size
+ name = "Mass Revectoring"
+ stealth = -4
+ resistance = 1
+ stage_speed = 2
+ transmittable = -2
+ level = 4
+ severity = 1
+
+/datum/symptom/size/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+
+ switch(A.stage)
+ if(4, 5)
+ M.emote("twitch")
+ Resize(M, rand(25, 200))
+
+/datum/symptom/size/proc/Resize(mob/living/M, var/size)
+ M.resize(size+M.size_multiplier/100)
+
+/*
+//////////////////////////////////////
+
+Enlargement Disorder
+
+ Very noticeable.
+ Increases resistance slightly.
+ Increases stage speed.
+ Decreases transmittablity
+ Intense level.
+
+BONUS
+ Grows the host to bigger sizes
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/size/grow
+ name = "Enlargement Disorder"
+
+/datum/symptom/size/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+
+ switch(A.stage)
+ if(4, 5)
+ M.emote("twitch")
+ Resize(M, rand(100, 200))
+
+/*
+//////////////////////////////////////
+
+Dwindling Malady
+
+ Very noticeable.
+ Increases resistance slightly.
+ Increases stage speed.
+ Decreases transmittablity
+ Intense level.
+
+BONUS
+ Shrinks the host to small sizes
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/size/shrink
+ name = "Dwindling Malady"
+
+/datum/symptom/size/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+
+ switch(A.stage)
+ if(4, 5)
+ M.emote("twitch")
+ Resize(M, rand(25, 100))
diff --git a/code/datums/diseases/advance/symptoms/sneeze.dm b/code/datums/diseases/advance/symptoms/sneeze.dm
new file mode 100644
index 00000000000..529596945b8
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/sneeze.dm
@@ -0,0 +1,119 @@
+/*
+//////////////////////////////////////
+
+Sneezing
+
+ Very Noticable.
+ Increases resistance.
+ Doesn't increase stage speed.
+ Very transmittable.
+ Low Level.
+
+Bonus
+ Forces a spread type of AIRBORNE
+ with extra range!
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/sneeze
+ name = "Sneezing"
+ stealth = -2
+ resistance = 3
+ stage_speed = 0
+ transmittable = 4
+ level = 1
+ severity = 1
+
+/datum/symptom/sneeze/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2, 3)
+ M.emote("sniff")
+ else
+ M.emote("sneeze")
+ if(!M.wear_mask) // Spread only if they're not covering their face
+ A.spread(5)
+
+ if(prob(30) && !M.wear_mask) // Same for mucus
+ var/obj/effect/decal/cleanable/mucus/icky = new(get_turf(M))
+ icky.viruses |= A.Copy()
+
+ return
+
+/*
+//////////////////////////////////////
+
+Bluespace Sneezing
+
+ Very Noticable.
+ Resistant
+ Doesn't increase stage speed.
+ Little transmittable.
+ Low Level.
+
+Bonus
+ Forces a spread type of AIRBORNE
+ with extra range AND teleports the mob
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/sneeze/bluespace
+ name = "Bluespace Sneezing"
+ stealth = -2
+ resistance = 3
+ stage_speed = 0
+ transmittable = 1
+ level = 4
+ severity = 1
+
+/datum/symptom/sneeze/bluespace/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2, 3)
+ M.emote("sniff")
+ else
+ SneezeTeleport(A, M)
+ A.spread(A.stage)
+ if(prob(30))
+ var/obj/effect/decal/cleanable/mucus/icky = new(get_turf(M))
+ icky.viruses |= A.Copy()
+
+ return
+
+/datum/symptom/sneeze/bluespace/proc/SneezeTeleport(datum/disease/advance/A, var/mob/living/M)
+ var/list/destination = list()
+ var/mob/living/carbon/human/H = M
+ var/place
+
+ for(var/mob/living/carbon/human/B in range(A.stage, M))
+ if(B.can_be_drop_pred && H.can_be_drop_prey && H.devourable)
+ destination += B.vore_selected
+
+ for(var/turf/T in range(A.stage, H))
+ if(istype(T, /turf/space)) // No danger, this is just a fun/vore symptom
+ continue
+ destination += T
+
+ if(isemptylist(destination))
+ to_chat(H, span_warning("You go to sneeze, but can't."))
+ return FALSE
+
+ place = safepick(destination)
+
+ var/mob/living/carbon/human/unlucky = locate() in place
+
+ if(unlucky)
+ if(unlucky.can_be_drop_pred && H.can_be_drop_prey && H.devourable)
+ place = unlucky.vore_selected
+ else if(unlucky.devourable && unlucky.can_be_drop_prey && H.can_be_drop_pred)
+ unlucky.forceMove(H.vore_selected)
+
+ H.emote("sneeze")
+ do_teleport(H, place)
+ return TRUE
diff --git a/code/datums/diseases/advance/symptoms/spin.dm b/code/datums/diseases/advance/symptoms/spin.dm
new file mode 100644
index 00000000000..055505dba95
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/spin.dm
@@ -0,0 +1,37 @@
+/*
+//////////////////////////////////////
+
+Spyndrome
+
+ Slightly hidden.
+ No change to resistance.
+ Increases stage speed.
+ Little transmittable.
+ Low Level.
+
+BONUS
+ Makes the host spin.
+ Should be used for buffing your disease.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/spyndrome
+ name = "Spyndrome"
+ stealth = 2
+ resistance = 0
+ stage_speed = 3
+ transmittable = 1
+ level = 1
+ severity = 1
+
+/datum/symptom/spyndrome/Activate(var/datum/disease/advance/A)
+ ..()
+
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ if(A.affected_mob.buckled())
+ to_chat(viewers(A.affected_mob), span_warning("[A.affected_mob.name] struggles violently against their restraints!"))
+ else
+ to_chat(viewers(A.affected_mob), span_warning("[A.affected_mob.name] spins around violently!"))
+ A.affected_mob.emote("spin")
+ return
diff --git a/code/datums/diseases/advance/symptoms/stimulant.dm b/code/datums/diseases/advance/symptoms/stimulant.dm
new file mode 100644
index 00000000000..4a427d4036f
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/stimulant.dm
@@ -0,0 +1,43 @@
+/*
+//////////////////////////////////////
+
+Healing
+
+ No change to stealth.
+ Slightly decreases resistance.
+ Increases stage speed.
+ Decreases transmittablity considerably.
+ Moderate Level.
+
+Bonus
+ Heals toxins in the affected mob's blood stream.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/stimulant
+ name = "Overactive Adrenal Gland"
+ stealth = 0
+ resistance = -1
+ stage_speed = 2
+ transmittable = -3
+ level = 3
+ severity = 1
+
+/datum/symptom/stimulant/Activate(datum/disease/advance/A)
+ ..()
+
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/L = A.affected_mob
+ to_chat(L, span_notice("You feel a rush of energy inside you!"))
+ switch(A.stage)
+ if(1, 2)
+ L.jitteriness += 5
+ if(3, 4)
+ L.jitteriness += 10
+ else
+ if(L.reagents.get_reagent_amount("hyperzine" < 10))
+ L.reagents.add_reagent("hyperzine", 5)
+ if(prob(30))
+ L.jitteriness += 15
+ return
diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm
new file mode 100644
index 00000000000..90b39fab3bd
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/symptoms.dm
@@ -0,0 +1,36 @@
+// Symptoms are the effects that engineered advanced diseases do.
+
+GLOBAL_LIST_INIT(list_symptoms, subtypesof(/datum/symptom))
+
+/datum/symptom
+ // Buffs/Debuffs the symptom has to the overall engineered disease.
+ var/name = ""
+ var/stealth = 0
+ var/resistance = 0
+ var/stage_speed = 0
+ var/transmittable = 0
+ // The type level of the symptom. Higher is harder to generate.
+ var/level = 0
+ // The severity level of the symptom. Higher is more dangerous.
+ var/severity = 0
+ // The hash tag for our diseases, we will add it up with our other symptoms to get a unique id! ID MUST BE UNIQUE!!!
+ var/id = ""
+
+/datum/symptom/New()
+ var/list/S = GLOB.list_symptoms
+ for(var/i = 1; i <= length(S); i++)
+ if(type == S[i])
+ id = "[i]"
+ return
+ CRASH("We couldn't assign an ID!")
+
+// Called when processing of the advance disease, which holds this symptom, starts.
+/datum/symptom/proc/Start(datum/disease/advance/A)
+ return
+
+// Called when the advance disease is going to be deleted or when the advance disease stops processing.
+/datum/symptom/proc/End(datum/disease/advance/A)
+ return
+
+/datum/symptom/proc/Activate(datum/disease/advance/A)
+ return
diff --git a/code/datums/diseases/advance/symptoms/synthetic_infection.dm b/code/datums/diseases/advance/symptoms/synthetic_infection.dm
new file mode 100644
index 00000000000..b34ce074818
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/synthetic_infection.dm
@@ -0,0 +1,31 @@
+/*
+//////////////////////////////////////
+
+Synthetic Infection
+
+ Slightly hidden.
+ Increases resistance.
+ Doesn't increase stage speed.
+ Slightly transmittable.
+ High Level.
+
+Bonus
+ Allows the disease to infect synthetics
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/infect_synthetics
+ name = "Synthetic Infection"
+ stealth = 1
+ resistance = 2
+ stage_speed = 0
+ transmittable = 1
+ level = 5
+ severity = 3
+
+/datum/symptom/infect_synthetics/Start(datum/disease/advance/A)
+ A.infect_synthetics = TRUE
+
+/datum/symptom/infect_synthetics/End(datum/disease/advance/A)
+ A.infect_synthetics = FALSE
diff --git a/code/datums/diseases/advance/symptoms/telepathy.dm b/code/datums/diseases/advance/symptoms/telepathy.dm
new file mode 100644
index 00000000000..3e02ec94d83
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/telepathy.dm
@@ -0,0 +1,36 @@
+/*
+//////////////////////////////////////
+
+Telepathy
+
+ Hidden.
+ Decreases resistance.
+ Decreases stage speed significantly.
+ Decreases transmittablity tremendously.
+ Critical Level.
+
+Bonus
+ The user gains telepathy.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/telepathy
+ name = "Pineal Gland Decalcification"
+ stealth = 2
+ resistance = -2
+ stage_speed = -3
+ transmittable = -4
+ level = 5
+
+/datum/symptom/telepathy/Start(datum/disease/advance/A)
+ var/mob/living/carbon/human/H = A.affected_mob
+ H.dna.SetSEState(REMOTETALKBLOCK, 1)
+ domutcheck(H, null, TRUE)
+ to_chat(H, span_notice("Your mind expands..."))
+
+/datum/symptom/telepathy/End(datum/disease/advance/A)
+ var/mob/living/carbon/human/H = A.affected_mob
+ H.dna.SetSEState(REMOTETALKBLOCK, 0)
+ domutcheck(H, null, TRUE)
+ to_chat(H, span_notice("Everything feels... Normal."))
diff --git a/code/datums/diseases/advance/symptoms/viral.dm b/code/datums/diseases/advance/symptoms/viral.dm
new file mode 100644
index 00000000000..3da1de698ca
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/viral.dm
@@ -0,0 +1,65 @@
+/*
+//////////////////////////////////////
+Viral adaptation
+
+ Moderate stealth boost.
+ Major Increases to resistance.
+ Reduces stage speed.
+ No change to transmission
+ Critical Level.
+
+BONUS
+ Extremely useful for buffing viruses
+
+//////////////////////////////////////
+*/
+/datum/symptom/viraladaptation
+ name = "Viral self-adaptation"
+ stealth = 3
+ resistance = 5
+ stage_speed = -3
+ transmittable = 0
+ level = 3
+
+/datum/symptom/viraladaptation/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1)
+ to_chat(M, span_notice("You feel off, but no different from before."))
+ if(5)
+ to_chat(M, span_notice("You feel better, but nothing interesting happens."))
+
+/*
+//////////////////////////////////////
+Viral evolution
+
+ Moderate stealth reductopn.
+ Major decreases to resistance.
+ increases stage speed.
+ increase to transmission
+ Critical Level.
+
+BONUS
+ Extremely useful for buffing viruses
+
+//////////////////////////////////////
+*/
+/datum/symptom/viralevolution
+ name = "Viral evolutionary acceleration"
+ stealth = -2
+ resistance = -3
+ stage_speed = 5
+ transmittable = 3
+ level = 3
+
+/datum/symptom/viralevolution/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1)
+ to_chat(M, span_notice("You feel better, but no different from before."))
+ if(5)
+ to_chat(M,span_notice("You feel off, but nothing interesting happens."))
diff --git a/code/datums/diseases/advance/symptoms/vision.dm b/code/datums/diseases/advance/symptoms/vision.dm
new file mode 100644
index 00000000000..d74b0c6a5dc
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/vision.dm
@@ -0,0 +1,50 @@
+/*
+//////////////////////////////////////
+
+Hyphema (Eye bleeding)
+
+ Slightly noticable.
+ Lowers resistance tremendously.
+ Decreases stage speed tremendously.
+ Decreases transmittablity.
+ Critical Level.
+
+Bonus
+ Causes blindness.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/visionloss
+ name = "Hyphema"
+ stealth = -1
+ resistance = -4
+ stage_speed = -4
+ transmittable = -3
+ level = 5
+ severity = 4
+
+/datum/symptom/visionloss/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/carbon/M = A.affected_mob
+ var/obj/item/organ/internal/eyes/eyes = M.internal_organs_by_name[O_EYES]
+ if(!eyes)
+ return
+ switch(A.stage)
+ if(1, 2)
+ to_chat(M, span_warning("Your eyes itch."))
+ if(3, 4)
+ to_chat(M, span_boldwarning("Your eyes burn!"))
+ M.eye_blurry = 20
+ eyes.take_damage(1)
+ else
+ to_chat(M, span_userdanger("Your eyes burn horrificly!"))
+ M.eye_blurry = 40
+ eyes.take_damage(5)
+ if(eyes.damage >= 10)
+ M.disabilities |= NEARSIGHTED
+ if(prob(eyes.damage - 10 + 1))
+ if(!M.eye_blind)
+ to_chat(M, span_userdanger("You go blind!"))
+ M.Blind(20)
diff --git a/code/datums/diseases/advance/symptoms/vomit.dm b/code/datums/diseases/advance/symptoms/vomit.dm
new file mode 100644
index 00000000000..06c2b0fafbf
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/vomit.dm
@@ -0,0 +1,34 @@
+/*
+//////////////////////////////////////
+
+Vomiting
+
+ Noticeable.
+ No change to resistance.
+ Slightly increases stage speed.
+ Increases transmissibility.
+ Medium Level.
+
+Bonus
+ Forces the affected mob to vomit
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/vomit
+ name = "Vomiting"
+ stealth = -2
+ resistance = 0
+ stage_speed = 1
+ transmittable = 2
+ level = 3
+ severity = 1
+
+/datum/symptom/vomit/Activate(datum/disease/advance/A)
+ if(!..())
+ return
+ var/mob/living/M = A.affected_mob
+ if(prob(2))
+ to_chat(M, span_warning(pick("you feel nauseated.", "You feel like you're going to throw up!")))
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ M.vomit()
diff --git a/code/datums/diseases/advance/symptoms/weakness.dm b/code/datums/diseases/advance/symptoms/weakness.dm
new file mode 100644
index 00000000000..917be5a46ce
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/weakness.dm
@@ -0,0 +1,43 @@
+/*
+//////////////////////////////////////
+
+Weakness
+
+ Slightly noticeable.
+ Lowers resistance slightly.
+ Decreases stage speed moderately.
+ Decreases transmittablity moderately.
+ Moderate Level.
+
+Bonus
+ Weakens the host
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/weakness
+ name = "Weakness"
+ stealth = -1
+ resistance = -1
+ stage_speed = -2
+ transmittable = -2
+ level = 3
+ severity = 3
+
+/datum/symptom/weakness/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2)
+ to_chat(M, span_warning(pick("You feel weak.", "You feel lazy.")))
+ if(3, 4)
+ to_chat(M, span_boldwarning(pick("You feel very frail.", "You think you might faint.")))
+ M.Weaken(10)
+ else
+ to_chat(M, span_userdanger(pick("You feel tremendously weak!", "Your body trembles as exhaustion creeps over you.")))
+ M.Weaken(20)
+ if(M.weakened > 60 && !M.stat)
+ M.visible_message(span_warning("[M] faints!"), span_userdanger("You swoon and faint..."))
+ M.AdjustSleeping(10)
+ return
diff --git a/code/datums/diseases/advance/symptoms/weigh.dm b/code/datums/diseases/advance/symptoms/weigh.dm
new file mode 100644
index 00000000000..ceca8a77f59
--- /dev/null
+++ b/code/datums/diseases/advance/symptoms/weigh.dm
@@ -0,0 +1,37 @@
+/*
+//////////////////////////////////////
+
+Weight Loss
+
+ Very Very Noticable.
+ Decreases resistance.
+ Decreases stage speed.
+ Reduced Transmittable.
+ High level.
+
+Bonus
+ Decreases the weight of the mob,
+ forcing it to be skinny.
+
+//////////////////////////////////////
+*/
+
+/datum/symptom/weight_loss
+ name = "Weight Loss"
+ stealth = -3
+ resistance = -2
+ stage_speed = -2
+ transmittable = -2
+ level = 3
+ severity = 1
+
+/datum/symptom/weight_loss/Activate(datum/disease/advance/A)
+ ..()
+ if(prob(SYMPTOM_ACTIVATION_PROB))
+ var/mob/living/M = A.affected_mob
+ switch(A.stage)
+ if(1, 2, 3, 4)
+ to_chat(M, span_warning(pick("You feel hungry.", "You crave for food.")))
+ else
+ to_chat(M, span_warning(pick("So hungry...", "You'd kill someone for a bite of food...", "Hunger cramps seize you...")))
+ M.adjust_nutrition(-20)
diff --git a/code/datums/diseases/anxiety.dm b/code/datums/diseases/anxiety.dm
new file mode 100644
index 00000000000..78b630bc152
--- /dev/null
+++ b/code/datums/diseases/anxiety.dm
@@ -0,0 +1,53 @@
+/datum/disease/anxiety
+ name = "Severe Anxiety"
+ form = "Infection"
+ max_stages = 4
+ spread_text = "On contact"
+ spread_flags = CONTACT_GENERAL
+ cure_text = "Ethanol"
+ cures = list("ethanol")
+ agent = "Excess Lepdopticides"
+ viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
+ desc = "If left untreated subject will regurgitate butterflies."
+ severity = MINOR
+
+/datum/disease/anxiety/stage_act()
+ if(!..())
+ return FALSE
+ switch(stage)
+ if(2)
+ if(prob(15))
+ to_chat(affected_mob, span_notice("You feel anxious."))
+ if(3)
+ if(prob(10))
+ to_chat(affected_mob, span_notice("Your stomach flutters."))
+ if(prob(5))
+ to_chat(affected_mob, span_notice("You feel panicky."))
+ if(prob(2))
+ to_chat(affected_mob, span_danger("You're overtaken with panic!"))
+ affected_mob.AdjustConfused(rand(4, 6))
+ if(4)
+ if(prob(10))
+ to_chat(affected_mob, span_danger("You feel butterflies in your stomach."))
+ if(prob(5))
+ affected_mob.visible_message(
+ span_danger("[affected_mob] stumbles around in a panic"),
+ span_userdanger("You have a panic attack!")
+ )
+ affected_mob.AdjustConfused(rand(12, 16))
+ affected_mob.jitteriness = rand(12, 16)
+ if(prob(2))
+ affected_mob.visible_message(
+ span_danger("[affected_mob] coughs up butterflies!"),
+ span_userdanger("You cough up butterflies!")
+ )
+ affected_mob.emote("cough")
+ for(var/i in 1 to 2)
+ var/mob/living/simple_mob/animal/sif/glitterfly/B = new(affected_mob.loc)
+ addtimer(CALLBACK(B, TYPE_PROC_REF(/mob/living/simple_mob/animal/sif/glitterfly, decompose)), rand(5, 25) SECONDS)
+
+/mob/living/simple_mob/animal/sif/glitterfly/proc/decompose()
+ visible_message(
+ span_notice("[src] decomposes due to being outside of its original habitat for too long!"),
+ span_userdanger("You decompose for being too long out of your habitat!"))
+ dust()
diff --git a/code/datums/diseases/appendicitis.dm b/code/datums/diseases/appendicitis.dm
new file mode 100644
index 00000000000..ab7f5383b31
--- /dev/null
+++ b/code/datums/diseases/appendicitis.dm
@@ -0,0 +1,45 @@
+/datum/disease/appendicitis
+ form = "Condition"
+ name = "Appendicitis"
+ max_stages = 3
+ spread_text = "Non-contagius"
+ spread_flags = NON_CONTAGIOUS
+ cure_text = "Surgery"
+ agent = "Shitty Appendix"
+ viable_mobtypes = list(/mob/living/carbon/human)
+ desc = "If left untreated the subject will become very weak, and may vomit often."
+ severity = MINOR
+ disease_flags = CAN_CARRY|CAN_CARRY
+ visibility_flags = HIDDEN_PANDEMIC
+ required_organs = list(/obj/item/organ/internal/appendix)
+ bypasses_immunity = TRUE
+ virus_heal_resistant = TRUE
+
+/datum/disease/appendicitis/stage_act()
+ if(!..())
+ return
+ switch(stage)
+ if(1)
+ if(prob(5))
+ affected_mob.adjustToxLoss(1)
+ if(2)
+ var/obj/item/organ/internal/appendix/A = affected_mob.internal_organs_by_name[O_APPENDIX]
+ if(A)
+ A.inflamed = TRUE
+ if(prob(3))
+ to_chat(affected_mob, span_warning("You feel a stabbing pain in your abdomen!"))
+ affected_mob.custom_emote(VISIBLE_MESSAGE, "winces painfully.")
+ affected_mob.Stun(rand(4, 6))
+ affected_mob.adjustToxLoss(1)
+ if(3)
+ if(prob(1))
+ to_chat(affected_mob, span_danger("Your abdomen is a world of pain!"))
+ affected_mob.custom_emote(VISIBLE_MESSAGE, "winces painfully.")
+ affected_mob.Weaken(10)
+ if(prob(1))
+ affected_mob.vomit(95)
+ if(prob(5))
+ to_chat(affected_mob, span_warning("You feel a stabbing pain in your abdomen!"))
+ affected_mob.custom_emote(VISIBLE_MESSAGE, "winces painfully.")
+ affected_mob.Stun(rand(4, 6))
+ affected_mob.adjustToxLoss(2)
diff --git a/code/datums/diseases/beesease.dm b/code/datums/diseases/beesease.dm
new file mode 100644
index 00000000000..a867c8d9d97
--- /dev/null
+++ b/code/datums/diseases/beesease.dm
@@ -0,0 +1,36 @@
+/datum/disease/beesease
+ name = "Beesease"
+ form = "Infection"
+ max_stages = 4
+ spread_text = "On contact"
+ spread_flags = CONTACT_GENERAL
+ cure_text = "Sugar"
+ cures = list("sugar")
+ agent = "Apidae Infection"
+ viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
+ desc = "If left untreated, subject will regurgitate bees."
+ severity = BIOHAZARD
+
+/datum/disease/beesease/stage_act()
+ if(!..())
+ return FALSE
+ switch(stage)
+ if(2)
+ if(prob(2))
+ to_chat(affected_mob, span_notice("You tastey hone in your mouth."))
+ if(3)
+ if(prob(10))
+ to_chat(affected_mob, span_notice("Your stomach rumbles"))
+ if(prob(2))
+ to_chat(affected_mob, span_notice("Your stomach stings painfully."))
+ if(prob(20))
+ affected_mob.adjustToxLoss(2)
+ if(4)
+ if(prob(10))
+ affected_mob.visible_message(span_danger("[affected_mob] buzzles loudly"), span_userdanger("Your stomach buzzles violently!"))
+ if(prob(5))
+ to_chat(affected_mob, span_danger("You feel something moving in your throat."))
+ if(prob(1))
+ affected_mob.visible_message(span_danger("[affected_mob] coughs up a swarm of bees!"), span_userdanger("You cough up a swarm of bees!"))
+ new /mob/living/simple_mob/vore/bee(affected_mob.loc)
+ return
diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm
new file mode 100644
index 00000000000..57899ef2014
--- /dev/null
+++ b/code/datums/diseases/brainrot.dm
@@ -0,0 +1,43 @@
+/datum/disease/brainrot
+ name = "Brainrot"
+ max_stages = 4
+ spread_text = "On contact"
+ spread_flags = CONTACT_GENERAL
+ cure_text = "Alkysine"
+ cures = list("alkysine")
+ agent = "Cryptococcus Cosmosis"
+ viable_mobtypes = list(/mob/living/carbon/human)
+ cure_chance = 15
+ desc = "This disease destroys the braincells, causing brain fever, brain necrosis and general intoxication."
+ required_organs = list(/obj/item/organ/internal/brain)
+ severity = HARMFUL
+
+/datum/disease/brainrot/stage_act()
+ if(!..())
+ return FALSE
+ switch(stage)
+ if(2)
+ if(prob(2))
+ affected_mob.say("*blink")
+ if(prob(2))
+ affected_mob.say("*yawn")
+ if(prob(2))
+ to_chat(affected_mob, span_danger("You don't feel like yourself."))
+ if(prob(5))
+ affected_mob.adjustBrainLoss(1)
+ if(3)
+ if(prob(2))
+ affected_mob.say("*stare")
+ if(prob(3))
+ affected_mob.say("*drool")
+ if(prob(10) && affected_mob.getBrainLoss() < 100)
+ affected_mob.adjustBrainLoss(3)
+ if(prob(2))
+ to_chat(affected_mob, span_danger("Strange buzzing fills your head, removing all thoughts."))
+ if(prob(3))
+ to_chat(affected_mob, span_danger("You lose consciousness..."))
+ affected_mob.Sleeping(rand(5, 10))
+ if(prob(1))
+ affected_mob.emote("snore")
+ if(prob(15))
+ affected_mob.apply_effect(5, STUTTER)
diff --git a/code/datums/diseases/choreomania.dm b/code/datums/diseases/choreomania.dm
new file mode 100644
index 00000000000..9fd41c4cd6f
--- /dev/null
+++ b/code/datums/diseases/choreomania.dm
@@ -0,0 +1,38 @@
+/datum/disease/choreomania
+ name = "Choreomania"
+ max_stages = 3
+ spread_text = "Airborne"
+ cure_text = "Adranol"
+ cures = list("adranol")
+ cure_chance = 10
+ agent = "TAP-DAnC3"
+ viable_mobtypes = list(/mob/living/carbon/human)
+ permeability_mod = 0.75
+ desc = "If left untreated the subject... Won't stop dancing!"
+ severity = MINOR
+
+ var/list/dance = list(2,4,8,2,4,8,2,4,8,2,4,8,1,4,1,4,1,4,2,4,8,2)
+
+/datum/disease/choreomania/stage_act()
+ if(!..())
+ return FALSE
+ switch(stage)
+ if(2)
+ if(prob(1))
+ to_chat(affected_mob, span_notice("You feel like dancing like a maniac, maniac..."))
+ if(prob(1))
+ affected_mob.emote("whistle")
+ if(3)
+ if(prob(1))
+ to_chat(affected_mob, span_notice("You feel like dancing like a maniac, maniac..."))
+ if(prob(1))
+ to_chat(affected_mob, span_notice("You really want to start a conga line!"))
+ if(prob(2))
+ for(var/D in dance)
+ affected_mob.dir = D
+ animate(affected_mob, pixel_x = 5, time = 5)
+ sleep(3)
+ animate(affected_mob, pixel_x = -5, time = 5)
+ animate(pixel_x = affected_mob.default_pixel_x, pixel_y = affected_mob.default_pixel_x, time = 2)
+ sleep(3)
+ return
diff --git a/code/datums/diseases/cold.dm b/code/datums/diseases/cold.dm
new file mode 100644
index 00000000000..487f466761c
--- /dev/null
+++ b/code/datums/diseases/cold.dm
@@ -0,0 +1,65 @@
+/datum/disease/cold
+ name = "The Cold"
+ max_stages = 3
+ spread_text = "Airborne"
+ spread_flags = AIRBORNE
+ cure_text = "Rest & Spaceacillin"
+ cures = list("spaceacillin", "chicken_soup")
+ needs_all_cures = FALSE
+ agent = "XY-rhinovirus"
+ viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
+ permeability_mod = 0.5
+ desc = "If left untreated the subject will contract the flu."
+ severity = MINOR
+
+/datum/disease/cold/stage_act()
+ if(!..())
+ return FALSE
+ switch(stage)
+ if(2)
+ if(affected_mob.stat == UNCONSCIOUS && prob(40))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ if(affected_mob.lying && prob(10))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ if(prob(1) && prob(5))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ if(prob(1))
+ affected_mob.emote("sneeze")
+ if(prob(1))
+ affected_mob.emote("cough")
+ if(prob(1))
+ to_chat(affected_mob, span_notice("Your throat feels sore."))
+ if(prob(1))
+ to_chat(affected_mob, span_notice("Mucous runs down the back of your throat."))
+ if(3)
+ if(affected_mob.stat == UNCONSCIOUS && prob(25))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ if(affected_mob.lying && prob(5))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ if(prob(1) && prob(1))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ if(prob(1))
+ affected_mob.emote("sneeze")
+ if(prob(1))
+ affected_mob.emote("cough")
+ if(prob(1))
+ to_chat(affected_mob, span_notice("Your throat feels sore."))
+ if(prob(1))
+ to_chat(affected_mob, span_notice("Mucous runs down the back of your throat."))
+ if(prob(1) && prob(50))
+ if(!affected_mob.resistances.Find(/datum/disease/flu))
+ var/datum/disease/Flu = new /datum/disease/flu(0)
+ affected_mob.ContractDisease(Flu)
+ cure()
diff --git a/code/datums/diseases/cold9.dm b/code/datums/diseases/cold9.dm
new file mode 100644
index 00000000000..a0fa6919764
--- /dev/null
+++ b/code/datums/diseases/cold9.dm
@@ -0,0 +1,30 @@
+/datum/disease/cold9
+ name = "The Cold"
+ medical_name = "ICE9 Cold"
+ max_stages = 3
+ spread_text = "On contact"
+ spread_flags = CONTACT_GENERAL
+ cure_text = "Spaceacillin"
+ cures = list("spaceacillin")
+ agent = "ICE9-rhinovirus"
+ viable_mobtypes = list(/mob/living/carbon/human)
+ desc = "If left untreated the subject will slow, as if partly frozen."
+ severity = HARMFUL
+
+/datum/disease/cold9/stage_act()
+ if(!..())
+ return FALSE
+ if(stage < 2)
+ return
+
+ var/stage_factor = stage - 1
+ affected_mob.bodytemperature -= 7.5 * stage_factor
+ if(prob(2 * stage_factor))
+ affected_mob.say("*sneeze")
+ if(prob(2 * stage_factor))
+ affected_mob.say("*cough")
+ if(prob(3 * stage_factor))
+ to_chat(affected_mob, span_danger("Your throat feels sore."))
+ if(prob(5 * stage_factor))
+ to_chat(affected_mob, span_danger("You feel stiff."))
+ affected_mob.adjustFireLoss(1)
diff --git a/code/datums/diseases/darkness.dm b/code/datums/diseases/darkness.dm
new file mode 100644
index 00000000000..b340ca5d45d
--- /dev/null
+++ b/code/datums/diseases/darkness.dm
@@ -0,0 +1,10 @@
+/datum/disease/darkness
+ name = "Dark Exposure"
+ form = "Bluespace Micro-fissures"
+ max_stages = 4
+ spread = NON_CONTAGIOUS
+ cure_text = "Exposure to light and the real world"
+ agent = "Bluespace Exposure"
+ viable_mobtypes = list(/mob/living/carbon/human)
+ desc = "If left untreated, subject will lose grip on reality."
+ severity = HARMFUL
diff --git a/code/datums/diseases/fake_gbs.dm b/code/datums/diseases/fake_gbs.dm
new file mode 100644
index 00000000000..ca36f57d872
--- /dev/null
+++ b/code/datums/diseases/fake_gbs.dm
@@ -0,0 +1,32 @@
+/datum/disease/fake_gbs
+ name = "GBS"
+ max_stages = 5
+ spread_text = "On contact"
+ spread_flags = CONTACT_GENERAL
+ cure_text = "Adranol & Sulfur"
+ cures = list("adranol", "sulfur")
+ agent = "Gravitokinetic Bipotential SADS-"
+ viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
+ desc = "if left untreated death will occur."
+ severity = BIOHAZARD // Mimics real GBS
+
+/datum/disease/fake_gbs/stage_act()
+ if(!..())
+ return FALSE
+ switch(stage)
+ if(2)
+ if(prob(1))
+ affected_mob.emote("sneeze")
+ if(3)
+ if(prob(5))
+ affected_mob.emote("cough")
+ else if(prob(5))
+ affected_mob.emote("gasp")
+ if(prob(10))
+ to_chat(span_danger("You're starting to feel very weak..."))
+ if(4)
+ if(prob(10))
+ affected_mob.emote("cough")
+ if(5)
+ if(prob(10))
+ affected_mob.emote("cough")
diff --git a/code/datums/diseases/flu.dm b/code/datums/diseases/flu.dm
new file mode 100644
index 00000000000..2962f48e9b4
--- /dev/null
+++ b/code/datums/diseases/flu.dm
@@ -0,0 +1,51 @@
+/datum/disease/flu
+ name = "The Flu"
+ max_stages = 3
+ spread_text = "Airborne"
+ cure_text = "Spaceacillin"
+ cures = list("spaceacillin", "chicken_soup")
+ needs_all_cures = FALSE
+ cure_chance = 10
+ agent = "H13N1 flu virion"
+ viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
+ permeability_mod = 0.75
+ desc = "If left untreated the subject will feel quite unwell."
+ severity = MINOR
+
+/datum/disease/flu/stage_act()
+ if(!..())
+ return FALSE
+ switch(stage)
+ if(2)
+ if(affected_mob.lying && prob(20))
+ to_chat(affected_mob, span_notice("You feel better."))
+ stage--
+ return
+ if(prob(1))
+ affected_mob.emote("sneeze")
+ if(prob(1))
+ affected_mob.emote("cough")
+ if(prob(1))
+ to_chat(affected_mob, span_danger("Your muscles ache."))
+ if(prob(20))
+ affected_mob.apply_damage(1)
+ if(prob(1))
+ to_chat(affected_mob, span_danger("Your stomach hurts."))
+ affected_mob.adjustToxLoss(1)
+ if(3)
+ if(affected_mob.lying && prob(15))
+ to_chat(affected_mob, span_notice("You feel better."))
+ stage--
+ return
+ if(prob(1))
+ affected_mob.emote("sneeze")
+ if(prob(1))
+ affected_mob.emote("cough")
+ if(prob(1))
+ to_chat(affected_mob, span_danger("Your muscles ache."))
+ if(prob(20))
+ affected_mob.apply_damage(1)
+ if(prob(1))
+ to_chat(affected_mob, span_danger("Your stomach hurts."))
+ affected_mob.adjustToxLoss(1)
+ return
diff --git a/code/datums/diseases/food_poisoning.dm b/code/datums/diseases/food_poisoning.dm
new file mode 100644
index 00000000000..cbb7a0c8046
--- /dev/null
+++ b/code/datums/diseases/food_poisoning.dm
@@ -0,0 +1,67 @@
+/datum/disease/food_poisoning
+ name = "Food Poisoning"
+ max_stages = 3
+ stage_prob = 5
+ spread_text = "Non-Contagious"
+ spread_flags = NON_CONTAGIOUS
+ cure_text = "Sleep"
+ agent = "Salmonella"
+ cures = list("chicken_soup")
+ cure_chance = 10
+ viable_mobtypes = list(/mob/living/carbon/human)
+ desc = "Nausea, sickness, and vomitting."
+ severity = MINOR
+ disease_flags = CURABLE
+ virus_heal_resistant = TRUE
+
+/datum/disease/food_poisoning/stage_act()
+ if(!..())
+ return FALSE
+ if(affected_mob.stat == UNCONSCIOUS && prob(33))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ switch(stage)
+ if(1)
+ if(prob(5))
+ to_chat(affected_mob, span_danger("Your stomach feels weird."))
+ if(prob(5))
+ to_chat(affected_mob, span_danger("You feel queasy."))
+ if(2)
+ if(affected_mob.stat == UNCONSCIOUS && prob(40))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ if(prob(1) && prob(10))
+ to_chat(affected_mob, span_notice("You feel better."))
+ if(prob(10))
+ affected_mob.emote("groan")
+ if(prob(5))
+ to_chat(affected_mob, span_danger("Your stomach aches."))
+ if(prob(5))
+ to_chat(affected_mob, span_danger("You feel nauseous"))
+ if(3)
+ if(affected_mob.stat == UNCONSCIOUS && prob(25))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ if(prob(1) && prob(10))
+ to_chat(affected_mob, span_notice("You feel better."))
+ cure()
+ return
+ if(prob(10))
+ affected_mob.emote("moan")
+ if(prob(10))
+ affected_mob.emote("groan")
+ if(prob(1))
+ to_chat(affected_mob, span_danger("Your stomach hurts."))
+ if(prob(1))
+ to_chat(affected_mob, span_danger("You feel sick."))
+ if(prob(5))
+ if(affected_mob.nutrition > 10)
+ affected_mob.emote("vomit")
+ else
+ to_chat(affected_mob, span_danger("Your stomach lurches painfully"))
+ affected_mob.visible_message(span_danger("[affected_mob] gags and retches!"))
+ affected_mob.Stun(rand(4, 8))
+ affected_mob.Weaken(rand(4, 8))
diff --git a/code/datums/diseases/gbs.dm b/code/datums/diseases/gbs.dm
new file mode 100644
index 00000000000..ea2c755e279
--- /dev/null
+++ b/code/datums/diseases/gbs.dm
@@ -0,0 +1,49 @@
+/datum/disease/gbs
+ name = "GBS"
+ max_stages = 5
+ spread_text = "On contact"
+ spread_flags = CONTACT_GENERAL
+ cure_text = "Adranol & Sulfur"
+ cures = list("adranol", "sulfur")
+ cure_chance = 15
+ agent = "Gravitokinetic Bipotential SADS+"
+ viable_mobtypes = list(/mob/living/carbon/human)
+ severity = BIOHAZARD
+
+/datum/disease/gbs/stage_act()
+ if(!..())
+ return FALSE
+ switch(stage)
+ if(2)
+ if(prob(45))
+ affected_mob.adjustToxLoss(5)
+ if(prob(1))
+ affected_mob.emote("sneeze")
+ if(3)
+ if(prob(5))
+ affected_mob.emote("cough")
+ else if(prob(5))
+ affected_mob.emote("gasp")
+ if(prob(10))
+ to_chat(affected_mob, span_danger("You're starting to feel very weak..."))
+ if(4)
+ if(prob(10))
+ affected_mob.emote("cough")
+ affected_mob.adjustToxLoss(5)
+ if(5)
+ to_chat(affected_mob, span_danger("Your body feels as if it's trying to rip itself open..."))
+ if(prob(50))
+ affected_mob.delayed_gib()
+ else
+ return
+
+/datum/disease/gbs/curable
+ name = "Non-Contagious GBS"
+ stage_prob = 5
+ spread_text = "Non-contagious"
+ spread_flags = NON_CONTAGIOUS
+ cure_text = "Cryoxadone"
+ cures = list("cryoxadone")
+ cure_chance = 10
+ agent = "gibbis"
+ disease_flags = CURABLE
diff --git a/code/datums/diseases/lycancoughy.dm b/code/datums/diseases/lycancoughy.dm
new file mode 100644
index 00000000000..6d8f1061638
--- /dev/null
+++ b/code/datums/diseases/lycancoughy.dm
@@ -0,0 +1,64 @@
+/datum/disease/lycan
+ name = "Lycancoughy"
+ form = "Infection"
+ max_stages = 4
+ spread_text = "On contact"
+ spread_flags = CONTACT_GENERAL
+ cure_text = "Ethanol"
+ cures = list("ethanol")
+ agent = "Excess Snuggles"
+ viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
+ desc = "If left untreated subject will regurgitate... puppies."
+ severity = HARMFUL
+ var/barklimit
+ var/list/puppy_types = list(/mob/living/simple_mob/animal/passive/dog/corgi/puppy)
+ var/list/plush_types = list(/obj/item/toy/plushie/orange_fox, /obj/item/toy/plushie/corgi, /obj/item/toy/plushie/robo_corgi, /obj/item/toy/plushie/pink_fox)
+
+/datum/disease/lycan/stage_act()
+ if(!..())
+ return FALSE
+
+ var/mob/living/carbon/human/H = affected_mob
+
+ switch(stage)
+ if(2)
+ if(prob(2))
+ H.emote("cough")
+ if(prob(3))
+ to_chat(H, span_notice("You itch."))
+ H.adjustBruteLoss(rand(4, 6))
+ if(3)
+ var/obj/item/organ/external/stomach = H.organs_by_name[pick("torso", "groin")]
+
+ if(prob(3))
+ H.emote("cough")
+ stomach.take_damage(BRUTE, rand(0, 5))
+ if(prob(3))
+ to_chat(H, span_notice("You hear a faint barking."))
+ stomach.take_damage(BRUTE, rand(4, 6))
+ if(prob(2))
+ to_chat(H, span_notice("You crave meat."))
+ if(prob(3))
+ to_chat(H, span_danger("Your stomach growls!"))
+ stomach.take_damage(BRUTE, rand(5, 10))
+ if(4)
+ var/obj/item/organ/external/stomach = H.organs_by_name[pick("torso", "groin")]
+
+ if(prob(5))
+ H.emote("cough")
+ stomach.take_damage(BRUTE, rand(0, 5))
+ if(prob(5))
+ H.emote("awoo2")
+ H.Confuse(rand(12, 16))
+ stomach.take_damage(rand(0, 5))
+ if(prob(5))
+ if(!barklimit)
+ to_chat(H, span_danger("Your stomach growls!"))
+ stomach.take_damage(BRUTE, rand(5, 10))
+ else
+ var/atom/hairball = pick(prob(50) ? puppy_types : plush_types)
+ H.visible_message(span_danger("[H] coughs up \a [initial(hairball.name)]!"), span_userdanger("You cough up \a [initial(hairball.name)]?!"))
+ H.emote("cough")
+ new hairball(H.loc)
+ barklimit--
+ stomach.take_damage(BRUTE, rand(10, 15))
diff --git a/code/datums/diseases/magnitis.dm b/code/datums/diseases/magnitis.dm
new file mode 100644
index 00000000000..24b2261cdaa
--- /dev/null
+++ b/code/datums/diseases/magnitis.dm
@@ -0,0 +1,63 @@
+/datum/disease/magnitis
+ name = "Magnitis"
+ max_stages = 4
+ spread_text = "Airbone"
+ cure_text = "Iron"
+ cures = list("iron")
+ agent = "Fukkos Miracos"
+ viable_mobtypes = list(/mob/living/carbon/human)
+ permeability_mod = 0.75
+ desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field."
+ severity = MINOR
+
+/datum/disease/magnitis/stage_act()
+ if(!..())
+ return FALSE
+ switch(stage)
+ if(2)
+ if(prob(2))
+ to_chat(affected_mob, span_danger("You feel a slight shock course through your body."))
+ if(prob(2))
+ for(var/obj/M in orange(2, affected_mob))
+ if(!M.anchored && prob(5))
+ INVOKE_ASYNC(M, TYPE_PROC_REF(/atom/movable, throw_at), affected_mob, rand(3, 10), rand(1, 3), src)
+ for(var/mob/living/silicon/S in orange(2, affected_mob))
+ if(isAI(S)) continue
+ INVOKE_ASYNC(S, TYPE_PROC_REF(/atom/movable, throw_at), affected_mob, rand(3, 10), rand(1, 3), src)
+ if(3)
+ if(prob(2))
+ to_chat(affected_mob, span_danger("You feel a strong shock course through your body."))
+ if(prob(2))
+ to_chat(affected_mob, span_danger("You feel like clowning aound."))
+ if(prob(4))
+ for(var/obj/M in orange(4, affected_mob))
+ if(!M.anchored && prob(5))
+ var/i
+ var/iter = rand(1,2)
+ for(i=0,iYou will not be prompted to join similar roles to [role_name] for the rest of this round. Note: If you save your character now, it will save this permanently.")
+ to_chat(D, span_notice("You will not be prompted to join similar roles to [role_name] for the rest of this round. Note: If you save your character now, it will save this permanently."))
else
- to_chat(D, "This type of ghost-joinable role doesn't have a role type flag associated with it, so I can't prevent future requests, sorry. Bug a dev!")
+ to_chat(D, span_warning("This type of ghost-joinable role doesn't have a role type flag associated with it, so I can't prevent future requests, sorry. Bug a dev!"))
if("Yes")
if(!evaluate_candidate(D)) // Failed revalidation
- to_chat(D, "Unfortunately, you no longer qualify for this role. Sorry.")
+ to_chat(D, span_warning("Unfortunately, you no longer qualify for this role. Sorry."))
else if(finished) // Already finished candidate list
- to_chat(D, "Unfortunately, you were not fast enough, and there are no more available roles. Sorry.")
+ to_chat(D, span_warning("Unfortunately, you were not fast enough, and there are no more available roles. Sorry."))
else // Prompt a second time
tgui_alert_async(D, "Are you sure you want to play as a [role_name]?", "[role_name] request", list("I'm Sure", "Nevermind"), CALLBACK(src, PROC_REF(get_reply)), wait_time SECONDS)
if("I'm Sure")
if(!evaluate_candidate(D)) // Failed revalidation
- to_chat(D, "Unfortunately, you no longer qualify for this role. Sorry.")
+ to_chat(D, span_warning("Unfortunately, you no longer qualify for this role. Sorry."))
else if(finished) // Already finished candidate list
- to_chat(D, "Unfortunately, you were not fast enough, and there are no more available roles. Sorry.")
+ to_chat(D, span_warning("Unfortunately, you were not fast enough, and there are no more available roles. Sorry."))
else // Accept their nomination
candidates.Add(D)
if(cutoff_number && candidates.len >= cutoff_number)
@@ -112,7 +112,7 @@
question = "Someone has activated a Positronic Brain. Would you like to play as one?"
query_sound = 'sound/machines/boobeebeep.ogg'
be_special_flag = BE_AI
- check_bans = list("AI", "Cyborg")
+ check_bans = list(JOB_AI, JOB_CYBORG)
cutoff_number = 1
/datum/ghost_query/drone_brain
@@ -120,7 +120,7 @@
question = "Someone has activated a Drone AI Chipset. Would you like to play as one?"
query_sound = 'sound/machines/boobeebeep.ogg'
be_special_flag = BE_AI
- check_bans = list("AI", "Cyborg")
+ check_bans = list(JOB_AI, JOB_CYBORG)
cutoff_number = 1
// Antags.
@@ -128,7 +128,7 @@
role_name = "Technomancer Apprentice"
question = "A Technomancer is requesting an Apprentice to help them on their adventure to the facility. Would you like to play as the Apprentice?"
be_special_flag = BE_WIZARD
- check_bans = list("Syndicate", "wizard")
+ check_bans = list(JOB_SYNDICATE, JOB_WIZARD)
cutoff_number = 1
/datum/ghost_query/xeno
@@ -141,7 +141,7 @@
role_name = "Xenomorph Larva"
question = "A xenomorph larva is ready to hatch from their egg. Would you like to join the hive?"
be_special_flag = BE_ALIEN
- check_bans = list("Xenomorph")
+ check_bans = list(JOB_XENOMORPH)
cutoff_number = 1
@@ -156,14 +156,14 @@
role_name = "Mercenary Drone"
question = "A team of dubious mercenaries have purchased a powerful drone, and they are attempting to activate it. Would you like to play as the drone?"
be_special_flag = BE_AI
- check_bans = list("AI", "Cyborg", "Syndicate")
+ check_bans = list(JOB_AI, JOB_CYBORG, JOB_SYNDICATE)
cutoff_number = 1
/datum/ghost_query/borer
role_name = "Cortical Borer"
question = "A cortical borer has just been created on the facility. Would you like to play as them?"
be_special_flag = BE_ALIEN
- check_bans = list("Syndicate", "Borer")
+ check_bans = list(JOB_SYNDICATE, JOB_BORER)
cutoff_number = 1
// Surface stuff.
@@ -171,14 +171,14 @@
role_name = "Lost Drone"
question = "A lost drone onboard has been discovered by a crewmember and they are attempting to reactivate it. Would you like to play as the drone?"
be_special_flag = BE_LOSTDRONE //VOREStation Edit
- check_bans = list("AI", "Cyborg")
+ check_bans = list(JOB_AI, JOB_CYBORG)
cutoff_number = 1
/datum/ghost_query/gravekeeper_drone
role_name = "Gravekeeper Drone"
question = "A gravekeeper drone is about to reactivate and tend to its gravesite. Would you like to play as the drone?"
be_special_flag = BE_AI
- check_bans = list("AI", "Cyborg")
+ check_bans = list(JOB_AI, JOB_CYBORG)
cutoff_number = 1
/datum/ghost_query/lost_passenger
diff --git a/code/datums/ghost_query_vr.dm b/code/datums/ghost_query_vr.dm
index 75356029be3..8f29b14bb35 100644
--- a/code/datums/ghost_query_vr.dm
+++ b/code/datums/ghost_query_vr.dm
@@ -7,5 +7,11 @@
/datum/ghost_query/maints_pred
role_name = "Maintenance Predator"
be_special_flag = BE_MAINTPRED
- question = "It appears a predatory critter is lurking in the maintenance. Do you want to play as it? ((You get to choose type of critter. Expect to be treated as vore predator.))"
- cutoff_number = 1
\ No newline at end of file
+ question = "It appears a predatory critter is lurking in maintenance. Do you want to play as it? ((You get to choose type of critter. Expect to be treated as vore predator.))"
+ cutoff_number = 1
+
+/datum/ghost_query/maints_lurker
+ role_name = "Maintenance Lurker"
+ be_special_flag = BE_MAINTLURKER
+ question = "It appears a strange individual is lurking in maintenance. Do you want to play as them? ((You can spawn as your currently loaded character slot. Expect to be treated as vore predator.))"
+ cutoff_number = 1
diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm
index 909be033a26..ece7799b442 100644
--- a/code/datums/helper_datums/getrev.dm
+++ b/code/datums/helper_datums/getrev.dm
@@ -1,5 +1,3 @@
-GLOBAL_DATUM(revdata, /datum/getrev)
-
/datum/getrev
var/branch
var/revision
@@ -50,33 +48,33 @@ GLOBAL_DATUM(revdata, /datum/getrev)
var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext_char(cm, 1, 11))
if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder))
continue
- . += "#[tm.number][details]"
+ . += "#[tm.number][details]"
/client/verb/showrevinfo()
- set category = "OOC"
+ set category = "OOC.Game"
set name = "Show Server Revision"
set desc = "Check the current server code revision"
if(!GLOB.revdata)
- to_chat(src, "Please wait until server initializations are complete.")
+ to_chat(src, span_warning("Please wait until server initializations are complete."))
return
var/list/msg = list()
if(GLOB.revdata.revision)
- msg += "Server revision: B:[GLOB.revdata.branch] D:[GLOB.revdata.date]"
- if(config.githuburl)
- msg += "Commit: [GLOB.revdata.revision]"
+ msg += span_bold("Server revision:") + " B:[GLOB.revdata.branch] D:[GLOB.revdata.date]"
+ if(CONFIG_GET(string/githuburl))
+ msg += span_bold("Commit:") + " [GLOB.revdata.revision]"
else
- msg += "Commit: GLOB.revdata.revision"
+ msg += span_bold("Commit:") + " GLOB.revdata.revision"
else
- msg += "Server revision: Unknown"
+ msg += span_bold("Server revision:") + " Unknown"
if(world.TgsAvailable())
var/datum/tgs_version/version = world.TgsVersion()
- msg += "TGS version: [version.raw_parameter]"
+ msg += span_bold("TGS version:") + " [version.raw_parameter]"
var/datum/tgs_version/api_version = world.TgsApiVersion()
- msg += "DMAPI version: [api_version.raw_parameter]"
+ msg += span_bold("DMAPI version:") + " [api_version.raw_parameter]"
if(GLOB.revdata.testmerge.len)
msg += GLOB.revdata.GetTestMergeInfo()
diff --git a/code/datums/helper_datums/stack_end_detector.dm b/code/datums/helper_datums/stack_end_detector.dm
new file mode 100644
index 00000000000..0d621f51b36
--- /dev/null
+++ b/code/datums/helper_datums/stack_end_detector.dm
@@ -0,0 +1,32 @@
+/**
+ Stack End Detector.
+ Can detect if a given code stack has exited, used by the mc for stack overflow detection.
+
+ **/
+/datum/stack_end_detector
+ var/datum/weakref/_WF
+ var/datum/stack_canary/_canary
+
+/datum/stack_end_detector/New()
+ _canary = new()
+ _WF = WEAKREF(_canary)
+
+/** Prime the stack overflow detector.
+ Store the return value of this proc call in a proc level var.
+ Can only be called once.
+**/
+/datum/stack_end_detector/proc/prime_canary()
+ if (!_canary)
+ CRASH("Prime_canary called twice")
+ . = _canary
+ _canary = null
+
+/// Returns true if the stack is still going. Calling before the canary has been primed also returns true
+/datum/stack_end_detector/proc/check()
+ return !!_WF.resolve()
+
+/// Stack canary. Will go away if the stack it was primed by is ended by byond for return or stack overflow reasons.
+/datum/stack_canary
+
+/// empty proc to avoid warnings about unused variables. Call this proc on your canary in the stack it's watching.
+/datum/stack_canary/proc/use_variable()
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index f79ad0f7286..07f4301ca2b 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -1,8 +1,8 @@
-var/bluespace_item_types = newlist(/obj/item/weapon/storage/backpack/holding,
-/obj/item/weapon/storage/bag/trash/holding,
-/obj/item/weapon/storage/pouch/holding,
-/obj/item/weapon/storage/belt/utility/holding,
-/obj/item/weapon/storage/belt/medical/holding
+var/bluespace_item_types = newlist(/obj/item/storage/backpack/holding,
+/obj/item/storage/bag/trash/holding,
+/obj/item/storage/pouch/holding,
+/obj/item/storage/belt/utility/holding,
+/obj/item/storage/belt/medical/holding
)
//wrapper
@@ -179,29 +179,29 @@ var/bluespace_item_types = newlist(/obj/item/weapon/storage/backpack/holding,
precision = max(rand(1,100)*bluespace_things.len,100)
if(istype(teleatom, /mob/living))
var/mob/living/MM = teleatom
- to_chat(MM, "The Bluespace interface on your [teleatom] interferes with the teleport!")
+ to_chat(MM, span_danger("The Bluespace interface on your [teleatom] interferes with the teleport!"))
return 1
/datum/teleport/instant/science/teleportChecks()
- if(istype(teleatom, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks get teleported --NeoFite
- teleatom.visible_message("\The [teleatom] bounces off of the portal!")
+ if(istype(teleatom, /obj/item/disk/nuclear)) // Don't let nuke disks get teleported --NeoFite
+ teleatom.visible_message(span_danger("\The [teleatom] bounces off of the portal!"))
return 0
- if(!isemptylist(teleatom.search_contents_for(/obj/item/weapon/disk/nuclear)))
+ if(!isemptylist(teleatom.search_contents_for(/obj/item/disk/nuclear)))
if(istype(teleatom, /mob/living))
var/mob/living/MM = teleatom
- MM.visible_message("\The [MM] bounces off of the portal!","Something you are carrying seems to be unable to pass through the portal. Better drop it if you want to go through.")
+ MM.visible_message(span_danger("\The [MM] bounces off of the portal!"),span_warning("Something you are carrying seems to be unable to pass through the portal. Better drop it if you want to go through."))
else
- teleatom.visible_message("\The [teleatom] bounces off of the portal!")
+ teleatom.visible_message(span_danger("\The [teleatom] bounces off of the portal!"))
return 0
/* VOREStation Removal
if(destination.z in using_map.admin_levels) //CentCom z-level
if(istype(teleatom, /obj/mecha))
var/obj/mecha/MM = teleatom
- to_chat(MM.occupant, "\The [MM] would not survive the jump to a location so far away!")
+ to_chat(MM.occupant, span_danger("\The [MM] would not survive the jump to a location so far away!"))
return 0
- if(!isemptylist(teleatom.search_contents_for(/obj/item/weapon/storage/backpack/holding)))
- teleatom.visible_message("\The [teleatom] bounces off of the portal!")
+ if(!isemptylist(teleatom.search_contents_for(/obj/item/storage/backpack/holding)))
+ teleatom.visible_message(span_danger("\The [teleatom] bounces off of the portal!"))
return 0
*/ //VOREStation Removal End
//VOREStation Edit Start
@@ -209,7 +209,7 @@ var/bluespace_item_types = newlist(/obj/item/weapon/storage/backpack/holding,
var/turf/dest_turf = get_turf(destination)
if(local && !(dest_turf.z in using_map.player_levels))
if(istype(teleatom, /mob/living))
- to_chat(teleatom, "The portal refuses to carry you that far away!")
+ to_chat(teleatom, span_warning("The portal refuses to carry you that far away!"))
return 0
else if(istype(destination.loc, /obj/belly))
var/obj/belly/destination_belly = destination.loc
@@ -226,9 +226,9 @@ var/bluespace_item_types = newlist(/obj/item/weapon/storage/backpack/holding,
obstructed = 1
else if(!((isturf(destination) && !destination.density) || (isturf(destination.loc) && !destination.loc.density)) || !destination.x || !destination.y || !destination.z) //If we're inside something or outside universe
obstructed = 1
- to_chat(teleatom, "Something is blocking way on the other side!")
+ to_chat(teleatom, span_warning("Something is blocking way on the other side!"))
if(obstructed)
return 0
else
return 1
- //VOREStation Edit End
\ No newline at end of file
+ //VOREStation Edit End
diff --git a/code/datums/json_savefile.dm b/code/datums/json_savefile.dm
new file mode 100644
index 00000000000..f93c885687f
--- /dev/null
+++ b/code/datums/json_savefile.dm
@@ -0,0 +1,116 @@
+/**
+ * A savefile implementation that handles all data using json.
+ * Also saves it using JSON too, fancy.
+ * If you pass in a null path, it simply acts as a memory tree instead, and cannot be saved.
+ */
+/datum/json_savefile
+ var/path = ""
+ VAR_PRIVATE/list/tree
+ /// If this is set to true, calling set_entry or remove_entry will automatically call save(), this does not catch modifying a sub-tree, nor do I know how to do that
+ var/auto_save = FALSE
+ /// Cooldown that tracks the time between attempts to download the savefile.
+ COOLDOWN_DECLARE(download_cooldown)
+
+GENERAL_PROTECT_DATUM(/datum/json_savefile)
+
+/datum/json_savefile/New(path)
+ src.path = path
+ tree = list()
+ if(path && fexists(path))
+ load()
+
+/**
+ * Gets an entry from the json tree, with an optional default value.
+ * If no key is specified it throws the entire tree at you instead
+ */
+/datum/json_savefile/proc/get_entry(key, default_value)
+ if(!key)
+ return tree
+ return (key in tree) ? tree[key] : default_value
+
+/// Sets an entry in the tree to the given value
+/datum/json_savefile/proc/set_entry(key, value)
+ tree[key] = value
+ if(auto_save)
+ save()
+
+/// Removes the given key from the tree
+/datum/json_savefile/proc/remove_entry(key)
+ if(key)
+ tree -= key
+ if(auto_save)
+ save()
+
+/// Wipes the entire tree
+/datum/json_savefile/proc/wipe()
+ tree?.Cut()
+
+/datum/json_savefile/proc/load()
+ if(!path || !fexists(path))
+ return FALSE
+ try
+ tree = json_decode(rustg_file_read(path))
+ return TRUE
+ catch(var/exception/err)
+ stack_trace("failed to load json savefile at '[path]': [err]")
+ return FALSE
+
+/datum/json_savefile/proc/save()
+ if(path)
+ rustg_file_write(json_encode(tree, JSON_PRETTY_PRINT), path)
+
+/// Traverses the entire dir tree of the given savefile and dynamically assembles the tree from it
+/datum/json_savefile/proc/import_byond_savefile(savefile/savefile)
+ tree.Cut()
+ var/list/dirs_to_go = list("/" = tree)
+ while(length(dirs_to_go))
+ var/dir = dirs_to_go[1]
+ var/list/region = dirs_to_go[dir]
+ dirs_to_go.Cut(1, 2)
+ savefile.cd = dir
+ for(var/entry in savefile.dir)
+ var/entry_value
+ savefile.cd = "[dir]/[entry]"
+ //eof refers to the path you are cd'ed into, not the savefile as a whole. being false right after cding into an entry means this entry has no buffer, which only happens with nested save file directories
+ if (savefile.eof)
+ region[entry] = list()
+ dirs_to_go["[dir]/[entry]"] = region[entry]
+ continue
+ READ_FILE(savefile, entry_value) //we are cd'ed to the entry, so we don't need to specify a path to read from
+ region[entry] = entry_value
+
+/// Proc that handles generating a JSON file (prettified if 515 and over!) of a user's preferences and showing it to them.
+/// Requester is passed in to the ftp() and tgui_alert() procs, and account_name is just used to generate the filename.
+/// We don't _need_ to pass in account_name since this is reliant on the json_savefile datum already knowing what we correspond to, but it's here to help people keep track of their stuff.
+/datum/json_savefile/proc/export_json_to_client(mob/requester, account_name)
+ if(!istype(requester) || !path)
+ return
+
+ if(!json_export_checks(requester))
+ return
+
+ // COOLDOWN_START(src, download_cooldown, (CONFIG_GET(number/seconds_cooldown_for_preferences_export) * (1 SECONDS)))
+ COOLDOWN_START(src, download_cooldown, (10 SECONDS))
+ var/file_name = "[account_name ? "[account_name]_" : ""]preferences_[time2text(world.timeofday, "MMM_DD_YYYY_hh-mm-ss")].json"
+ var/temporary_file_storage = "data/preferences_export_working_directory/[file_name]"
+
+ if(!text2file(json_encode(tree, JSON_PRETTY_PRINT), temporary_file_storage))
+ tgui_alert(requester, "Failed to export preferences to JSON! You might need to try again later.", "Export Preferences JSON")
+ return
+
+ var/exportable_json = file(temporary_file_storage)
+
+ DIRECT_OUTPUT(requester, ftp(exportable_json, file_name))
+ fdel(temporary_file_storage)
+
+/// Proc that just handles all of the checks for exporting a preferences file, returns TRUE if all checks are passed, FALSE otherwise.
+/// Just done like this to make the code in the export_json_to_client() proc a bit cleaner.
+/datum/json_savefile/proc/json_export_checks(mob/requester)
+ if(!COOLDOWN_FINISHED(src, download_cooldown))
+ tgui_alert(requester, "You must wait [DisplayTimeText(COOLDOWN_TIMELEFT(src, download_cooldown))] before exporting your preferences again!", "Export Preferences JSON")
+ return FALSE
+
+ if(tgui_alert(requester, "Are you sure you want to export your preferences as a JSON file? This will save to a file on your computer.", "Export Preferences JSON", list("Cancel", "Yes")) == "Yes")
+ return TRUE
+
+ return FALSE
diff --git a/code/datums/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm
index 078db317d5e..d842dd83360 100644
--- a/code/datums/looping_sounds/_looping_sound.dm
+++ b/code/datums/looping_sounds/_looping_sound.dm
@@ -100,7 +100,7 @@
if(direct)
if(ismob(thing))
var/mob/M = thing
- if(pref_check && !M.is_preference_enabled(pref_check))
+ if(!M.check_sound_preference(pref_check))
continue
SEND_SOUND(thing, S)
else
diff --git a/code/datums/looping_sounds/machinery_sounds.dm b/code/datums/looping_sounds/machinery_sounds.dm
index 8005d950163..3c0c8c15d2d 100644
--- a/code/datums/looping_sounds/machinery_sounds.dm
+++ b/code/datums/looping_sounds/machinery_sounds.dm
@@ -13,7 +13,7 @@
mid_length = 60
volume = 40
extra_range = 10
- pref_check = /datum/client_preference/supermatter_hum
+ pref_check = /datum/preference/toggle/supermatter_hum
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -104,7 +104,7 @@
mid_length = 70
end_sound = 'sound/machines/air_pump/airpumpshutdown.ogg'
volume = 15
- pref_check = /datum/client_preference/air_pump_noise
+ pref_check = /datum/preference/toggle/air_pump_noise
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/code/datums/looping_sounds/weather_sounds.dm b/code/datums/looping_sounds/weather_sounds.dm
index db8396f3a31..41210df1053 100644
--- a/code/datums/looping_sounds/weather_sounds.dm
+++ b/code/datums/looping_sounds/weather_sounds.dm
@@ -1,5 +1,5 @@
/datum/looping_sound/weather
- pref_check = /datum/client_preference/weather_sounds
+ pref_check = /datum/preference/toggle/weather_sounds
/datum/looping_sound/weather/outside_blizzard
mid_sounds = list(
@@ -95,4 +95,4 @@
volume = 20 //Sound is already quieter in file
/datum/looping_sound/weather/rain/indoors/heavy
- volume = 40
\ No newline at end of file
+ volume = 40
diff --git a/code/datums/managed_browsers/feedback_form.dm b/code/datums/managed_browsers/feedback_form.dm
index cd7b3a8b207..15bf63f535e 100644
--- a/code/datums/managed_browsers/feedback_form.dm
+++ b/code/datums/managed_browsers/feedback_form.dm
@@ -19,7 +19,7 @@ GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form)
var/feedback_hide_author = FALSE
/datum/managed_browser/feedback_form/New(client/new_client)
- feedback_topic = config.sqlite_feedback_topics[1]
+ feedback_topic = CONFIG_GET(str_list/sqlite_feedback_topics)[1]
..(new_client)
/datum/managed_browser/feedback_form/Destroy()
@@ -29,7 +29,7 @@ GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form)
// Privacy option is allowed if both the config allows it, and the pepper file exists and isn't blank.
/datum/managed_browser/feedback_form/proc/can_be_private()
- return config.sqlite_feedback_privacy && SSsqlite.get_feedback_pepper()
+ return CONFIG_GET(flag/sqlite_feedback_privacy) && SSsqlite.get_feedback_pepper()
/datum/managed_browser/feedback_form/display()
if(!my_client)
@@ -58,34 +58,35 @@ GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form)
if(can_be_private())
if(!feedback_hide_author)
dat += "[my_client.ckey] "
- dat += span("linkOn", "Visible")
+ dat += span_linkOn(span_bold("Visible"))
dat += " | "
dat += href(src, list("feedback_hide_author" = 1), "Hashed")
else
dat += "[md5(ckey(lowertext(my_client.ckey + SSsqlite.get_feedback_pepper())))] "
dat += href(src, list("feedback_hide_author" = 0), "Visible")
dat += " | "
- dat += span("linkOn", "Hashed")
+ dat += span_linkOn(span_bold("Hashed"))
else
dat += my_client.ckey
dat += "
"
- if(config.sqlite_feedback_topics.len > 1)
+ var/list/sqlite_feedback_topics = CONFIG_GET(str_list/sqlite_feedback_topics)
+ if(sqlite_feedback_topics.len > 1)
dat += "Topic: [href(src, list("feedback_choose_topic" = 1), feedback_topic)]
"
else
- dat += "Topic: [config.sqlite_feedback_topics[1]]
"
+ dat += "Topic: [sqlite_feedback_topics[1]]
"
dat += "
"
if(feedback_body)
dat += replacetext(feedback_body, "\n", "
") // So newlines will look like they work in the preview.
else
- dat += "\[Feedback goes here...\]"
+ dat += span_italics("\[Feedback goes here...\]")
dat += "
"
dat += href(src, list("feedback_edit_body" = 1), "Edit")
dat += "
"
- if(config.sqlite_feedback_cooldown)
- dat += "Please note that you will have to wait [config.sqlite_feedback_cooldown] day\s before \
+ if(CONFIG_GET(number/sqlite_feedback_cooldown))
+ dat += "Please note that you will have to wait [CONFIG_GET(number/sqlite_feedback_cooldown)] day\s before \
being able to write more feedback after submitting.
"
dat += href(src, list("feedback_submit" = 1), "Submit")
@@ -112,7 +113,7 @@ GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form)
return
if(href_list["feedback_choose_topic"])
- feedback_topic = tgui_input_list(my_client, "Choose the topic you want to submit your feedback under.", "Feedback Topic", config.sqlite_feedback_topics)
+ feedback_topic = tgui_input_list(my_client, "Choose the topic you want to submit your feedback under.", "Feedback Topic", CONFIG_GET(str_list/sqlite_feedback_topics))
display()
return
@@ -120,13 +121,13 @@ GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form)
// Do some last minute validation, and tell the user if something goes wrong,
// so we don't wipe out their ten thousand page essay due to having a few too many characters.
if(length(feedback_body) > MAX_FEEDBACK_LENGTH)
- to_chat(my_client, span("warning", "Your feedback is too long, at [length(feedback_body)] characters, where as the \
+ to_chat(my_client, span_warning("Your feedback is too long, at [length(feedback_body)] characters, where as the \
limit is [MAX_FEEDBACK_LENGTH]. Please shorten it and try again."))
return
var/text = sanitize(feedback_body, max_length = 0, encode = TRUE, trim = FALSE, extra = FALSE)
if(!text) // No text, or it was super invalid.
- to_chat(my_client, span("warning", "It appears you didn't write anything, or it was invalid."))
+ to_chat(my_client, span_warning("It appears you didn't write anything, or it was invalid."))
return
if(tgui_alert(my_client, "Are you sure you want to submit your feedback?", "Confirm Submission", list("No", "Yes")) == "Yes")
@@ -136,7 +137,7 @@ GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form)
var/success = SSsqlite.insert_feedback(author = author_text, topic = feedback_topic, content = feedback_body, sqlite_object = SSsqlite.sqlite_db)
if(!success)
- to_chat(my_client, span("warning", "Something went wrong while inserting your feedback into the database. Please try again. \
+ to_chat(my_client, span_warning("Something went wrong while inserting your feedback into the database. Please try again. \
If this happens again, you should contact a developer."))
return
@@ -144,4 +145,4 @@ GENERAL_PROTECT_DATUM(/datum/managed_browser/feedback_form)
if(istype(my_client.mob, /mob/new_player))
var/mob/new_player/NP = my_client.mob
NP.new_player_panel_proc() // So the feedback button goes away, if the user gets put on cooldown.
- qdel(src)
\ No newline at end of file
+ qdel(src)
diff --git a/code/datums/managed_browsers/feedback_viewer.dm b/code/datums/managed_browsers/feedback_viewer.dm
index 59fbc679c4e..eca1fff099f 100644
--- a/code/datums/managed_browsers/feedback_viewer.dm
+++ b/code/datums/managed_browsers/feedback_viewer.dm
@@ -2,7 +2,7 @@
var/datum/managed_browser/feedback_viewer/feedback_viewer = null
/datum/admins/proc/view_feedback()
- set category = "Admin"
+ set category = "Admin.Misc"
set name = "View Feedback"
set desc = "Open the Feedback Viewer"
@@ -143,7 +143,7 @@
if(href_list["filter_topic"])
var/topic_to_search = tgui_input_text(my_client, "Write desired topic here. Partial topics are allowed. \
- \nThe current topics in the config are [english_list(config.sqlite_feedback_topics)].", "Filter by Topic", null)
+ \nThe current topics in the config are [english_list(CONFIG_GET(str_list/sqlite_feedback_topics))].", "Filter by Topic", null)
if(topic_to_search)
last_query = feedback_filter(SQLITE_FEEDBACK_COLUMN_TOPIC, topic_to_search)
@@ -159,4 +159,4 @@
last_query = feedback_filter(SQLITE_FEEDBACK_COLUMN_DATETIME, datetime_to_search)
// Refresh.
- display()
\ No newline at end of file
+ display()
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 777ecc42369..17b39256456 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -88,7 +88,7 @@
if(current) //remove ourself from our old body's mind variable
if(changeling)
current.remove_changeling_powers()
- current.verbs -= /datum/changeling/proc/EvolutionMenu
+ remove_verb(current, /datum/changeling/proc/EvolutionMenu)
current.mind = null
if(new_character.mind) //remove any mind currently in our new body's mind variable
@@ -103,11 +103,15 @@
if(active)
new_character.key = key //now transfer the key to link the client to our new body
+ if(new_character.client)
+ new_character.client.init_verbs() // re-initialize character specific verbs
+ new_character.set_listed_turf(null)
+
/datum/mind/proc/store_memory(new_text)
memory += "[new_text]
"
/datum/mind/proc/show_memory(mob/recipient)
- var/output = "[current.real_name]'s Memory
"
+ var/output = span_bold("[current.real_name]'s Memory") + "
"
output += memory
if(objectives.len>0)
@@ -115,7 +119,7 @@
var/obj_count = 1
for(var/datum/objective/objective in objectives)
- output += "Objective #[obj_count]: [objective.explanation_text]"
+ output += span_bold("Objective #[obj_count]") + ": [objective.explanation_text]"
obj_count++
if(ambitions)
@@ -127,7 +131,7 @@
tgui_alert_async(usr, "Not before round-start!", "Alert")
return
- var/out = "[name][(current&&(current.real_name!=name))?" (as [current.real_name])":""]
"
+ var/out = span_bold("[name]") + "[(current&&(current.real_name!=name))?" (as [current.real_name])":""]
"
out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]
"
out += "Assigned role: [assigned_role]. Edit
"
out += "
"
@@ -136,12 +140,12 @@
var/datum/antagonist/antag = all_antag_types[antag_type]
out += "[antag.get_panel_entry(src)]"
out += "
"
- out += "Objectives"
+ out += span_bold("Objectives") + ""
if(objectives && objectives.len)
var/num = 1
for(var/datum/objective/O in objectives)
- out += "Objective #[num]: [O.explanation_text] "
+ out += span_bold("Objective #[num]:") + " [O.explanation_text] "
if(O.completed)
out += "([span_green("complete")])"
else
@@ -154,7 +158,7 @@
else
out += "None."
out += "
\[add\]
"
- out += "Ambitions: [ambitions ? ambitions : "None"] \[edit\]"
+ out += span_bold("Ambitions:") + " [ambitions ? ambitions : "None"] \[edit\]"
usr << browse(out, "window=edit_memory[src]")
/datum/mind/Topic(href, href_list)
@@ -166,7 +170,7 @@
if(antag.add_antagonist(src, 1, 1, 0, 1, 1)) // Ignore equipment and role type for this.
log_admin("[key_name_admin(usr)] made [key_name(src)] into a [antag.role_text].")
else
- to_chat(usr, "[src] could not be made into a [antag.role_text]!")
+ to_chat(usr, span_warning("[src] could not be made into a [antag.role_text]!"))
else if(href_list["remove_antagonist"])
var/datum/antagonist/antag = all_antag_types[href_list["remove_antagonist"]]
@@ -203,7 +207,7 @@
return
if(mind)
mind.ambitions = sanitize(new_ambition)
- to_chat(mind.current, "Your ambitions have been changed by higher powers, they are now: [mind.ambitions]")
+ to_chat(mind.current, span_warning("Your ambitions have been changed by higher powers, they are now: [mind.ambitions]"))
log_and_message_admins("made [key_name(mind.current)]'s ambitions be '[mind.ambitions]'.")
else if (href_list["obj_edit"] || href_list["obj_add"])
@@ -348,15 +352,15 @@
switch(href_list["implant"])
if("remove")
- for(var/obj/item/weapon/implant/loyalty/I in H.contents)
+ for(var/obj/item/implant/loyalty/I in H.contents)
for(var/obj/item/organ/external/organs in H.organs)
if(I in organs.implants)
qdel(I)
break
- to_chat(H, "Your loyalty implant has been deactivated.")
+ to_chat(H, span_notice("Your loyalty implant has been deactivated."))
log_admin("[key_name_admin(usr)] has de-loyalty implanted [current].")
if("add")
- to_chat(H, "You somehow have become the recepient of a loyalty transplant, and it just activated!")
+ to_chat(H, span_danger("You somehow have become the recepient of a loyalty transplant, and it just activated!"))
H.implant_loyalty(override = TRUE)
log_admin("[key_name_admin(usr)] has loyalty implanted [current].")
else
@@ -410,7 +414,7 @@
memory = null//Remove any memory they may have had.
if("crystals")
if (usr.client.holder.rights & R_FUN)
- // var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink() No longer needed, uses stored in mind
+ // var/obj/item/uplink/hidden/suplink = find_syndicate_uplink() No longer needed, uses stored in mind
var/crystals
crystals = tcrystals
crystals = tgui_input_number(usr, "Amount of telecrystals for [key]", crystals)
@@ -421,7 +425,7 @@
var/obj_count = 1
to_chat(current, span_blue("Your current objectives:"))
for(var/datum/objective/objective in objectives)
- to_chat(current, "Objective #[obj_count]: [objective.explanation_text]")
+ to_chat(current, span_bold("Objective #[obj_count]") + ": [objective.explanation_text]")
obj_count++
edit_memory()
@@ -433,7 +437,7 @@
return null
/datum/mind/proc/take_uplink()
- var/obj/item/device/uplink/hidden/H = find_syndicate_uplink()
+ var/obj/item/uplink/hidden/H = find_syndicate_uplink()
if(H)
qdel(H)
@@ -448,10 +452,10 @@
var/is_currently_brigged = 0
if(istype(T.loc,/area/security/brig))
is_currently_brigged = 1
- for(var/obj/item/weapon/card/id/card in current)
+ for(var/obj/item/card/id/card in current)
is_currently_brigged = 0
break // if they still have ID they're not brigged
- for(var/obj/item/device/pda/P in current)
+ for(var/obj/item/pda/P in current)
if(P.id)
is_currently_brigged = 0
break // if they still have ID they're not brigged
@@ -516,64 +520,64 @@
if(!mind.name) mind.name = real_name
mind.current = src
if(player_is_antag(mind))
- src.client.verbs += /client/proc/aooc
+ add_verb(src.client, /client/proc/aooc)
//HUMAN
/mob/living/carbon/human/mind_initialize()
. = ..()
if(!mind.assigned_role)
- mind.assigned_role = USELESS_JOB //defualt //VOREStation Edit - Visitor not Assistant
+ mind.assigned_role = JOB_ALT_VISITOR //defualt //VOREStation Edit - Visitor not Assistant
//slime
/mob/living/simple_mob/slime/mind_initialize()
. = ..()
- mind.assigned_role = "slime"
+ mind.assigned_role = JOB_SLIME
/mob/living/carbon/alien/larva/mind_initialize()
. = ..()
- mind.special_role = "Larva"
+ mind.special_role = JOB_LARVA
//AI
/mob/living/silicon/ai/mind_initialize()
. = ..()
- mind.assigned_role = "AI"
+ mind.assigned_role = JOB_AI
//BORG
/mob/living/silicon/robot/mind_initialize()
. = ..()
- mind.assigned_role = "Cyborg"
+ mind.assigned_role = JOB_CYBORG
//PAI
/mob/living/silicon/pai/mind_initialize()
. = ..()
- mind.assigned_role = "pAI"
+ mind.assigned_role = JOB_PAI
mind.special_role = ""
//Animals
/mob/living/simple_mob/mind_initialize()
. = ..()
- mind.assigned_role = "Simple Mob"
+ mind.assigned_role = JOB_SIMPLE_MOB
/mob/living/simple_mob/animal/passive/dog/corgi/mind_initialize()
. = ..()
- mind.assigned_role = "Corgi"
+ mind.assigned_role = JOB_CORGI
/mob/living/simple_mob/construct/shade/mind_initialize()
. = ..()
- mind.assigned_role = "Shade"
- mind.special_role = "Cultist"
+ mind.assigned_role = JOB_SHADE
+ mind.special_role = JOB_CULTIST
/mob/living/simple_mob/construct/artificer/mind_initialize()
. = ..()
- mind.assigned_role = "Artificer"
- mind.special_role = "Cultist"
+ mind.assigned_role = JOB_ARTIFICER
+ mind.special_role = JOB_CULTIST
/mob/living/simple_mob/construct/wraith/mind_initialize()
. = ..()
- mind.assigned_role = "Wraith"
- mind.special_role = "Cultist"
+ mind.assigned_role = JOB_WRAITH
+ mind.special_role = JOB_CULTIST
/mob/living/simple_mob/construct/juggernaut/mind_initialize()
. = ..()
- mind.assigned_role = "Juggernaut"
- mind.special_role = "Cultist"
+ mind.assigned_role = JOB_JUGGERNAUT
+ mind.special_role = JOB_CULTIST
diff --git a/code/datums/observation/stat_set.dm b/code/datums/observation/stat_set.dm
index c818a505320..08db60a3801 100644
--- a/code/datums/observation/stat_set.dm
+++ b/code/datums/observation/stat_set.dm
@@ -30,6 +30,6 @@ stat_set_event, /decl/observ/stat_set, new)
if(!ourbelly.owner.client)
return
if(stat == CONSCIOUS)
- to_chat(ourbelly.owner, "\The [src.name] is awake.")
+ to_chat(ourbelly.owner, span_notice("\The [src.name] is awake."))
else if(stat == UNCONSCIOUS)
- to_chat(ourbelly.owner, "\The [src.name] has fallen unconscious!")
+ to_chat(ourbelly.owner, span_red("\The [src.name] has fallen unconscious!"))
diff --git a/code/datums/observation/unequipped.dm b/code/datums/observation/unequipped.dm
index 353332de022..5b0dd0fe839 100644
--- a/code/datums/observation/unequipped.dm
+++ b/code/datums/observation/unequipped.dm
@@ -35,7 +35,7 @@ GLOBAL_DATUM_INIT(item_unequipped_event, /decl/observ/item_unequipped, new)
**********************/
/obj/item/dropped(var/mob/user)
- ..()
+ . = ..(user)
//SEND_SIGNAL(user, COMSIG_OBSERVER_MOB_UNEQUIPPED, src)
//SEND_SIGNAL(src, COMSIG_OBSERVER_ITEM_UNEQUIPPED, user)
if(user) // Cannot always guarantee that user won't be null
diff --git a/code/datums/outfits/costumes/halloween.dm b/code/datums/outfits/costumes/halloween.dm
index 35f4aa238d5..04eff3fc058 100644
--- a/code/datums/outfits/costumes/halloween.dm
+++ b/code/datums/outfits/costumes/halloween.dm
@@ -6,7 +6,7 @@
mask = /obj/item/clothing/mask/surgical
head = /obj/item/clothing/head/welding
suit = /obj/item/clothing/suit/storage/apron
- r_hand = /obj/item/weapon/material/twohanded/fireaxe/foam
+ r_hand = /obj/item/material/twohanded/fireaxe/foam
/decl/hierarchy/outfit/costume/masked_killer/post_equip(var/mob/living/carbon/human/H)
var/victim = get_mannequin(H.ckey)
@@ -22,10 +22,10 @@
l_pocket = /obj/item/toy/sword
/decl/hierarchy/outfit/costume/professional/post_equip(var/mob/living/carbon/human/H)
- var/obj/item/weapon/storage/briefcase/new_briefcase = new(H)
+ var/obj/item/storage/briefcase/new_briefcase = new(H)
for(var/obj/item/briefcase_item in new_briefcase)
qdel(briefcase_item)
- new_briefcase.contents += new /obj/item/weapon/gun/projectile/pistol/toy
+ new_briefcase.contents += new /obj/item/gun/projectile/pistol/toy
new_briefcase.contents += new /obj/item/ammo_magazine/mfoam_dart/pistol
new_briefcase.contents += new /obj/item/clothing/mask/gas/clown_hat
H.equip_to_slot_or_del(new_briefcase, slot_l_hand)
@@ -38,7 +38,7 @@
glasses = /obj/item/clothing/glasses/fakesunglasses
mask = /obj/item/clothing/mask/fakemoustache
head = /obj/item/clothing/head/beret
- r_hand = /obj/item/weapon/gun/projectile/revolver/capgun
+ r_hand = /obj/item/gun/projectile/revolver/capgun
/decl/hierarchy/outfit/costume/horrorcop/post_equip(var/mob/living/carbon/human/H)
var/obj/item/clothing/under/U = H.w_uniform
@@ -55,7 +55,7 @@
head = /obj/item/clothing/head/cowboy
gloves = /obj/item/clothing/gloves/fingerless
suit = /obj/item/clothing/accessory/poncho
- r_hand = /obj/item/weapon/gun/projectile/revolver/capgun
+ r_hand = /obj/item/gun/projectile/revolver/capgun
/decl/hierarchy/outfit/costume/cowboy/post_equip(var/mob/living/carbon/human/H)
var/obj/item/clothing/under/U = H.w_uniform
@@ -72,7 +72,7 @@
head = /obj/item/clothing/head/beanie
gloves = /obj/item/clothing/gloves/fingerless
suit = /obj/item/clothing/suit/storage/flannel/red
- r_hand = /obj/item/weapon/material/twohanded/fireaxe/foam
+ r_hand = /obj/item/material/twohanded/fireaxe/foam
/decl/hierarchy/outfit/costume/firefighter
name = OUTFIT_COSTUME("Firefighter")
@@ -87,14 +87,14 @@
uniform = /obj/item/clothing/under/kilt
shoes = /obj/item/clothing/shoes/boots/jackboots
head = /obj/item/clothing/head/beret
- r_hand = /obj/item/weapon/material/sword/foam
+ r_hand = /obj/item/material/sword/foam
/decl/hierarchy/outfit/costume/vampire
name = OUTFIT_COSTUME("Vampire")
uniform = /obj/item/clothing/under/suit_jacket/really_black
shoes = /obj/item/clothing/shoes/dress
gloves = /obj/item/clothing/gloves/white
- r_hand = /obj/item/weapon/bedsheet/red
+ r_hand = /obj/item/bedsheet/red
/decl/hierarchy/outfit/costume/vampire_hunter
name = OUTFIT_COSTUME("Vampire Hunter")
@@ -102,8 +102,8 @@
suit = /obj/item/clothing/suit/storage/toggle/brown_jacket/sleeveless
shoes = /obj/item/clothing/shoes/boots/jackboots
gloves = /obj/item/clothing/gloves/fingerless
- l_pocket = /obj/item/weapon/gun/projectile/revolver/toy/crossbow/halloween
- r_pocket = /obj/item/device/flashlight/color/red
+ l_pocket = /obj/item/gun/projectile/revolver/toy/crossbow/halloween
+ r_pocket = /obj/item/flashlight/color/red
/decl/hierarchy/outfit/costume/pirate
name = OUTFIT_COSTUME("Pirate")
@@ -127,4 +127,4 @@
shoes = /obj/item/clothing/shoes/brown
head = /obj/item/clothing/head/marine
suit = /obj/item/clothing/suit/marine
- r_hand = /obj/item/weapon/gun/projectile/revolver/toy/sawnoff
\ No newline at end of file
+ r_hand = /obj/item/gun/projectile/revolver/toy/sawnoff
\ No newline at end of file
diff --git a/code/datums/outfits/horror_killers.dm b/code/datums/outfits/horror_killers.dm
index 59507d4f347..6f38c18df0e 100644
--- a/code/datums/outfits/horror_killers.dm
+++ b/code/datums/outfits/horror_killers.dm
@@ -5,16 +5,19 @@
gloves = /obj/item/clothing/gloves/black
mask = /obj/item/clothing/mask/gas/clown_hat
head = /obj/item/clothing/head/chaplain_hood
- l_ear = /obj/item/device/radio/headset
glasses = /obj/item/clothing/glasses/thermal/plain/monocle
suit = /obj/item/clothing/suit/storage/hooded/chaplain_hoodie
- r_pocket = /obj/item/weapon/bikehorn
- r_hand = /obj/item/weapon/material/twohanded/fireaxe
+ r_pocket = /obj/item/bikehorn
+ r_hand = /obj/item/material/twohanded/fireaxe
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/syndicate/station_access
+ id_type = /obj/item/card/id/syndicate/station_access
id_pda_assignment = "Tunnel Clown!"
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset/alt
+ headset_earbud = /obj/item/radio/headset/earbud
+
/decl/hierarchy/outfit/masked_killer
name = "Masked Killer"
uniform = /obj/item/clothing/under/overalls
@@ -22,12 +25,15 @@
gloves = /obj/item/clothing/gloves/sterile/latex
mask = /obj/item/clothing/mask/surgical
head = /obj/item/clothing/head/welding
- l_ear = /obj/item/device/radio/headset
glasses = /obj/item/clothing/glasses/thermal/plain/monocle
suit = /obj/item/clothing/suit/storage/apron
- l_pocket = /obj/item/weapon/material/knife/tacknife
- r_pocket = /obj/item/weapon/surgical/scalpel
- r_hand = /obj/item/weapon/material/twohanded/fireaxe
+ l_pocket = /obj/item/material/knife/tacknife
+ r_pocket = /obj/item/surgical/scalpel
+ r_hand = /obj/item/material/twohanded/fireaxe
+
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset/alt
+ headset_earbud = /obj/item/radio/headset/earbud
/decl/hierarchy/outfit/masked_killer/post_equip(var/mob/living/carbon/human/H)
var/victim = get_mannequin(H.ckey)
@@ -39,24 +45,27 @@
uniform = /obj/item/clothing/under/suit_jacket{ starting_accessories=list(/obj/item/clothing/accessory/wcoat) }
shoes = /obj/item/clothing/shoes/black
gloves = /obj/item/clothing/gloves/black
- l_ear = /obj/item/device/radio/headset
glasses = /obj/item/clothing/glasses/sunglasses
- l_pocket = /obj/item/weapon/melee/energy/sword
+ l_pocket = /obj/item/melee/energy/sword
mask = /obj/item/clothing/mask/gas/clown_hat
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/syndicate/station_access
+ id_type = /obj/item/card/id/syndicate/station_access
pda_slot = slot_belt
- pda_type = /obj/item/device/pda/heads
+ pda_type = /obj/item/pda/heads
+
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset/alt
+ headset_earbud = /obj/item/radio/headset/earbud
/decl/hierarchy/outfit/professional/post_equip(var/mob/living/carbon/human/H)
- var/obj/item/weapon/storage/secure/briefcase/sec_briefcase = new(H)
+ var/obj/item/storage/secure/briefcase/sec_briefcase = new(H)
for(var/obj/item/briefcase_item in sec_briefcase)
qdel(briefcase_item)
for(var/i=3, i>0, i--)
- sec_briefcase.contents += new /obj/item/weapon/spacecash/c1000
- sec_briefcase.contents += new /obj/item/weapon/gun/energy/crossbow
- sec_briefcase.contents += new /obj/item/weapon/gun/projectile/revolver/mateba
+ sec_briefcase.contents += new /obj/item/spacecash/c1000
+ sec_briefcase.contents += new /obj/item/gun/energy/crossbow
+ sec_briefcase.contents += new /obj/item/gun/projectile/revolver/mateba
sec_briefcase.contents += new /obj/item/ammo_magazine/s357
- sec_briefcase.contents += new /obj/item/weapon/plastique
+ sec_briefcase.contents += new /obj/item/plastique
H.equip_to_slot_or_del(sec_briefcase, slot_l_hand)
diff --git a/code/datums/outfits/jobs/YW.dm b/code/datums/outfits/jobs/YW.dm
index 3c267ec5a6a..cc00cf7bc94 100644
--- a/code/datums/outfits/jobs/YW.dm
+++ b/code/datums/outfits/jobs/YW.dm
@@ -1,8 +1,8 @@
/decl/hierarchy/outfit/job/blueshield
name = OUTFIT_JOB_NAME("Blueshield Guard")
uniform = /obj/item/clothing/under/yw/blueshield
- l_ear = /obj/item/device/radio/headset/heads/blueshield
+ l_ear = /obj/item/radio/headset/heads/blueshield
shoes = /obj/item/clothing/shoes/laceup
- id_type = /obj/item/weapon/card/id/blueshield
- pda_type = /obj/item/device/pda/captain
- r_hand = /obj/item/weapon/clipboard
+ id_type = /obj/item/card/id/blueshield
+ pda_type = /obj/item/pda/captain
+ r_hand = /obj/item/clipboard
diff --git a/code/datums/outfits/jobs/cargo.dm b/code/datums/outfits/jobs/cargo.dm
index e7b8701a373..bed1308f398 100644
--- a/code/datums/outfits/jobs/cargo.dm
+++ b/code/datums/outfits/jobs/cargo.dm
@@ -1,30 +1,39 @@
/decl/hierarchy/outfit/job/cargo
- l_ear = /obj/item/device/radio/headset/headset_cargo
hierarchy_type = /decl/hierarchy/outfit/job/cargo
+ headset = /obj/item/radio/headset/cargo
+ headset_alt = /obj/item/radio/headset/alt/cargo
+ headset_earbud = /obj/item/radio/headset/earbud/cargo
+
/decl/hierarchy/outfit/job/cargo/qm
name = OUTFIT_JOB_NAME("Cargo")
uniform = /obj/item/clothing/under/rank/cargo
- l_ear = /obj/item/device/radio/headset/headset_qm //VOREStation Add
shoes = /obj/item/clothing/shoes/brown
glasses = /obj/item/clothing/glasses/sunglasses
- l_hand = /obj/item/weapon/clipboard
- id_type = /obj/item/weapon/card/id/cargo/head
- pda_type = /obj/item/device/pda/quartermaster
+ l_hand = /obj/item/clipboard
+ id_type = /obj/item/card/id/cargo/head
+ pda_type = /obj/item/pda/quartermaster
+
+ headset = /obj/item/radio/headset/qm
+ headset_alt = /obj/item/radio/headset/alt/qm
+ headset_earbud = /obj/item/radio/headset/earbud/qm
/decl/hierarchy/outfit/job/cargo/cargo_tech
name = OUTFIT_JOB_NAME("Cargo technician")
uniform = /obj/item/clothing/under/rank/cargotech
- id_type = /obj/item/weapon/card/id/cargo
- pda_type = /obj/item/device/pda/cargo
+ id_type = /obj/item/card/id/cargo
+ pda_type = /obj/item/pda/cargo
/decl/hierarchy/outfit/job/cargo/mining
name = OUTFIT_JOB_NAME("Shaft miner")
uniform = /obj/item/clothing/under/rank/miner
- l_ear = /obj/item/device/radio/headset/headset_mine
- backpack = /obj/item/weapon/storage/backpack/industrial
- satchel_one = /obj/item/weapon/storage/backpack/satchel/eng
- id_type = /obj/item/weapon/card/id/cargo/miner
- pda_type = /obj/item/device/pda/shaftminer
- backpack_contents = list(/obj/item/weapon/tool/crowbar = 1, /obj/item/weapon/storage/bag/ore = 1)
+ backpack = /obj/item/storage/backpack/industrial
+ satchel_one = /obj/item/storage/backpack/satchel/eng
+ id_type = /obj/item/card/id/cargo/miner
+ pda_type = /obj/item/pda/shaftminer
+ backpack_contents = list(/obj/item/tool/crowbar = 1, /obj/item/storage/bag/ore = 1)
flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL
+
+ headset = /obj/item/radio/headset/miner
+ headset_alt = /obj/item/radio/headset/miner
+ headset_earbud = /obj/item/radio/headset/miner
diff --git a/code/datums/outfits/jobs/civilian.dm b/code/datums/outfits/jobs/civilian.dm
index 554666cbca8..829e6f9c649 100644
--- a/code/datums/outfits/jobs/civilian.dm
+++ b/code/datums/outfits/jobs/civilian.dm
@@ -1,32 +1,35 @@
/decl/hierarchy/outfit/job/assistant
- name = OUTFIT_JOB_NAME(USELESS_JOB) //VOREStation Edit - Visitor not Assistant
- id_type = /obj/item/weapon/card/id/generic //VOREStation Edit
+ name = OUTFIT_JOB_NAME(JOB_ALT_VISITOR) //VOREStation Edit - Visitor not Assistant
+ id_type = /obj/item/card/id/generic //VOREStation Edit
/decl/hierarchy/outfit/job/assistant/visitor
- name = OUTFIT_JOB_NAME("Visitor")
- id_pda_assignment = "Visitor"
+ name = OUTFIT_JOB_NAME(JOB_ALT_VISITOR)
+ id_pda_assignment = JOB_ALT_VISITOR
uniform = /obj/item/clothing/under/assistantformal
//VOREStation Add - Interns
/decl/hierarchy/outfit/job/assistant/intern
- name = OUTFIT_JOB_NAME("Intern")
- id_type = /obj/item/weapon/card/id/civilian
+ name = OUTFIT_JOB_NAME(JOB_INTERN)
+ id_type = /obj/item/card/id/civilian
//VOREStation Add End - Interns
/decl/hierarchy/outfit/job/assistant/resident
- name = OUTFIT_JOB_NAME("Resident")
- id_pda_assignment = "Resident"
+ name = OUTFIT_JOB_NAME(JOB_ALT_RESIDENT)
+ id_pda_assignment = JOB_ALT_RESIDENT
uniform = /obj/item/clothing/under/color/white
/decl/hierarchy/outfit/job/service
- l_ear = /obj/item/device/radio/headset/headset_service
hierarchy_type = /decl/hierarchy/outfit/job/service
+ headset = /obj/item/radio/headset/service
+ headset_alt = /obj/item/radio/headset/alt/service
+ headset_earbud = /obj/item/radio/headset/earbud/service
+
/decl/hierarchy/outfit/job/service/bartender
- name = OUTFIT_JOB_NAME("Bartender")
+ name = OUTFIT_JOB_NAME(JOB_BARTENDER)
uniform = /obj/item/clothing/under/rank/bartender
- id_type = /obj/item/weapon/card/id/civilian/service/bartender //VOREStation Edit
- pda_type = /obj/item/device/pda/bar
+ id_type = /obj/item/card/id/civilian/service/bartender //VOREStation Edit
+ pda_type = /obj/item/pda/bar
backpack_contents = list(/obj/item/clothing/accessory/permit/gun/bar = 1)
/decl/hierarchy/outfit/job/service/bartender/post_equip(mob/living/carbon/human/H)
@@ -36,88 +39,94 @@
permit.set_name(H.real_name)
/decl/hierarchy/outfit/job/service/bartender/barista
- name = OUTFIT_JOB_NAME("Barista")
- id_pda_assignment = "Barista"
+ name = OUTFIT_JOB_NAME(JOB_ALT_BARISTA)
+ id_pda_assignment = JOB_ALT_BARISTA
backpack_contents = null
/decl/hierarchy/outfit/job/service/chef
- name = OUTFIT_JOB_NAME("Chef")
+ name = OUTFIT_JOB_NAME(JOB_CHEF)
uniform = /obj/item/clothing/under/rank/chef
suit = /obj/item/clothing/suit/chef
head = /obj/item/clothing/head/chefhat
- id_type = /obj/item/weapon/card/id/civilian/service/chef //VOREStation Edit
- pda_type = /obj/item/device/pda/chef
+ id_type = /obj/item/card/id/civilian/service/chef //VOREStation Edit
+ pda_type = /obj/item/pda/chef
/decl/hierarchy/outfit/job/service/chef/cook
- name = OUTFIT_JOB_NAME("Cook")
- id_pda_assignment = "Cook"
+ name = OUTFIT_JOB_NAME(JOB_ALT_COOK)
+ id_pda_assignment = JOB_ALT_COOK
// Rykka adds Server Outfit
/decl/hierarchy/outfit/job/service/server
- name = OUTFIT_JOB_NAME("Server")
+ name = OUTFIT_JOB_NAME(JOB_ALT_SERVER)
uniform = /obj/item/clothing/under/waiter
// End Outfit addition
/decl/hierarchy/outfit/job/service/gardener
- name = OUTFIT_JOB_NAME("Gardener")
+ name = OUTFIT_JOB_NAME(JOB_ALT_GARDENER)
uniform = /obj/item/clothing/under/rank/hydroponics
suit = /obj/item/clothing/suit/storage/apron
gloves = /obj/item/clothing/gloves/botanic_leather
- r_pocket = /obj/item/device/analyzer/plant_analyzer
- backpack = /obj/item/weapon/storage/backpack/hydroponics
- satchel_one = /obj/item/weapon/storage/backpack/satchel/hyd
- messenger_bag = /obj/item/weapon/storage/backpack/messenger/hyd
- sports_bag = /obj/item/weapon/storage/backpack/sport/hyd
- id_type = /obj/item/weapon/card/id/civilian/service/botanist //VOREStation Edit
- pda_type = /obj/item/device/pda/botanist
+ r_pocket = /obj/item/analyzer/plant_analyzer
+ backpack = /obj/item/storage/backpack/hydroponics
+ satchel_one = /obj/item/storage/backpack/satchel/hyd
+ messenger_bag = /obj/item/storage/backpack/messenger/hyd
+ sports_bag = /obj/item/storage/backpack/sport/hyd
+ id_type = /obj/item/card/id/civilian/service/botanist //VOREStation Edit
+ pda_type = /obj/item/pda/botanist
/decl/hierarchy/outfit/job/service/janitor
- name = OUTFIT_JOB_NAME("Janitor")
+ name = OUTFIT_JOB_NAME(JOB_JANITOR)
uniform = /obj/item/clothing/under/rank/janitor
- id_type = /obj/item/weapon/card/id/civilian/service/janitor //VOREStation Edit
- pda_type = /obj/item/device/pda/janitor
+ id_type = /obj/item/card/id/civilian/service/janitor //VOREStation Edit
+ pda_type = /obj/item/pda/janitor
/decl/hierarchy/outfit/job/librarian
- name = OUTFIT_JOB_NAME("Librarian")
+ name = OUTFIT_JOB_NAME(JOB_LIBRARIAN)
uniform = /obj/item/clothing/under/suit_jacket/red
- l_hand = /obj/item/weapon/barcodescanner
- id_type = /obj/item/weapon/card/id/civilian
- pda_type = /obj/item/device/pda/librarian
+ l_hand = /obj/item/barcodescanner
+ id_type = /obj/item/card/id/civilian
+ pda_type = /obj/item/pda/librarian
/decl/hierarchy/outfit/job/librarian/journalist
- id_type = /obj/item/weapon/card/id/civilian/journalist
+ id_type = /obj/item/card/id/civilian/journalist
/decl/hierarchy/outfit/job/internal_affairs_agent
name = OUTFIT_JOB_NAME("Internal affairs agent")
- l_ear = /obj/item/device/radio/headset/ia
uniform = /obj/item/clothing/under/rank/internalaffairs
suit = /obj/item/clothing/suit/storage/toggle/internalaffairs
shoes = /obj/item/clothing/shoes/brown
glasses = /obj/item/clothing/glasses/sunglasses/big
- l_hand = /obj/item/weapon/clipboard
- id_type = /obj/item/weapon/card/id/civilian/internal_affairs
- pda_type = /obj/item/device/pda/lawyer
+ l_hand = /obj/item/clipboard
+ id_type = /obj/item/card/id/civilian/internal_affairs
+ pda_type = /obj/item/pda/lawyer
+
+ headset = /obj/item/radio/headset/ia
+ headset_alt = /obj/item/radio/headset/alt/ia
+ headset_earbud = /obj/item/radio/headset/earbud/ia
/decl/hierarchy/outfit/job/chaplain
- name = OUTFIT_JOB_NAME("Chaplain")
+ name = OUTFIT_JOB_NAME(JOB_CHAPLAIN)
uniform = /obj/item/clothing/under/rank/chaplain
- l_hand = /obj/item/weapon/storage/bible
- id_type = /obj/item/weapon/card/id/civilian/chaplain
- pda_type = /obj/item/device/pda/chaplain
+ l_hand = /obj/item/storage/bible
+ id_type = /obj/item/card/id/civilian/chaplain
+ pda_type = /obj/item/pda/chaplain
/decl/hierarchy/outfit/job/explorer
- name = OUTFIT_JOB_NAME("Explorer")
+ name = OUTFIT_JOB_NAME(JOB_EXPLORER)
shoes = /obj/item/clothing/shoes/boots/winter/explorer
uniform = /obj/item/clothing/under/explorer
mask = /obj/item/clothing/mask/gas/explorer
suit = /obj/item/clothing/suit/storage/hooded/explorer
gloves = /obj/item/clothing/gloves/black
- l_ear = /obj/item/device/radio/headset
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/exploration //VOREStation Edit
+ id_type = /obj/item/card/id/exploration //VOREStation Edit
pda_slot = slot_belt
- pda_type = /obj/item/device/pda/cargo // Brown looks more rugged
- r_pocket = /obj/item/device/gps/explorer
- id_pda_assignment = "Explorer"
+ pda_type = /obj/item/pda/cargo // Brown looks more rugged
+ r_pocket = /obj/item/gps/explorer
+ id_pda_assignment = JOB_EXPLORER
+
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset/alt
+ headset_earbud = /obj/item/radio/headset/earbud
diff --git a/code/datums/outfits/jobs/civilian_vr.dm b/code/datums/outfits/jobs/civilian_vr.dm
index 74e441e5eef..f25f6ac08ac 100644
--- a/code/datums/outfits/jobs/civilian_vr.dm
+++ b/code/datums/outfits/jobs/civilian_vr.dm
@@ -1,92 +1,92 @@
/decl/hierarchy/outfit/job/assistant/worker
- id_type = /obj/item/weapon/card/id/civilian/service
+ id_type = /obj/item/card/id/civilian/service
/decl/hierarchy/outfit/job/assistant/cargo
- id_type = /obj/item/weapon/card/id/cargo
+ id_type = /obj/item/card/id/cargo
/decl/hierarchy/outfit/job/assistant/engineer
- id_type = /obj/item/weapon/card/id/engineering
+ id_type = /obj/item/card/id/engineering
flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL
/decl/hierarchy/outfit/job/assistant/medic
- id_type = /obj/item/weapon/card/id/medical
+ id_type = /obj/item/card/id/medical
/decl/hierarchy/outfit/job/assistant/scientist
- id_type = /obj/item/weapon/card/id/science
+ id_type = /obj/item/card/id/science
/decl/hierarchy/outfit/job/assistant/officer
- id_type = /obj/item/weapon/card/id/security
+ id_type = /obj/item/card/id/security
/decl/hierarchy/outfit/job/assistant/entertainer
- id_type = /obj/item/weapon/card/id/civilian/entertainer
+ id_type = /obj/item/card/id/civilian/entertainer
/decl/hierarchy/outfit/job/assistant/entrepreneur
- id_type = /obj/item/weapon/card/id/civilian/entrepreneur
- l_hand = /obj/item/device/ticket_printer/train
+ id_type = /obj/item/card/id/civilian/entrepreneur
+ l_hand = /obj/item/ticket_printer/train
uniform = /obj/item/clothing/under/tropical/pink
/decl/hierarchy/outfit/job/assistant/entrepreneur/lawyer
uniform = /obj/item/clothing/under/lawyer/red
- r_hand = /obj/item/weapon/clipboard
- l_pocket = /obj/item/weapon/pen/fountain3
+ r_hand = /obj/item/clipboard
+ l_pocket = /obj/item/pen/fountain3
/decl/hierarchy/outfit/job/assistant/entrepreneur/private_eye
- l_hand = /obj/item/weapon/storage/box/private_investigator
+ l_hand = /obj/item/storage/box/private_investigator
suit = /obj/item/clothing/suit/storage/trench
head = /obj/item/clothing/head/fedora/brown
/decl/hierarchy/outfit/job/assistant/entrepreneur/bodyguard
glasses = /obj/item/clothing/glasses/sunglasses
- l_pocket = /obj/item/weapon/reagent_containers/spray/pepper
+ l_pocket = /obj/item/reagent_containers/spray/pepper
suit = /obj/item/clothing/accessory/sweater/blackneck
/decl/hierarchy/outfit/job/assistant/entrepreneur/personal_physician
suit = /obj/item/clothing/suit/storage/toggle/labcoat
l_pocket = /obj/item/clothing/accessory/stethoscope
- r_pocket = /obj/item/device/healthanalyzer
+ r_pocket = /obj/item/healthanalyzer
/decl/hierarchy/outfit/job/assistant/entrepreneur/dentist
- l_hand = /obj/item/weapon/storage/box/dentist
+ l_hand = /obj/item/storage/box/dentist
suit = /obj/item/clothing/suit/storage/toggle/labcoat
/decl/hierarchy/outfit/job/assistant/entrepreneur/fitness_instructor
- l_hand = /obj/item/weapon/storage/box/fitness_trainer
+ l_hand = /obj/item/storage/box/fitness_trainer
/decl/hierarchy/outfit/job/assistant/entrepreneur/yoga_teacher
uniform = /obj/item/clothing/under/pants/yogapants
- l_hand = /obj/item/weapon/storage/box/yoga_teacher
+ l_hand = /obj/item/storage/box/yoga_teacher
/decl/hierarchy/outfit/job/assistant/entrepreneur/masseuse
r_hand = /obj/item/roller/massage
/decl/hierarchy/outfit/job/assistant/entrepreneur/tradesperson
- r_hand = /obj/item/weapon/storage/toolbox/brass
+ r_hand = /obj/item/storage/toolbox/brass
/decl/hierarchy/outfit/job/assistant/entrepreneur/streamer
- l_pocket = /obj/item/device/tvcamera/streamer
+ l_pocket = /obj/item/tvcamera/streamer
/decl/hierarchy/outfit/job/assistant/entrepreneur/influencer
- l_pocket = /obj/item/device/camera/selfie
+ l_pocket = /obj/item/camera/selfie
/decl/hierarchy/outfit/job/assistant/entrepreneur/paranormal_investigator
- l_hand = /obj/item/weapon/storage/box/paranormal_investigator
+ l_hand = /obj/item/storage/box/paranormal_investigator
/decl/hierarchy/outfit/job/assistant/entrepreneur/stylist
- l_hand = /obj/item/weapon/storage/box/stylist
+ l_hand = /obj/item/storage/box/stylist
/decl/hierarchy/outfit/job/assistant/entrepreneur/fisher
- r_hand = /obj/item/weapon/material/fishing_rod/modern
- l_pocket = /obj/item/weapon/material/fishing_net
+ r_hand = /obj/item/material/fishing_rod/modern
+ l_pocket = /obj/item/material/fishing_net
head = /obj/item/clothing/head/fishing
- r_pocket = /obj/item/weapon/storage/box/wormcan
+ r_pocket = /obj/item/storage/box/wormcan
/decl/hierarchy/outfit/job/assistant/entrepreneur/personal_secretary
uniform = /obj/item/clothing/under/lawyer/blue
- r_hand = /obj/item/weapon/clipboard
- l_pocket = /obj/item/weapon/pen/fountain3
+ r_hand = /obj/item/clipboard
+ l_pocket = /obj/item/pen/fountain3
/decl/hierarchy/outfit/job/assistant/entrepreneur/fortune_teller
- l_hand = /obj/item/weapon/storage/box/fortune_teller
+ l_hand = /obj/item/storage/box/fortune_teller
/decl/hierarchy/outfit/job/assistant/entrepreneur/spirit_healer
- l_hand = /obj/item/weapon/storage/box/spirit_healer
+ l_hand = /obj/item/storage/box/spirit_healer
diff --git a/code/datums/outfits/jobs/command.dm b/code/datums/outfits/jobs/command.dm
index d8a74f925da..e5a869d9ddf 100644
--- a/code/datums/outfits/jobs/command.dm
+++ b/code/datums/outfits/jobs/command.dm
@@ -1,14 +1,18 @@
/decl/hierarchy/outfit/job/captain
- name = OUTFIT_JOB_NAME("Captain")
+ name = OUTFIT_JOB_NAME(JOB_ALT_CAPTAIN) // Keep Captain for now, not JOB_SITE_MANAGER
glasses = /obj/item/clothing/glasses/sunglasses
uniform = /obj/item/clothing/under/rank/captain
- l_ear = /obj/item/device/radio/headset/heads/captain
+
shoes = /obj/item/clothing/shoes/brown
- backpack = /obj/item/weapon/storage/backpack/captain
- satchel_one = /obj/item/weapon/storage/backpack/satchel/cap
- messenger_bag = /obj/item/weapon/storage/backpack/messenger/com
- id_type = /obj/item/weapon/card/id/gold
- pda_type = /obj/item/device/pda/captain
+ backpack = /obj/item/storage/backpack/captain
+ satchel_one = /obj/item/storage/backpack/satchel/cap
+ messenger_bag = /obj/item/storage/backpack/messenger/com
+ id_type = /obj/item/card/id/gold
+ pda_type = /obj/item/pda/captain
+
+ headset = /obj/item/radio/headset/heads/captain
+ headset_alt = /obj/item/radio/headset/alt/heads/captain
+ headset_earbud = /obj/item/radio/headset/earbud/heads/captain
/decl/hierarchy/outfit/job/captain/post_equip(var/mob/living/carbon/human/H)
..()
@@ -24,24 +28,30 @@
qdel(medal)
/decl/hierarchy/outfit/job/hop
- name = OUTFIT_JOB_NAME("Head of Personnel")
+ name = OUTFIT_JOB_NAME(JOB_HEAD_OF_PERSONNEL)
uniform = /obj/item/clothing/under/rank/head_of_personnel
- l_ear = /obj/item/device/radio/headset/heads/hop
shoes = /obj/item/clothing/shoes/brown
- id_type = /obj/item/weapon/card/id/silver/hop
- pda_type = /obj/item/device/pda/heads/hop
+ id_type = /obj/item/card/id/silver/hop
+ pda_type = /obj/item/pda/heads/hop
+
+ headset = /obj/item/radio/headset/heads/hop
+ headset_alt = /obj/item/radio/headset/alt/heads/hop
+ headset_earbud = /obj/item/radio/headset/earbud/heads/hop
/decl/hierarchy/outfit/job/secretary
- name = OUTFIT_JOB_NAME("Command Secretary")
- l_ear = /obj/item/device/radio/headset/headset_com
+ name = OUTFIT_JOB_NAME(JOB_COMMAND_SECRETARY)
shoes = /obj/item/clothing/shoes/brown
- id_type = /obj/item/weapon/card/id/silver/secretary
- pda_type = /obj/item/device/pda/heads
- r_hand = /obj/item/weapon/clipboard
+ id_type = /obj/item/card/id/silver/secretary
+ pda_type = /obj/item/pda/heads
+ r_hand = /obj/item/clipboard
+
+ headset = /obj/item/radio/headset/headset_com
+ headset_alt = /obj/item/radio/headset/alt/headset_com
+ headset_earbud = /obj/item/radio/headset/earbud/headset_com
/decl/hierarchy/outfit/job/secretary/pre_equip(mob/living/carbon/human/H)
..()
if(H.gender == FEMALE)
uniform = /obj/item/clothing/under/suit_jacket/female/skirt
else
- uniform = /obj/item/clothing/under/suit_jacket/charcoal
\ No newline at end of file
+ uniform = /obj/item/clothing/under/suit_jacket/charcoal
diff --git a/code/datums/outfits/jobs/command_vr.dm b/code/datums/outfits/jobs/command_vr.dm
index 5e90123ffcc..d120a0c41e9 100644
--- a/code/datums/outfits/jobs/command_vr.dm
+++ b/code/datums/outfits/jobs/command_vr.dm
@@ -1,5 +1,5 @@
/decl/hierarchy/outfit/job/hop
- id_type = /obj/item/weapon/card/id/silver/hop
+ id_type = /obj/item/card/id/silver/hop
/decl/hierarchy/outfit/job/secretary
- id_type = /obj/item/weapon/card/id/silver/secretary
\ No newline at end of file
+ id_type = /obj/item/card/id/silver/secretary
\ No newline at end of file
diff --git a/code/datums/outfits/jobs/engineering.dm b/code/datums/outfits/jobs/engineering.dm
index 86bf9fa8cfa..11c4a4cd3ce 100644
--- a/code/datums/outfits/jobs/engineering.dm
+++ b/code/datums/outfits/jobs/engineering.dm
@@ -1,34 +1,41 @@
/decl/hierarchy/outfit/job/engineering
hierarchy_type = /decl/hierarchy/outfit/job/engineering
- belt = /obj/item/weapon/storage/belt/utility/full/multitool
- l_ear = /obj/item/device/radio/headset/headset_eng
+ belt = /obj/item/storage/belt/utility/full/multitool
shoes = /obj/item/clothing/shoes/boots/workboots
- r_pocket = /obj/item/device/t_scanner
- backpack = /obj/item/weapon/storage/backpack/industrial
- satchel_one = /obj/item/weapon/storage/backpack/satchel/eng
- messenger_bag = /obj/item/weapon/storage/backpack/messenger/engi
+ r_pocket = /obj/item/t_scanner
+ backpack = /obj/item/storage/backpack/industrial
+ satchel_one = /obj/item/storage/backpack/satchel/eng
+ messenger_bag = /obj/item/storage/backpack/messenger/engi
pda_slot = slot_l_store
flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL
+ headset = /obj/item/radio/headset/headset_eng
+ headset_alt = /obj/item/radio/headset/alt/headset_eng
+ headset_earbud = /obj/item/radio/headset/earbud/headset_eng
+
/decl/hierarchy/outfit/job/engineering/chief_engineer
- name = OUTFIT_JOB_NAME("Chief engineer")
+ name = OUTFIT_JOB_NAME(JOB_CHIEF_ENGINEER)
head = /obj/item/clothing/head/hardhat/white
uniform = /obj/item/clothing/under/rank/chief_engineer
- l_ear = /obj/item/device/radio/headset/heads/ce
+
gloves = /obj/item/clothing/gloves/black
- id_type = /obj/item/weapon/card/id/engineering/head
- pda_type = /obj/item/device/pda/heads/ce
+ id_type = /obj/item/card/id/engineering/head
+ pda_type = /obj/item/pda/heads/ce
+
+ headset = /obj/item/radio/headset/heads/ce
+ headset_alt = /obj/item/radio/headset/alt/heads/ce
+ headset_earbud = /obj/item/radio/headset/earbud/heads/ce
/decl/hierarchy/outfit/job/engineering/engineer
- name = OUTFIT_JOB_NAME("Engineer")
+ name = OUTFIT_JOB_NAME(JOB_ENGINEER)
head = /obj/item/clothing/head/hardhat
uniform = /obj/item/clothing/under/rank/engineer
- id_type = /obj/item/weapon/card/id/engineering
- pda_type = /obj/item/device/pda/engineering
+ id_type = /obj/item/card/id/engineering
+ pda_type = /obj/item/pda/engineering
/decl/hierarchy/outfit/job/engineering/atmos
- name = OUTFIT_JOB_NAME("Atmospheric technician")
+ name = OUTFIT_JOB_NAME(JOB_ATMOSPHERIC_TECHNICIAN)
uniform = /obj/item/clothing/under/rank/atmospheric_technician
- belt = /obj/item/weapon/storage/belt/utility/atmostech
- id_type = /obj/item/weapon/card/id/engineering/atmos
- pda_type = /obj/item/device/pda/atmos
+ belt = /obj/item/storage/belt/utility/atmostech
+ id_type = /obj/item/card/id/engineering/atmos
+ pda_type = /obj/item/pda/atmos
diff --git a/code/datums/outfits/jobs/job.dm b/code/datums/outfits/jobs/job.dm
index 5c419f8fb28..fdb7af5dbed 100644
--- a/code/datums/outfits/jobs/job.dm
+++ b/code/datums/outfits/jobs/job.dm
@@ -3,18 +3,21 @@
hierarchy_type = /decl/hierarchy/outfit/job
uniform = /obj/item/clothing/under/color/grey
- l_ear = /obj/item/device/radio/headset
shoes = /obj/item/clothing/shoes/black
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/civilian
+ id_type = /obj/item/card/id/civilian
pda_slot = slot_belt
- pda_type = /obj/item/device/pda
+ pda_type = /obj/item/pda
flags = OUTFIT_HAS_BACKPACK
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset/alt
+ headset_earbud = /obj/item/radio/headset/earbud
+
/decl/hierarchy/outfit/job/equip_id(mob/living/carbon/human/H, rank, assignment)
- var/obj/item/weapon/card/id/C = ..()
+ var/obj/item/card/id/C = ..()
var/datum/job/J = job_master.GetJob(rank)
if(J)
C.access = J.get_access()
diff --git a/code/datums/outfits/jobs/medical.dm b/code/datums/outfits/jobs/medical.dm
index b474f92f727..6a4d120d37d 100644
--- a/code/datums/outfits/jobs/medical.dm
+++ b/code/datums/outfits/jobs/medical.dm
@@ -1,51 +1,58 @@
/decl/hierarchy/outfit/job/medical
hierarchy_type = /decl/hierarchy/outfit/job/medical
- l_ear = /obj/item/device/radio/headset/headset_med
shoes = /obj/item/clothing/shoes/white
- pda_type = /obj/item/device/pda/medical
+ pda_type = /obj/item/pda/medical
pda_slot = slot_l_store
- backpack = /obj/item/weapon/storage/backpack/medic
- satchel_one = /obj/item/weapon/storage/backpack/satchel/med
- messenger_bag = /obj/item/weapon/storage/backpack/messenger/med
+
+ backpack = /obj/item/storage/backpack/medic
+ satchel_one = /obj/item/storage/backpack/satchel/med
+ messenger_bag = /obj/item/storage/backpack/messenger/med
+
+ headset = /obj/item/radio/headset/headset_med
+ headset_alt = /obj/item/radio/headset/alt/headset_med
+ headset_earbud = /obj/item/radio/headset/earbud/headset_med
/decl/hierarchy/outfit/job/medical/cmo
- name = OUTFIT_JOB_NAME("Chief Medical Officer")
- l_ear =/obj/item/device/radio/headset/heads/cmo
+ name = OUTFIT_JOB_NAME(JOB_CHIEF_MEDICAL_OFFICER)
uniform = /obj/item/clothing/under/rank/chief_medical_officer
suit = /obj/item/clothing/suit/storage/toggle/labcoat/cmo
shoes = /obj/item/clothing/shoes/brown
- l_hand = /obj/item/weapon/storage/firstaid/adv
- r_pocket = /obj/item/device/healthanalyzer
- id_type = /obj/item/weapon/card/id/medical/head
- pda_type = /obj/item/device/pda/heads/cmo
+ l_hand = /obj/item/storage/firstaid/adv
+ r_pocket = /obj/item/healthanalyzer
+ id_type = /obj/item/card/id/medical/head
+ pda_type = /obj/item/pda/heads/cmo
+
+ headset = /obj/item/radio/headset/heads/cmo
+ headset_alt = /obj/item/radio/headset/alt/heads/cmo
+ headset_earbud = /obj/item/radio/headset/earbud/heads/cmo
/decl/hierarchy/outfit/job/medical/doctor
- name = OUTFIT_JOB_NAME("Medical Doctor")
+ name = OUTFIT_JOB_NAME(JOB_MEDICAL_DOCTOR)
uniform = /obj/item/clothing/under/rank/medical
suit = /obj/item/clothing/suit/storage/toggle/labcoat
- l_hand = /obj/item/weapon/storage/firstaid/regular
- r_pocket = /obj/item/device/flashlight/pen
- id_type = /obj/item/weapon/card/id/medical
+ l_hand = /obj/item/storage/firstaid/regular
+ r_pocket = /obj/item/flashlight/pen
+ id_type = /obj/item/card/id/medical
/decl/hierarchy/outfit/job/medical/doctor/emergency_physician
- name = OUTFIT_JOB_NAME("Emergency Physician")
+ name = OUTFIT_JOB_NAME(JOB_ALT_EMERGENCY_PHYSICIAN)
suit = /obj/item/clothing/suit/storage/toggle/fr_jacket
/decl/hierarchy/outfit/job/medical/doctor/surgeon
- name = OUTFIT_JOB_NAME("Surgeon")
+ name = OUTFIT_JOB_NAME(JOB_ALT_SURGEON)
uniform = /obj/item/clothing/under/rank/medical/scrubs
head = /obj/item/clothing/head/surgery/blue
/decl/hierarchy/outfit/job/medical/doctor/virologist
- name = OUTFIT_JOB_NAME("Virologist")
+ name = OUTFIT_JOB_NAME(JOB_ALT_VIROLOGIST)
uniform = /obj/item/clothing/under/rank/virologist
suit = /obj/item/clothing/suit/storage/toggle/labcoat/virologist
mask = /obj/item/clothing/mask/surgical
- backpack = /obj/item/weapon/storage/backpack/virology
- satchel_one = /obj/item/weapon/storage/backpack/satchel/vir
+ backpack = /obj/item/storage/backpack/virology
+ satchel_one = /obj/item/storage/backpack/satchel/vir
/decl/hierarchy/outfit/job/medical/doctor/nurse
- name = OUTFIT_JOB_NAME("Nurse")
+ name = OUTFIT_JOB_NAME(JOB_ALT_NURSE)
suit = null
/decl/hierarchy/outfit/job/medical/doctor/nurse/pre_equip(mob/living/carbon/human/H)
@@ -60,48 +67,48 @@
..()
/decl/hierarchy/outfit/job/medical/chemist
- name = OUTFIT_JOB_NAME("Chemist")
+ name = OUTFIT_JOB_NAME(JOB_CHEMIST)
uniform = /obj/item/clothing/under/rank/chemist
suit = /obj/item/clothing/suit/storage/toggle/labcoat/chemist
- backpack = /obj/item/weapon/storage/backpack/chemistry
- satchel_one = /obj/item/weapon/storage/backpack/satchel/chem
- sports_bag = /obj/item/weapon/storage/backpack/sport/chem
- id_type = /obj/item/weapon/card/id/medical/chemist
- pda_type = /obj/item/device/pda/chemist
+ backpack = /obj/item/storage/backpack/chemistry
+ satchel_one = /obj/item/storage/backpack/satchel/chem
+ sports_bag = /obj/item/storage/backpack/sport/chem
+ id_type = /obj/item/card/id/medical/chemist
+ pda_type = /obj/item/pda/chemist
/decl/hierarchy/outfit/job/medical/geneticist
- name = OUTFIT_JOB_NAME("Geneticist")
+ name = OUTFIT_JOB_NAME(JOB_GENETICIST)
uniform = /obj/item/clothing/under/rank/geneticist
suit = /obj/item/clothing/suit/storage/toggle/labcoat/genetics
- backpack = /obj/item/weapon/storage/backpack/genetics
- r_pocket = /obj/item/device/flashlight/pen
- satchel_one = /obj/item/weapon/storage/backpack/satchel/gen
- id_type = /obj/item/weapon/card/id/medical/geneticist
- pda_type = /obj/item/device/pda/geneticist
+ backpack = /obj/item/storage/backpack/genetics
+ r_pocket = /obj/item/flashlight/pen
+ satchel_one = /obj/item/storage/backpack/satchel/gen
+ id_type = /obj/item/card/id/medical/geneticist
+ pda_type = /obj/item/pda/geneticist
/decl/hierarchy/outfit/job/medical/psychiatrist
- name = OUTFIT_JOB_NAME("Psychiatrist")
+ name = OUTFIT_JOB_NAME(JOB_PSYCHIATRIST)
uniform = /obj/item/clothing/under/rank/psych
suit = /obj/item/clothing/suit/storage/toggle/labcoat
shoes = /obj/item/clothing/shoes/laceup
- id_type = /obj/item/weapon/card/id/medical/psych
+ id_type = /obj/item/card/id/medical/psych
/decl/hierarchy/outfit/job/medical/psychiatrist/psychologist
- name = OUTFIT_JOB_NAME("Psychologist")
+ name = OUTFIT_JOB_NAME(JOB_ALT_PSYCHOLOGIST)
uniform = /obj/item/clothing/under/rank/psych/turtleneck
/decl/hierarchy/outfit/job/medical/paramedic
- name = OUTFIT_JOB_NAME("Paramedic")
+ name = OUTFIT_JOB_NAME(JOB_PARAMEDIC)
uniform = /obj/item/clothing/under/rank/medical/paramedic
suit = /obj/item/clothing/suit/storage/toggle/fr_jacket
shoes = /obj/item/clothing/shoes/boots/jackboots
- l_hand = /obj/item/weapon/storage/firstaid/regular
- belt = /obj/item/weapon/storage/belt/medical/emt
+ l_hand = /obj/item/storage/firstaid/regular
+ belt = /obj/item/storage/belt/medical/emt
pda_slot = slot_l_store
- id_type = /obj/item/weapon/card/id/medical/emt
+ id_type = /obj/item/card/id/medical/emt
flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL
/decl/hierarchy/outfit/job/medical/paramedic/emt
- name = OUTFIT_JOB_NAME("Emergency Medical Technician")
+ name = OUTFIT_JOB_NAME(JOB_ALT_EMERGENCY_MEDICAL_TECHNICIAN)
uniform = /obj/item/clothing/under/rank/medical/paramedic_alt
suit = /obj/item/clothing/suit/storage/toggle/labcoat/emt
diff --git a/code/datums/outfits/jobs/medical_vr.dm b/code/datums/outfits/jobs/medical_vr.dm
index e9b2c1a0d02..5576e71cada 100644
--- a/code/datums/outfits/jobs/medical_vr.dm
+++ b/code/datums/outfits/jobs/medical_vr.dm
@@ -1,2 +1,2 @@
/decl/hierarchy/outfit/job/medical/doctor/virologist
- id_type = /obj/item/weapon/card/id/medical/virologist
\ No newline at end of file
+ id_type = /obj/item/card/id/medical/virologist
\ No newline at end of file
diff --git a/code/datums/outfits/jobs/misc.dm b/code/datums/outfits/jobs/misc.dm
index 43bbd919f8e..28cfa9e2361 100644
--- a/code/datums/outfits/jobs/misc.dm
+++ b/code/datums/outfits/jobs/misc.dm
@@ -3,9 +3,9 @@
hierarchy_type = /decl/hierarchy/outfit/job/silicon
/decl/hierarchy/outfit/job/silicon/ai
- name = OUTFIT_JOB_NAME("AI")
+ name = OUTFIT_JOB_NAME(JOB_AI)
suit = /obj/item/clothing/suit/straight_jacket
/decl/hierarchy/outfit/job/silicon/cyborg
- name = OUTFIT_JOB_NAME("Cyborg")
+ name = OUTFIT_JOB_NAME(JOB_CYBORG)
suit = /obj/item/clothing/suit/cardborg
diff --git a/code/datums/outfits/jobs/science.dm b/code/datums/outfits/jobs/science.dm
index fcccfb8f8c6..eeeb84951d0 100644
--- a/code/datums/outfits/jobs/science.dm
+++ b/code/datums/outfits/jobs/science.dm
@@ -1,43 +1,50 @@
/decl/hierarchy/outfit/job/science
hierarchy_type = /decl/hierarchy/outfit/job/science
- l_ear = /obj/item/device/radio/headset/headset_sci
suit = /obj/item/clothing/suit/storage/toggle/labcoat
shoes = /obj/item/clothing/shoes/white
- pda_type = /obj/item/device/pda/science
- backpack = /obj/item/weapon/storage/backpack/toxins
- satchel_one = /obj/item/weapon/storage/backpack/satchel/tox
- messenger_bag = /obj/item/weapon/storage/backpack/messenger/tox
- sports_bag = /obj/item/weapon/storage/backpack/sport/tox
+ pda_type = /obj/item/pda/science
+
+ backpack = /obj/item/storage/backpack/toxins
+ satchel_one = /obj/item/storage/backpack/satchel/tox
+ messenger_bag = /obj/item/storage/backpack/messenger/tox
+ sports_bag = /obj/item/storage/backpack/sport/tox
+
+ headset = /obj/item/radio/headset/headset_sci
+ headset_alt = /obj/item/radio/headset/alt/headset_sci
+ headset_earbud = /obj/item/radio/headset/earbud/headset_sci
/decl/hierarchy/outfit/job/science/rd
name = OUTFIT_JOB_NAME("Research Director")
- l_ear = /obj/item/device/radio/headset/heads/rd
uniform = /obj/item/clothing/under/rank/research_director
shoes = /obj/item/clothing/shoes/brown
- l_hand = /obj/item/weapon/clipboard
- id_type = /obj/item/weapon/card/id/science/head
- pda_type = /obj/item/device/pda/heads/rd
+ l_hand = /obj/item/clipboard
+ id_type = /obj/item/card/id/science/head
+ pda_type = /obj/item/pda/heads/rd
+
+ headset = /obj/item/radio/headset/heads/rd
+ headset_alt = /obj/item/radio/headset/alt/heads/rd
+ headset_earbud = /obj/item/radio/headset/earbud/heads/rd
/decl/hierarchy/outfit/job/science/scientist
- name = OUTFIT_JOB_NAME("Scientist")
+ name = OUTFIT_JOB_NAME(JOB_SCIENTIST)
uniform = /obj/item/clothing/under/rank/scientist
- id_type = /obj/item/weapon/card/id/science
+ id_type = /obj/item/card/id/science
suit = /obj/item/clothing/suit/storage/toggle/labcoat/science
/decl/hierarchy/outfit/job/science/xenobiologist
- name = OUTFIT_JOB_NAME("Xenobiologist")
+ name = OUTFIT_JOB_NAME(JOB_XENOBIOLOGIST)
uniform = /obj/item/clothing/under/rank/scientist
- id_type = /obj/item/weapon/card/id/science
+ id_type = /obj/item/card/id/science
suit = /obj/item/clothing/suit/storage/toggle/labcoat/science
/decl/hierarchy/outfit/job/science/roboticist
- name = OUTFIT_JOB_NAME("Roboticist")
+ name = OUTFIT_JOB_NAME(JOB_ROBOTICIST)
uniform = /obj/item/clothing/under/rank/roboticist
shoes = /obj/item/clothing/shoes/black
- belt = /obj/item/weapon/storage/belt/utility/full/multitool
- id_type = /obj/item/weapon/card/id/science
+ belt = /obj/item/storage/belt/utility/full/multitool
+ id_type = /obj/item/card/id/science
pda_slot = slot_r_store
- pda_type = /obj/item/device/pda/roboticist
- backpack = /obj/item/weapon/storage/backpack
- satchel_one = /obj/item/weapon/storage/backpack/satchel/norm
- suit = /obj/item/clothing/suit/storage/toggle/labcoat/roboticist
\ No newline at end of file
+ pda_type = /obj/item/pda/roboticist
+ backpack = /obj/item/storage/backpack
+ satchel_one = /obj/item/storage/backpack/satchel/norm
+ suit = /obj/item/clothing/suit/storage/toggle/labcoat/roboticist
diff --git a/code/datums/outfits/jobs/science_vr.dm b/code/datums/outfits/jobs/science_vr.dm
index cf0e9e4b3a6..74242d7b1d4 100644
--- a/code/datums/outfits/jobs/science_vr.dm
+++ b/code/datums/outfits/jobs/science_vr.dm
@@ -1,8 +1,8 @@
/decl/hierarchy/outfit/job/science/xenobiologist
- id_type = /obj/item/weapon/card/id/science/xenobiologist
+ id_type = /obj/item/card/id/science/xenobiologist
/decl/hierarchy/outfit/job/science/xenobotanist
- name = OUTFIT_JOB_NAME("Xenobotanist")
+ name = OUTFIT_JOB_NAME(JOB_XENOBOTANIST)
uniform = /obj/item/clothing/under/rank/scientist
- id_type = /obj/item/weapon/card/id/science/xenobotanist
- suit = /obj/item/clothing/suit/storage/toggle/labcoat/science
\ No newline at end of file
+ id_type = /obj/item/card/id/science/xenobotanist
+ suit = /obj/item/clothing/suit/storage/toggle/labcoat/science
diff --git a/code/datums/outfits/jobs/security.dm b/code/datums/outfits/jobs/security.dm
index 4a044d8aaa4..595601bbcdd 100644
--- a/code/datums/outfits/jobs/security.dm
+++ b/code/datums/outfits/jobs/security.dm
@@ -1,42 +1,49 @@
/decl/hierarchy/outfit/job/security
hierarchy_type = /decl/hierarchy/outfit/job/security
glasses = /obj/item/clothing/glasses/sunglasses/sechud
- l_ear = /obj/item/device/radio/headset/headset_sec
gloves = /obj/item/clothing/gloves/black
shoes = /obj/item/clothing/shoes/boots/jackboots
- backpack = /obj/item/weapon/storage/backpack/security
- satchel_one = /obj/item/weapon/storage/backpack/satchel/sec
- backpack_contents = list(/obj/item/weapon/handcuffs = 1)
- messenger_bag = /obj/item/weapon/storage/backpack/messenger/sec
- sports_bag = /obj/item/weapon/storage/backpack/sport/sec
+
+ backpack = /obj/item/storage/backpack/security
+ satchel_one = /obj/item/storage/backpack/satchel/sec
+ backpack_contents = list(/obj/item/handcuffs = 1)
+ messenger_bag = /obj/item/storage/backpack/messenger/sec
+ sports_bag = /obj/item/storage/backpack/sport/sec
+
+ headset = /obj/item/radio/headset/headset_sec
+ headset_alt = /obj/item/radio/headset/alt/headset_sec
+ headset_earbud = /obj/item/radio/headset/earbud/headset_sec
/decl/hierarchy/outfit/job/security/hos
- name = OUTFIT_JOB_NAME("Head of security")
- l_ear = /obj/item/device/radio/headset/heads/hos
+ name = OUTFIT_JOB_NAME(JOB_HEAD_OF_SECURITY)
uniform = /obj/item/clothing/under/rank/head_of_security
- id_type = /obj/item/weapon/card/id/security/head
- pda_type = /obj/item/device/pda/heads/hos
+ id_type = /obj/item/card/id/security/head
+ pda_type = /obj/item/pda/heads/hos
+
+ headset = /obj/item/radio/headset/heads/hos
+ headset_alt = /obj/item/radio/headset/alt/heads/hos
+ headset_earbud = /obj/item/radio/headset/earbud/heads/hos
/decl/hierarchy/outfit/job/security/warden
- name = OUTFIT_JOB_NAME("Warden")
+ name = OUTFIT_JOB_NAME(JOB_WARDEN)
uniform = /obj/item/clothing/under/rank/warden
- l_pocket = /obj/item/device/flash
- id_type = /obj/item/weapon/card/id/security/warden
- pda_type = /obj/item/device/pda/warden
+ l_pocket = /obj/item/flash
+ id_type = /obj/item/card/id/security/warden
+ pda_type = /obj/item/pda/warden
/decl/hierarchy/outfit/job/security/detective
- name = OUTFIT_JOB_NAME("Detective")
+ name = OUTFIT_JOB_NAME(JOB_DETECTIVE)
head = /obj/item/clothing/head/det
uniform = /obj/item/clothing/under/det
suit = /obj/item/clothing/suit/storage/det_trench
- l_pocket = /obj/item/weapon/flame/lighter/zippo
+ l_pocket = /obj/item/flame/lighter/zippo
shoes = /obj/item/clothing/shoes/laceup
- r_hand = /obj/item/weapon/storage/briefcase/crimekit
- id_type = /obj/item/weapon/card/id/security/detective
- pda_type = /obj/item/device/pda/detective
- backpack = /obj/item/weapon/storage/backpack
- satchel_one = /obj/item/weapon/storage/backpack/satchel/norm
- backpack_contents = list(/obj/item/weapon/storage/box/evidence = 1)
+ r_hand = /obj/item/storage/briefcase/crimekit
+ id_type = /obj/item/card/id/security/detective
+ pda_type = /obj/item/pda/detective
+ backpack = /obj/item/storage/backpack
+ satchel_one = /obj/item/storage/backpack/satchel/norm
+ backpack_contents = list(/obj/item/storage/box/evidence = 1)
//VOREStation Edit - More cyberpunky
/decl/hierarchy/outfit/job/security/detective/forensic
@@ -47,8 +54,8 @@
//VOREStation Edit End
/decl/hierarchy/outfit/job/security/officer
- name = OUTFIT_JOB_NAME("Security Officer")
+ name = OUTFIT_JOB_NAME(JOB_SECURITY_OFFICER)
uniform = /obj/item/clothing/under/rank/security
- l_pocket = /obj/item/device/flash
- id_type = /obj/item/weapon/card/id/security
- pda_type = /obj/item/device/pda/security
+ l_pocket = /obj/item/flash
+ id_type = /obj/item/card/id/security
+ pda_type = /obj/item/pda/security
diff --git a/code/datums/outfits/jobs/security_yw.dm b/code/datums/outfits/jobs/security_yw.dm
index c5a878f26e9..0812de84e34 100644
--- a/code/datums/outfits/jobs/security_yw.dm
+++ b/code/datums/outfits/jobs/security_yw.dm
@@ -1,5 +1,5 @@
/decl/hierarchy/outfit/job/security/pilot
name = OUTFIT_JOB_NAME("Security Pilot")
uniform = /obj/item/clothing/under/rank/khi/sec/pilot
- id_type = /obj/item/weapon/card/id/security
- pda_type = /obj/item/device/pda/security
\ No newline at end of file
+ id_type = /obj/item/card/id/security
+ pda_type = /obj/item/pda/security
diff --git a/code/datums/outfits/jobs/special_vr.dm b/code/datums/outfits/jobs/special_vr.dm
index 20473f0e8eb..0e1fcf2a70e 100644
--- a/code/datums/outfits/jobs/special_vr.dm
+++ b/code/datums/outfits/jobs/special_vr.dm
@@ -4,50 +4,56 @@
gloves = /obj/item/clothing/gloves/white
shoes = /obj/item/clothing/shoes/laceup
head = /obj/item/clothing/head/beret/centcom/officer
- l_ear = /obj/item/device/radio/headset/centcom
glasses = /obj/item/clothing/glasses/omnihud/all
- id_type = /obj/item/weapon/card/id/centcom
- pda_type = /obj/item/device/pda/centcom
+ id_type = /obj/item/card/id/centcom
+ pda_type = /obj/item/pda/centcom
flags = OUTFIT_EXTENDED_SURVIVAL|OUTFIT_COMPREHENSIVE_SURVIVAL
+ headset = /obj/item/radio/headset/centcom
+ headset_alt = /obj/item/radio/headset/centcom
+ headset_earbud = /obj/item/radio/headset/centcom
+
/decl/hierarchy/outfit/job/emergency_responder
name = OUTFIT_JOB_NAME("Emergency Responder")
uniform = /obj/item/clothing/under/ert
shoes = /obj/item/clothing/shoes/boots/swat
gloves = /obj/item/clothing/gloves/swat
- l_ear = /obj/item/device/radio/headset/ert
glasses = /obj/item/clothing/glasses/sunglasses
- back = /obj/item/weapon/storage/backpack/satchel
- id_type = /obj/item/weapon/card/id/centcom/ERT
- pda_type = /obj/item/device/pda/centcom
+ back = /obj/item/storage/backpack/satchel
+ id_type = /obj/item/card/id/centcom/ERT
+ pda_type = /obj/item/pda/centcom
flags = OUTFIT_EXTENDED_SURVIVAL|OUTFIT_COMPREHENSIVE_SURVIVAL
+ headset = /obj/item/radio/headset/ert
+ headset_alt = /obj/item/radio/headset/ert
+ headset_earbud = /obj/item/radio/headset/ert
+
/decl/hierarchy/outfit/job/emergency_responder/post_equip(var/mob/living/carbon/human/H)
..()
ert.add_antagonist(H.mind)
/decl/hierarchy/outfit/job/clown
- name = OUTFIT_JOB_NAME("Clown")
+ name = OUTFIT_JOB_NAME(JOB_CLOWN)
uniform = /obj/item/clothing/under/rank/clown
- back = /obj/item/weapon/storage/backpack/clown
+ back = /obj/item/storage/backpack/clown
shoes = /obj/item/clothing/shoes/clown_shoes
mask = /obj/item/clothing/mask/gas/clown_hat
- backpack_contents = list(/obj/item/weapon/stamp/clown = 1, /obj/item/weapon/bikehorn = 1)
- id_type = /obj/item/weapon/card/id/civilian/clown
- pda_type = /obj/item/device/pda/clown
+ backpack_contents = list(/obj/item/stamp/clown = 1, /obj/item/bikehorn = 1)
+ id_type = /obj/item/card/id/civilian/clown
+ pda_type = /obj/item/pda/clown
flags = 0
/decl/hierarchy/outfit/job/mime
- name = OUTFIT_JOB_NAME("Mime")
+ name = OUTFIT_JOB_NAME(JOB_MIME)
uniform = /obj/item/clothing/under/mime
shoes = /obj/item/clothing/shoes/mime
head = /obj/item/clothing/head/soft/mime
mask = /obj/item/clothing/mask/gas/mime
- backpack_contents = list(/obj/item/weapon/pen/crayon/mime = 1)
- id_type = /obj/item/weapon/card/id/civilian/mime
- pda_type = /obj/item/device/pda/mime
+ backpack_contents = list(/obj/item/pen/crayon/mime = 1)
+ id_type = /obj/item/card/id/civilian/mime
+ pda_type = /obj/item/pda/mime
/decl/hierarchy/outfit/job/mime/post_equip(var/mob/living/carbon/human/H)
..()
if(H.backbag == 1)
- H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/mime(H), slot_l_hand)
+ H.equip_to_slot_or_del(new /obj/item/pen/crayon/mime(H), slot_l_hand)
diff --git a/code/datums/outfits/military/military.dm b/code/datums/outfits/military/military.dm
index eb00eb6871d..fb47db35f5a 100644
--- a/code/datums/outfits/military/military.dm
+++ b/code/datums/outfits/military/military.dm
@@ -2,4 +2,6 @@
name = "Military Uniform"
hierarchy_type = /decl/hierarchy/outfit/military
- l_ear = /obj/item/device/radio/headset
\ No newline at end of file
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset
+ headset_earbud = /obj/item/radio/headset
\ No newline at end of file
diff --git a/code/datums/outfits/misc.dm b/code/datums/outfits/misc.dm
index 7facd60d5e4..13620cbf9a9 100644
--- a/code/datums/outfits/misc.dm
+++ b/code/datums/outfits/misc.dm
@@ -4,7 +4,7 @@
head = /obj/item/clothing/head/helmet/space
suit = /obj/item/clothing/suit/space
uniform = /obj/item/clothing/under/color/grey
- back = /obj/item/weapon/tank/jetpack/oxygen
+ back = /obj/item/tank/jetpack/oxygen
mask = /obj/item/clothing/mask/breath
flags = OUTFIT_HAS_JETPACK
@@ -14,7 +14,7 @@
head = /obj/item/clothing/head/helmet/space/emergency
suit = /obj/item/clothing/suit/space/emergency
uniform = /obj/item/clothing/under/color/grey
- back = /obj/item/weapon/tank/oxygen
+ back = /obj/item/tank/oxygen
mask = /obj/item/clothing/mask/breath
/decl/hierarchy/outfit/soviet_soldier
@@ -23,31 +23,37 @@
shoes = /obj/item/clothing/shoes/boots/combat
head = /obj/item/clothing/head/ushanka/soviet
gloves = /obj/item/clothing/gloves/combat
- back = /obj/item/weapon/storage/backpack/satchel
- belt = /obj/item/weapon/gun/projectile/revolver/mateba
+ back = /obj/item/storage/backpack/satchel
+ belt = /obj/item/gun/projectile/revolver/mateba
/decl/hierarchy/outfit/soviet_soldier/admiral
name = "Soviet admiral"
head = /obj/item/clothing/head/hgpiratecap
- l_ear = /obj/item/device/radio/headset/heads/captain
glasses = /obj/item/clothing/glasses/thermal/plain/eyepatch
suit = /obj/item/clothing/suit/hgpirate
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/centcom //station
+ id_type = /obj/item/card/id/centcom //station
id_pda_assignment = "Admiral"
+ headset = /obj/item/radio/headset/heads/captain
+ headset_alt = /obj/item/radio/headset/heads/captain
+ headset_earbud = /obj/item/radio/headset/heads/captain
+
/decl/hierarchy/outfit/merchant
name = "Merchant"
shoes = /obj/item/clothing/shoes/black
- l_ear = /obj/item/device/radio/headset
uniform = /obj/item/clothing/under/color/grey
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/civilian //merchant
+ id_type = /obj/item/card/id/civilian //merchant
pda_slot = slot_r_store
- pda_type = /obj/item/device/pda/chef //cause I like the look
+ pda_type = /obj/item/pda/chef //cause I like the look
id_pda_assignment = "Merchant"
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset
+ headset_earbud = /obj/item/radio/headset
+
/decl/hierarchy/outfit/merchant/vox
name = "Merchant - Vox"
shoes = /obj/item/clothing/shoes/boots/jackboots/toeless
@@ -57,4 +63,16 @@
/decl/hierarchy/outfit/zaddat
name = "Zaddat Suit"
suit = /obj/item/clothing/suit/space/void/zaddat/
- mask = /obj/item/clothing/mask/gas/zaddat
\ No newline at end of file
+ mask = /obj/item/clothing/mask/gas/zaddat
+
+/decl/hierarchy/outfit/maint_lurker
+ name = "Maintenance Lurker Outfit"
+ id_slot = slot_wear_id
+ id_type = /obj/item/card/id/civilian/lurker
+ pda_slot = slot_belt
+ pda_type = /obj/item/pda
+ id_pda_assignment = "NO DATA"
+
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset/alt
+ headset_earbud = /obj/item/radio/headset/earbud
diff --git a/code/datums/outfits/nanotrasen.dm b/code/datums/outfits/nanotrasen.dm
index 4fd219685ba..3fde80dd0bb 100644
--- a/code/datums/outfits/nanotrasen.dm
+++ b/code/datums/outfits/nanotrasen.dm
@@ -3,30 +3,39 @@
uniform = /obj/item/clothing/under/rank/centcom
shoes = /obj/item/clothing/shoes/laceup
gloves = /obj/item/clothing/gloves/white
- l_ear = /obj/item/device/radio/headset/heads/hop
glasses = /obj/item/clothing/glasses/sunglasses
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/centcom //station
+ id_type = /obj/item/card/id/centcom //station
pda_slot = slot_r_store
- pda_type = /obj/item/device/pda/heads
+ pda_type = /obj/item/pda/heads
+
+ headset = /obj/item/radio/headset/heads/hop
+ headset_alt = /obj/item/radio/headset/heads/hop
+ headset_earbud = /obj/item/radio/headset/heads/hop
/decl/hierarchy/outfit/nanotrasen/representative
name = "Nanotrasen representative"
- belt = /obj/item/weapon/clipboard
+ belt = /obj/item/clipboard
id_pda_assignment = "NanoTrasen Navy Representative"
/decl/hierarchy/outfit/nanotrasen/officer
name = "Nanotrasen officer"
head = /obj/item/clothing/head/beret/centcom/officer
- l_ear = /obj/item/device/radio/headset/heads/captain
- belt = /obj/item/weapon/gun/energy
+ belt = /obj/item/gun/energy
id_pda_assignment = "NanoTrasen Navy Officer"
+ headset = /obj/item/radio/headset/heads/captain
+ headset_alt = /obj/item/radio/headset/heads/captain
+ headset_earbud = /obj/item/radio/headset/heads/captain
+
/decl/hierarchy/outfit/nanotrasen/captain
name = "Nanotrasen captain"
uniform = /obj/item/clothing/under/rank/centcom_captain
- l_ear = /obj/item/device/radio/headset/heads/captain
head = /obj/item/clothing/head/beret/centcom/captain
- belt = /obj/item/weapon/gun/energy
+ belt = /obj/item/gun/energy
id_pda_assignment = "NanoTrasen Navy Captain"
+
+ headset = /obj/item/radio/headset/heads/captain
+ headset_alt = /obj/item/radio/headset/heads/captain
+ headset_earbud = /obj/item/radio/headset/heads/captain
diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm
index b27093934e0..43fe69f0f22 100644
--- a/code/datums/outfits/outfit.dm
+++ b/code/datums/outfits/outfit.dm
@@ -52,12 +52,16 @@ var/list/outfits_decls_by_type_
var/id_pda_assignment
- var/backpack = /obj/item/weapon/storage/backpack
- var/satchel_one = /obj/item/weapon/storage/backpack/satchel/norm
- var/satchel_two = /obj/item/weapon/storage/backpack/satchel
- var/messenger_bag = /obj/item/weapon/storage/backpack/messenger
- var/sports_bag = /obj/item/weapon/storage/backpack/sport
- var/satchel_three = /obj/item/weapon/storage/backpack/satchel/strapless
+ var/headset = /obj/item/radio/headset
+ var/headset_alt = /obj/item/radio/headset/alt
+ var/headset_earbud = /obj/item/radio/headset/earbud
+
+ var/backpack = /obj/item/storage/backpack
+ var/satchel_one = /obj/item/storage/backpack/satchel/norm
+ var/satchel_two = /obj/item/storage/backpack/satchel
+ var/messenger_bag = /obj/item/storage/backpack/messenger
+ var/sports_bag = /obj/item/storage/backpack/sport
+ var/satchel_three = /obj/item/storage/backpack/satchel/strapless
var/flags // Specific flags
@@ -72,7 +76,11 @@ var/list/outfits_decls_by_type_
dd_insertObjectList(outfits_decls_, src)
/decl/hierarchy/outfit/proc/pre_equip(mob/living/carbon/human/H)
- if(flags & OUTFIT_HAS_BACKPACK)
+ switch(H.headset)
+ if(1) l_ear = headset
+ if(2) l_ear = headset_alt
+ if(3) l_ear = headset_earbud
+ if(flags && OUTFIT_HAS_BACKPACK)
switch(H.backbag)
if(2) back = backpack
if(3) back = satchel_one
@@ -84,7 +92,7 @@ var/list/outfits_decls_by_type_
/decl/hierarchy/outfit/proc/post_equip(mob/living/carbon/human/H)
if(flags & OUTFIT_HAS_JETPACK)
- var/obj/item/weapon/tank/jetpack/J = locate(/obj/item/weapon/tank/jetpack) in H
+ var/obj/item/tank/jetpack/J = locate(/obj/item/tank/jetpack) in H
if(!J)
return
J.toggle()
@@ -95,7 +103,7 @@ var/list/outfits_decls_by_type_
rank = rank || id_pda_assignment
assignment = id_pda_assignment || assignment || rank
- var/obj/item/weapon/card/id/W = equip_id(H, rank, assignment)
+ var/obj/item/card/id/W = equip_id(H, rank, assignment)
if(W)
rank = W.rank
assignment = W.assignment
@@ -164,7 +172,7 @@ var/list/outfits_decls_by_type_
/decl/hierarchy/outfit/proc/equip_id(mob/living/carbon/human/H, rank, assignment)
if(!id_slot || !id_type)
return
- var/obj/item/weapon/card/id/W = new id_type(H)
+ var/obj/item/card/id/W = new id_type(H)
if(id_desc)
W.desc = id_desc
if(rank)
@@ -177,13 +185,13 @@ var/list/outfits_decls_by_type_
/decl/hierarchy/outfit/proc/equip_pda(mob/living/carbon/human/H, rank, assignment)
if(!pda_slot || !pda_type)
return
- var/obj/item/device/pda/pda = new pda_type(H)
+ var/obj/item/pda/pda = new pda_type(H)
if(H.equip_to_slot_or_del(pda, pda_slot))
pda.owner = H.real_name
pda.ownjob = assignment
pda.ownrank = rank
pda.name = "PDA-[H.real_name] ([assignment])"
- if(H.client.prefs.ringtone) // if null we use the job default
+ if(H.client?.prefs.ringtone) // if null we use the job default
pda.ttone = H.client.prefs.ringtone
return pda
diff --git a/code/datums/outfits/outfit_vr.dm b/code/datums/outfits/outfit_vr.dm
index 1883f2b005b..97dd17c7b23 100644
--- a/code/datums/outfits/outfit_vr.dm
+++ b/code/datums/outfits/outfit_vr.dm
@@ -3,20 +3,23 @@
uniform = /obj/item/clothing/under/solgov/utility/army/urban
shoes = /obj/item/clothing/shoes/boots/jackboots
gloves = /obj/item/clothing/gloves/combat
- l_ear = /obj/item/device/radio/headset/centcom
r_pocket = /obj/item/ammo_magazine/m95
l_pocket = /obj/item/ammo_magazine/m95
l_hand = /obj/item/ammo_magazine/m95
r_hand = /obj/item/ammo_magazine/m95
- back = /obj/item/weapon/gun/projectile/automatic/battlerifle
- backpack_contents = list(/obj/item/weapon/storage/box = 1)
+ back = /obj/item/gun/projectile/automatic/battlerifle
+ backpack_contents = list(/obj/item/storage/box = 1)
hierarchy_type = /decl/hierarchy/outfit/wizard
head = /obj/item/clothing/head/helmet/combat/USDF
suit = /obj/item/clothing/suit/armor/combat/USDF
- belt = /obj/item/weapon/storage/belt/security/tactical
+ belt = /obj/item/storage/belt/security/tactical
+
+ headset = /obj/item/radio/headset/centcom
+ headset_alt = /obj/item/radio/headset/centcom
+ headset_earbud = /obj/item/radio/headset/centcom
/decl/hierarchy/outfit/USDF/Marine/equip_id(mob/living/carbon/human/H)
- var/obj/item/weapon/card/id/C = ..()
+ var/obj/item/card/id/C = ..()
C.name = "[H.real_name]'s military ID Card"
C.icon_state = "lifetime"
C.access = get_all_station_access()
@@ -29,17 +32,20 @@
name = "USDF officer"
head = /obj/item/clothing/head/dress/army/command
shoes = /obj/item/clothing/shoes/boots/jackboots
- l_ear = /obj/item/device/radio/headset/centcom
uniform = /obj/item/clothing/under/solgov/mildress/army/command
- back = /obj/item/weapon/storage/backpack/satchel
- belt = /obj/item/weapon/gun/projectile/revolver/consul
+ back = /obj/item/storage/backpack/satchel
+ belt = /obj/item/gun/projectile/revolver/consul
l_pocket = /obj/item/ammo_magazine/s44
r_pocket = /obj/item/ammo_magazine/s44
r_hand = /obj/item/clothing/accessory/holster/hip
l_hand = /obj/item/clothing/accessory/tie/black
+ headset = /obj/item/radio/headset/centcom
+ headset_alt = /obj/item/radio/headset/centcom
+ headset_earbud = /obj/item/radio/headset/centcom
+
/decl/hierarchy/outfit/USDF/Officer/equip_id(mob/living/carbon/human/H)
- var/obj/item/weapon/card/id/C = ..()
+ var/obj/item/card/id/C = ..()
C.name = "[H.real_name]'s military ID Card"
C.icon_state = "lifetime"
C.access = get_all_station_access()
@@ -51,16 +57,19 @@
/decl/hierarchy/outfit/solcom/representative
name = "SolGov Representative" //YW EDIT: SolGov
shoes = /obj/item/clothing/shoes/laceup
- l_ear = /obj/item/device/radio/headset/centcom
uniform = /obj/item/clothing/under/suit_jacket/navy
- back = /obj/item/weapon/storage/backpack/satchel
- l_pocket = /obj/item/weapon/pen/blue
- r_pocket = /obj/item/weapon/pen/red
- r_hand = /obj/item/device/pda/centcom
- l_hand = /obj/item/weapon/clipboard
+ back = /obj/item/storage/backpack/satchel
+ l_pocket = /obj/item/pen/blue
+ r_pocket = /obj/item/pen/red
+ r_hand = /obj/item/pda/centcom
+ l_hand = /obj/item/clipboard
+
+ headset = /obj/item/radio/headset/centcom
+ headset_alt = /obj/item/radio/headset/centcom
+ headset_earbud = /obj/item/radio/headset/centcom
/decl/hierarchy/outfit/solcom/representative/equip_id(mob/living/carbon/human/H)
- var/obj/item/weapon/card/id/C = ..()
+ var/obj/item/card/id/C = ..()
C.name = "[H.real_name]'s SolGov ID Card" //YW EDIT: SolGov
C.icon_state = "lifetime"
C.access = get_all_station_access()
@@ -74,33 +83,39 @@
head = /obj/item/clothing/head/helmet/combat/imperial
shoes =/obj/item/clothing/shoes/leg_guard/combat/imperial
gloves = /obj/item/clothing/gloves/arm_guard/combat/imperial
- l_ear = /obj/item/device/radio/headset/syndicate
uniform = /obj/item/clothing/under/imperial
mask = /obj/item/clothing/mask/gas/imperial
suit = /obj/item/clothing/suit/armor/combat/imperial
- back = /obj/item/weapon/storage/backpack/satchel
- belt = /obj/item/weapon/storage/belt/security/tactical/bandolier
- l_pocket = /obj/item/weapon/cell/device/weapon
- r_pocket = /obj/item/weapon/cell/device/weapon
- r_hand = /obj/item/weapon/melee/energy/sword/imperial
- l_hand = /obj/item/weapon/shield/energy/imperial
- suit_store = /obj/item/weapon/gun/energy/imperial
+ back = /obj/item/storage/backpack/satchel
+ belt = /obj/item/storage/belt/security/tactical/bandolier
+ l_pocket = /obj/item/cell/device/weapon
+ r_pocket = /obj/item/cell/device/weapon
+ r_hand = /obj/item/melee/energy/sword/imperial
+ l_hand = /obj/item/shield/energy/imperial
+ suit_store = /obj/item/gun/energy/imperial
+
+ headset = /obj/item/radio/headset/syndicate
+ headset_alt = /obj/item/radio/headset/syndicate
+ headset_earbud = /obj/item/radio/headset/syndicate
/decl/hierarchy/outfit/imperial/officer
name = "Imperial officer"
head = /obj/item/clothing/head/helmet/combat/imperial/centurion
shoes = /obj/item/clothing/shoes/leg_guard/combat/imperial
gloves = /obj/item/clothing/gloves/arm_guard/combat/imperial
- l_ear = /obj/item/device/radio/headset/syndicate
uniform = /obj/item/clothing/under/imperial
mask = /obj/item/clothing/mask/gas/imperial
suit = /obj/item/clothing/suit/armor/combat/imperial/centurion
- belt = /obj/item/weapon/storage/belt/security/tactical/bandolier
- l_pocket = /obj/item/weapon/cell/device/weapon
- r_pocket = /obj/item/weapon/cell/device/weapon
- r_hand = /obj/item/weapon/melee/energy/sword/imperial
- l_hand = /obj/item/weapon/shield/energy/imperial
- suit_store = /obj/item/weapon/gun/energy/imperial
+ belt = /obj/item/storage/belt/security/tactical/bandolier
+ l_pocket = /obj/item/cell/device/weapon
+ r_pocket = /obj/item/cell/device/weapon
+ r_hand = /obj/item/melee/energy/sword/imperial
+ l_hand = /obj/item/shield/energy/imperial
+ suit_store = /obj/item/gun/energy/imperial
+
+ headset = /obj/item/radio/headset/syndicate
+ headset_alt = /obj/item/radio/headset/syndicate
+ headset_earbud = /obj/item/radio/headset/syndicate
/*
SOUTHERN CROSS OUTFITS
@@ -109,65 +124,77 @@ Keep outfits simple. Spawn with basic uniforms and minimal gear. Gear instead go
/decl/hierarchy/outfit/job/explorer2
- name = OUTFIT_JOB_NAME("Explorer")
+ name = OUTFIT_JOB_NAME(JOB_EXPLORER)
shoes = /obj/item/clothing/shoes/boots/winter/explorer
uniform = /obj/item/clothing/under/explorer
- l_ear = /obj/item/device/radio/headset/explorer
id_slot = slot_wear_id
pda_slot = slot_l_store
- pda_type = /obj/item/device/pda/explorer
- id_type = /obj/item/weapon/card/id/exploration
- id_pda_assignment = "Explorer"
- backpack = /obj/item/weapon/storage/backpack/explorer
- satchel_one = /obj/item/weapon/storage/backpack/satchel/explorer
- messenger_bag = /obj/item/weapon/storage/backpack/messenger/explorer
+ pda_type = /obj/item/pda/explorer
+ id_type = /obj/item/card/id/exploration
+ id_pda_assignment = JOB_EXPLORER
+ backpack = /obj/item/storage/backpack/explorer
+ satchel_one = /obj/item/storage/backpack/satchel/explorer
+ messenger_bag = /obj/item/storage/backpack/messenger/explorer
flags = OUTFIT_HAS_BACKPACK|OUTFIT_COMPREHENSIVE_SURVIVAL
+ headset = /obj/item/radio/headset/explorer
+ headset_alt = /obj/item/radio/headset/alt/explorer
+ headset_earbud = /obj/item/radio/headset/explorer
+
/decl/hierarchy/outfit/job/pilot
- name = OUTFIT_JOB_NAME("Pilot")
+ name = OUTFIT_JOB_NAME(JOB_PILOT)
shoes = /obj/item/clothing/shoes/black
uniform = /obj/item/clothing/under/rank/pilot1/no_webbing
suit = /obj/item/clothing/suit/storage/toggle/bomber/pilot
gloves = /obj/item/clothing/gloves/fingerless
glasses = /obj/item/clothing/glasses/fakesunglasses/aviator
- l_ear = /obj/item/device/radio/headset/pilot/alt
uniform_accessories = list(/obj/item/clothing/accessory/storage/webbing/pilot1 = 1)
id_slot = slot_wear_id
pda_slot = slot_belt
- pda_type = /obj/item/device/pda/pilot
- id_type = /obj/item/weapon/card/id/civilian/pilot
- id_pda_assignment = "Pilot"
+ pda_type = /obj/item/pda/pilot
+ id_type = /obj/item/card/id/civilian/pilot
+ id_pda_assignment = JOB_PILOT
flags = OUTFIT_HAS_BACKPACK|OUTFIT_COMPREHENSIVE_SURVIVAL
+ headset = /obj/item/radio/headset/pilot
+ headset_alt = /obj/item/radio/headset/alt/pilot
+ headset_earbud = /obj/item/radio/headset/alt/pilot
+
/decl/hierarchy/outfit/job/medical/sar
- name = OUTFIT_JOB_NAME("Field Medic")
+ name = OUTFIT_JOB_NAME(JOB_FIELD_MEDIC)
uniform = /obj/item/clothing/under/utility/blue
//suit = /obj/item/clothing/suit/storage/hooded/wintercoat/medical/sar
shoes = /obj/item/clothing/shoes/boots/winter/explorer
- l_ear = /obj/item/device/radio/headset/sar
- l_hand = /obj/item/weapon/storage/firstaid/regular
- belt = /obj/item/weapon/storage/belt/medical/emt
+ l_hand = /obj/item/storage/firstaid/regular
+ belt = /obj/item/storage/belt/medical/emt
pda_slot = slot_l_store
- pda_type = /obj/item/device/pda/sar
- id_type = /obj/item/weapon/card/id/exploration/fm
- id_pda_assignment = "Field Medic"
- backpack = /obj/item/weapon/storage/backpack/explorer
- satchel_one = /obj/item/weapon/storage/backpack/satchel/explorer
- messenger_bag = /obj/item/weapon/storage/backpack/messenger/explorer
+ pda_type = /obj/item/pda/sar
+ id_type = /obj/item/card/id/exploration/fm
+ id_pda_assignment = JOB_FIELD_MEDIC
+ backpack = /obj/item/storage/backpack/explorer
+ satchel_one = /obj/item/storage/backpack/satchel/explorer
+ messenger_bag = /obj/item/storage/backpack/messenger/explorer
flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL|OUTFIT_COMPREHENSIVE_SURVIVAL
+ headset = /obj/item/radio/headset/sar
+ headset_alt = /obj/item/radio/headset/alt/sar
+ headset_earbud = /obj/item/radio/headset/sar
+
/decl/hierarchy/outfit/job/pathfinder
- name = OUTFIT_JOB_NAME("Pathfinder")
+ name = OUTFIT_JOB_NAME(JOB_PATHFINDER)
shoes = /obj/item/clothing/shoes/boots/winter/explorer
uniform = /obj/item/clothing/under/explorer //TODO: Uniforms.
- l_ear = /obj/item/device/radio/headset/pathfinder
id_slot = slot_wear_id
pda_slot = slot_l_store
- pda_type = /obj/item/device/pda/pathfinder
- id_type = /obj/item/weapon/card/id/exploration/head
- id_pda_assignment = "Pathfinder"
+ pda_type = /obj/item/pda/pathfinder
+ id_type = /obj/item/card/id/exploration/head
+ id_pda_assignment = JOB_PATHFINDER
flags = OUTFIT_HAS_BACKPACK|OUTFIT_EXTENDED_SURVIVAL|OUTFIT_COMPREHENSIVE_SURVIVAL
+ headset = /obj/item/radio/headset/pathfinder
+ headset_alt = /obj/item/radio/headset/alt/pathfinder
+ headset_earbud = /obj/item/radio/headset/pathfinder
+
/decl/hierarchy/outfit/job/assistant/explorer
- id_type = /obj/item/weapon/card/id/exploration
+ id_type = /obj/item/card/id/exploration
flags = OUTFIT_HAS_BACKPACK|OUTFIT_COMPREHENSIVE_SURVIVAL
diff --git a/code/datums/outfits/pirates.dm b/code/datums/outfits/pirates.dm
index 0d15c3067db..5595ee357d7 100644
--- a/code/datums/outfits/pirates.dm
+++ b/code/datums/outfits/pirates.dm
@@ -5,7 +5,7 @@
shoes = /obj/item/clothing/shoes/brown
head = /obj/item/clothing/head/bandana
glasses = /obj/item/clothing/glasses/eyepatch
- l_hand = /obj/item/weapon/melee/energy/sword/pirate
+ l_hand = /obj/item/melee/energy/sword/pirate
/decl/hierarchy/outfit/pirate/norm
@@ -13,5 +13,5 @@
name = "Pirate - Space"
head = /obj/item/clothing/head/helmet/space
suit = /obj/item/clothing/suit/pirate
- back = /obj/item/weapon/tank/jetpack/oxygen
+ back = /obj/item/tank/jetpack/oxygen
flags = OUTFIT_HAS_JETPACK
diff --git a/code/datums/outfits/spec_op.dm b/code/datums/outfits/spec_op.dm
index bb43b4cb9bd..22da415b98b 100644
--- a/code/datums/outfits/spec_op.dm
+++ b/code/datums/outfits/spec_op.dm
@@ -2,24 +2,27 @@
name = "Special ops - Officer"
uniform = /obj/item/clothing/under/syndicate/combat
suit = /obj/item/clothing/suit/armor/swat/officer
- l_ear = /obj/item/device/radio/headset/ert
glasses = /obj/item/clothing/glasses/thermal/plain/eyepatch
mask = /obj/item/clothing/mask/smokable/cigarette/cigar/havana
head = /obj/item/clothing/head/beret //deathsquad
- belt = /obj/item/weapon/gun/energy/pulse_rifle/compact/admin
- back = /obj/item/weapon/storage/backpack/satchel
+ belt = /obj/item/gun/energy/pulse_rifle/compact/admin
+ back = /obj/item/storage/backpack/satchel
shoes = /obj/item/clothing/shoes/boots/combat
gloves = /obj/item/clothing/gloves/combat
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/centcom/ERT
+ id_type = /obj/item/card/id/centcom/ERT
id_desc = "Special operations ID."
id_pda_assignment = "Special Operations Officer"
+ headset = /obj/item/radio/headset/ert
+ headset_alt = /obj/item/radio/headset/ert
+ headset_earbud = /obj/item/radio/headset/ert
+
/decl/hierarchy/outfit/spec_op_officer/space
name = "Special ops - Officer in space"
suit = /obj/item/clothing/suit/armor/swat //obj/item/clothing/suit/space/void/swat
- back = /obj/item/weapon/tank/jetpack/oxygen
+ back = /obj/item/tank/jetpack/oxygen
mask = /obj/item/clothing/mask/gas/swat
flags = OUTFIT_HAS_JETPACK
@@ -29,13 +32,16 @@
uniform = /obj/item/clothing/under/ert
shoes = /obj/item/clothing/shoes/boots/swat
gloves = /obj/item/clothing/gloves/swat
- l_ear = /obj/item/device/radio/headset/ert
- belt = /obj/item/weapon/gun/energy/gun
+ belt = /obj/item/gun/energy/gun
glasses = /obj/item/clothing/glasses/sunglasses
- back = /obj/item/weapon/storage/backpack/satchel
+ back = /obj/item/storage/backpack/satchel
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/centcom/ERT
+ id_type = /obj/item/card/id/centcom/ERT
+
+ headset = /obj/item/radio/headset/ert
+ headset_alt = /obj/item/radio/headset/ert
+ headset_earbud = /obj/item/radio/headset/ert
/decl/hierarchy/outfit/death_command
name = "Spec ops - Death commando"
@@ -55,15 +61,18 @@
name = "Spec ops - Mercenary"
uniform = /obj/item/clothing/under/syndicate
shoes = /obj/item/clothing/shoes/boots/combat
- l_ear = /obj/item/device/radio/headset/syndicate
- belt = /obj/item/weapon/storage/belt/security
+ belt = /obj/item/storage/belt/security
glasses = /obj/item/clothing/glasses/sunglasses
gloves = /obj/item/clothing/gloves/swat
- l_pocket = /obj/item/weapon/reagent_containers/pill/cyanide
+ l_pocket = /obj/item/reagent_containers/pill/cyanide
id_slot = slot_wear_id
- id_type = /obj/item/weapon/card/id/syndicate
+ id_type = /obj/item/card/id/syndicate
id_pda_assignment = "Mercenary"
+ headset = /obj/item/radio/headset/syndicate
+ headset_alt = /obj/item/radio/headset/alt/syndicate
+ headset_earbud = /obj/item/radio/headset/earbud/syndicate
+
flags = OUTFIT_HAS_BACKPACK
diff --git a/code/datums/outfits/tournament.dm b/code/datums/outfits/tournament.dm
index a0c31f406bf..af524a1665f 100644
--- a/code/datums/outfits/tournament.dm
+++ b/code/datums/outfits/tournament.dm
@@ -2,9 +2,9 @@
hierarchy_type = /decl/hierarchy/outfit/tournament_gear
head = /obj/item/clothing/head/helmet/thunderdome
suit = /obj/item/clothing/suit/armor/vest
- l_hand = /obj/item/weapon/material/knife
- r_hand = /obj/item/weapon/gun/energy/pulse_rifle/destroyer
- r_pocket = /obj/item/weapon/grenade/smokebomb
+ l_hand = /obj/item/material/knife
+ r_hand = /obj/item/gun/energy/pulse_rifle/destroyer
+ r_pocket = /obj/item/grenade/smokebomb
shoes = /obj/item/clothing/shoes/black
/decl/hierarchy/outfit/tournament_gear/red
@@ -21,7 +21,7 @@
uniform = /obj/item/clothing/under/det
suit_store = /obj/item/clothing/suit/storage/det_trench
glasses = /obj/item/clothing/glasses/thermal/plain/monocle
- r_hand = /obj/item/weapon/gun/projectile/revolver
+ r_hand = /obj/item/gun/projectile/revolver
l_pocket = /obj/item/ammo_magazine/s357
/decl/hierarchy/outfit/tournament_gear/chef
@@ -29,21 +29,21 @@
head = /obj/item/clothing/head/chefhat
uniform = /obj/item/clothing/under/rank/chef
suit = /obj/item/clothing/suit/chef
- r_hand = /obj/item/weapon/material/kitchen/rollingpin
- l_pocket = /obj/item/weapon/material/knife/tacknife
- r_pocket = /obj/item/weapon/material/knife/tacknife
+ r_hand = /obj/item/material/kitchen/rollingpin
+ l_pocket = /obj/item/material/knife/tacknife
+ r_pocket = /obj/item/material/knife/tacknife
/decl/hierarchy/outfit/tournament_gear/janitor
name = "Tournament gear - Janitor"
uniform = /obj/item/clothing/under/rank/janitor
- back = /obj/item/weapon/storage/backpack
- r_hand = /obj/item/weapon/mop
- l_hand = /obj/item/weapon/reagent_containers/glass/bucket
- l_pocket = /obj/item/weapon/grenade/chem_grenade/cleaner
- r_pocket = /obj/item/weapon/grenade/chem_grenade/cleaner
+ back = /obj/item/storage/backpack
+ r_hand = /obj/item/mop
+ l_hand = /obj/item/reagent_containers/glass/bucket
+ l_pocket = /obj/item/grenade/chem_grenade/cleaner
+ r_pocket = /obj/item/grenade/chem_grenade/cleaner
backpack_contents = list(/obj/item/stack/tile/floor = 6)
/decl/hierarchy/outfit/tournament_gear/janitor/post_equip(var/mob/living/carbon/human/H)
- var/obj/item/weapon/reagent_containers/glass/bucket/bucket = locate(/obj/item/weapon/reagent_containers/glass/bucket) in H
+ var/obj/item/reagent_containers/glass/bucket/bucket = locate(/obj/item/reagent_containers/glass/bucket) in H
if(bucket)
bucket.reagents.add_reagent(/datum/reagent/water, 70)
diff --git a/code/datums/outfits/wizardry.dm b/code/datums/outfits/wizardry.dm
index 4d25979f18e..0cb82f75f28 100644
--- a/code/datums/outfits/wizardry.dm
+++ b/code/datums/outfits/wizardry.dm
@@ -1,14 +1,17 @@
/decl/hierarchy/outfit/wizard
uniform = /obj/item/clothing/under/color/lightpurple
shoes = /obj/item/clothing/shoes/sandal
- l_ear = /obj/item/device/radio/headset
- r_pocket = /obj/item/weapon/teleportation_scroll
- l_hand = /obj/item/weapon/staff
- r_hand = /obj/item/weapon/spellbook
- back = /obj/item/weapon/storage/backpack
- backpack_contents = list(/obj/item/weapon/storage/box = 1)
+ r_pocket = /obj/item/teleportation_scroll
+ l_hand = /obj/item/staff
+ r_hand = /obj/item/spellbook
+ back = /obj/item/storage/backpack
+ backpack_contents = list(/obj/item/storage/box = 1)
hierarchy_type = /decl/hierarchy/outfit/wizard
+ headset = /obj/item/radio/headset
+ headset_alt = /obj/item/radio/headset
+ headset_earbud = /obj/item/radio/headset
+
/decl/hierarchy/outfit/wizard/blue
name = "Wizard - Blue"
head = /obj/item/clothing/head/wizard
diff --git a/code/datums/progressbar.dm b/code/datums/progressbar.dm
index 8da8d7c0004..b0825c63298 100644
--- a/code/datums/progressbar.dm
+++ b/code/datums/progressbar.dm
@@ -41,7 +41,7 @@
progress = CLAMP(progress, 0, goal)
bar.icon_state = "prog_bar_[round(((progress / goal) * 100), 5)]"
- if(!shown && user.is_preference_enabled(/datum/client_preference/show_progress_bar))
+ if(!shown && user.client?.prefs?.read_preference(/datum/preference/toggle/show_progress_bar))
user.client.images += bar
shown = 1
@@ -66,4 +66,4 @@
qdel(bar)
. = ..()
-#undef PROGRESSBAR_HEIGHT
\ No newline at end of file
+#undef PROGRESSBAR_HEIGHT
diff --git a/code/datums/repositories/crew.dm b/code/datums/repositories/crew.dm
index 861e02ae4b5..ae94e78726a 100644
--- a/code/datums/repositories/crew.dm
+++ b/code/datums/repositories/crew.dm
@@ -25,7 +25,7 @@ var/global/datum/repository/crew/crew_repository = new()
for(var/obj/item/clothing/under/C in tracked)
var/turf/pos = get_turf(C)
var/area/B = pos?.loc //VOREStation Add: No sensor in Dorm
- if((C.has_sensor) && (pos?.z == zLevel) && (C.sensor_mode != SUIT_SENSOR_OFF) && !(B.block_suit_sensors) && !(is_jammed(C)) && !(is_vore_jammed(C))) //VOREStation Edit
+ if((C.has_sensor) && (pos?.z == zLevel) && (C.sensor_mode != SUIT_SENSOR_OFF) && !(B.flag_check(AREA_BLOCK_SUIT_SENSORS)) && !(is_jammed(C)) && !(is_vore_jammed(C))) //VOREStation Edit
if(istype(C.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C.loc
if(H.w_uniform != C)
diff --git a/code/datums/riding.dm b/code/datums/riding.dm
index ebe600c718f..72b4f2bd984 100644
--- a/code/datums/riding.dm
+++ b/code/datums/riding.dm
@@ -93,7 +93,7 @@
if(only_one_driver && ridden.buckled_mobs.len)
var/mob/living/driver = ridden.buckled_mobs[1]
if(driver != user)
- to_chat(user, "\The [ridden] can only be controlled by one person at a time, and is currently being controlled by \the [driver].")
+ to_chat(user, span_warning("\The [ridden] can only be controlled by one person at a time, and is currently being controlled by \the [driver]."))
return
if(world.time < next_vehicle_move)
@@ -109,7 +109,7 @@
handle_vehicle_layer()
handle_vehicle_offsets()
else
- to_chat(user, "You'll need [key_name] in one of your hands to move \the [ridden].")
+ to_chat(user, span_warning("You'll need [key_name] in one of your hands to move \the [ridden]."))
/datum/riding/proc/Unbuckle(atom/movable/M)
// addtimer(CALLBACK(ridden, TYPE_PROC_REF(/atom/movable, unbuckle_mob), M), 0, TIMER_UNIQUE)
@@ -119,7 +119,7 @@
ridden.unbuckle_mob(M)
/datum/riding/proc/Process_Spacemove(direction)
- if(ridden.has_gravity())
+ if(ridden.get_gravity())
return TRUE
return FALSE
@@ -133,7 +133,7 @@
// I'm on a
/datum/riding/boat
- keytype = /obj/item/weapon/oar
+ keytype = /obj/item/oar
key_name = "an oar"
nonhuman_key_exemption = TRUE // Borgs can't hold oars.
only_one_driver = TRUE // Would be pretty crazy if five people try to move at the same time.
@@ -143,12 +143,12 @@
var/turf/current = get_turf(ridden)
if(istype(current, /turf/simulated/floor/water/underwater)) //don't work at the bottom of the ocean!
- to_chat(user, "The boat has sunk!")
+ to_chat(user, span_warning("The boat has sunk!"))
return FALSE
else if(istype(next, /turf/simulated/floor/water) || istype(current, /turf/simulated/floor/water)) //We can move from land to water, or water to land, but not from land to land
..()
else
- to_chat(user, "Boats don't go on land!")
+ to_chat(user, span_warning("Boats don't go on land!"))
return FALSE
/datum/riding/boat/small // 'Small' boats can hold up to two people.
diff --git a/code/datums/roundstats/departmentgoal.dm b/code/datums/roundstats/departmentgoal.dm
index 333e6c03963..ebebd56136f 100644
--- a/code/datums/roundstats/departmentgoal.dm
+++ b/code/datums/roundstats/departmentgoal.dm
@@ -41,16 +41,16 @@ GLOBAL_LIST(active_department_goals)
for(var/category in GLOB.active_department_goals)
var/list/cat_goals = GLOB.active_department_goals[category]
- to_world("[category]")
+ to_world(span_world("[category]"))
if(!LAZYLEN(cat_goals))
- to_world("There were no assigned goals!")
+ to_world(span_filter_system("There were no assigned goals!"))
else
for(var/datum/goal/G in cat_goals)
var/success = G.check_completion()
- to_world("[success ? "[G.name]" : "[G.name]"]")
- to_world("[G.goal_text]")
+ to_world(span_filter_system("[success ? span_notice("[G.name]") : span_warning("[G.name]")]"))
+ to_world(span_filter_system("[G.goal_text]"))
return 1
/datum/goal
diff --git a/code/datums/roundstats/roundstats.dm b/code/datums/roundstats/roundstats.dm
index ebff1fea4fa..c01a38a2e74 100644
--- a/code/datums/roundstats/roundstats.dm
+++ b/code/datums/roundstats/roundstats.dm
@@ -58,7 +58,7 @@ var/global/list/security_printer_tickets = list() //VOREStation Edit
//VOREStation add Start - Ticket time!
if(security_printer_tickets.len)
- valid_stats_list.Add("[security_printer_tickets.len] unique security tickets were issued today!
Examples include:")
+ valid_stats_list.Add(span_danger("[security_printer_tickets.len] unique security tickets were issued today!") + "
Examples include:")
var/good_num = 5
var/ourticket
while(good_num > 0)
@@ -67,7 +67,7 @@ var/global/list/security_printer_tickets = list() //VOREStation Edit
ourticket = pick(security_printer_tickets)
security_printer_tickets -= ourticket
if(ourticket)
- valid_stats_list.Add("-\"[ourticket]\"")
+ valid_stats_list.Add(span_bold("-")+"\"[ourticket]\"")
good_num--
else
good_num = 0
@@ -84,7 +84,7 @@ var/global/list/security_printer_tickets = list() //VOREStation Edit
//VOREStation Add End
if(LAZYLEN(valid_stats_list))
- to_world("Shift trivia!")
+ to_world(span_world("Shift trivia!"))
for(var/body in valid_stats_list)
- to_world("[body]")
+ to_world(span_filter_system("[body]"))
diff --git a/code/datums/supplypacks/atmospherics.dm b/code/datums/supplypacks/atmospherics.dm
index 13ca4cf1a95..883fec6fe47 100644
--- a/code/datums/supplypacks/atmospherics.dm
+++ b/code/datums/supplypacks/atmospherics.dm
@@ -9,7 +9,7 @@
/datum/supply_pack/atmos/inflatable
name = "Inflatable barriers"
- contains = list(/obj/item/weapon/storage/briefcase/inflatable = 3)
+ contains = list(/obj/item/storage/briefcase/inflatable = 3)
cost = 20
containertype = /obj/structure/closet/crate/aether
containername = "Inflatable Barrier Crate"
@@ -66,7 +66,7 @@
access = access_atmospherics
/datum/supply_pack/atmos/rapid_pipe_dispenser
- contains = list(/obj/item/weapon/pipe_dispenser)
+ contains = list(/obj/item/pipe_dispenser)
name = "Rapid Pipe Dispenser"
cost = 100
containertype = /obj/structure/closet/crate/secure/aether
@@ -77,7 +77,7 @@
name = "Internals crate"
contains = list(
/obj/item/clothing/mask/gas = 3,
- /obj/item/weapon/tank/air = 3
+ /obj/item/tank/air = 3
)
cost = 10
containertype = /obj/structure/closet/crate/aether
@@ -86,10 +86,10 @@
/datum/supply_pack/atmos/evacuation
name = "Emergency equipment"
contains = list(
- /obj/item/weapon/storage/toolbox/emergency = 2,
+ /obj/item/storage/toolbox/emergency = 2,
/obj/item/clothing/suit/storage/hazardvest = 2,
/obj/item/clothing/suit/storage/vest = 2,
- /obj/item/weapon/tank/emergency/oxygen/engi = 4,
+ /obj/item/tank/emergency/oxygen/engi = 4,
/obj/item/clothing/suit/space/emergency = 4,
/obj/item/clothing/head/helmet/space/emergency = 4,
/obj/item/clothing/mask/gas = 4
@@ -102,9 +102,9 @@
name = "Firefighting equipment"
contains = list(
/obj/item/clothing/suit/fire/heavy = 2,
- /obj/item/weapon/tank/oxygen/red = 2,
- /obj/item/weapon/watertank/atmos = 2,
- /obj/item/device/flashlight = 2,
+ /obj/item/tank/oxygen/red = 2,
+ /obj/item/watertank/atmos = 2,
+ /obj/item/flashlight = 2,
/obj/item/clothing/head/hardhat/firefighter/atmos = 2
)
cost = 35
diff --git a/code/datums/supplypacks/contraband.dm b/code/datums/supplypacks/contraband.dm
index a2b9fcbd3bc..215ec5288a7 100644
--- a/code/datums/supplypacks/contraband.dm
+++ b/code/datums/supplypacks/contraband.dm
@@ -8,9 +8,9 @@
num_contained = 5
contains = list(
/obj/item/seeds/bloodtomatoseed,
- /obj/item/weapon/storage/pill_bottle/zoom,
- /obj/item/weapon/storage/pill_bottle/happy,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/pwine
+ /obj/item/storage/pill_bottle/zoom,
+ /obj/item/storage/pill_bottle/happy,
+ /obj/item/reagent_containers/food/drinks/bottle/pwine
)
name = "Contraband crate"
@@ -23,9 +23,9 @@
/datum/supply_pack/security/specialops
name = "Special Ops supplies"
contains = list(
- /obj/item/weapon/storage/box/emps,
- /obj/item/weapon/grenade/smokebomb = 4,
- /obj/item/weapon/grenade/chem_grenade/incendiary
+ /obj/item/storage/box/emps,
+ /obj/item/grenade/smokebomb = 4,
+ /obj/item/grenade/chem_grenade/incendiary
)
cost = 25
containertype = /obj/structure/closet/crate/weapon
@@ -35,8 +35,8 @@
/datum/supply_pack/supply/moghes
name = "Moghes imports"
contains = list(
- /obj/item/weapon/reagent_containers/food/drinks/bottle/redeemersbrew = 2,
- /obj/item/weapon/reagent_containers/food/snacks/unajerky = 4
+ /obj/item/reagent_containers/food/drinks/bottle/redeemersbrew = 2,
+ /obj/item/reagent_containers/food/snacks/unajerky = 4
)
cost = 25
containertype = /obj/structure/closet/crate/unathi
@@ -46,7 +46,7 @@
/datum/supply_pack/munitions/bolt_rifles_militia
name = "Weapon - Surplus militia rifles"
contains = list(
- /obj/item/weapon/gun/projectile/shotgun/pump/rifle = 3,
+ /obj/item/gun/projectile/shotgun/pump/rifle = 3,
/obj/item/ammo_magazine/clip/c762 = 6
)
cost = 1000
@@ -59,37 +59,59 @@
num_contained = 1
contains = list(
list( //the operator,
+ /obj/item/gun/projectile/shotgun/pump/combat,
/obj/item/clothing/suit/storage/vest/heavy/merc,
/obj/item/clothing/glasses/night,
- /obj/item/weapon/storage/box/anti_photons
+ /obj/item/storage/box/anti_photons,
+ /obj/item/ammo_magazine/clip/c12g/pellet,
+ /obj/item/ammo_magazine/clip/c12g
),
- list( //the indian,
- /obj/item/weapon/gun/projectile/dartgun,
+ list( //the doc,
+ /obj/item/storage/firstaid/combat,
+ /obj/item/gun/projectile/dartgun,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/reagent_containers/glass/bottle/chloralhydrate,
+ /obj/item/reagent_containers/glass/bottle/cyanide,
/obj/item/ammo_magazine/chemdart
),
list( //the doc,
- /obj/item/weapon/storage/firstaid/combat,
- /obj/item/weapon/reagent_containers/hypospray
+ /obj/item/storage/firstaid/combat,
+ /obj/item/reagent_containers/hypospray
),
list( //the sapper,
- /obj/item/weapon/melee/energy/sword/ionic_rapier,
- /obj/item/weapon/storage/box/syndie_kit/space, //doesn't matter what species you are,
- /obj/item/device/multitool/ai_detector,
- /obj/item/weapon/storage/toolbox/syndicate/powertools
+ /obj/item/melee/energy/sword/ionic_rapier,
+ /obj/item/storage/box/syndie_kit/space, //doesn't matter what species you are,
+ /obj/item/storage/box/syndie_kit/demolitions,
+ /obj/item/multitool/ai_detector,
+ /obj/item/plastique,
+ /obj/item/storage/toolbox/syndicate/powertools
),
list( //the infiltrator,
- /obj/item/device/chameleon,
- /obj/item/weapon/storage/box/syndie_kit/chameleon,
- /obj/item/device/encryptionkey/syndicate,
- /obj/item/weapon/card/id/syndicate,
+ /obj/item/gun/projectile/silenced,
+ /obj/item/chameleon,
+ /obj/item/storage/box/syndie_kit/chameleon,
+ /obj/item/encryptionkey/syndicate,
+ /obj/item/card/id/syndicate,
/obj/item/clothing/mask/gas/voice,
- /obj/item/weapon/makeover
+ /obj/item/makeover
+ ),
+ list( //the hacker,
+ /obj/item/gun/projectile/silenced,
+ /obj/item/gun/energy/ionrifle/pistol,
+ /obj/item/clothing/glasses/thermal/syndi,
+ /obj/item/ammo_magazine/m45/ap,
+ /obj/item/material/knife/tacknife/combatknife,
+ /obj/item/multitool/hacktool/modified
),
list( //the professional,
- /obj/item/weapon/gun/energy/ionrifle/pistol,
- /obj/item/weapon/material/knife/tacknife/combatknife,
+ /obj/item/gun/projectile/silenced,
+ /obj/item/gun/energy/ionrifle/pistol,
+ /obj/item/clothing/glasses/thermal/syndi,
+ /obj/item/card/emag,
+ /obj/item/ammo_magazine/m45/ap,
+ /obj/item/material/knife/tacknife/combatknife,
/obj/item/clothing/mask/balaclava
)
)
diff --git a/code/datums/supplypacks/costumes.dm b/code/datums/supplypacks/costumes.dm
index 6bdb9adce8e..7e6ae4a9edd 100644
--- a/code/datums/supplypacks/costumes.dm
+++ b/code/datums/supplypacks/costumes.dm
@@ -13,7 +13,7 @@
/datum/supply_pack/costumes/wizard
name = "Wizard costume"
contains = list(
- /obj/item/weapon/staff,
+ /obj/item/staff,
/obj/item/clothing/suit/wizrobe/fake,
/obj/item/clothing/shoes/sandal,
/obj/item/clothing/head/wizard/fake
@@ -118,7 +118,7 @@
/obj/item/clothing/suit/wizrobe/marisa/fake,
/obj/item/clothing/shoes/sandal,
/obj/item/clothing/head/wizard/marisa/fake,
- /obj/item/weapon/staff/broom
+ /obj/item/staff/broom
)
/datum/supply_pack/randomised/costumes/costume_hats
@@ -536,9 +536,9 @@
/datum/supply_pack/costumes/taurbags
name = "Saddlebags crate"
contains = list(
- /obj/item/weapon/storage/backpack/saddlebag_common,
- /obj/item/weapon/storage/backpack/saddlebag_common/robust,
- /obj/item/weapon/storage/backpack/saddlebag_common/vest
+ /obj/item/storage/backpack/saddlebag_common,
+ /obj/item/storage/backpack/saddlebag_common/robust,
+ /obj/item/storage/backpack/saddlebag_common/vest
)
cost = 60
containertype = /obj/structure/closet/crate
diff --git a/code/datums/supplypacks/engineering.dm b/code/datums/supplypacks/engineering.dm
index a8f763c7a2f..f0a8e4d4b70 100644
--- a/code/datums/supplypacks/engineering.dm
+++ b/code/datums/supplypacks/engineering.dm
@@ -9,28 +9,28 @@
/datum/supply_pack/eng/lightbulbs
name = "Replacement lights"
- contains = list(/obj/item/weapon/storage/box/lights/mixed = 3)
+ contains = list(/obj/item/storage/box/lights/mixed = 3)
cost = 10
containertype = /obj/structure/closet/crate/galaksi
containername = "Replacement lights"
/datum/supply_pack/eng/smescoil
name = "Superconducting Magnetic Coil"
- contains = list(/obj/item/weapon/smes_coil)
+ contains = list(/obj/item/smes_coil)
cost = 75
containertype = /obj/structure/closet/crate/focalpoint
containername = "Superconducting Magnetic Coil crate"
/datum/supply_pack/eng/smescoil/super_capacity
name = "Superconducting Capacitance Coil"
- contains = list(/obj/item/weapon/smes_coil/super_capacity)
+ contains = list(/obj/item/smes_coil/super_capacity)
cost = 90
containertype = /obj/structure/closet/crate/focalpoint
containername = "Superconducting Capacitance Coil crate"
/datum/supply_pack/eng/smescoil/super_io
name = "Superconducting Transmission Coil"
- contains = list(/obj/item/weapon/smes_coil/super_io)
+ contains = list(/obj/item/smes_coil/super_io)
cost = 90
containertype = /obj/structure/closet/crate/focalpoint
containername = "Superconducting Transmission Coil crate"
@@ -79,14 +79,14 @@
/datum/supply_pack/eng/point_defense_cannon_circuit
name = "Point Defense Turret Circuit"
- contains = list(/obj/item/weapon/circuitboard/pointdefense = 2)
+ contains = list(/obj/item/circuitboard/pointdefense = 2)
cost = 20
containertype = /obj/structure/closet/crate/heph
containername = "point defense turret circuit crate"
/datum/supply_pack/eng/point_defense_control_circuit
name = "Point Defense Controller Circuit"
- contains = list(/obj/item/weapon/circuitboard/pointdefense_control = 1)
+ contains = list(/obj/item/circuitboard/pointdefense_control = 1)
cost = 30
containertype = /obj/structure/closet/crate/heph
containername = "point defense mainframe circuit crate"
@@ -94,10 +94,10 @@
/datum/supply_pack/eng/electrical
name = "Electrical maintenance crate"
contains = list(
- /obj/item/weapon/storage/toolbox/electrical = 2,
+ /obj/item/storage/toolbox/electrical = 2,
/obj/item/clothing/gloves/yellow = 2,
- /obj/item/weapon/cell = 2,
- /obj/item/weapon/cell/high = 2
+ /obj/item/cell = 2,
+ /obj/item/cell/high = 2
)
cost = 10
containertype = /obj/structure/closet/crate/ward
@@ -106,7 +106,7 @@
/datum/supply_pack/eng/e_welders
name = "Electric welder crate"
contains = list(
- /obj/item/weapon/weldingtool/electric = 3
+ /obj/item/weldingtool/electric = 3
)
cost = 15
containertype = /obj/structure/closet/crate/ward
@@ -115,7 +115,7 @@
/datum/supply_pack/eng/mechanical
name = "Mechanical maintenance crate"
contains = list(
- /obj/item/weapon/storage/belt/utility/full = 3,
+ /obj/item/storage/belt/utility/full = 3,
/obj/item/clothing/suit/storage/hazardvest = 3,
/obj/item/clothing/head/welding = 2,
/obj/item/clothing/head/hardhat
@@ -135,9 +135,9 @@
name = "Solar Pack crate"
contains = list(
/obj/item/solar_assembly = 21,
- /obj/item/weapon/circuitboard/solar_control,
- /obj/item/weapon/tracker_electronics,
- /obj/item/weapon/paper/solar
+ /obj/item/circuitboard/solar_control,
+ /obj/item/tracker_electronics,
+ /obj/item/paper/solar
)
cost = 20
containertype = /obj/structure/closet/crate/einstein
@@ -195,7 +195,7 @@
access = access_ce
/datum/supply_pack/eng/shield_gen
- contains = list(/obj/item/weapon/circuitboard/shield_gen)
+ contains = list(/obj/item/circuitboard/shield_gen)
name = "Bubble shield generator circuitry"
cost = 30
containertype = /obj/structure/closet/crate/secure/focalpoint
@@ -203,7 +203,7 @@
access = access_ce
/datum/supply_pack/eng/shield_gen_ex
- contains = list(/obj/item/weapon/circuitboard/shield_gen_ex)
+ contains = list(/obj/item/circuitboard/shield_gen_ex)
name = "Hull shield generator circuitry"
cost = 30
containertype = /obj/structure/closet/crate/secure/focalpoint
@@ -211,7 +211,7 @@
access = access_ce
/datum/supply_pack/eng/shield_cap
- contains = list(/obj/item/weapon/circuitboard/shield_cap)
+ contains = list(/obj/item/circuitboard/shield_cap)
name = "Bubble shield capacitor circuitry"
cost = 30
containertype = /obj/structure/closet/crate/secure/focalpoint
@@ -269,10 +269,10 @@
containertype = /obj/structure/closet/crate/secure/focalpoint
access = access_tech_storage
contains = list(
- /obj/item/weapon/stock_parts/micro_laser,
- /obj/item/weapon/stock_parts/capacitor,
- /obj/item/weapon/stock_parts/matter_bin,
- /obj/item/weapon/circuitboard/pacman
+ /obj/item/stock_parts/micro_laser,
+ /obj/item/stock_parts/capacitor,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/circuitboard/pacman
)
/datum/supply_pack/eng/super_pacman_parts
@@ -282,10 +282,10 @@
containertype = /obj/structure/closet/crate/secure/focalpoint
access = access_tech_storage
contains = list(
- /obj/item/weapon/stock_parts/micro_laser,
- /obj/item/weapon/stock_parts/capacitor,
- /obj/item/weapon/stock_parts/matter_bin,
- /obj/item/weapon/circuitboard/pacman/super
+ /obj/item/stock_parts/micro_laser,
+ /obj/item/stock_parts/capacitor,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/circuitboard/pacman/super
)
/datum/supply_pack/eng/fusion_core
@@ -295,9 +295,9 @@
containertype = /obj/structure/closet/crate/secure/einstein
access = access_engine
contains = list(
- /obj/item/weapon/book/manual/rust_engine,
+ /obj/item/book/manual/rust_engine,
/obj/machinery/power/fusion_core,
- /obj/item/weapon/circuitboard/fusion_core
+ /obj/item/circuitboard/fusion_core
)
/datum/supply_pack/eng/fusion_fuel_injector
@@ -309,7 +309,7 @@
contains = list(
/obj/machinery/fusion_fuel_injector,
/obj/machinery/fusion_fuel_injector,
- /obj/item/weapon/circuitboard/fusion_injector
+ /obj/item/circuitboard/fusion_injector
)
/datum/supply_pack/eng/gyrotron
@@ -320,7 +320,7 @@
access = access_engine
contains = list(
/obj/machinery/power/emitter/gyrotron,
- /obj/item/weapon/circuitboard/gyrotron
+ /obj/item/circuitboard/gyrotron
)
/datum/supply_pack/eng/fusion_fuel_compressor
@@ -328,7 +328,14 @@
cost = 10
containername = "Fusion Fuel Compressor circuitry crate"
containertype = /obj/structure/closet/crate/einstein
- contains = list(/obj/item/weapon/circuitboard/fusion_fuel_compressor)
+ contains = list(/obj/item/circuitboard/fusion_fuel_compressor)
+
+/datum/supply_pack/eng/deuterium
+ name = "Deuterium crate"
+ cost = 50
+ containername = "Deuterium crate"
+ containertype = /obj/structure/closet/crate/einstein
+ contains = list(/obj/fiftyspawner/deuterium)
/datum/supply_pack/eng/tritium
name = "Tritium crate"
@@ -340,12 +347,12 @@
/datum/supply_pack/eng/modern_shield
name = "Modern Shield Construction Kit"
contains = list(
- /obj/item/weapon/circuitboard/shield_generator,
- /obj/item/weapon/stock_parts/capacitor,
- /obj/item/weapon/stock_parts/micro_laser,
- /obj/item/weapon/smes_coil,
- /obj/item/weapon/stock_parts/console_screen,
- /obj/item/weapon/stock_parts/subspace/amplifier
+ /obj/item/circuitboard/shield_generator,
+ /obj/item/stock_parts/capacitor,
+ /obj/item/stock_parts/micro_laser,
+ /obj/item/smes_coil,
+ /obj/item/stock_parts/console_screen,
+ /obj/item/stock_parts/subspace/amplifier
)
cost = 80
containertype = /obj/structure/closet/crate/focalpoint
@@ -366,7 +373,7 @@
)
/datum/supply_pack/eng/dosimeter
- contains = list(/obj/item/weapon/storage/box/dosimeter = 6)
+ contains = list(/obj/item/storage/box/dosimeter = 6)
name = "Dosimeters"
cost = 10
containertype = /obj/structure/closet/crate
@@ -387,7 +394,7 @@
access = access_ce
/datum/supply_pack/eng/inducer
- contains = list(/obj/item/weapon/inducer = 3)
+ contains = list(/obj/item/inducer = 3)
name = "inducer"
cost = 90 //Relatively expensive
containertype = /obj/structure/closet/crate/xion
diff --git a/code/datums/supplypacks/hardsuits.dm b/code/datums/supplypacks/hardsuits.dm
index 1b84c5e6c9a..4bbb5b5158c 100644
--- a/code/datums/supplypacks/hardsuits.dm
+++ b/code/datums/supplypacks/hardsuits.dm
@@ -10,7 +10,7 @@
/datum/supply_pack/hardsuits/eva_rig
name = "eva hardsuit (empty)"
contains = list(
- /obj/item/weapon/rig/eva = 1
+ /obj/item/rig/eva = 1
)
cost = 150
containertype = /obj/structure/closet/crate/secure/gear
@@ -23,7 +23,7 @@
/datum/supply_pack/hardsuits/mining_rig
name = "industrial hardsuit (empty)"
contains = list(
- /obj/item/weapon/rig/industrial = 1
+ /obj/item/rig/industrial = 1
)
cost = 150
containertype = /obj/structure/closet/crate/secure/gear
@@ -35,7 +35,7 @@
/datum/supply_pack/hardsuits/medical_rig
name = "medical hardsuit (empty)"
contains = list(
- /obj/item/weapon/rig/medical = 1
+ /obj/item/rig/medical = 1
)
cost = 150
containertype = /obj/structure/closet/crate/secure/gear
@@ -45,7 +45,7 @@
/datum/supply_pack/hardsuits/security_rig
name = "hazard hardsuit (empty)"
contains = list(
- /obj/item/weapon/rig/hazard = 1
+ /obj/item/rig/hazard = 1
)
cost = 150
containertype = /obj/structure/closet/crate/secure/gear
@@ -55,7 +55,7 @@
/datum/supply_pack/hardsuits/science_rig
name = "ami hardsuit (empty)"
contains = list(
- /obj/item/weapon/rig/hazmat = 1
+ /obj/item/rig/hazmat = 1
)
cost = 150
containertype = /obj/structure/closet/crate/secure/gear
@@ -65,7 +65,7 @@
/datum/supply_pack/hardsuits/ce_rig
name = "advanced hardsuit (empty)"
contains = list(
- /obj/item/weapon/rig/ce = 1
+ /obj/item/rig/ce = 1
)
cost = 150
containertype = /obj/structure/closet/crate/secure/gear
@@ -75,7 +75,7 @@
/datum/supply_pack/hardsuits/com_medical_rig
name = "solgov medical hardsuit (loaded)" //YW EDIT
contains = list(
- /obj/item/weapon/rig/baymed/equipped = 1
+ /obj/item/rig/baymed/equipped = 1
)
cost = 250
containertype = /obj/structure/closet/crate/secure/gear
@@ -85,7 +85,7 @@
/datum/supply_pack/hardsuits/com_engineering_rig
name = "solgov engineering hardsuit (loaded)" //YW EDIT
contains = list(
- /obj/item/weapon/rig/bayeng/equipped = 1
+ /obj/item/rig/bayeng/equipped = 1
)
cost = 250
containertype = /obj/structure/closet/crate/secure/gear
@@ -96,7 +96,7 @@
/datum/supply_pack/hardsuits/breacher_rig
name = "unathi breacher hardsuit (empty)"
contains = list(
- /obj/item/weapon/rig/breacher = 1
+ /obj/item/rig/breacher = 1
)
cost = 250
containertype = /obj/structure/closet/crate/secure/gear
@@ -107,7 +107,7 @@
/datum/supply_pack/hardsuits/zero_rig
name = "null hardsuit (jets)"
contains = list(
- /obj/item/weapon/rig/zero = 1
+ /obj/item/rig/zero = 1
)
cost = 75
containertype = /obj/structure/closet/crate/secure/gear
diff --git a/code/datums/supplypacks/hospitality.dm b/code/datums/supplypacks/hospitality.dm
index baef23eb1a8..8ee18ac817b 100644
--- a/code/datums/supplypacks/hospitality.dm
+++ b/code/datums/supplypacks/hospitality.dm
@@ -10,18 +10,18 @@
/datum/supply_pack/hospitality/party
name = "Party equipment"
contains = list(
- /obj/item/weapon/storage/box/mixedglasses = 2,
- /obj/item/weapon/storage/box/glasses/square,
- /obj/item/weapon/reagent_containers/food/drinks/shaker,
- /obj/item/weapon/reagent_containers/food/drinks/flask/barflask,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/patron,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/specialwhiskey,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/jager,
- /obj/item/weapon/storage/fancy/cigarettes/dromedaryco,
- /obj/item/weapon/lipstick/random,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/small/ale = 2,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/small/beer = 4,
+ /obj/item/storage/box/mixedglasses = 2,
+ /obj/item/storage/box/glasses/square,
+ /obj/item/reagent_containers/food/drinks/shaker,
+ /obj/item/reagent_containers/food/drinks/flask/barflask,
+ /obj/item/reagent_containers/food/drinks/bottle/patron,
+ /obj/item/reagent_containers/food/drinks/bottle/goldschlager,
+ /obj/item/reagent_containers/food/drinks/bottle/specialwhiskey,
+ /obj/item/reagent_containers/food/drinks/bottle/jager,
+ /obj/item/storage/fancy/cigarettes/dromedaryco,
+ /obj/item/lipstick/random,
+ /obj/item/reagent_containers/food/drinks/bottle/small/ale = 2,
+ /obj/item/reagent_containers/food/drinks/bottle/small/beer = 4,
)
cost = 10
containertype = /obj/structure/closet/crate/gilthari
@@ -30,19 +30,19 @@
/datum/supply_pack/hospitality/barsupplies
name = "Bar supplies"
contains = list(
- /obj/item/weapon/storage/box/glasses/cocktail,
- /obj/item/weapon/storage/box/glasses/rocks,
- /obj/item/weapon/storage/box/glasses/square,
- /obj/item/weapon/storage/box/glasses/pint,
- /obj/item/weapon/storage/box/glasses/wine,
- /obj/item/weapon/storage/box/glasses/shake,
- /obj/item/weapon/storage/box/glasses/shot,
- /obj/item/weapon/storage/box/glasses/mug,
- /obj/item/weapon/storage/box/glasses/meta,
- /obj/item/weapon/storage/box/glasses/meta/metapint,
- /obj/item/weapon/reagent_containers/food/drinks/shaker,
- /obj/item/weapon/storage/box/glass_extras/straws,
- /obj/item/weapon/storage/box/glass_extras/sticks
+ /obj/item/storage/box/glasses/cocktail,
+ /obj/item/storage/box/glasses/rocks,
+ /obj/item/storage/box/glasses/square,
+ /obj/item/storage/box/glasses/pint,
+ /obj/item/storage/box/glasses/wine,
+ /obj/item/storage/box/glasses/shake,
+ /obj/item/storage/box/glasses/shot,
+ /obj/item/storage/box/glasses/mug,
+ /obj/item/storage/box/glasses/meta,
+ /obj/item/storage/box/glasses/meta/metapint,
+ /obj/item/reagent_containers/food/drinks/shaker,
+ /obj/item/storage/box/glass_extras/straws,
+ /obj/item/storage/box/glass_extras/sticks
)
cost = 10
containertype = /obj/structure/closet/crate/gilthari
@@ -59,7 +59,7 @@
name = "Surprise pack of five pizzas"
contains = list(
/obj/random/pizzabox/supplypack = 5,
- /obj/item/weapon/material/knife/plastic,
+ /obj/item/material/knife/plastic,
/obj/item/clothing/under/pizzaguy,
/obj/item/clothing/head/pizzaguy
)
@@ -71,11 +71,11 @@
name = "Gift crate"
contains = list(
/obj/item/toy/bouquet = 3,
- /obj/item/weapon/storage/fancy/heartbox = 2,
- /obj/item/weapon/paper/card/smile,
- /obj/item/weapon/paper/card/heart,
- /obj/item/weapon/paper/card/cat,
- /obj/item/weapon/paper/card/flower
+ /obj/item/storage/fancy/heartbox = 2,
+ /obj/item/paper/card/smile,
+ /obj/item/paper/card/heart,
+ /obj/item/paper/card/cat,
+ /obj/item/paper/card/flower
)
cost = 10
containertype = /obj/structure/closet/crate/allico
@@ -86,7 +86,7 @@
contains = list(
/obj/item/paint_brush = 2,
/obj/item/paint_palette = 2,
- /obj/item/weapon/reagent_containers/glass/rag = 2,
+ /obj/item/reagent_containers/glass/rag = 2,
/obj/structure/easel = 1, // How does that even fit
/obj/item/canvas = 1,
/obj/item/canvas/nineteen_nineteen = 1,
@@ -101,7 +101,7 @@
/datum/supply_pack/hospitality/holywater
name = "Holy water crate"
contains = list(
- /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 3
+ /obj/item/reagent_containers/food/drinks/bottle/holywater = 3
)
cost = 15
containertype = /obj/structure/closet/crate/gilthari
@@ -113,11 +113,11 @@
/datum/supply_pack/randomised/hospitality/burgers_vr
num_contained = 5
contains = list(
- /obj/item/weapon/reagent_containers/food/snacks/bigbiteburger,
- /obj/item/weapon/reagent_containers/food/snacks/cheeseburger,
- /obj/item/weapon/reagent_containers/food/snacks/jellyburger,
- /obj/item/weapon/reagent_containers/food/snacks/tofuburger,
- /obj/item/weapon/reagent_containers/food/snacks/fries
+ /obj/item/reagent_containers/food/snacks/bigbiteburger,
+ /obj/item/reagent_containers/food/snacks/cheeseburger,
+ /obj/item/reagent_containers/food/snacks/jellyburger,
+ /obj/item/reagent_containers/food/snacks/tofuburger,
+ /obj/item/reagent_containers/food/snacks/fries
)
name = "Burger crate"
cost = 25
@@ -127,23 +127,23 @@
/datum/supply_pack/randomised/hospitality/bakery_vr
num_contained = 5
contains = list(
- /obj/item/weapon/reagent_containers/food/snacks/baguette,
- /obj/item/weapon/reagent_containers/food/snacks/appletart,
- /obj/item/weapon/reagent_containers/food/snacks/berrymuffin,
- /obj/item/weapon/reagent_containers/food/snacks/bunbun,
- /obj/item/weapon/reagent_containers/food/snacks/cherrypie,
- /obj/item/weapon/reagent_containers/food/snacks/cookie,
- /obj/item/weapon/reagent_containers/food/snacks/croissant,
- /obj/item/weapon/reagent_containers/food/snacks/donut/normal,
- /obj/item/weapon/reagent_containers/food/snacks/donut/jelly,
- /obj/item/weapon/reagent_containers/food/snacks/donut/cherryjelly,
- /obj/item/weapon/reagent_containers/food/snacks/muffin,
- /obj/item/weapon/reagent_containers/food/snacks/pie,
- /obj/item/weapon/reagent_containers/food/snacks/plump_pie,
- /obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit,
- /obj/item/weapon/reagent_containers/food/snacks/poppypretzel,
- /obj/item/weapon/reagent_containers/food/snacks/sugarcookie,
- /obj/item/weapon/reagent_containers/food/snacks/waffles
+ /obj/item/reagent_containers/food/snacks/baguette,
+ /obj/item/reagent_containers/food/snacks/appletart,
+ /obj/item/reagent_containers/food/snacks/berrymuffin,
+ /obj/item/reagent_containers/food/snacks/bunbun,
+ /obj/item/reagent_containers/food/snacks/cherrypie,
+ /obj/item/reagent_containers/food/snacks/cookie,
+ /obj/item/reagent_containers/food/snacks/croissant,
+ /obj/item/reagent_containers/food/snacks/donut/normal,
+ /obj/item/reagent_containers/food/snacks/donut/jelly,
+ /obj/item/reagent_containers/food/snacks/donut/cherryjelly,
+ /obj/item/reagent_containers/food/snacks/muffin,
+ /obj/item/reagent_containers/food/snacks/pie,
+ /obj/item/reagent_containers/food/snacks/plump_pie,
+ /obj/item/reagent_containers/food/snacks/plumphelmetbiscuit,
+ /obj/item/reagent_containers/food/snacks/poppypretzel,
+ /obj/item/reagent_containers/food/snacks/sugarcookie,
+ /obj/item/reagent_containers/food/snacks/waffles
)
name = "Bakery products crate"
cost = 25
@@ -153,15 +153,15 @@
/datum/supply_pack/randomised/hospitality/cakes_vr
num_contained = 2
contains = list(
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/applecake,
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake,
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake,
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesecake,
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/chocolatecake,
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/lemoncake,
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/limecake,
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/orangecake,
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake
+ /obj/item/reagent_containers/food/snacks/sliceable/applecake,
+ /obj/item/reagent_containers/food/snacks/sliceable/birthdaycake,
+ /obj/item/reagent_containers/food/snacks/sliceable/carrotcake,
+ /obj/item/reagent_containers/food/snacks/sliceable/cheesecake,
+ /obj/item/reagent_containers/food/snacks/sliceable/chocolatecake,
+ /obj/item/reagent_containers/food/snacks/sliceable/lemoncake,
+ /obj/item/reagent_containers/food/snacks/sliceable/limecake,
+ /obj/item/reagent_containers/food/snacks/sliceable/orangecake,
+ /obj/item/reagent_containers/food/snacks/sliceable/plaincake
)
name = "Cake crate"
cost = 100
@@ -171,10 +171,10 @@
/datum/supply_pack/randomised/hospitality/mexican_vr
num_contained = 5
contains = list(
- /obj/item/weapon/reagent_containers/food/snacks/cheeseburrito,
- /obj/item/weapon/reagent_containers/food/snacks/enchiladas,
- /obj/item/weapon/reagent_containers/food/snacks/meatburrito,
- /obj/item/weapon/reagent_containers/food/snacks/taco
+ /obj/item/reagent_containers/food/snacks/cheeseburrito,
+ /obj/item/reagent_containers/food/snacks/enchiladas,
+ /obj/item/reagent_containers/food/snacks/meatburrito,
+ /obj/item/reagent_containers/food/snacks/taco
)
name = "Mexican takeout crate"
cost = 50
@@ -184,8 +184,8 @@
/datum/supply_pack/randomised/hospitality/asian_vr
num_contained = 5
contains = list(
- /obj/item/weapon/reagent_containers/food/snacks/generalschicken,
- /obj/item/weapon/reagent_containers/food/snacks/hotandsoursoup
+ /obj/item/reagent_containers/food/snacks/generalschicken,
+ /obj/item/reagent_containers/food/snacks/hotandsoursoup
)
name = "Chinese takeout crate"
cost = 50
@@ -194,16 +194,16 @@
/datum/supply_pack/randomised/hospitality/jaffacake
contains = list(
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/jaffacake
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/jaffacake
)
name = "Desatti jaffa cake crate"
cost = 25
@@ -213,11 +213,11 @@
/datum/supply_pack/randomised/hospitality/sweets
num_contained = 5
contains = list(
- /obj/item/weapon/storage/box/jaffacake,
- /obj/item/weapon/storage/box/winegum,
- /obj/item/weapon/storage/box/saucer,
- /obj/item/weapon/storage/box/shrimpsandbananas,
- /obj/item/weapon/storage/box/rhubarbcustard
+ /obj/item/storage/box/jaffacake,
+ /obj/item/storage/box/winegum,
+ /obj/item/storage/box/saucer,
+ /obj/item/storage/box/shrimpsandbananas,
+ /obj/item/storage/box/rhubarbcustard
)
name = "Sweets crate"
cost = 25
diff --git a/code/datums/supplypacks/hydroponics.dm b/code/datums/supplypacks/hydroponics.dm
index d2e55469af1..fad0054a36f 100644
--- a/code/datums/supplypacks/hydroponics.dm
+++ b/code/datums/supplypacks/hydroponics.dm
@@ -9,28 +9,28 @@
/datum/supply_pack/hydro/monkey
name = "Monkey crate"
- contains = list (/obj/item/weapon/storage/box/monkeycubes)
+ contains = list (/obj/item/storage/box/monkeycubes)
cost = 20
containertype = /obj/structure/closet/crate/freezer/nanotrasen
containername = "Monkey crate"
/datum/supply_pack/hydro/farwa
name = "Farwa crate"
- contains = list (/obj/item/weapon/storage/box/monkeycubes/farwacubes)
+ contains = list (/obj/item/storage/box/monkeycubes/farwacubes)
cost = 20
containertype = /obj/structure/closet/crate/freezer
containername = "Farwa crate"
/datum/supply_pack/hydro/neara
name = "Neaera crate"
- contains = list (/obj/item/weapon/storage/box/monkeycubes/neaeracubes)
+ contains = list (/obj/item/storage/box/monkeycubes/neaeracubes)
cost = 20
containertype = /obj/structure/closet/crate/freezer
containername = "Neaera crate"
/datum/supply_pack/hydro/stok
name = "Stok crate"
- contains = list (/obj/item/weapon/storage/box/monkeycubes/stokcubes)
+ contains = list (/obj/item/storage/box/monkeycubes/stokcubes)
cost = 20
containertype = /obj/structure/closet/crate/freezer
containername = "Stok crate"
@@ -59,15 +59,15 @@
/datum/supply_pack/hydro/hydroponics
name = "Hydroponics Supply Crate"
contains = list(
- /obj/item/weapon/reagent_containers/spray/plantbgone = 4,
- /obj/item/weapon/reagent_containers/glass/bottle/ammonia = 2,
- /obj/item/weapon/material/knife/machete/hatchet,
- /obj/item/weapon/material/minihoe,
- /obj/item/device/analyzer/plant_analyzer,
+ /obj/item/reagent_containers/spray/plantbgone = 4,
+ /obj/item/reagent_containers/glass/bottle/ammonia = 2,
+ /obj/item/material/knife/machete/hatchet,
+ /obj/item/material/minihoe,
+ /obj/item/analyzer/plant_analyzer,
/obj/item/clothing/gloves/botanic_leather,
/obj/item/clothing/suit/storage/apron,
- /obj/item/weapon/material/minihoe,
- /obj/item/weapon/storage/box/botanydisk
+ /obj/item/material/minihoe,
+ /obj/item/storage/box/botanydisk
)
cost = 20
containertype = /obj/structure/closet/crate/hydroponics
@@ -95,6 +95,13 @@
containername = "Chicken crate"
access = access_hydroponics
+/datum/supply_pack/hydro/turkey
+ name = "Turkey crate"
+ cost = 25
+ containertype = /obj/structure/largecrate/animal/turkey
+ containername = "Turkey crate"
+ access = access_hydroponics
+
/datum/supply_pack/hydro/seeds
name = "Seeds crate"
contains = list(
@@ -124,11 +131,11 @@
/datum/supply_pack/hydro/weedcontrol
name = "Weed control crate"
contains = list(
- /obj/item/weapon/material/knife/machete/hatchet = 2,
- /obj/item/weapon/reagent_containers/spray/plantbgone = 4,
+ /obj/item/material/knife/machete/hatchet = 2,
+ /obj/item/reagent_containers/spray/plantbgone = 4,
/obj/item/clothing/mask/gas = 2,
- /obj/item/weapon/grenade/chem_grenade/antiweed = 2,
- /obj/item/weapon/material/twohanded/fireaxe/scythe
+ /obj/item/grenade/chem_grenade/antiweed = 2,
+ /obj/item/material/twohanded/fireaxe/scythe
)
cost = 45
containertype = /obj/structure/closet/crate/grayson
@@ -172,28 +179,28 @@
/datum/supply_pack/hydro/sobaka
name = "Sobaka crate"
- contains = list (/obj/item/weapon/storage/box/monkeycubes/sobakacubes)
+ contains = list (/obj/item/storage/box/monkeycubes/sobakacubes)
cost = 20
containertype = /obj/structure/closet/crate/freezer
containername = "Sobaka crate"
/datum/supply_pack/hydro/saru
name = "Saru crate"
- contains = list (/obj/item/weapon/storage/box/monkeycubes/sarucubes)
+ contains = list (/obj/item/storage/box/monkeycubes/sarucubes)
cost = 20
containertype = /obj/structure/closet/crate/freezer
containername = "Saru crate"
/datum/supply_pack/hydro/sparra
name = "Sparra crate"
- contains = list (/obj/item/weapon/storage/box/monkeycubes/sparracubes)
+ contains = list (/obj/item/storage/box/monkeycubes/sparracubes)
cost = 20
containertype = /obj/structure/closet/crate/freezer
containername = "Sparra crate"
/datum/supply_pack/hydro/wolpin
name = "Wolpin crate"
- contains = list (/obj/item/weapon/storage/box/monkeycubes/wolpincubes)
+ contains = list (/obj/item/storage/box/monkeycubes/wolpincubes)
cost = 20
containertype = /obj/structure/closet/crate/freezer
containername = "Wolpin crate"
@@ -207,9 +214,9 @@
/datum/supply_pack/hydro/fish
name = "Fish supply crate"
contains = list(
- /obj/item/weapon/reagent_containers/food/snacks/lobster = 6,
- /obj/item/weapon/reagent_containers/food/snacks/cuttlefish = 8,
- /obj/item/weapon/reagent_containers/food/snacks/sliceable/monkfish = 1
+ /obj/item/reagent_containers/food/snacks/lobster = 6,
+ /obj/item/reagent_containers/food/snacks/cuttlefish = 8,
+ /obj/item/reagent_containers/food/snacks/sliceable/monkfish = 1
)
cost = 20
containertype = /obj/structure/closet/crate/freezer
@@ -218,14 +225,14 @@
/datum/supply_pack/hydro/fennec_food
name = "Fennec treats crate"
contains = list(
- /obj/item/weapon/reagent_containers/food/snacks/locust = 6,
- /obj/item/weapon/storage/box/wings/bucket = 2,
- /obj/item/weapon/reagent_containers/food/snacks/grub_pink = 2,
- /obj/item/weapon/reagent_containers/food/snacks/grub_blue = 2,
- /obj/item/weapon/reagent_containers/food/snacks/grub_purple = 2,
- /obj/item/weapon/reagent_containers/food/snacks/honey_candy = 4,
- /obj/item/weapon/reagent_containers/food/snacks/scorpion = 4,
- /obj/item/weapon/reagent_containers/food/snacks/ant = 4
+ /obj/item/reagent_containers/food/snacks/locust = 6,
+ /obj/item/storage/box/wings/bucket = 2,
+ /obj/item/reagent_containers/food/snacks/grub_pink = 2,
+ /obj/item/reagent_containers/food/snacks/grub_blue = 2,
+ /obj/item/reagent_containers/food/snacks/grub_purple = 2,
+ /obj/item/reagent_containers/food/snacks/honey_candy = 4,
+ /obj/item/reagent_containers/food/snacks/scorpion = 4,
+ /obj/item/reagent_containers/food/snacks/ant = 4
)
cost = 20
containertype = /obj/structure/closet/crate/fennec
diff --git a/code/datums/supplypacks/medical.dm b/code/datums/supplypacks/medical.dm
index e958f8133fe..2e498c92f10 100644
--- a/code/datums/supplypacks/medical.dm
+++ b/code/datums/supplypacks/medical.dm
@@ -10,16 +10,16 @@
/datum/supply_pack/med/medical
name = "Medical crate"
contains = list(
- /obj/item/weapon/storage/firstaid/regular,
- /obj/item/weapon/storage/firstaid/fire,
- /obj/item/weapon/storage/firstaid/toxin,
- /obj/item/weapon/storage/firstaid/o2,
- /obj/item/weapon/storage/firstaid/adv,
- /obj/item/weapon/reagent_containers/glass/bottle/antitoxin,
- /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline,
- /obj/item/weapon/reagent_containers/glass/bottle/stoxin,
- /obj/item/weapon/storage/box/syringes,
- /obj/item/weapon/storage/box/autoinjectors
+ /obj/item/storage/firstaid/regular,
+ /obj/item/storage/firstaid/fire,
+ /obj/item/storage/firstaid/toxin,
+ /obj/item/storage/firstaid/o2,
+ /obj/item/storage/firstaid/adv,
+ /obj/item/reagent_containers/glass/bottle/antitoxin,
+ /obj/item/reagent_containers/glass/bottle/inaprovaline,
+ /obj/item/reagent_containers/glass/bottle/stoxin,
+ /obj/item/storage/box/syringes,
+ /obj/item/storage/box/autoinjectors
)
cost = 15
containertype = /obj/structure/closet/crate/zenghu
@@ -27,21 +27,21 @@
/datum/supply_pack/med/bloodpack
name = "BloodPack crate"
- contains = list(/obj/item/weapon/storage/box/bloodpacks = 3)
+ contains = list(/obj/item/storage/box/bloodpacks = 3)
cost = 10
containertype = /obj/structure/closet/crate/nanomed
containername = "BloodPack crate"
/datum/supply_pack/med/synthplas
name = "BloodPack (Synthplas) crate"
- contains = list(/obj/item/weapon/reagent_containers/blood/synthplas = 6)
+ contains = list(/obj/item/reagent_containers/blood/synthplas = 6)
cost = 80
containertype = /obj/structure/closet/crate/nanomed
containername = "SynthPlas crate"
/datum/supply_pack/med/bodybag
name = "Body bag crate"
- contains = list(/obj/item/weapon/storage/box/bodybags = 3)
+ contains = list(/obj/item/storage/box/bodybags = 3)
cost = 10
containertype = /obj/structure/closet/crate/nanomed
containername = "Body bag crate"
@@ -56,17 +56,17 @@
/datum/supply_pack/med/surgery
name = "Surgery crate"
contains = list(
- /obj/item/weapon/surgical/cautery,
- /obj/item/weapon/surgical/surgicaldrill,
+ /obj/item/surgical/cautery,
+ /obj/item/surgical/surgicaldrill,
/obj/item/clothing/mask/breath/medical,
- /obj/item/weapon/tank/anesthetic,
- /obj/item/weapon/surgical/FixOVein,
- /obj/item/weapon/surgical/hemostat,
- /obj/item/weapon/surgical/scalpel,
- /obj/item/weapon/surgical/bonegel,
- /obj/item/weapon/surgical/retractor,
- /obj/item/weapon/surgical/bonesetter,
- /obj/item/weapon/surgical/circular_saw
+ /obj/item/tank/anesthetic,
+ /obj/item/surgical/FixOVein,
+ /obj/item/surgical/hemostat,
+ /obj/item/surgical/scalpel,
+ /obj/item/surgical/bonegel,
+ /obj/item/surgical/retractor,
+ /obj/item/surgical/bonesetter,
+ /obj/item/surgical/circular_saw
)
cost = 25
containertype = /obj/structure/closet/crate/secure/veymed
@@ -76,8 +76,8 @@
/datum/supply_pack/med/deathalarm
name = "Death Alarm crate"
contains = list(
- /obj/item/weapon/storage/box/cdeathalarm_kit,
- /obj/item/weapon/storage/box/cdeathalarm_kit
+ /obj/item/storage/box/cdeathalarm_kit,
+ /obj/item/storage/box/cdeathalarm_kit
)
cost = 40
containertype = /obj/structure/closet/crate/secure/ward
@@ -87,7 +87,7 @@
/datum/supply_pack/med/clotting
name = "Clotting Medicine crate"
contains = list(
- /obj/item/weapon/storage/firstaid/clotting
+ /obj/item/storage/firstaid/clotting
)
cost = 100
containertype = /obj/structure/closet/crate/secure/zenghu
@@ -99,9 +99,9 @@
contains = list(
/obj/item/clothing/under/rank/medical/scrubs/green = 2,
/obj/item/clothing/head/surgery/green = 2,
- /obj/item/weapon/storage/box/masks,
- /obj/item/weapon/storage/box/gloves,
- /obj/item/weapon/storage/belt/medical = 3
+ /obj/item/storage/box/masks,
+ /obj/item/storage/box/gloves,
+ /obj/item/storage/belt/medical = 3
)
cost = 10
containertype = /obj/structure/closet/crate/veymed
@@ -110,9 +110,9 @@
/datum/supply_pack/med/extragear
name = "Medical surplus equipment"
contains = list(
- /obj/item/weapon/storage/belt/medical = 3,
+ /obj/item/storage/belt/medical = 3,
/obj/item/clothing/glasses/hud/health = 3,
- /obj/item/device/radio/headset/headset_med/alt = 3,
+ /obj/item/radio/headset/alt/headset_med = 3,
/obj/item/clothing/suit/storage/hooded/wintercoat/medical = 3
)
cost = 10
@@ -123,21 +123,21 @@
/datum/supply_pack/med/cmogear
name = "Chief medical officer equipment"
contains = list(
- /obj/item/weapon/storage/belt/medical,
- /obj/item/device/radio/headset/heads/cmo,
+ /obj/item/storage/belt/medical,
+ /obj/item/radio/headset/heads/cmo,
/obj/item/clothing/under/rank/chief_medical_officer,
- /obj/item/weapon/reagent_containers/hypospray/vial,
+ /obj/item/reagent_containers/hypospray/vial,
/obj/item/clothing/accessory/stethoscope,
/obj/item/clothing/glasses/hud/health,
/obj/item/clothing/suit/storage/toggle/labcoat/cmo,
/obj/item/clothing/suit/storage/toggle/labcoat/cmoalt,
/obj/item/clothing/mask/surgical,
/obj/item/clothing/shoes/white,
- /obj/item/weapon/cartridge/cmo,
+ /obj/item/cartridge/cmo,
/obj/item/clothing/gloves/sterile/latex,
- /obj/item/device/healthanalyzer,
- /obj/item/device/flashlight/pen,
- /obj/item/weapon/reagent_containers/syringe
+ /obj/item/healthanalyzer,
+ /obj/item/flashlight/pen,
+ /obj/item/reagent_containers/syringe
)
cost = 50
containertype = /obj/structure/closet/crate/secure/nanomed
@@ -145,56 +145,56 @@
access = access_cmo
/datum/supply_pack/med/doctorgear
- name = "Medical Doctor equipment"
+ name = JOB_MEDICAL_DOCTOR + " equipment"
contains = list(
- /obj/item/weapon/storage/belt/medical,
- /obj/item/device/radio/headset/headset_med,
+ /obj/item/storage/belt/medical,
+ /obj/item/radio/headset/headset_med,
/obj/item/clothing/under/rank/medical,
/obj/item/clothing/accessory/stethoscope,
/obj/item/clothing/glasses/hud/health,
/obj/item/clothing/suit/storage/toggle/labcoat,
/obj/item/clothing/mask/surgical,
- /obj/item/weapon/storage/firstaid/adv,
+ /obj/item/storage/firstaid/adv,
/obj/item/clothing/shoes/white,
- /obj/item/weapon/cartridge/medical,
+ /obj/item/cartridge/medical,
/obj/item/clothing/gloves/sterile/latex,
- /obj/item/device/healthanalyzer,
- /obj/item/device/flashlight/pen,
- /obj/item/weapon/reagent_containers/syringe
+ /obj/item/healthanalyzer,
+ /obj/item/flashlight/pen,
+ /obj/item/reagent_containers/syringe
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanomed
- containername = "Medical Doctor equipment"
+ containername = JOB_MEDICAL_DOCTOR + " equipment"
access = access_medical_equip
/datum/supply_pack/med/chemistgear
- name = "Chemist equipment"
+ name = JOB_CHEMIST + " equipment"
contains = list(
- /obj/item/weapon/storage/box/beakers,
- /obj/item/device/radio/headset/headset_med,
- /obj/item/weapon/storage/box/autoinjectors,
+ /obj/item/storage/box/beakers,
+ /obj/item/radio/headset/headset_med,
+ /obj/item/storage/box/autoinjectors,
/obj/item/clothing/under/rank/chemist,
/obj/item/clothing/glasses/science,
/obj/item/clothing/suit/storage/toggle/labcoat/chemist,
/obj/item/clothing/mask/surgical,
/obj/item/clothing/shoes/white,
- /obj/item/weapon/cartridge/chemistry,
+ /obj/item/cartridge/chemistry,
/obj/item/clothing/gloves/sterile/latex,
- /obj/item/weapon/reagent_containers/dropper,
- /obj/item/device/healthanalyzer,
- /obj/item/weapon/storage/box/pillbottles,
- /obj/item/weapon/reagent_containers/syringe
+ /obj/item/reagent_containers/dropper,
+ /obj/item/healthanalyzer,
+ /obj/item/storage/box/pillbottles,
+ /obj/item/reagent_containers/syringe
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanomed
- containername = "Chemist equipment"
+ containername = JOB_CHEMIST + " equipment"
access = access_chemistry
/datum/supply_pack/med/paramedicgear
- name = "Paramedic equipment"
+ name = JOB_PARAMEDIC + " equipment"
contains = list(
- /obj/item/weapon/storage/belt/medical/emt,
- /obj/item/device/radio/headset/headset_med,
+ /obj/item/storage/belt/medical/emt,
+ /obj/item/radio/headset/headset_med,
/obj/item/clothing/under/rank/medical/scrubs/black,
/obj/item/clothing/accessory/armband/medblue,
/obj/item/clothing/glasses/hud/health,
@@ -204,37 +204,37 @@
/obj/item/clothing/mask/gas,
/obj/item/clothing/under/rank/medical/paramedic_alt,
/obj/item/clothing/accessory/stethoscope,
- /obj/item/weapon/storage/firstaid/adv,
+ /obj/item/storage/firstaid/adv,
/obj/item/clothing/shoes/boots/jackboots,
/obj/item/clothing/gloves/sterile/latex,
- /obj/item/device/healthanalyzer,
- /obj/item/weapon/cartridge/medical,
- /obj/item/device/flashlight/pen,
- /obj/item/weapon/reagent_containers/syringe,
+ /obj/item/healthanalyzer,
+ /obj/item/cartridge/medical,
+ /obj/item/flashlight/pen,
+ /obj/item/reagent_containers/syringe,
/obj/item/clothing/accessory/storage/white_vest
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanomed
- containername = "Paramedic equipment"
+ containername = JOB_PARAMEDIC + " equipment"
access = access_medical_equip
/datum/supply_pack/med/psychiatristgear
- name = "Psychiatrist equipment"
+ name = JOB_PSYCHIATRIST + " equipment"
contains = list(
/obj/item/clothing/under/rank/psych,
- /obj/item/device/radio/headset/headset_med,
+ /obj/item/radio/headset/headset_med,
/obj/item/clothing/under/rank/psych/turtleneck,
/obj/item/clothing/shoes/laceup,
/obj/item/clothing/suit/storage/toggle/labcoat,
/obj/item/clothing/shoes/white,
- /obj/item/weapon/clipboard,
- /obj/item/weapon/folder/white,
- /obj/item/weapon/pen,
- /obj/item/weapon/cartridge/medical
+ /obj/item/clipboard,
+ /obj/item/folder/white,
+ /obj/item/pen,
+ /obj/item/cartridge/medical
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanomed
- containername = "Psychiatrist equipment"
+ containername = JOB_PSYCHIATRIST + " equipment"
access = access_psychiatrist
/datum/supply_pack/med/medicalscrubs
@@ -250,8 +250,8 @@
/obj/item/clothing/head/surgery/blue = 3,
/obj/item/clothing/head/surgery/green = 3,
/obj/item/clothing/head/surgery/black = 3,
- /obj/item/weapon/storage/box/masks,
- /obj/item/weapon/storage/box/gloves
+ /obj/item/storage/box/masks,
+ /obj/item/storage/box/gloves
)
cost = 10
containertype = /obj/structure/closet/crate/secure/nanomed
@@ -261,14 +261,14 @@
/datum/supply_pack/med/autopsy
name = "Autopsy equipment"
contains = list(
- /obj/item/weapon/folder/white,
- /obj/item/device/camera,
- /obj/item/device/camera_film = 2,
- /obj/item/weapon/autopsy_scanner,
- /obj/item/weapon/surgical/scalpel,
- /obj/item/weapon/storage/box/masks,
- /obj/item/weapon/storage/box/gloves,
- /obj/item/weapon/pen
+ /obj/item/folder/white,
+ /obj/item/camera,
+ /obj/item/camera_film = 2,
+ /obj/item/autopsy_scanner,
+ /obj/item/surgical/scalpel,
+ /obj/item/storage/box/masks,
+ /obj/item/storage/box/gloves,
+ /obj/item/pen
)
cost = 20
containertype = /obj/structure/closet/crate/secure/veymed
@@ -294,8 +294,8 @@
/obj/item/clothing/suit/storage/toggle/labcoat/genetics,
/obj/item/clothing/suit/storage/toggle/labcoat/virologist,
/obj/item/clothing/suit/storage/toggle/labcoat/chemist,
- /obj/item/weapon/storage/box/masks,
- /obj/item/weapon/storage/box/gloves
+ /obj/item/storage/box/masks,
+ /obj/item/storage/box/gloves
)
cost = 10
containertype = /obj/structure/closet/crate/secure/nanomed
@@ -311,9 +311,9 @@
/obj/item/clothing/suit/bio_suit/cmo,
/obj/item/clothing/head/bio_hood/cmo,
/obj/item/clothing/mask/gas = 5,
- /obj/item/weapon/tank/oxygen = 5,
- /obj/item/weapon/storage/box/masks,
- /obj/item/weapon/storage/box/gloves
+ /obj/item/tank/oxygen = 5,
+ /obj/item/storage/box/masks,
+ /obj/item/storage/box/gloves
)
cost = 50
containertype = /obj/structure/closet/crate/secure/nanomed
@@ -322,23 +322,23 @@
/datum/supply_pack/med/portablefreezers
name = "Portable freezers crate"
- contains = list(/obj/item/weapon/storage/box/freezer = 7)
+ contains = list(/obj/item/storage/box/freezer = 7)
cost = 25
containertype = /obj/structure/closet/crate/secure/veymed
containername = "Portable freezers"
access = access_medical_equip
/datum/supply_pack/med/virus
- name = "Virus sample crate"
- contains = list(/obj/item/weapon/virusdish/random = 4)
+ name = "Virus culture crate"
+ contains = list(/obj/item/reagent_containers/glass/bottle/culture/cold = 1, /obj/item/reagent_containers/glass/bottle/culture/flu = 1)
cost = 25
containertype = /obj/structure/closet/crate/secure/zenghu
- containername = "Virus sample crate"
+ containername = "Virus culture crate"
access = access_cmo
/datum/supply_pack/med/defib
name = "Defibrillator crate"
- contains = list(/obj/item/device/defib_kit = 2)
+ contains = list(/obj/item/defib_kit = 2)
cost = 30
containertype = /obj/structure/closet/crate/veymed
containername = "Defibrillator crate"
@@ -388,9 +388,9 @@
/obj/item/clothing/head/bio_hood/cmo,
/obj/item/clothing/shoes/white = 7,
/obj/item/clothing/mask/gas = 7,
- /obj/item/weapon/tank/oxygen = 7,
- /obj/item/weapon/storage/box/masks,
- /obj/item/weapon/storage/box/gloves
+ /obj/item/tank/oxygen = 7,
+ /obj/item/storage/box/masks,
+ /obj/item/storage/box/gloves
)
cost = 40
@@ -400,9 +400,9 @@
/obj/item/clothing/suit/bio_suit/virology = 3,
/obj/item/clothing/head/bio_hood/virology = 3,
/obj/item/clothing/mask/gas = 3,
- /obj/item/weapon/tank/oxygen = 3,
- /obj/item/weapon/storage/box/masks,
- /obj/item/weapon/storage/box/gloves
+ /obj/item/tank/oxygen = 3,
+ /obj/item/storage/box/masks,
+ /obj/item/storage/box/gloves
)
cost = 40
containertype = /obj/structure/closet/crate/secure
@@ -410,11 +410,11 @@
access = access_medical_equip
/datum/supply_pack/med/virus
- name = "Virus sample crate"
- contains = list(/obj/item/weapon/virusdish/random = 4)
+ name = "Virus culture crate"
+ contains = list(/obj/item/reagent_containers/glass/bottle/culture/cold = 1, /obj/item/reagent_containers/glass/bottle/culture/flu = 1)
cost = 25
containertype = /obj/structure/closet/crate/secure
- containername = "Virus sample crate"
+ containername = "Virus culture crate"
access = access_medical_equip
@@ -423,7 +423,7 @@
/datum/supply_pack/med/compactdefib
name = "Compact Defibrillator crate"
- contains = list(/obj/item/device/defib_kit/compact = 1)
+ contains = list(/obj/item/defib_kit/compact = 1)
cost = 90
containertype = /obj/structure/closet/crate/secure
containername = "Compact Defibrillator crate"
diff --git a/code/datums/supplypacks/misc.dm b/code/datums/supplypacks/misc.dm
index ac5c7f5fb9c..a7a1ba13b40 100644
--- a/code/datums/supplypacks/misc.dm
+++ b/code/datums/supplypacks/misc.dm
@@ -14,9 +14,9 @@
/datum/supply_pack/randomised/misc/card_packs
num_contained = 5
contains = list(
- /obj/item/weapon/pack/cardemon,
- /obj/item/weapon/pack/spaceball,
- /obj/item/weapon/deck/holder
+ /obj/item/pack/cardemon,
+ /obj/item/pack/spaceball,
+ /obj/item/deck/holder
)
name = "Trading Card Crate"
cost = 10
@@ -80,6 +80,7 @@
/obj/item/toy/plushie/slimeplushie,
/obj/item/toy/plushie/box,
/obj/item/toy/plushie/borgplushie,
+ /obj/item/toy/plushie/borgplushie/drake/eng,
/obj/item/toy/plushie/borgplushie/medihound,
/obj/item/toy/plushie/borgplushie/scrubpuppy,
/obj/item/toy/plushie/foxbear,
@@ -100,14 +101,14 @@
containername = "Plushies Crate"
/datum/supply_pack/misc/eftpos
- contains = list(/obj/item/device/eftpos)
+ contains = list(/obj/item/eftpos)
name = "EFTPOS scanner"
cost = 10
containertype = /obj/structure/closet/crate/nanotrasen
containername = "EFTPOS crate"
/datum/supply_pack/misc/chaplaingear
- name = "Chaplain equipment"
+ name = JOB_CHAPLAIN + " equipment"
contains = list(
/obj/item/clothing/under/rank/chaplain,
/obj/item/clothing/shoes/black,
@@ -117,12 +118,12 @@
/obj/item/clothing/suit/storage/hooded/chaplain_hoodie/whiteout,
/obj/item/clothing/suit/holidaypriest,
/obj/item/clothing/under/wedding/bride_white,
- /obj/item/weapon/storage/backpack/cultpack,
- /obj/item/weapon/storage/fancy/candle_box = 3
+ /obj/item/storage/backpack/cultpack,
+ /obj/item/storage/fancy/candle_box = 3
)
cost = 10
containertype = /obj/structure/closet/crate/gilthari
- containername = "Chaplain equipment crate"
+ containername = JOB_CHAPLAIN + " equipment crate"
/datum/supply_pack/misc/hoverpod
name = "Hoverpod Shipment"
@@ -157,7 +158,7 @@
/datum/supply_pack/misc/glucose_hypos
name = "Glucose Hypoinjectors"
contains = list(
- /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5
+ /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5
)
cost = 25
containertype = /obj/structure/closet/crate/zenghu
@@ -166,16 +167,16 @@
/datum/supply_pack/misc/mre_rations
num_contained = 6
name = "Emergency - MREs"
- contains = list(/obj/item/weapon/storage/mre,
- /obj/item/weapon/storage/mre/menu2,
- /obj/item/weapon/storage/mre/menu3,
- /obj/item/weapon/storage/mre/menu4,
- /obj/item/weapon/storage/mre/menu5,
- /obj/item/weapon/storage/mre/menu6,
- /obj/item/weapon/storage/mre/menu7,
- /obj/item/weapon/storage/mre/menu8,
- /obj/item/weapon/storage/mre/menu9,
- /obj/item/weapon/storage/mre/menu10)
+ contains = list(/obj/item/storage/mre,
+ /obj/item/storage/mre/menu2,
+ /obj/item/storage/mre/menu3,
+ /obj/item/storage/mre/menu4,
+ /obj/item/storage/mre/menu5,
+ /obj/item/storage/mre/menu6,
+ /obj/item/storage/mre/menu7,
+ /obj/item/storage/mre/menu8,
+ /obj/item/storage/mre/menu9,
+ /obj/item/storage/mre/menu10)
cost = 50
containertype = /obj/structure/closet/crate/centauri
containername = "ready to eat rations"
@@ -183,7 +184,7 @@
/datum/supply_pack/misc/paste_rations
name = "Emergency - Paste"
contains = list(
- /obj/item/weapon/storage/mre/menu11 = 2
+ /obj/item/storage/mre/menu11 = 2
)
cost = 25
containertype = /obj/structure/closet/crate/freezer/centauri
@@ -192,7 +193,7 @@
/datum/supply_pack/misc/medical_rations
name = "Emergency - VitaPaste"
contains = list(
- /obj/item/weapon/storage/mre/menu13 = 2
+ /obj/item/storage/mre/menu13 = 2
)
cost = 40
containertype = /obj/structure/closet/crate/zenghu
@@ -210,12 +211,12 @@
/datum/supply_pack/misc/beltminer
name = "Belt-miner gear crate"
contains = list(
- /obj/item/weapon/gun/energy/particle = 2,
- /obj/item/weapon/cell/device/weapon = 2,
- /obj/item/weapon/storage/firstaid/regular = 1,
- /obj/item/device/gps = 2,
- /obj/item/weapon/storage/box/traumainjectors = 1,
- /obj/item/device/binoculars = 1
+ /obj/item/gun/energy/particle = 2,
+ /obj/item/cell/device/weapon = 2,
+ /obj/item/storage/firstaid/regular = 1,
+ /obj/item/gps = 2,
+ /obj/item/storage/box/traumainjectors = 1,
+ /obj/item/binoculars = 1
)
cost = 60
containertype = /obj/structure/closet/crate/secure/gear
@@ -227,7 +228,7 @@
/datum/supply_pack/misc/jetpack
name = "jetpack (empty)"
contains = list(
- /obj/item/weapon/tank/jetpack = 1
+ /obj/item/tank/jetpack = 1
)
cost = 75
containertype = /obj/structure/closet/crate/secure/gear
@@ -239,11 +240,11 @@
one_access = TRUE
/datum/supply_pack/randomised/misc/explorer_shield
- name = "Away Team shield"
+ name = JOB_EXPLORER + " shield"
num_contained = 2
contains = list(
- /obj/item/weapon/shield/riot/explorer,
- /obj/item/weapon/shield/riot/explorer/purple
+ /obj/item/shield/riot/explorer,
+ /obj/item/shield/riot/explorer/purple
)
cost = 75
containertype = /obj/structure/closet/crate/secure/gear
@@ -255,7 +256,7 @@
/datum/supply_pack/misc/music_players
name = "music players (3)"
contains = list(
- /obj/item/device/walkpod = 3
+ /obj/item/walkpod = 3
)
cost = 150
containertype = /obj/structure/closet/crate
@@ -264,7 +265,7 @@
/datum/supply_pack/misc/juke_remotes
name = "jukebox remote speakers (2)"
contains = list(
- /obj/item/device/juke_remote = 2
+ /obj/item/juke_remote = 2
)
cost = 300
containertype = /obj/structure/closet/crate
@@ -273,7 +274,7 @@
/datum/supply_pack/misc/explorer_headsets
name = "shortwave-capable headsets (x4)"
contains = list(
- /obj/item/device/radio/headset/explorer = 4
+ /obj/item/radio/headset/explorer = 4
)
cost = 20
containertype = /obj/structure/closet/crate/secure/gear
@@ -288,7 +289,7 @@
/datum/supply_pack/misc/emergency_beacons
name = "emergency locator beacons (x4)"
contains = list(
- /obj/item/device/emergency_beacon = 4
+ /obj/item/emergency_beacon = 4
)
cost = 20
containertype = /obj/structure/closet/crate
diff --git a/code/datums/supplypacks/misc_yw.dm b/code/datums/supplypacks/misc_yw.dm
index 6a5e26f1d0c..d3e54de2888 100644
--- a/code/datums/supplypacks/misc_yw.dm
+++ b/code/datums/supplypacks/misc_yw.dm
@@ -13,7 +13,7 @@
containertype = /obj/structure/closet/crate/secure/weapon
containername = "Blueshield equipment"
access = access_blueshield_exclusive
-
+
/datum/supply_pack/misc/blueshieldweapons
name = "Blueshield Weapon Kits"
contains = list(
@@ -28,8 +28,8 @@
/datum/supply_pack/misc/bluespaceradioyw
name = "Bluespace Radio Packs"
contains = list(
- /obj/item/device/bluespaceradio/cryogaia_prelinked = 2
+ /obj/item/bluespaceradio/cryogaia_prelinked = 2
)
cost = 75
containertype = /obj/structure/closet/crate
- containername = "Bluespace Radio Packs"
\ No newline at end of file
+ containername = "Bluespace Radio Packs"
diff --git a/code/datums/supplypacks/munitions.dm b/code/datums/supplypacks/munitions.dm
index e6f3c7b3124..44f74d1c54d 100644
--- a/code/datums/supplypacks/munitions.dm
+++ b/code/datums/supplypacks/munitions.dm
@@ -12,12 +12,12 @@
/datum/supply_pack/munitions/weapons
name = "Weapons - Security basic equipment"
contains = list(
- /obj/item/device/flash = 2,
- /obj/item/weapon/reagent_containers/spray/pepper = 2,
- /obj/item/weapon/melee/baton/loaded = 2,
- /obj/item/weapon/gun/energy/taser = 2,
- /obj/item/weapon/gun/projectile/colt/detective = 2,
- /obj/item/weapon/storage/box/flashbangs = 2
+ /obj/item/flash = 2,
+ /obj/item/reagent_containers/spray/pepper = 2,
+ /obj/item/melee/baton/loaded = 2,
+ /obj/item/gun/energy/taser = 2,
+ /obj/item/gun/projectile/colt/detective = 2,
+ /obj/item/storage/box/flashbangs = 2
)
cost = 40
containertype = /obj/structure/closet/crate/secure/lawson
@@ -26,7 +26,7 @@
/datum/supply_pack/munitions/egunpistol
name = "Weapons - Energy sidearms"
- contains = list(/obj/item/weapon/gun/energy/gun = 2)
+ contains = list(/obj/item/gun/energy/gun = 2)
cost = 40
containertype = /obj/structure/closet/crate/secure/lawson
containername = "Energy sidearms crate"
@@ -35,9 +35,9 @@
/datum/supply_pack/munitions/flareguns
name = "Weapons - Flare guns"
contains = list(
- /obj/item/weapon/gun/projectile/sec/flash,
+ /obj/item/gun/projectile/sec/flash,
/obj/item/ammo_magazine/m45/flash,
- /obj/item/weapon/gun/projectile/shotgun/doublebarrel/flare,
+ /obj/item/gun/projectile/shotgun/doublebarrel/flare,
/obj/item/ammo_magazine/ammo_box/b12g/flash
)
cost = 25
@@ -48,8 +48,8 @@
/datum/supply_pack/munitions/eweapons
name = "Weapons - Experimental weapons crate"
contains = list(
- /obj/item/weapon/gun/energy/xray = 2,
- /obj/item/weapon/shield/energy = 2)
+ /obj/item/gun/energy/xray = 2,
+ /obj/item/shield/energy = 2)
cost = 100
containertype = /obj/structure/closet/crate/secure/science
containername = "Experimental weapons crate"
@@ -57,7 +57,7 @@
/datum/supply_pack/munitions/energyweapons
name = "Weapons - Laser rifle crate"
- contains = list(/obj/item/weapon/gun/energy/laser = 2) //VOREStation Edit - Made to be consistent with the energy guns crate.
+ contains = list(/obj/item/gun/energy/laser = 2) //VOREStation Edit - Made to be consistent with the energy guns crate.
cost = 50
containertype = /obj/structure/closet/crate/secure/heph
containername = "Energy weapons crate"
@@ -68,7 +68,7 @@
contains = list(
/obj/item/ammo_magazine/ammo_box/b12g,
/obj/item/ammo_magazine/ammo_box/b12g/pellet,
- /obj/item/weapon/gun/projectile/shotgun/pump/combat = 2
+ /obj/item/gun/projectile/shotgun/pump/combat = 2
)
cost = 50
containertype = /obj/structure/closet/crate/secure/weapon
@@ -81,7 +81,7 @@
contains = list(
/obj/item/ammo_magazine/ammo_box/b12g,
/obj/item/ammo_magazine/ammo_box/b12g/pellet,
- /obj/item/weapon/gun/projectile/shotgun/semi = 2
+ /obj/item/gun/projectile/shotgun/semi = 2
)
cost = 100
containertype = /obj/structure/closet/crate/secure/weapon
@@ -90,7 +90,7 @@
/datum/supply_pack/munitions/erifle
name = "Weapons - Energy marksman"
- contains = list(/obj/item/weapon/gun/energy/sniperrifle = 2)
+ contains = list(/obj/item/gun/energy/sniperrifle = 2)
cost = 100
containertype = /obj/structure/closet/crate/secure/heph
containername = "Energy marksman crate"
@@ -98,7 +98,7 @@
/datum/supply_pack/munitions/burstlaser
name = "Weapons - Burst laser"
- contains = list(/obj/item/weapon/gun/energy/gun/burst = 2)
+ contains = list(/obj/item/gun/energy/gun/burst = 2)
cost = 50
containertype = /obj/structure/closet/crate/secure/lawson
containername = "Burst laser crate"
@@ -107,8 +107,8 @@
/datum/supply_pack/munitions/ionweapons
name = "Weapons - Electromagnetic Rifles"
contains = list(
- /obj/item/weapon/gun/energy/ionrifle = 2,
- /obj/item/weapon/storage/box/empslite
+ /obj/item/gun/energy/ionrifle = 2,
+ /obj/item/storage/box/empslite
)
cost = 50
containertype = /obj/structure/closet/crate/secure/ward
@@ -118,8 +118,8 @@
/datum/supply_pack/munitions/ionpistols
name = "Weapons - Electromagnetic pistols"
contains = list(
- /obj/item/weapon/gun/energy/ionrifle/pistol = 2,
- /obj/item/weapon/storage/box/empslite
+ /obj/item/gun/energy/ionrifle/pistol = 2,
+ /obj/item/storage/box/empslite
)
cost = 30
containertype = /obj/structure/closet/crate/secure/ward
@@ -128,7 +128,7 @@
/datum/supply_pack/munitions/bsmg
name = "Weapons - Ballistic SMGs"
- contains = list(/obj/item/weapon/gun/projectile/automatic/wt550 = 2)
+ contains = list(/obj/item/gun/projectile/automatic/wt550 = 2)
cost = 50
containertype = /obj/structure/closet/crate/secure/ward
containername = "Ballistic weapon crate"
@@ -136,7 +136,7 @@
/datum/supply_pack/munitions/brifle
name = "Weapons - Ballistic Rifles"
- contains = list(/obj/item/weapon/gun/projectile/automatic/z8 = 2)
+ contains = list(/obj/item/gun/projectile/automatic/z8 = 2)
cost = 80
containertype = /obj/structure/closet/crate/secure/weapon
containername = "Ballistic weapon crate"
@@ -145,7 +145,7 @@
/datum/supply_pack/munitions/bolt_rifles_lethal
name = "Weapons - Bolt-Action Rifles"
contains = list(
- /obj/item/weapon/gun/projectile/shotgun/pump/rifle = 2,
+ /obj/item/gun/projectile/shotgun/pump/rifle = 2,
/obj/item/ammo_magazine/ammo_box/b762 = 4,
)
cost = 60
@@ -156,8 +156,8 @@
/datum/supply_pack/munitions/bolt_rifles_competitive
name = "Weapons - Competitive shooting rifles"
contains = list(
- /obj/item/device/assembly/timer,
- /obj/item/weapon/gun/projectile/shotgun/pump/rifle/practice = 2,
+ /obj/item/assembly/timer,
+ /obj/item/gun/projectile/shotgun/pump/rifle/practice = 2,
/obj/item/ammo_magazine/clip/c762/practice = 4,
/obj/item/target = 2,
/obj/item/target/alien = 2,
@@ -171,7 +171,7 @@
/datum/supply_pack/munitions/caseless
name = "Weapons - Prototype Caseless Rifle"
contains = list(
- /obj/item/weapon/gun/projectile/caseless/prototype,
+ /obj/item/gun/projectile/caseless/prototype,
/obj/item/ammo_magazine/m5mmcaseless = 3
)
cost = 60
@@ -181,7 +181,7 @@
/datum/supply_pack/munitions/mrifle
name = "Weapons - Magnetic Rifles"
- contains = list(/obj/item/weapon/gun/magnetic/railgun/heater = 2)
+ contains = list(/obj/item/gun/magnetic/railgun/heater = 2)
cost = 120
containertype = /obj/structure/closet/crate/secure/heph
containername = "Magnetic weapon crate"
@@ -189,7 +189,7 @@
/datum/supply_pack/munitions/mpistol
name = "Weapons - Magnetic Pistols"
- contains = list(/obj/item/weapon/gun/magnetic/railgun/heater/pistol = 2)
+ contains = list(/obj/item/gun/magnetic/railgun/heater/pistol = 2)
cost = 200
containertype = /obj/structure/closet/crate/secure/heph
containername = "Magnetic weapon crate"
@@ -197,7 +197,7 @@
/datum/supply_pack/munitions/mcarbine
name = "Weapons - Magnetic Carbines"
- contains = list(/obj/item/weapon/gun/magnetic/railgun/flechette/sif = 2)
+ contains = list(/obj/item/gun/magnetic/railgun/flechette/sif = 2)
cost = 130
containertype = /obj/structure/closet/crate/secure/lawson
containername = "Magnetic weapon crate"
@@ -205,7 +205,7 @@
/datum/supply_pack/munitions/mshells
name = "Weapons - Magnetic Shells"
- contains = list(/obj/item/weapon/magnetic_ammo = 3)
+ contains = list(/obj/item/magnetic_ammo = 3)
cost = 100
containertype = /obj/structure/closet/crate/secure/weapon
containername = "Magnetic ammunition crate"
@@ -213,7 +213,7 @@
/datum/supply_pack/munitions/claymore
name = "Weapons - Melee - Claymores"
- contains = list(/obj/item/weapon/material/sword = 2)
+ contains = list(/obj/item/material/sword = 2)
cost = 150
containertype = /obj/structure/closet/crate/secure/weapon
containername = "Claymore crate"
@@ -264,7 +264,7 @@
/datum/supply_pack/munitions/pcellammo
name = "Ammunition - Power cell"
- contains = list(/obj/item/weapon/cell/device/weapon = 3)
+ contains = list(/obj/item/cell/device/weapon = 3)
cost = 50
containertype = /obj/structure/closet/crate/secure/weapon
containername = "Energy ammunition crate"
@@ -274,8 +274,8 @@
/datum/supply_pack/munitions/expeditionguns
name = "Frontier phaser (station-locked) crate"
contains = list(
- /obj/item/weapon/gun/energy/locked/frontier = 2,
- /obj/item/weapon/gun/energy/locked/frontier/holdout = 2,
+ /obj/item/gun/energy/locked/frontier = 2,
+ /obj/item/gun/energy/locked/frontier/holdout = 2,
)
cost = 35
containertype = /obj/structure/closet/crate/secure
@@ -285,7 +285,7 @@
/datum/supply_pack/munitions/expeditionbows
name = "Frontier bows (station-locked) crate"
contains = list(
- /obj/item/weapon/gun/energy/locked/frontier/handbow=2
+ /obj/item/gun/energy/locked/frontier/handbow=2
)
cost = 20
containertype = /obj/structure/closet/crate/secure
@@ -336,7 +336,7 @@
/datum/supply_pack/munitions/longsword
name = "Weapons - Melee -Longsword (Steel)"
contains = list(
- /obj/item/weapon/material/twohanded/longsword=2
+ /obj/item/material/twohanded/longsword=2
)
cost = 50
containertype = /obj/structure/closet/crate/secure
@@ -348,12 +348,12 @@
name = "Revolver Crate"
num_contained = 2
contains = list(
- /obj/item/weapon/gun/projectile/revolver/cerberus,
- /obj/item/weapon/gun/projectile/revolver/nova,
- /obj/item/weapon/gun/projectile/revolver/detective,
- /obj/item/weapon/gun/projectile/revolver/deckard,
- /obj/item/weapon/gun/projectile/revolver/mateba,
- /obj/item/weapon/gun/projectile/derringer
+ /obj/item/gun/projectile/revolver/cerberus,
+ /obj/item/gun/projectile/revolver/nova,
+ /obj/item/gun/projectile/revolver/detective,
+ /obj/item/gun/projectile/revolver/deckard,
+ /obj/item/gun/projectile/revolver/mateba,
+ /obj/item/gun/projectile/derringer
)
cost = 150
containertype = /obj/structure/closet/crate/secure
@@ -364,9 +364,9 @@
name = "Assault rifle crate"
num_contained = 2
contains = list(
- /obj/item/weapon/gun/projectile/automatic/tommygun,
- /obj/item/weapon/gun/projectile/automatic/c20r,
- /obj/item/weapon/gun/projectile/automatic/sts35
+ /obj/item/gun/projectile/automatic/tommygun,
+ /obj/item/gun/projectile/automatic/c20r,
+ /obj/item/gun/projectile/automatic/sts35
)
cost = 250
containertype = /obj/structure/closet/crate/secure
@@ -377,8 +377,8 @@
name = "Smg crate"
num_contained = 2
contains = list(
- /obj/item/weapon/gun/projectile/automatic/c20r,
- /obj/item/weapon/gun/projectile/automatic/pdw
+ /obj/item/gun/projectile/automatic/c20r,
+ /obj/item/gun/projectile/automatic/pdw
)
cost = 100
containertype = /obj/structure/closet/crate/secure
@@ -387,7 +387,7 @@
/datum/supply_pack/munitions/munitions/yw_mg
name = "Light machine gun crate"
- contains = list(/obj/item/weapon/gun/projectile/automatic/l6_saw = 1)
+ contains = list(/obj/item/gun/projectile/automatic/l6_saw = 1)
cost = 500
containertype = /obj/structure/closet/crate/secure
containername = "Light machine gun crate"
diff --git a/code/datums/supplypacks/recreation.dm b/code/datums/supplypacks/recreation.dm
index 3b274ff17fb..ab7f37da80b 100644
--- a/code/datums/supplypacks/recreation.dm
+++ b/code/datums/supplypacks/recreation.dm
@@ -14,10 +14,10 @@
/datum/supply_pack/recreation/foam_weapons
name = "Foam Weapon Crate"
contains = list(
- /obj/item/weapon/material/sword/foam = 2,
- /obj/item/weapon/material/twohanded/baseballbat/foam = 2,
- /obj/item/weapon/material/twohanded/spear/foam = 2,
- /obj/item/weapon/material/twohanded/fireaxe/foam = 2
+ /obj/item/material/sword/foam = 2,
+ /obj/item/material/twohanded/baseballbat/foam = 2,
+ /obj/item/material/twohanded/spear/foam = 2,
+ /obj/item/material/twohanded/fireaxe/foam = 2
)
cost = 50
containertype = /obj/structure/closet/crate/allico
@@ -27,8 +27,8 @@
name = "Donk-Soft Weapon Crate"
contains = list(
/obj/item/ammo_magazine/ammo_box/foam = 2,
- /obj/item/weapon/gun/projectile/shotgun/pump/toy = 2,
- /obj/item/weapon/gun/projectile/pistol/toy = 2,
+ /obj/item/gun/projectile/shotgun/pump/toy = 2,
+ /obj/item/gun/projectile/pistol/toy = 2,
/obj/item/ammo_magazine/mfoam_dart/pistol = 2
)
cost = 50
@@ -54,9 +54,9 @@
/datum/supply_pack/recreation/lasertag
name = "Lasertag equipment"
contains = list(
- /obj/item/weapon/gun/energy/lasertag/red,
+ /obj/item/gun/energy/lasertag/red,
/obj/item/clothing/suit/redtag,
- /obj/item/weapon/gun/energy/lasertag/blue,
+ /obj/item/gun/energy/lasertag/blue,
/obj/item/clothing/suit/bluetag
)
containertype = /obj/structure/closet/crate/ward
@@ -66,14 +66,14 @@
/datum/supply_pack/recreation/artscrafts
name = "Arts and Crafts supplies"
contains = list(
- /obj/item/weapon/storage/fancy/crayons,
- /obj/item/weapon/storage/fancy/markers,
- /obj/item/device/camera,
- /obj/item/device/camera_film = 2,
- /obj/item/weapon/storage/photo_album,
- /obj/item/weapon/packageWrap,
+ /obj/item/storage/fancy/crayons,
+ /obj/item/storage/fancy/markers,
+ /obj/item/camera,
+ /obj/item/camera_film = 2,
+ /obj/item/storage/photo_album,
+ /obj/item/packageWrap,
/obj/item/poster/custom,
- /obj/item/weapon/wrapping_paper = 3,
+ /obj/item/wrapping_paper = 3,
/obj/structure/easel,
/obj/item/paint_brush,
/obj/item/paint_palette,
@@ -93,19 +93,19 @@
containername = "station painting supplies crate"
containertype = /obj/structure/closet/crate/grayson
contains = list(
- /obj/item/device/pipe_painter = 2,
- /obj/item/device/floor_painter = 2,
- /obj/item/weapon/reagent_containers/glass/paint/red,
- /obj/item/weapon/reagent_containers/glass/paint/green,
- /obj/item/weapon/reagent_containers/glass/paint/blue,
- /obj/item/weapon/reagent_containers/glass/paint/yellow,
- /obj/item/weapon/reagent_containers/glass/paint/violet,
- /obj/item/weapon/reagent_containers/glass/paint/cyan,
- /obj/item/weapon/reagent_containers/glass/paint/orange,
- /obj/item/weapon/reagent_containers/glass/paint/purple,
- /obj/item/weapon/reagent_containers/glass/paint/grey,
- /obj/item/weapon/reagent_containers/glass/paint/black,
- /obj/item/weapon/reagent_containers/glass/paint/white = 3
+ /obj/item/pipe_painter = 2,
+ /obj/item/floor_painter = 2,
+ /obj/item/reagent_containers/glass/paint/red,
+ /obj/item/reagent_containers/glass/paint/green,
+ /obj/item/reagent_containers/glass/paint/blue,
+ /obj/item/reagent_containers/glass/paint/yellow,
+ /obj/item/reagent_containers/glass/paint/violet,
+ /obj/item/reagent_containers/glass/paint/cyan,
+ /obj/item/reagent_containers/glass/paint/orange,
+ /obj/item/reagent_containers/glass/paint/purple,
+ /obj/item/reagent_containers/glass/paint/grey,
+ /obj/item/reagent_containers/glass/paint/black,
+ /obj/item/reagent_containers/glass/paint/white = 3
)
/datum/supply_pack/recreation/cheapbait
@@ -114,7 +114,7 @@
containername = "cheap bait crate"
containertype = /obj/structure/closet/crate/freezer
contains = list(
- /obj/item/weapon/storage/box/wormcan/sickly = 5
+ /obj/item/storage/box/wormcan/sickly = 5
)
/datum/supply_pack/randomised/recreation/cheapbait
@@ -124,8 +124,8 @@
containertype = /obj/structure/closet/crate/carp
num_contained = 8
contains = list(
- /obj/item/weapon/storage/box/wormcan,
- /obj/item/weapon/storage/box/wormcan/deluxe
+ /obj/item/storage/box/wormcan,
+ /obj/item/storage/box/wormcan/deluxe
)
/datum/supply_pack/recreation/ltagturrets
@@ -144,7 +144,7 @@
containername = "monster bait crate"
containertype = /obj/structure/closet/crate/allico
contains = list(
- /obj/item/weapon/toy/monster_bait
+ /obj/item/toy/monster_bait
)
/*
@@ -162,14 +162,14 @@
contains = list(
/obj/item/clothing/mask/muzzle,
/obj/item/clothing/glasses/sunglasses/blindfold,
- /obj/item/weapon/handcuffs/fuzzy,
- /obj/item/weapon/tape_roll,
+ /obj/item/handcuffs/fuzzy,
+ /obj/item/tape_roll,
/obj/item/stack/cable_coil/random,
/obj/item/clothing/accessory/collar/shock,
/obj/item/clothing/suit/straight_jacket,
- /obj/item/weapon/handcuffs/legcuffs/fuzzy,
- /obj/item/weapon/melee/fluff/holochain/mass,
- /obj/item/weapon/material/twohanded/riding_crop,
+ /obj/item/handcuffs/legcuffs/fuzzy,
+ /obj/item/melee/fluff/holochain/mass,
+ /obj/item/material/twohanded/riding_crop,
/obj/item/clothing/under/fluff/latexmaid
)
containertype = /obj/structure/closet/crate
@@ -182,8 +182,8 @@
/obj/item/clothing/head/fluff/wolfgirl = 1,
/obj/item/clothing/shoes/fluff/wolfgirl = 1,
/obj/item/clothing/under/fluff/wolfgirl = 1,
- /obj/item/weapon/melee/fluffstuff/wolfgirlsword = 1,
- /obj/item/weapon/shield/fluff/wolfgirlshield = 1
+ /obj/item/melee/fluffstuff/wolfgirlsword = 1,
+ /obj/item/shield/fluff/wolfgirlshield = 1
)
cost = 50
containertype = /obj/structure/closet/crate
@@ -240,7 +240,7 @@
/datum/supply_pack/recreation/smoleworld
name = "Smole Bulding Bricks"
contains = list(
- /obj/item/weapon/storage/smolebrickcase, /obj/item/weapon/storage/smolebrickcase,
+ /obj/item/storage/smolebrickcase, /obj/item/storage/smolebrickcase,
)
cost = 50
containertype = /obj/structure/closet/crate
@@ -250,7 +250,7 @@
name = "Snack planets pack"
num_contained = 4
contains = list(
- /obj/item/weapon/storage/bagoplanets, /obj/item/weapon/storage/bagoplanets
+ /obj/item/storage/bagoplanets, /obj/item/storage/bagoplanets
)
cost = 25
containertype = /obj/structure/closet/crate
@@ -259,7 +259,7 @@
/datum/supply_pack/recreation/pinkpillows
name = "Pillow Crate - Pink"
contains = list(
- /obj/item/weapon/bedsheet/pillow = 6
+ /obj/item/bedsheet/pillow = 6
)
cost = 10
containertype = /obj/structure/closet/crate
@@ -267,7 +267,7 @@
/datum/supply_pack/recreation/tealpillows
name = "Pillow Crate - Teal"
contains = list(
- /obj/item/weapon/bedsheet/pillow/teal = 6
+ /obj/item/bedsheet/pillow/teal = 6
)
cost = 10
containertype = /obj/structure/closet/crate
@@ -275,7 +275,7 @@
/datum/supply_pack/recreation/whitepillows
name = "Pillow Crate - White"
contains = list(
- /obj/item/weapon/bedsheet/pillow/white = 6
+ /obj/item/bedsheet/pillow/white = 6
)
cost = 10
containertype = /obj/structure/closet/crate
@@ -283,7 +283,7 @@
/datum/supply_pack/recreation/blackpillows
name = "Pillow Crate - Black"
contains = list(
- /obj/item/weapon/bedsheet/pillow/black = 6
+ /obj/item/bedsheet/pillow/black = 6
)
cost = 10
containertype = /obj/structure/closet/crate
@@ -291,7 +291,7 @@
/datum/supply_pack/recreation/redpillows
name = "Pillow Crate - Red"
contains = list(
- /obj/item/weapon/bedsheet/pillow/red = 6
+ /obj/item/bedsheet/pillow/red = 6
)
cost = 10
containertype = /obj/structure/closet/crate
@@ -299,7 +299,7 @@
/datum/supply_pack/recreation/greenpillows
name = "Pillow Crate - Green"
contains = list(
- /obj/item/weapon/bedsheet/pillow/green = 6
+ /obj/item/bedsheet/pillow/green = 6
)
cost = 10
containertype = /obj/structure/closet/crate
@@ -307,7 +307,7 @@
/datum/supply_pack/recreation/orangepillows
name = "Pillow Crate - Orange"
contains = list(
- /obj/item/weapon/bedsheet/pillow/orange = 6
+ /obj/item/bedsheet/pillow/orange = 6
)
cost = 10
containertype = /obj/structure/closet/crate
@@ -315,7 +315,7 @@
/datum/supply_pack/recreation/yellowpillows
name = "Pillow Crate - Yellow"
contains = list(
- /obj/item/weapon/bedsheet/pillow/yellow = 6
+ /obj/item/bedsheet/pillow/yellow = 6
)
cost = 10
containertype = /obj/structure/closet/crate
diff --git a/code/datums/supplypacks/robotics.dm b/code/datums/supplypacks/robotics.dm
index a5fec8e2bb1..900d56d5f6e 100644
--- a/code/datums/supplypacks/robotics.dm
+++ b/code/datums/supplypacks/robotics.dm
@@ -14,10 +14,10 @@
/datum/supply_pack/robotics/robotics_assembly
name = "Robotics assembly crate"
contains = list(
- /obj/item/device/assembly/prox_sensor = 3,
- /obj/item/weapon/storage/toolbox/electrical,
- /obj/item/device/flash = 4,
- /obj/item/weapon/cell/high = 2
+ /obj/item/assembly/prox_sensor = 3,
+ /obj/item/storage/toolbox/electrical,
+ /obj/item/flash = 4,
+ /obj/item/cell/high = 2
)
cost = 10
containertype = /obj/structure/closet/crate/secure/nanotrasen
@@ -27,8 +27,8 @@
/*/datum/supply_pack/robotics/robolimbs_basic
name = "Basic robolimb blueprints"
contains = list(
- /obj/item/weapon/disk/limb/morpheus,
- /obj/item/weapon/disk/limb/xion
+ /obj/item/disk/limb/morpheus,
+ /obj/item/disk/limb/xion
)
cost = 15
containertype = /obj/structure/closet/crate/secure/gear
@@ -38,13 +38,13 @@
/datum/supply_pack/robotics/robolimbs_adv
name = "All robolimb blueprints"
contains = list(
- /obj/item/weapon/disk/limb/bishop,
- /obj/item/weapon/disk/limb/hephaestus,
- /obj/item/weapon/disk/limb/morpheus,
- /obj/item/weapon/disk/limb/veymed,
- /obj/item/weapon/disk/limb/wardtakahashi,
- /obj/item/weapon/disk/limb/xion,
- /obj/item/weapon/disk/limb/zenghu,
+ /obj/item/disk/limb/bishop,
+ /obj/item/disk/limb/hephaestus,
+ /obj/item/disk/limb/morpheus,
+ /obj/item/disk/limb/veymed,
+ /obj/item/disk/limb/wardtakahashi,
+ /obj/item/disk/limb/xion,
+ /obj/item/disk/limb/zenghu,
)
cost = 40
containertype = /obj/structure/closet/crate/secure/gear
@@ -54,7 +54,7 @@
/datum/supply_pack/robotics/robolimbs/morpheus
name = "Morpheus robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/morpheus)
+ contains = list(/obj/item/disk/limb/morpheus)
cost = 20
containertype = /obj/structure/closet/crate/secure/morpheus
containername = "Robolimb blueprints (Morpheus)"
@@ -62,7 +62,7 @@
/datum/supply_pack/robotics/robolimbs/cybersolutions
name = "Cyber Solutions robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/cybersolutions)
+ contains = list(/obj/item/disk/limb/cybersolutions)
cost = 20
containertype = /obj/structure/closet/crate/secure/cybersolutions
containername = "Robolimb blueprints (Cyber Solutions)"
@@ -70,7 +70,7 @@
/datum/supply_pack/robotics/robolimbs/xion
name = "Xion robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/xion)
+ contains = list(/obj/item/disk/limb/xion)
cost = 20
containertype = /obj/structure/closet/crate/secure/xion
containername = "Robolimb blueprints (Xion)"
@@ -78,7 +78,7 @@
/datum/supply_pack/robotics/robolimbs/grayson
name = "Grayson robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/grayson)
+ contains = list(/obj/item/disk/limb/grayson)
cost = 30
containertype = /obj/structure/closet/crate/secure/grayson
containername = "Robolimb blueprints (Grayson)"
@@ -86,7 +86,7 @@
/datum/supply_pack/robotics/robolimbs/hephaestus
name = "Hephaestus robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/hephaestus)
+ contains = list(/obj/item/disk/limb/hephaestus)
cost = 35
containertype = /obj/structure/closet/crate/secure/heph
containername = "Robolimb blueprints (Hephaestus)"
@@ -94,7 +94,7 @@
/datum/supply_pack/robotics/robolimbs/wardtakahashi
name = "Ward-Takahashi robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/wardtakahashi)
+ contains = list(/obj/item/disk/limb/wardtakahashi)
cost = 35
containertype = /obj/structure/closet/crate/secure/ward
containername = "Robolimb blueprints (Ward-Takahashi)"
@@ -102,7 +102,7 @@
/datum/supply_pack/robotics/robolimbs/zenghu
name = "Zeng Hu robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/zenghu)
+ contains = list(/obj/item/disk/limb/zenghu)
cost = 35
containertype = /obj/structure/closet/crate/secure/zenghu
containername = "Robolimb blueprints (Zeng Hu)"
@@ -110,7 +110,7 @@
/datum/supply_pack/robotics/robolimbs/bishop
name = "Bishop robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/bishop)
+ contains = list(/obj/item/disk/limb/bishop)
cost = 70
containertype = /obj/structure/closet/crate/secure/bishop
containername = "Robolimb blueprints (Bishop)"
@@ -118,7 +118,7 @@
/datum/supply_pack/robotics/robolimbs/cenilimicybernetics
name = "Cenilimi Cybernetics robolimb blueprints"
- contains = list(/obj/item/weapon/disk/limb/cenilimicybernetics)
+ contains = list(/obj/item/disk/limb/cenilimicybernetics)
cost = 45
containertype = /obj/structure/closet/crate/secure/science
containername = "Robolimb blueprints (Cenilimi Cybernetics)"
@@ -128,9 +128,9 @@
/datum/supply_pack/robotics/mecha_ripley
name = "Circuit Crate (\"Ripley\" APLU)"
contains = list(
- /obj/item/weapon/book/manual/ripley_build_and_repair,
- /obj/item/weapon/circuitboard/mecha/ripley/main,
- /obj/item/weapon/circuitboard/mecha/ripley/peripherals
+ /obj/item/book/manual/ripley_build_and_repair,
+ /obj/item/circuitboard/mecha/ripley/main,
+ /obj/item/circuitboard/mecha/ripley/peripherals
)
cost = 25
containertype = /obj/structure/closet/crate/secure/xion
@@ -140,8 +140,8 @@
/datum/supply_pack/robotics/mecha_odysseus
name = "Circuit Crate (\"Odysseus\")"
contains = list(
- /obj/item/weapon/circuitboard/mecha/odysseus/peripherals,
- /obj/item/weapon/circuitboard/mecha/odysseus/main
+ /obj/item/circuitboard/mecha/odysseus/peripherals,
+ /obj/item/circuitboard/mecha/odysseus/main
)
cost = 25
containertype = /obj/structure/closet/crate/secure/veymed
@@ -151,10 +151,10 @@
/datum/supply_pack/randomised/robotics/exosuit_mod
num_contained = 1
contains = list(
- /obj/item/device/kit/paint/ripley,
- /obj/item/device/kit/paint/ripley/death,
- /obj/item/device/kit/paint/ripley/flames_red,
- /obj/item/device/kit/paint/ripley/flames_blue
+ /obj/item/kit/paint/ripley,
+ /obj/item/kit/paint/ripley/death,
+ /obj/item/kit/paint/ripley/flames_red,
+ /obj/item/kit/paint/ripley/flames_blue
)
name = "Random APLU modkit"
cost = 200
@@ -163,18 +163,18 @@
/datum/supply_pack/randomised/robotics/exosuit_mod/durand
contains = list(
- /obj/item/device/kit/paint/durand,
- /obj/item/device/kit/paint/durand/seraph,
- /obj/item/device/kit/paint/durand/phazon
+ /obj/item/kit/paint/durand,
+ /obj/item/kit/paint/durand/seraph,
+ /obj/item/kit/paint/durand/phazon
)
name = "Random Durand exosuit modkit"
containertype = /obj/structure/closet/crate/heph
/datum/supply_pack/randomised/robotics/exosuit_mod/gygax
contains = list(
- /obj/item/device/kit/paint/gygax,
- /obj/item/device/kit/paint/gygax/darkgygax,
- /obj/item/device/kit/paint/gygax/recitence
+ /obj/item/kit/paint/gygax,
+ /obj/item/kit/paint/gygax/darkgygax,
+ /obj/item/kit/paint/gygax/recitence
)
name = "Random Gygax exosuit modkit"
containertype = /obj/structure/closet/crate/heph
@@ -182,7 +182,7 @@
/datum/supply_pack/robotics/jumper_cables
name = "Jumper kit crate"
contains = list(
- /obj/item/device/defib_kit/jumper_kit = 2
+ /obj/item/defib_kit/jumper_kit = 2
)
cost = 30
containertype = /obj/structure/closet/crate/secure/einstein
@@ -192,8 +192,8 @@
/datum/supply_pack/robotics/restrainingbolt
name = "Restraining bolt crate"
contains = list(
- /obj/item/weapon/implanter = 1,
- /obj/item/weapon/implantcase/restrainingbolt = 2
+ /obj/item/implanter = 1,
+ /obj/item/implantcase/restrainingbolt = 2
)
cost = 40
containertype = /obj/structure/closet/crate/secure/cybersolutions
@@ -224,8 +224,8 @@
/datum/supply_pack/robotics/mecha_gopher
name = "Circuit Crate (\"Gopher\" APLU)"
contains = list(
- /obj/item/weapon/circuitboard/mecha/gopher/main,
- /obj/item/weapon/circuitboard/mecha/gopher/peripherals
+ /obj/item/circuitboard/mecha/gopher/main,
+ /obj/item/circuitboard/mecha/gopher/peripherals
)
cost = 25
containertype = /obj/structure/closet/crate/secure/science
@@ -235,9 +235,9 @@
/datum/supply_pack/robotics/mecha_polecat
name = "Circuit Crate (\"Polecat\" APLU)"
contains = list(
- /obj/item/weapon/circuitboard/mecha/polecat/main,
- /obj/item/weapon/circuitboard/mecha/polecat/peripherals,
- /obj/item/weapon/circuitboard/mecha/polecat/targeting
+ /obj/item/circuitboard/mecha/polecat/main,
+ /obj/item/circuitboard/mecha/polecat/peripherals,
+ /obj/item/circuitboard/mecha/polecat/targeting
)
cost = 25
containertype = /obj/structure/closet/crate/secure/science
@@ -247,9 +247,9 @@
/datum/supply_pack/robotics/mecha_weasel
name = "Circuit Crate (\"Weasel\" APLU)"
contains = list(
- /obj/item/weapon/circuitboard/mecha/weasel/main,
- /obj/item/weapon/circuitboard/mecha/weasel/peripherals,
- /obj/item/weapon/circuitboard/mecha/weasel/targeting
+ /obj/item/circuitboard/mecha/weasel/main,
+ /obj/item/circuitboard/mecha/weasel/peripherals,
+ /obj/item/circuitboard/mecha/weasel/targeting
)
cost = 25
containertype = /obj/structure/closet/crate/secure/science
@@ -259,9 +259,9 @@
/datum/supply_pack/robotics/some_robolimbs
name = "Basic Robolimb Blueprints"
contains = list(
- /obj/item/weapon/disk/limb/morpheus,
- /obj/item/weapon/disk/limb/xion,
- /obj/item/weapon/disk/limb/talon
+ /obj/item/disk/limb/morpheus,
+ /obj/item/disk/limb/xion,
+ /obj/item/disk/limb/talon
)
cost = 15
containertype = /obj/structure/closet/crate/secure
@@ -271,24 +271,24 @@
/datum/supply_pack/robotics/all_robolimbs
name = "Advanced Robolimb Blueprints"
contains = list(
- /obj/item/weapon/disk/limb/bishop,
- /obj/item/weapon/disk/limb/hephaestus,
- /obj/item/weapon/disk/limb/morpheus,
- /obj/item/weapon/disk/limb/veymed,
- /obj/item/weapon/disk/limb/wardtakahashi,
- /obj/item/weapon/disk/limb/xion,
- /obj/item/weapon/disk/limb/zenghu,
- /obj/item/weapon/disk/limb/talon,
- /obj/item/weapon/disk/limb/dsi_tajaran,
- /obj/item/weapon/disk/limb/dsi_lizard,
- /obj/item/weapon/disk/limb/dsi_sergal,
- /obj/item/weapon/disk/limb/dsi_nevrean,
- /obj/item/weapon/disk/limb/dsi_vulpkanin,
- /obj/item/weapon/disk/limb/dsi_akula,
- /obj/item/weapon/disk/limb/dsi_spider,
- /obj/item/weapon/disk/limb/dsi_teshari,
- /obj/item/weapon/disk/limb/eggnerdltd,
- /obj/item/weapon/disk/limb/eggnerdltdred
+ /obj/item/disk/limb/bishop,
+ /obj/item/disk/limb/hephaestus,
+ /obj/item/disk/limb/morpheus,
+ /obj/item/disk/limb/veymed,
+ /obj/item/disk/limb/wardtakahashi,
+ /obj/item/disk/limb/xion,
+ /obj/item/disk/limb/zenghu,
+ /obj/item/disk/limb/talon,
+ /obj/item/disk/limb/dsi_tajaran,
+ /obj/item/disk/limb/dsi_lizard,
+ /obj/item/disk/limb/dsi_sergal,
+ /obj/item/disk/limb/dsi_nevrean,
+ /obj/item/disk/limb/dsi_vulpkanin,
+ /obj/item/disk/limb/dsi_akula,
+ /obj/item/disk/limb/dsi_spider,
+ /obj/item/disk/limb/dsi_teshari,
+ /obj/item/disk/limb/eggnerdltd,
+ /obj/item/disk/limb/eggnerdltdred
)
cost = 40
containertype = /obj/structure/closet/crate/secure
diff --git a/code/datums/supplypacks/science.dm b/code/datums/supplypacks/science.dm
index 729a543a19d..94469a886fe 100644
--- a/code/datums/supplypacks/science.dm
+++ b/code/datums/supplypacks/science.dm
@@ -15,13 +15,13 @@
/datum/supply_pack/sci/phoron
name = "Phoron research crate"
contains = list(
- /obj/item/weapon/tank/phoron = 3,
- /obj/item/weapon/tank/oxygen = 3,
- /obj/item/device/assembly/igniter = 3,
- /obj/item/device/assembly/prox_sensor = 3,
- /obj/item/device/assembly/timer = 3,
- /obj/item/device/assembly/signaler = 3,
- /obj/item/device/transfer_valve = 3
+ /obj/item/tank/phoron = 3,
+ /obj/item/tank/oxygen = 3,
+ /obj/item/assembly/igniter = 3,
+ /obj/item/assembly/prox_sensor = 3,
+ /obj/item/assembly/timer = 3,
+ /obj/item/assembly/signaler = 3,
+ /obj/item/transfer_valve = 3
)
cost = 10
containertype = /obj/structure/closet/crate/secure/phoron
@@ -45,14 +45,14 @@
/datum/supply_pack/sci/integrated_circuit_printer
name = "Integrated circuit printer"
- contains = list(/obj/item/device/integrated_circuit_printer = 2)
+ contains = list(/obj/item/integrated_circuit_printer = 2)
cost = 15
containertype = /obj/structure/closet/crate/ward
containername = "Integrated circuit crate"
/datum/supply_pack/sci/integrated_circuit_printer_upgrade
name = "Integrated circuit printer upgrade - advanced designs"
- contains = list(/obj/item/weapon/disk/integrated_circuit/upgrade/advanced)
+ contains = list(/obj/item/disk/integrated_circuit/upgrade/advanced)
cost = 30
containertype = /obj/structure/closet/crate/ward
containername = "Integrated circuit crate"
@@ -60,20 +60,20 @@
/datum/supply_pack/sci/xenoarch
name = "Xenoarchaeology Tech crate"
contains = list(
- /obj/item/weapon/pickaxe/excavationdrill,
- /obj/item/device/xenoarch_multi_tool,
+ /obj/item/pickaxe/excavationdrill,
+ /obj/item/xenoarch_multi_tool,
/obj/item/clothing/suit/space/anomaly,
/obj/item/clothing/head/helmet/space/anomaly,
- /obj/item/weapon/storage/belt/archaeology,
- /obj/item/device/flashlight/lantern,
- /obj/item/device/core_sampler,
- /obj/item/device/gps,
- /obj/item/device/beacon_locator,
- /obj/item/device/radio/beacon,
+ /obj/item/storage/belt/archaeology,
+ /obj/item/flashlight/lantern,
+ /obj/item/core_sampler,
+ /obj/item/gps,
+ /obj/item/beacon_locator,
+ /obj/item/radio/beacon,
/obj/item/clothing/glasses/meson,
- /obj/item/weapon/pickaxe,
- /obj/item/weapon/storage/bag/fossils,
- /obj/item/weapon/hand_labeler)
+ /obj/item/pickaxe,
+ /obj/item/storage/bag/fossils,
+ /obj/item/hand_labeler)
cost = 100
containertype = /obj/structure/closet/crate/secure/xion
containername = "Xenoarchaeology Tech crate"
diff --git a/code/datums/supplypacks/security.dm b/code/datums/supplypacks/security.dm
index 9e58d74f1cf..1f2cf06f89e 100644
--- a/code/datums/supplypacks/security.dm
+++ b/code/datums/supplypacks/security.dm
@@ -253,12 +253,12 @@
/datum/supply_pack/security/riot_gear
name = "Gear - Riot"
contains = list(
- /obj/item/weapon/melee/baton = 3,
- /obj/item/weapon/shield/riot = 3,
- /obj/item/weapon/handcuffs = 3,
- /obj/item/weapon/storage/box/flashbangs,
+ /obj/item/melee/baton = 3,
+ /obj/item/shield/riot = 3,
+ /obj/item/handcuffs = 3,
+ /obj/item/storage/box/flashbangs,
/obj/item/ammo_magazine/ammo_box/b12g/beanbag,
- /obj/item/weapon/storage/box/handcuffs
+ /obj/item/storage/box/handcuffs
)
cost = 40
containertype = /obj/structure/closet/crate/secure/lawson
@@ -292,7 +292,7 @@
/datum/supply_pack/security/riot_sprayer
name = "Gear - Riot sprayer"
contains = list(
- /obj/item/weapon/watertank/pepperspray
+ /obj/item/watertank/pepperspray
)
cost = 40
containertype = /obj/structure/closet/crate/secure/lawson
@@ -373,7 +373,7 @@
/obj/item/clothing/head/helmet/tactical,
/obj/item/clothing/mask/balaclava/tactical,
/obj/item/clothing/glasses/sunglasses/sechud/tactical,
- /obj/item/weapon/storage/belt/security/tactical,
+ /obj/item/storage/belt/security/tactical,
/obj/item/clothing/shoes/boots/jackboots,
/obj/item/clothing/gloves/black,
/obj/item/clothing/under/tactical,
@@ -381,7 +381,7 @@
/obj/item/clothing/head/helmet/tactical,
/obj/item/clothing/mask/balaclava/tactical,
/obj/item/clothing/glasses/sunglasses/sechud/tactical,
- /obj/item/weapon/storage/belt/security/tactical,
+ /obj/item/storage/belt/security/tactical,
/obj/item/clothing/shoes/boots/jackboots,
/obj/item/clothing/gloves/black
)
@@ -400,14 +400,14 @@
/obj/item/clothing/gloves/arm_guard/flexitac,
/obj/item/clothing/mask/balaclava/tactical,
/obj/item/clothing/glasses/sunglasses/sechud/tactical,
- /obj/item/weapon/storage/belt/security/tactical,
+ /obj/item/storage/belt/security/tactical,
/obj/item/clothing/suit/storage/vest/heavy/flexitac,
/obj/item/clothing/head/helmet/flexitac,
/obj/item/clothing/shoes/leg_guard/flexitac,
/obj/item/clothing/gloves/arm_guard/flexitac,
/obj/item/clothing/mask/balaclava/tactical,
/obj/item/clothing/glasses/sunglasses/sechud/tactical,
- /obj/item/weapon/storage/belt/security/tactical
+ /obj/item/storage/belt/security/tactical
)
/datum/supply_pack/security/securitybarriers
@@ -442,9 +442,9 @@
/datum/supply_pack/security/extragear
name = "Gear - Security surplus equipment"
contains = list(
- /obj/item/weapon/storage/belt/security = 3,
+ /obj/item/storage/belt/security = 3,
/obj/item/clothing/glasses/sunglasses/sechud = 3,
- /obj/item/device/radio/headset/headset_sec/alt = 3,
+ /obj/item/radio/headset/alt/headset_sec = 3,
/obj/item/clothing/suit/storage/hooded/wintercoat/security = 3,
/obj/item/clothing/glasses/sunglasses/sechud/tactical_sec_vis = 3
)
@@ -455,25 +455,25 @@
/datum/supply_pack/security/detectivegear
name = "Forensic - Investigation equipment"
contains = list(
- /obj/item/weapon/storage/box/evidence = 2,
+ /obj/item/storage/box/evidence = 2,
/obj/item/clothing/suit/storage/vest/detective,
- /obj/item/weapon/cartridge/detective,
- /obj/item/device/radio/headset/headset_sec,
+ /obj/item/cartridge/detective,
+ /obj/item/radio/headset/headset_sec,
/obj/item/taperoll/police,
/obj/item/clothing/glasses/sunglasses,
- /obj/item/device/camera,
- /obj/item/weapon/folder/red,
- /obj/item/weapon/folder/blue,
- /obj/item/weapon/storage/belt/detective,
+ /obj/item/camera,
+ /obj/item/folder/red,
+ /obj/item/folder/blue,
+ /obj/item/storage/belt/detective,
/obj/item/clothing/gloves/black,
- /obj/item/device/taperecorder,
- /obj/item/device/mass_spectrometer,
- /obj/item/device/camera_film = 2,
- /obj/item/weapon/storage/photo_album,
- /obj/item/device/reagent_scanner,
- /obj/item/device/flashlight/maglight,
- /obj/item/weapon/storage/briefcase/crimekit,
- /obj/item/weapon/storage/bag/detective
+ /obj/item/taperecorder,
+ /obj/item/mass_spectrometer,
+ /obj/item/camera_film = 2,
+ /obj/item/storage/photo_album,
+ /obj/item/reagent_scanner,
+ /obj/item/flashlight/maglight,
+ /obj/item/storage/briefcase/crimekit,
+ /obj/item/storage/bag/detective
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanotrasen
@@ -483,10 +483,10 @@
/datum/supply_pack/security/detectivescan
name = "Forensic - Scanning Equipment"
contains = list(
- /obj/item/device/mass_spectrometer,
- /obj/item/device/reagent_scanner,
- /obj/item/weapon/storage/briefcase/crimekit,
- /obj/item/device/detective_scanner
+ /obj/item/mass_spectrometer,
+ /obj/item/reagent_scanner,
+ /obj/item/storage/briefcase/crimekit,
+ /obj/item/detective_scanner
)
cost = 60
containertype = /obj/structure/closet/crate/secure/ward
@@ -520,25 +520,25 @@
contains = list(
/obj/item/clothing/suit/storage/vest/officer,
/obj/item/clothing/head/helmet,
- /obj/item/weapon/cartridge/security,
+ /obj/item/cartridge/security,
/obj/item/clothing/accessory/badge/holo,
/obj/item/clothing/accessory/badge/holo/cord,
- /obj/item/device/radio/headset/headset_sec,
- /obj/item/weapon/storage/belt/security,
- /obj/item/device/flash,
- /obj/item/weapon/reagent_containers/spray/pepper,
- /obj/item/weapon/grenade/flashbang,
- /obj/item/weapon/melee/baton/loaded,
+ /obj/item/radio/headset/headset_sec,
+ /obj/item/storage/belt/security,
+ /obj/item/flash,
+ /obj/item/reagent_containers/spray/pepper,
+ /obj/item/grenade/flashbang,
+ /obj/item/melee/baton/loaded,
/obj/item/clothing/glasses/sunglasses/sechud,
/obj/item/taperoll/police,
/obj/item/clothing/gloves/black,
- /obj/item/device/hailer,
- /obj/item/device/flashlight/flare,
+ /obj/item/hailer,
+ /obj/item/flashlight/flare,
/obj/item/clothing/accessory/storage/black_vest,
/obj/item/clothing/head/soft/sec/corp,
/obj/item/clothing/under/rank/security/corp,
- /obj/item/weapon/gun/energy/taser,
- /obj/item/device/flashlight/maglight
+ /obj/item/gun/energy/taser,
+ /obj/item/flashlight/maglight
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanotrasen
@@ -546,7 +546,7 @@
access = access_brig
/datum/supply_pack/security/wardengear
- name = "Gear - Warden equipment"
+ name = "Gear - " + JOB_WARDEN + " equipment"
contains = list(
/obj/item/clothing/suit/storage/vest/warden,
/obj/item/clothing/under/rank/warden,
@@ -555,27 +555,27 @@
/obj/item/clothing/suit/storage/vest/wardencoat/alt,
/obj/item/clothing/suit/storage/vest/wardencoat/alt2, //VOREStation Add,
/obj/item/clothing/head/helmet/warden,
- /obj/item/weapon/cartridge/security,
- /obj/item/device/radio/headset/headset_sec,
+ /obj/item/cartridge/security,
+ /obj/item/radio/headset/headset_sec,
/obj/item/clothing/glasses/sunglasses/sechud,
/obj/item/taperoll/police,
- /obj/item/device/hailer,
+ /obj/item/hailer,
/obj/item/clothing/accessory/badge/holo/warden,
- /obj/item/weapon/storage/box/flashbangs,
- /obj/item/weapon/storage/belt/security,
- /obj/item/weapon/reagent_containers/spray/pepper,
- /obj/item/weapon/melee/baton/loaded,
- /obj/item/weapon/storage/box/holobadge,
+ /obj/item/storage/box/flashbangs,
+ /obj/item/storage/belt/security,
+ /obj/item/reagent_containers/spray/pepper,
+ /obj/item/melee/baton/loaded,
+ /obj/item/storage/box/holobadge,
/obj/item/clothing/head/beret/sec/corporate/warden,
- /obj/item/device/flashlight/maglight
+ /obj/item/flashlight/maglight
)
cost = 20
containertype = /obj/structure/closet/crate/secure/nanotrasen
- containername = "Warden equipment"
+ containername = JOB_WARDEN + " equipment"
access = access_armory
/datum/supply_pack/security/headofsecgear
- name = "Gear - Head of security equipment"
+ name = "Gear - " + JOB_HEAD_OF_SECURITY + " equipment"
contains = list(
/obj/item/clothing/head/helmet/HoS,
/obj/item/clothing/suit/storage/vest/hos,
@@ -583,29 +583,29 @@
/obj/item/clothing/suit/storage/vest/hoscoat,
/obj/item/clothing/suit/storage/vest/hoscoat/jensen/alt, //VOREStation Add,
/obj/item/clothing/head/helmet/dermal,
- /obj/item/weapon/cartridge/hos,
- /obj/item/device/radio/headset/heads/hos,
+ /obj/item/cartridge/hos,
+ /obj/item/radio/headset/heads/hos,
/obj/item/clothing/glasses/sunglasses/sechud,
- /obj/item/weapon/storage/belt/security,
- /obj/item/device/flash,
- /obj/item/device/hailer,
+ /obj/item/storage/belt/security,
+ /obj/item/flash,
+ /obj/item/hailer,
/obj/item/clothing/accessory/badge/holo/hos,
/obj/item/clothing/accessory/holster/waist,
- /obj/item/weapon/melee/telebaton,
- /obj/item/weapon/shield/riot/tele,
+ /obj/item/melee/telebaton,
+ /obj/item/shield/riot/tele,
/obj/item/clothing/head/beret/sec/corporate/hos,
- /obj/item/device/flashlight/maglight
+ /obj/item/flashlight/maglight
)
cost = 50
containertype = /obj/structure/closet/crate/secure/nanotrasen
- containername = "Head of security equipment"
+ containername = JOB_HEAD_OF_SECURITY + " equipment"
access = access_hos
/datum/supply_pack/security/securityclothing
name = "Misc - Security uniform red"
contains = list(
- /obj/item/weapon/storage/backpack/satchel/sec = 2,
- /obj/item/weapon/storage/backpack/security = 2,
+ /obj/item/storage/backpack/satchel/sec = 2,
+ /obj/item/storage/backpack/security = 2,
/obj/item/clothing/accessory/armband = 4,
/obj/item/clothing/under/rank/security = 4,
/obj/item/clothing/under/rank/security2 = 4,
@@ -613,7 +613,7 @@
/obj/item/clothing/under/rank/head_of_security,
/obj/item/clothing/head/soft/sec = 4,
/obj/item/clothing/gloves/black = 4,
- /obj/item/weapon/storage/box/holobadge
+ /obj/item/storage/box/holobadge
)
cost = 10
containertype = /obj/structure/closet/crate/secure/nanotrasen
@@ -622,8 +622,8 @@
/datum/supply_pack/security/navybluesecurityclothing
name = "Misc - Security uniform navy blue"
contains = list(
- /obj/item/weapon/storage/backpack/satchel/sec = 2,
- /obj/item/weapon/storage/backpack/security = 2,
+ /obj/item/storage/backpack/satchel/sec = 2,
+ /obj/item/storage/backpack/security = 2,
/obj/item/clothing/under/rank/security/navyblue = 4,
/obj/item/clothing/suit/security/navyofficer = 4,
/obj/item/clothing/under/rank/warden/navyblue,
@@ -634,7 +634,7 @@
/obj/item/clothing/head/beret/sec/navy/warden,
/obj/item/clothing/head/beret/sec/navy/hos,
/obj/item/clothing/gloves/black = 4,
- /obj/item/weapon/storage/box/holobadge
+ /obj/item/storage/box/holobadge
)
cost = 10
containertype = /obj/structure/closet/crate/secure/nanotrasen
@@ -643,8 +643,8 @@
/datum/supply_pack/security/corporatesecurityclothing
name = "Misc - Security uniform corporate"
contains = list(
- /obj/item/weapon/storage/backpack/satchel/sec = 2,
- /obj/item/weapon/storage/backpack/security = 2,
+ /obj/item/storage/backpack/satchel/sec = 2,
+ /obj/item/storage/backpack/security = 2,
/obj/item/clothing/under/rank/security/corp = 4,
/obj/item/clothing/head/soft/sec/corp = 4,
/obj/item/clothing/under/rank/warden/corp,
@@ -654,7 +654,7 @@
/obj/item/clothing/head/beret/sec/corporate/hos,
/obj/item/clothing/under/det/corporate = 2,
/obj/item/clothing/gloves/black = 4,
- /obj/item/weapon/storage/box/holobadge
+ /obj/item/storage/box/holobadge
)
cost = 10
containertype = /obj/structure/closet/crate/secure/nanotrasen
@@ -668,9 +668,9 @@
/obj/item/clothing/suit/bio_suit/security = 3,
/obj/item/clothing/shoes/white = 3,
/obj/item/clothing/mask/gas = 3,
- /obj/item/weapon/tank/oxygen = 3,
+ /obj/item/tank/oxygen = 3,
/obj/item/clothing/gloves/sterile/latex,
- /obj/item/weapon/storage/box/gloves
+ /obj/item/storage/box/gloves
)
cost = 25
containertype = /obj/structure/closet/crate/secure/nanotrasen
@@ -715,16 +715,16 @@
/obj/item/clothing/suit/bio_suit/security = 3,
/obj/item/clothing/shoes/white = 3,
/obj/item/clothing/mask/gas = 3,
- /obj/item/weapon/tank/oxygen = 3,
+ /obj/item/tank/oxygen = 3,
/obj/item/clothing/gloves/sterile/latex,
- /obj/item/weapon/storage/box/gloves
+ /obj/item/storage/box/gloves
)
cost = 40
/datum/supply_pack/security/trackingimplant
name = "Implants - Tracking"
contains = list(
- /obj/item/weapon/storage/box/trackimp = 1
+ /obj/item/storage/box/trackimp = 1
)
cost = 25
containertype = /obj/structure/closet/crate/secure
@@ -734,7 +734,7 @@
/datum/supply_pack/security/chemicalimplant
name = "Implants - Chemical"
contains = list(
- /obj/item/weapon/storage/box/chemimp = 1
+ /obj/item/storage/box/chemimp = 1
)
cost = 25
containertype = /obj/structure/closet/crate/secure
diff --git a/code/datums/supplypacks/security_yw.dm b/code/datums/supplypacks/security_yw.dm
index 1b2909556bd..f303dc7de7c 100644
--- a/code/datums/supplypacks/security_yw.dm
+++ b/code/datums/supplypacks/security_yw.dm
@@ -1,7 +1,7 @@
/datum/supply_pack/security/loyaltyimplants
name = "Loyalty Implant Lockbox"
contains = list(
- /obj/item/weapon/storage/lockbox/loyalty
+ /obj/item/storage/lockbox/loyalty
)
cost = 100
containertype = /obj/structure/closet/crate/secure/gear
@@ -11,11 +11,11 @@
/datum/supply_pack/security/covenantmeleeweapons
name = "Covenant melee weapon pack"
contains = list(
- /obj/item/weapon/melee/energy/elite_sword,
- /obj/item/weapon/melee/energy/elite_sword/dagger,
- /obj/item/weapon/melee/energy/elite_sword/dagger,
- /obj/item/weapon/melee/blamite/dagger,
- /obj/item/weapon/melee/blamite/dagger
+ /obj/item/melee/energy/elite_sword,
+ /obj/item/melee/energy/elite_sword/dagger,
+ /obj/item/melee/energy/elite_sword/dagger,
+ /obj/item/melee/blamite/dagger,
+ /obj/item/melee/blamite/dagger
)
cost = 200
containertype = /obj/structure/closet/crate/secure/gear
diff --git a/code/datums/supplypacks/supply.dm b/code/datums/supplypacks/supply.dm
index ed12a28884e..b6c79687531 100644
--- a/code/datums/supplypacks/supply.dm
+++ b/code/datums/supplypacks/supply.dm
@@ -9,14 +9,14 @@
/datum/supply_pack/supply/food
name = "Kitchen supply crate"
contains = list(
- /obj/item/weapon/reagent_containers/food/condiment/carton/flour = 6,
- /obj/item/weapon/reagent_containers/food/drinks/milk = 3,
- /obj/item/weapon/reagent_containers/food/drinks/soymilk = 2,
- /obj/item/weapon/storage/fancy/egg_box = 2,
- /obj/item/weapon/reagent_containers/food/snacks/tofu = 4,
- /obj/item/weapon/reagent_containers/food/snacks/meat = 4,
- /obj/item/weapon/reagent_containers/food/condiment/yeast = 3,
- /obj/item/weapon/reagent_containers/food/condiment/sprinkles = 1
+ /obj/item/reagent_containers/food/condiment/carton/flour = 6,
+ /obj/item/reagent_containers/food/drinks/milk = 3,
+ /obj/item/reagent_containers/food/drinks/soymilk = 2,
+ /obj/item/storage/fancy/egg_box = 2,
+ /obj/item/reagent_containers/food/snacks/tofu = 4,
+ /obj/item/reagent_containers/food/snacks/meat = 4,
+ /obj/item/reagent_containers/food/condiment/yeast = 3,
+ /obj/item/reagent_containers/food/condiment/sprinkles = 1
)
cost = 10
containertype = /obj/structure/closet/crate/freezer/centauri
@@ -25,8 +25,8 @@
/datum/supply_pack/supply/fancyfood
name = "Artisanal food delivery"
contains = list(
- /obj/item/weapon/reagent_containers/food/condiment/carton/flour/rustic = 6,
- /obj/item/weapon/reagent_containers/food/condiment/carton/sugar/rustic = 6
+ /obj/item/reagent_containers/food/condiment/carton/flour/rustic = 6,
+ /obj/item/reagent_containers/food/condiment/carton/sugar/rustic = 6
)
cost = 25
containertype = /obj/structure/closet/crate/freezer/centauri
@@ -35,7 +35,7 @@
/datum/supply_pack/supply/toner
name = "Toner cartridges"
- contains = list(/obj/item/device/toner = 6)
+ contains = list(/obj/item/toner = 6)
cost = 10
containertype = /obj/structure/closet/crate/ummarcar
containername = "Toner cartridges"
@@ -43,20 +43,20 @@
/datum/supply_pack/supply/janitor
name = "Janitorial supplies"
contains = list(
- /obj/item/weapon/reagent_containers/glass/bucket,
- /obj/item/weapon/mop,
+ /obj/item/reagent_containers/glass/bucket,
+ /obj/item/mop,
/obj/item/clothing/under/rank/janitor,
- /obj/item/weapon/cartridge/janitor,
+ /obj/item/cartridge/janitor,
/obj/item/clothing/gloves/black,
/obj/item/clothing/head/soft/purple,
- /obj/item/weapon/storage/belt/janitor,
+ /obj/item/storage/belt/janitor,
/obj/item/clothing/shoes/galoshes,
/obj/item/clothing/suit/caution = 4,
- /obj/item/weapon/storage/bag/trash,
- /obj/item/device/lightreplacer,
- /obj/item/weapon/reagent_containers/spray/cleaner,
- /obj/item/weapon/reagent_containers/glass/rag,
- /obj/item/weapon/grenade/chem_grenade/cleaner = 3,
+ /obj/item/storage/bag/trash,
+ /obj/item/lightreplacer,
+ /obj/item/reagent_containers/spray/cleaner,
+ /obj/item/reagent_containers/glass/rag,
+ /obj/item/grenade/chem_grenade/cleaner = 3,
/obj/item/clothing/glasses/hud/janitor,
/obj/structure/mopbucket
)
@@ -68,30 +68,30 @@
name = "Shipping supplies"
contains = list(
/obj/fiftyspawner/cardboard,
- /obj/item/weapon/packageWrap = 4,
- /obj/item/weapon/wrapping_paper = 2,
- /obj/item/device/destTagger,
- /obj/item/weapon/hand_labeler,
- /obj/item/weapon/tool/wirecutters,
- /obj/item/weapon/tape_roll = 2)
+ /obj/item/packageWrap = 4,
+ /obj/item/wrapping_paper = 2,
+ /obj/item/destTagger,
+ /obj/item/hand_labeler,
+ /obj/item/tool/wirecutters,
+ /obj/item/tape_roll = 2)
cost = 10
containertype = /obj/structure/closet/crate/ummarcar
containername = "Shipping supplies crate"
/datum/supply_pack/supply/bureaucracy
contains = list(
- /obj/item/weapon/clipboard = 2,
- /obj/item/weapon/pen/red,
- /obj/item/weapon/pen/blue,
- /obj/item/weapon/pen/blue,
- /obj/item/device/camera_film,
- /obj/item/weapon/folder/blue,
- /obj/item/weapon/folder/red,
- /obj/item/weapon/folder/yellow,
- /obj/item/weapon/hand_labeler,
- /obj/item/weapon/tape_roll,
+ /obj/item/clipboard = 2,
+ /obj/item/pen/red,
+ /obj/item/pen/blue,
+ /obj/item/pen/blue,
+ /obj/item/camera_film,
+ /obj/item/folder/blue,
+ /obj/item/folder/red,
+ /obj/item/folder/yellow,
+ /obj/item/hand_labeler,
+ /obj/item/tape_roll,
/obj/structure/filingcabinet/chestdrawer{anchored = FALSE},
- /obj/item/weapon/paper_bin
+ /obj/item/paper_bin
)
name = "Office supplies"
cost = 15
@@ -110,24 +110,24 @@
cost = 10
containertype = /obj/structure/closet/crate/thinktronic
containername = "Spare PDA crate"
- contains = list(/obj/item/device/pda = 3)
+ contains = list(/obj/item/pda = 3)
/datum/supply_pack/supply/minergear
name = "Shaft miner equipment"
contains = list(
- /obj/item/weapon/storage/backpack/industrial,
- /obj/item/weapon/storage/backpack/satchel/eng,
+ /obj/item/storage/backpack/industrial,
+ /obj/item/storage/backpack/satchel/eng,
/obj/item/clothing/suit/storage/hooded/wintercoat/miner,
- /obj/item/device/radio/headset/headset_cargo,
+ /obj/item/radio/headset/miner,
/obj/item/clothing/under/rank/miner,
/obj/item/clothing/gloves/black,
/obj/item/clothing/shoes/black,
- /obj/item/device/analyzer,
- /obj/item/weapon/storage/bag/ore,
- /obj/item/device/flashlight/lantern,
- /obj/item/weapon/shovel,
- /obj/item/weapon/pickaxe,
- /obj/item/weapon/mining_scanner,
+ /obj/item/analyzer,
+ /obj/item/storage/bag/ore,
+ /obj/item/flashlight/lantern,
+ /obj/item/shovel,
+ /obj/item/pickaxe,
+ /obj/item/mining_scanner,
/obj/item/clothing/glasses/material,
/obj/item/clothing/glasses/meson
)
@@ -157,55 +157,55 @@
cost = 15
/datum/supply_pack/explorergear
- name="Explorer gear" // YW EDIT
+ name= JOB_EXPLORER + " gear"
contains = list (
- /obj/item/device/cataloguer,
- /obj/item/device/geiger,
+ /obj/item/cataloguer,
+ /obj/item/geiger,
/obj/item/clothing/suit/storage/hooded/explorer,
- /obj/item/device/flashlight/glowstick,
- /obj/item/device/flashlight,
+ /obj/item/flashlight/glowstick,
+ /obj/item/flashlight,
/obj/item/stack/marker_beacon/thirty,
- /obj/item/weapon/storage/belt/explorer,
+ /obj/item/storage/belt/explorer,
/obj/item/clothing/mask/gas/explorer,
- /obj/item/weapon/cartridge/explorer,
- /obj/item/device/gps/explorer,
+ /obj/item/cartridge/explorer,
+ /obj/item/gps/explorer,
/obj/item/clothing/under/explorer,
- /obj/item/device/radio/headset/explorer,
+ /obj/item/radio/headset/explorer,
/obj/item/clothing/shoes/boots/winter/explorer,
- /obj/item/weapon/material/knife/tacknife/survival,
- /obj/item/weapon/material/knife/machete,
+ /obj/item/material/knife/tacknife/survival,
+ /obj/item/material/knife/machete,
/obj/item/clothing/accessory/holster/machete,
- /obj/item/clothing/gloves/watch/survival
+ /obj/item/clothing/accessory/watch/survival
)
cost=25
containertype = /obj/structure/closet/crate/secure/xion
- containername = "Explorer equipment" // YW EDIT
+ containername = JOB_EXPLORER + " equipment"
access = list(access_eva, access_explorer)
/datum/supply_pack/pilotgear
- name= "Pilot gear"
+ name= JOB_PILOT + " gear"
contains = list (
- /obj/item/weapon/storage/backpack/parachute,
- /obj/item/device/radio/headset/pilot,
- /obj/item/device/radio/headset/pilot/alt,
+ /obj/item/storage/backpack/parachute,
+ /obj/item/radio/headset/pilot,
+ /obj/item/radio/headset/alt/pilot,
/obj/item/clothing/mask/gas/half,
- /obj/item/device/flashlight/glowstick,
+ /obj/item/flashlight/glowstick,
/obj/item/stack/marker_beacon/thirty,
- /obj/item/device/gps/explorer,
+ /obj/item/gps/explorer,
/obj/item/clothing/gloves/fingerless,
/obj/item/clothing/suit/storage/toggle/bomber/pilot,
/obj/item/clothing/shoes/boots/winter/explorer,
- /obj/item/device/flashlight,
- /obj/item/weapon/material/knife/tacknife/survival,
+ /obj/item/flashlight,
+ /obj/item/material/knife/tacknife/survival,
/obj/item/clothing/head/pilot_vr,
/obj/item/clothing/under/rank/pilot1,
- /obj/item/weapon/gun/energy/gun/protector/pilotgun/locked,
- /obj/item/clothing/gloves/watch/survival,
- /obj/item/device/cataloguer/compact
+ /obj/item/gun/energy/gun/protector/pilotgun/locked,
+ /obj/item/clothing/accessory/watch/survival,
+ /obj/item/cataloguer/compact // YW EDIT
)
cost=20
containertype = /obj/structure/closet/crate/secure/xion
- containername = "Pilot equipment"
+ containername = JOB_PILOT + " equipment"
access = access_pilot
/datum/supply_pack/supply/foodcubes
@@ -217,29 +217,29 @@
containername = "food cubes"
/datum/supply_pack/pathfindergear
- name="Away Team Leader gear"
+ name= JOB_PATHFINDER + " gear"
contains = list (
- /obj/item/device/cataloguer/compact/pathfinder,
- /obj/item/device/geiger,
+ /obj/item/cataloguer/compact/pathfinder,
+ /obj/item/geiger,
/obj/item/clothing/suit/storage/hooded/explorer,
- /obj/item/device/flashlight/glowstick,
- /obj/item/device/flashlight,
+ /obj/item/flashlight/glowstick,
+ /obj/item/flashlight,
/obj/item/stack/marker_beacon/thirty,
- /obj/item/weapon/storage/belt/explorer/pathfinder,
+ /obj/item/storage/belt/explorer/pathfinder,
/obj/item/clothing/mask/gas/explorer,
- /obj/item/weapon/cartridge/explorer,
- /obj/item/device/gps/explorer,
+ /obj/item/cartridge/explorer,
+ /obj/item/gps/explorer,
/obj/item/clothing/under/explorer,
- /obj/item/device/radio/headset/pathfinder,
+ /obj/item/radio/headset/pathfinder,
/obj/item/clothing/shoes/boots/winter/explorer,
- /obj/item/weapon/material/knife/tacknife/survival,
- /obj/item/weapon/material/knife/machete/deluxe,
+ /obj/item/material/knife/tacknife/survival,
+ /obj/item/material/knife/machete/deluxe,
/obj/item/clothing/accessory/holster/machete,
- /obj/item/weapon/storage/box/explorerkeys,
- /obj/item/device/mapping_unit,
- /obj/item/clothing/gloves/watch/survival
+ /obj/item/storage/box/explorerkeys,
+ /obj/item/mapping_unit,
+ /obj/item/clothing/accessory/watch/survival
)
cost = 75
containertype = /obj/structure/closet/crate/secure/xion
- containername = "Away Team Leader equipment"
+ containername = JOB_PATHFINDER + " equipment"
access = list(access_explorer)
diff --git a/code/datums/supplypacks/vending_refills.dm b/code/datums/supplypacks/vending_refills.dm
index 06119f2d4f2..e8cf8aa88bf 100644
--- a/code/datums/supplypacks/vending_refills.dm
+++ b/code/datums/supplypacks/vending_refills.dm
@@ -9,122 +9,122 @@
containername = "vendor refill cartridge crate"
/datum/supply_pack/vending_refills/snack
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/snack)
+ contains = list(/obj/item/refill_cartridge/autoname/food/snack)
name = "Getmore Chocolate Corp Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/fitness
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/fitness)
+ contains = list(/obj/item/refill_cartridge/autoname/food/fitness)
name = "SweatMAX Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/weeb
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/weeb)
+ contains = list(/obj/item/refill_cartridge/autoname/food/weeb)
name = "Nippon-tan Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/sol
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/sol)
+ contains = list(/obj/item/refill_cartridge/autoname/food/sol)
name = "Sol-Snacks Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/snix
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/snix)
+ contains = list(/obj/item/refill_cartridge/autoname/food/snix)
name = "Snix Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/snlvend
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/snlvend)
+ contains = list(/obj/item/refill_cartridge/autoname/food/snlvend)
name = "Shop-n-Large Snacks Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/sovietvend
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/sovietvend)
+ contains = list(/obj/item/refill_cartridge/autoname/food/sovietvend)
name = "Ration Station Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/altevian
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/altevian)
+ contains = list(/obj/item/refill_cartridge/autoname/food/altevian)
name = "Altevian Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/coffee
- contains = list(/obj/item/weapon/refill_cartridge/autoname/drink/coffee)
+ contains = list(/obj/item/refill_cartridge/autoname/drink/coffee)
name = "Hot Drinks Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/cola
- contains = list(/obj/item/weapon/refill_cartridge/autoname/drink/cola)
+ contains = list(/obj/item/refill_cartridge/autoname/drink/cola)
name = "Robust Softdrinks Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/sovietsoda
- contains = list(/obj/item/weapon/refill_cartridge/autoname/drink/sovietsoda)
+ contains = list(/obj/item/refill_cartridge/autoname/drink/sovietsoda)
name = "BODA Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/bepis
- contains = list(/obj/item/weapon/refill_cartridge/autoname/drink/bepis)
+ contains = list(/obj/item/refill_cartridge/autoname/drink/bepis)
name = "Bepis Softdrinks Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/cigarette
- contains = list(/obj/item/weapon/refill_cartridge/autoname/cigarette)
+ contains = list(/obj/item/refill_cartridge/autoname/cigarette)
name = "Cigarette Vendor Refill Cartridge"
cost = 15
/datum/supply_pack/vending_refills/wardrobe
- contains = list(/obj/item/weapon/refill_cartridge/multitype/wardrobe)
+ contains = list(/obj/item/refill_cartridge/multitype/wardrobe)
name = "Wardrobe Vendor Refill Cartridge"
cost = 10
/datum/supply_pack/vending_refills/giftvendor
- contains = list(/obj/item/weapon/refill_cartridge/autoname/giftvendor)
+ contains = list(/obj/item/refill_cartridge/autoname/giftvendor)
name = "AlliCo Baubles and Confectionaries Vendor Refill Cartridge"
cost = 20
/datum/supply_pack/vending_refills/general_food
- contains = list(/obj/item/weapon/refill_cartridge/multitype/food = 5)
+ contains = list(/obj/item/refill_cartridge/multitype/food = 5)
name = "5-Pack Food Vendor Refill Cartridges"
cost = 75
/datum/supply_pack/vending_refills/general_drink
- contains = list(/obj/item/weapon/refill_cartridge/multitype/drink = 5)
+ contains = list(/obj/item/refill_cartridge/multitype/drink = 5)
name = "5-Pack Drink Vendor Refill Cartridges"
cost = 75
/datum/supply_pack/vending_refills/general_clothing
- contains = list(/obj/item/weapon/refill_cartridge/multitype/clothing = 5)
+ contains = list(/obj/item/refill_cartridge/multitype/clothing = 5)
name = "5-Pack Clothing Vendor Refill Cartridges"
cost = 75
/datum/supply_pack/vending_refills/general_technical
- contains = list(/obj/item/weapon/refill_cartridge/multitype/technical = 5)
+ contains = list(/obj/item/refill_cartridge/multitype/technical = 5)
name = "5-Pack Technical Vendor Refill Cartridges"
cost = 75
/datum/supply_pack/vending_refills/general_specialty
- contains = list(/obj/item/weapon/refill_cartridge/multitype/specialty = 5)
+ contains = list(/obj/item/refill_cartridge/multitype/specialty = 5)
name = "5-Pack Specialty Vendor Refill Cartridges"
cost = 150
/datum/supply_pack/randomised/vending_refills/value_pack // 5 random vendor-specific cartridges at lower average price. But why?
num_contained = 5
- contains = list(/obj/item/weapon/refill_cartridge/autoname/food/snack,
- /obj/item/weapon/refill_cartridge/autoname/food/fitness,
- /obj/item/weapon/refill_cartridge/autoname/food/weeb,
- /obj/item/weapon/refill_cartridge/autoname/food/sol,
- /obj/item/weapon/refill_cartridge/autoname/food/snix,
- /obj/item/weapon/refill_cartridge/autoname/food/snlvend,
- /obj/item/weapon/refill_cartridge/autoname/food/sovietvend,
- /obj/item/weapon/refill_cartridge/autoname/drink/coffee,
- /obj/item/weapon/refill_cartridge/autoname/drink/cola,
- /obj/item/weapon/refill_cartridge/autoname/drink/sovietsoda,
- /obj/item/weapon/refill_cartridge/autoname/drink/bepis,
- /obj/item/weapon/refill_cartridge/autoname/cigarette,
- /obj/item/weapon/refill_cartridge/multitype/wardrobe,
- /obj/item/weapon/refill_cartridge/autoname/technical/assist,
- /obj/item/weapon/refill_cartridge/autoname/technical/tool,
- /obj/item/weapon/refill_cartridge/autoname/giftvendor)
+ contains = list(/obj/item/refill_cartridge/autoname/food/snack,
+ /obj/item/refill_cartridge/autoname/food/fitness,
+ /obj/item/refill_cartridge/autoname/food/weeb,
+ /obj/item/refill_cartridge/autoname/food/sol,
+ /obj/item/refill_cartridge/autoname/food/snix,
+ /obj/item/refill_cartridge/autoname/food/snlvend,
+ /obj/item/refill_cartridge/autoname/food/sovietvend,
+ /obj/item/refill_cartridge/autoname/drink/coffee,
+ /obj/item/refill_cartridge/autoname/drink/cola,
+ /obj/item/refill_cartridge/autoname/drink/sovietsoda,
+ /obj/item/refill_cartridge/autoname/drink/bepis,
+ /obj/item/refill_cartridge/autoname/cigarette,
+ /obj/item/refill_cartridge/multitype/wardrobe,
+ /obj/item/refill_cartridge/autoname/technical/assist,
+ /obj/item/refill_cartridge/autoname/technical/tool,
+ /obj/item/refill_cartridge/autoname/giftvendor)
name = "5-pack Extra-Cheap Vendor Refill Cartridges"
cost = 35
\ No newline at end of file
diff --git a/code/datums/supplypacks/voidsuits.dm b/code/datums/supplypacks/voidsuits.dm
index 429913b36a5..7b6a0769b25 100644
--- a/code/datums/supplypacks/voidsuits.dm
+++ b/code/datums/supplypacks/voidsuits.dm
@@ -14,7 +14,7 @@
/obj/item/clothing/head/helmet/space/void/atmos = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2,
+ /obj/item/tank/oxygen = 2,
)
cost = 35
containertype = /obj/structure/closet/crate/secure/aether
@@ -28,7 +28,7 @@
/obj/item/clothing/head/helmet/space/void/atmos/alt = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2,
+ /obj/item/tank/oxygen = 2,
)
cost = 60
containertype = /obj/structure/closet/crate/secure/aether
@@ -42,7 +42,7 @@
/obj/item/clothing/head/helmet/space/void/engineering = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 35
containertype = /obj/structure/closet/crate/secure/xion
@@ -56,7 +56,7 @@
/obj/item/clothing/head/helmet/space/void/engineering/construction = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 35
containertype = /obj/structure/closet/crate/secure/xion
@@ -70,7 +70,7 @@
/obj/item/clothing/head/helmet/space/void/engineering/hazmat = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 35
containertype = /obj/structure/closet/crate/secure/xion
@@ -84,7 +84,7 @@
/obj/item/clothing/head/helmet/space/void/engineering/alt = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 60
containertype = /obj/structure/closet/crate/secure/xion
@@ -98,7 +98,7 @@
/obj/item/clothing/head/helmet/space/void/medical = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 35
containertype = /obj/structure/closet/crate/secure/veymed
@@ -112,7 +112,7 @@
/obj/item/clothing/head/helmet/space/void/medical/emt = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 35
containertype = /obj/structure/closet/crate/secure/veymed
@@ -126,7 +126,7 @@
/obj/item/clothing/head/helmet/space/void/medical/bio = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 35
containertype = /obj/structure/closet/crate/secure/nanomed
@@ -140,7 +140,7 @@
/obj/item/clothing/head/helmet/space/void/medical/alt = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 60
containertype = /obj/structure/closet/crate/secure/veymed
@@ -154,7 +154,7 @@
/obj/item/clothing/head/helmet/space/void/medical/alt/tesh = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
containername = "Vey-Med Autoadaptive voidsuit (teshari) crate"
@@ -165,7 +165,7 @@
/obj/item/clothing/head/helmet/space/void/security = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 35
containertype = /obj/structure/closet/crate/secure/heph
@@ -178,7 +178,7 @@
/obj/item/clothing/head/helmet/space/void/security/riot = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 60
containertype = /obj/structure/closet/crate/secure/heph
@@ -192,7 +192,7 @@
/obj/item/clothing/head/helmet/space/void/security/alt = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 60
containertype = /obj/structure/closet/crate/secure/heph
@@ -205,7 +205,7 @@
/obj/item/clothing/suit/space/void/mining = 2,
/obj/item/clothing/head/helmet/space/void/mining = 2,
/obj/item/clothing/mask/breath = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 35
containertype = /obj/structure/closet/crate/secure/xion
@@ -218,7 +218,7 @@
/obj/item/clothing/suit/space/void/mining/alt = 2,
/obj/item/clothing/head/helmet/space/void/mining/alt = 2,
/obj/item/clothing/mask/breath = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 60
containertype = /obj/structure/closet/crate/secure/grayson
@@ -237,45 +237,45 @@
access = null
/datum/supply_pack/voidsuits/explorer
- name = "Expedition voidsuits" //YW Edit
+ name = JOB_EXPLORER + " voidsuits"
contains = list(
/obj/item/clothing/suit/space/void/exploration = 2,
/obj/item/clothing/head/helmet/space/void/exploration = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 45
containertype = /obj/structure/closet/crate/secure
- containername = "Exploration voidsuit crate" //YW Edit
+ containername = JOB_EXPLORER + "voidsuit crate"
access = list(access_eva, access_explorer)
/datum/supply_pack/voidsuits/explorer_medic
- name = "Expedition Medic voidsuits" //YW Edit
+ name = JOB_FIELD_MEDIC + " voidsuits"
contains = list(
/obj/item/clothing/suit/space/void/exploration = 2,
/obj/item/clothing/head/helmet/space/void/exploration = 2,
/obj/item/clothing/mask/breath = 2,
/obj/item/clothing/shoes/magboots = 2,
- /obj/item/weapon/tank/oxygen = 2
+ /obj/item/tank/oxygen = 2
)
cost = 45
containertype = /obj/structure/closet/crate/secure
- containername = "Exploration Medic voidsuit crate" //YW Edit
- access = access_explorer // YW EDIT
+ containername = JOB_FIELD_MEDIC + " voidsuit crate"
+ access = access_explorer // YW EDI
/datum/supply_pack/voidsuits/pilot
- name = "Pilot voidsuits"
+ name = JOB_PILOT + " voidsuits"
contains = list(
/obj/item/clothing/suit/space/void/pilot = 1,
/obj/item/clothing/head/helmet/space/void/pilot = 1,
/obj/item/clothing/mask/breath = 1,
/obj/item/clothing/shoes/magboots = 1,
- /obj/item/weapon/tank/oxygen = 1
+ /obj/item/tank/oxygen = 1
)
cost = 20
containertype = /obj/structure/closet/crate/secure
- containername = "Pilot voidsuit crate"
+ containername = JOB_PILOT + " voidsuit crate"
access = access_pilot
// Surplus!
@@ -383,7 +383,7 @@
contains = list(
/obj/item/clothing/suit/space/void/salvagecorp_shipbreaker,
/obj/item/clothing/head/helmet/space/void/salvagecorp_shipbreaker,
- /obj/item/weapon/tank/jetpack/breaker
+ /obj/item/tank/jetpack/breaker
)
cost = 100
containertype = /obj/structure/closet/crate/coyote_salvage
@@ -391,7 +391,7 @@
/datum/supply_pack/voidsuits/unathi_bs_yw
name = "Unathi breacher chassis"
- contains = list(/obj/item/weapon/rig/breacher) //YW Edit
+ contains = list(/obj/item/rig/breacher) //YW Edit
cost = 350
containertype = /obj/structure/closet/crate/secure
containername = "Unathi breacher chassis crate"
diff --git a/code/datums/underwear/top.dm b/code/datums/underwear/top.dm
index 629027a2f44..12e53627caa 100644
--- a/code/datums/underwear/top.dm
+++ b/code/datums/underwear/top.dm
@@ -78,6 +78,10 @@
name = "Binder"
icon_state = "binder_s"
+/datum/category_item/underwear/top/binder_hyper
+ name = "HYPER Binder"
+ icon_state = "hyper_binder"
+
/datum/category_item/underwear/top/straplessbinder
name = "Binder Strapless"
icon_state = "straplessbinder_s"
diff --git a/code/datums/underwear/undershirts.dm b/code/datums/underwear/undershirts.dm
index 5a34d645e73..c74186ab0f4 100644
--- a/code/datums/underwear/undershirts.dm
+++ b/code/datums/underwear/undershirts.dm
@@ -253,6 +253,36 @@
icon_state = "leotard"
has_color = TRUE
+/datum/category_item/underwear/undershirt/tshirt
+ name = "Feminine T-Shirt"
+ icon_state = "t-shirt_full"
+ has_color = TRUE
+
+/datum/category_item/underwear/undershirt/tshirt_midriff
+ name = "Feminine T-Shirt (midriff)"
+ icon_state = "t-shirt_midriff"
+ has_color = TRUE
+
+/datum/category_item/underwear/undershirt/tshirt_shoulders
+ name = "Feminine T-Shirt (black with shoulders)"
+ icon_state = "t-shirt_full_shoulders"
+ has_color = TRUE
+
+/datum/category_item/underwear/undershirt/tshirt_midriff_shoulders
+ name = "Feminine T-Shirt (midriff, black with shoulders)"
+ icon_state = "t-shirt_midriff_shoulders"
+ has_color = TRUE
+
+/datum/category_item/underwear/undershirt/tshirt_shoulders_text
+ name = "Feminine T-Shirt (black with shoulders and text)"
+ icon_state = "t-shirt_full_shoulders_text"
+ has_color = TRUE
+
+/datum/category_item/underwear/undershirt/tshirt_midriff_shoulders_text
+ name = "Feminine T-Shirt (midriff, black with shoulders and text)"
+ icon_state = "t-shirt_midriff_shoulders_text"
+ has_color = TRUE
+
// YW CHANGES START HERE //
/datum/category_item/underwear/undershirt/alien
diff --git a/code/datums/uplink/ammunition.dm b/code/datums/uplink/ammunition.dm
index 8a749250b66..76b5d440635 100644
--- a/code/datums/uplink/ammunition.dm
+++ b/code/datums/uplink/ammunition.dm
@@ -130,4 +130,4 @@
/datum/uplink_item/item/ammo/cell
name = "weapon cell"
- path = /obj/item/weapon/cell/device/weapon
\ No newline at end of file
+ path = /obj/item/cell/device/weapon
\ No newline at end of file
diff --git a/code/datums/uplink/ammunition_vr.dm b/code/datums/uplink/ammunition_vr.dm
index 2783710f7eb..a9c722b3573 100644
--- a/code/datums/uplink/ammunition_vr.dm
+++ b/code/datums/uplink/ammunition_vr.dm
@@ -7,22 +7,22 @@
/datum/uplink_item/item/ammo/cell/box
name = "Weapon cell box"
- path = /obj/item/weapon/storage/box/weapon_cells
+ path = /obj/item/storage/box/weapon_cells
item_cost = 70
/datum/uplink_item/item/ammo/highcell
name = "High capacity cell"
- path = /obj/item/weapon/cell/high
+ path = /obj/item/cell/high
item_cost = 15
/datum/uplink_item/item/ammo/supercell
name = "Super capacity cell"
- path = /obj/item/weapon/cell/super
+ path = /obj/item/cell/super
item_cost = 30
/datum/uplink_item/item/ammo/voidcell
name = "Void cell"
- path = /obj/item/weapon/cell/device/weapon/recharge/alien/hybrid
+ path = /obj/item/cell/device/weapon/recharge/alien/hybrid
item_cost = DEFAULT_TELECRYSTAL_AMOUNT * 1.5
antag_roles = list("ert")
blacklisted = 1
diff --git a/code/datums/uplink/announcements.dm b/code/datums/uplink/announcements.dm
index 5bc7dde793c..12330db3b80 100644
--- a/code/datums/uplink/announcements.dm
+++ b/code/datums/uplink/announcements.dm
@@ -5,7 +5,7 @@
category = /datum/uplink_category/services
blacklisted = 1
-/datum/uplink_item/abstract/announcements/buy(var/obj/item/device/uplink/U, var/mob/user)
+/datum/uplink_item/abstract/announcements/buy(var/obj/item/uplink/U, var/mob/user)
. = ..()
if(.)
log_and_message_admins("has triggered a falsified [src]", user)
@@ -24,7 +24,7 @@
return
return list("title" = title, "message" = message)
-/datum/uplink_item/abstract/announcements/fake_centcom/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user, var/list/args)
+/datum/uplink_item/abstract/announcements/fake_centcom/get_goods(var/obj/item/uplink/U, var/loc, var/mob/user, var/list/args)
post_comm_message(args["title"], replacetext(args["message"], "\n", "
"))
command_announcement.Announce(args["message"], args["title"])
return 1
@@ -34,11 +34,11 @@
desc = "Creates a fake crew arrival announcement as well as fake crew records, using your current appearance (including held items!) and worn id card. Trigger with care!"
item_cost = 15
-/datum/uplink_item/abstract/announcements/fake_crew_arrival/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user, var/list/args)
+/datum/uplink_item/abstract/announcements/fake_crew_arrival/get_goods(var/obj/item/uplink/U, var/loc, var/mob/user, var/list/args)
if(!user)
return 0
- var/obj/item/weapon/card/id/I = user.GetIdCard()
+ var/obj/item/card/id/I = user.GetIdCard()
var/datum/data/record/random_general_record
var/datum/data/record/random_medical_record
if(data_core.general.len)
@@ -93,7 +93,7 @@
desc = "Interferes with the station's ion sensors. Triggers immediately upon investment."
item_cost = 10
-/datum/uplink_item/abstract/announcements/fake_ion_storm/get_goods(var/obj/item/device/uplink/U, var/loc)
+/datum/uplink_item/abstract/announcements/fake_ion_storm/get_goods(var/obj/item/uplink/U, var/loc)
ion_storm_announcement()
return 1
@@ -102,7 +102,7 @@
desc = "Interferes with the station's radiation sensors. Triggers immediately upon investment."
item_cost = 15
-/datum/uplink_item/abstract/announcements/fake_radiation/get_goods(var/obj/item/device/uplink/U, var/loc)
+/datum/uplink_item/abstract/announcements/fake_radiation/get_goods(var/obj/item/uplink/U, var/loc)
var/datum/event_meta/EM = new(EVENT_LEVEL_MUNDANE, "Fake Radiation Storm", add_to_queue = 0)
new/datum/event/radiation_storm/syndicate(EM)
return 1
diff --git a/code/datums/uplink/armor.dm b/code/datums/uplink/armor.dm
index 362aec5d92b..c82ba17b43f 100644
--- a/code/datums/uplink/armor.dm
+++ b/code/datums/uplink/armor.dm
@@ -7,7 +7,7 @@
/datum/uplink_item/item/armor/combat
name = "Combat Armor Set"
item_cost = 30
- path = /obj/item/weapon/storage/box/syndie_kit/combat_armor
+ path = /obj/item/storage/box/syndie_kit/combat_armor
/datum/uplink_item/item/armor/heavy_vest
name = "Heavy Armor Vest"
@@ -17,12 +17,12 @@
/datum/uplink_item/item/armor/gorlexsuit
name = "Mercenary Voidsuit"
item_cost = 20
- path = /obj/item/weapon/storage/box/syndie_kit/voidsuit
+ path = /obj/item/storage/box/syndie_kit/voidsuit
/datum/uplink_item/item/armor/gorlexsuit_fire
name = "Mercenary Voidsuit (Fire)"
item_cost = 20
- path = /obj/item/weapon/storage/box/syndie_kit/voidsuit/fire
+ path = /obj/item/storage/box/syndie_kit/voidsuit/fire
/datum/uplink_item/item/armor/combat
name = "Combat Platecarrier Set"
diff --git a/code/datums/uplink/backup.dm b/code/datums/uplink/backup.dm
index 3e21676da3b..d85d67aa057 100644
--- a/code/datums/uplink/backup.dm
+++ b/code/datums/uplink/backup.dm
@@ -12,7 +12,7 @@
a stunbaton, handcuffs, an agent ID, energy sword, pinpointer, and a jetpack."
item_cost = DEFAULT_TELECRYSTAL_AMOUNT * 1.5
antag_roles = list("mercenary", "ert") //VOREStation Edit
- path = /obj/item/weapon/antag_spawner/syndicate_drone/protector
+ path = /obj/item/antag_spawner/syndicate_drone/protector
/datum/uplink_item/item/backup/syndicate_drone_combat_medic
name = "Drone (Combat Medic)"
@@ -22,7 +22,7 @@
sword, pinpointer, and a jetpack."
item_cost = DEFAULT_TELECRYSTAL_AMOUNT * 1.5
antag_roles = list("mercenary", "ert") //VOREStation Edit
- path = /obj/item/weapon/antag_spawner/syndicate_drone/combat_medic
+ path = /obj/item/antag_spawner/syndicate_drone/combat_medic
/datum/uplink_item/item/backup/syndicate_drone_mechanist
name = "Drone (Mechanist)"
@@ -32,4 +32,4 @@
a set of construction materials, an ionic rapier, an agent ID, energy sword, pinpointer, and a jetpack."
item_cost = DEFAULT_TELECRYSTAL_AMOUNT * 1.5
antag_roles = list("mercenary", "ert") //VOREStation Edit
- path = /obj/item/weapon/antag_spawner/syndicate_drone/mechanist
\ No newline at end of file
+ path = /obj/item/antag_spawner/syndicate_drone/mechanist
\ No newline at end of file
diff --git a/code/datums/uplink/badassery.dm b/code/datums/uplink/badassery.dm
index 2541bac5045..c6c597918d9 100644
--- a/code/datums/uplink/badassery.dm
+++ b/code/datums/uplink/badassery.dm
@@ -21,21 +21,21 @@
name = "Random Item"
desc = "Buys you one random item."
-/datum/uplink_item/item/badassery/random_one/buy(var/obj/item/device/uplink/U, var/mob/user)
+/datum/uplink_item/item/badassery/random_one/buy(var/obj/item/uplink/U, var/mob/user)
var/datum/uplink_item/item = default_uplink_selection.get_random_item((user ? user.mind.tcrystals : DEFAULT_TELECRYSTAL_AMOUNT), U)
return item.buy(U, user)
-/datum/uplink_item/item/badassery/random_one/can_buy(var/obj/item/device/uplink/U, var/telecrystals)
+/datum/uplink_item/item/badassery/random_one/can_buy(var/obj/item/uplink/U, var/telecrystals)
return default_uplink_selection.get_random_item(telecrystals, U) != null
/datum/uplink_item/item/badassery/random_many
name = "Random Items"
desc = "Buys you as many random items you can afford. Convenient packaging NOT included."
-/datum/uplink_item/item/badassery/random_many/cost(obj/item/device/uplink/U, var/telecrystals)
+/datum/uplink_item/item/badassery/random_many/cost(obj/item/uplink/U, var/telecrystals)
return max(1, telecrystals)
-/datum/uplink_item/item/badassery/random_many/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/M)
+/datum/uplink_item/item/badassery/random_many/get_goods(var/obj/item/uplink/U, var/loc, var/mob/M)
var/list/bought_items = list()
for(var/datum/uplink_item/UI in get_random_uplink_items(U, M.mind.tcrystals, loc))
UI.purchase_log(U)
@@ -45,7 +45,7 @@
return bought_items
-/datum/uplink_item/item/badassery/random_many/purchase_log(obj/item/device/uplink/U)
+/datum/uplink_item/item/badassery/random_many/purchase_log(obj/item/uplink/U)
feedback_add_details("traitor_uplink_items_bought", "[src]")
log_and_message_admins("used \the [U.loc] to buy \a [src] at random")
@@ -77,7 +77,7 @@
..()
desc = "A crate containing [item_worth] telecrystal\s worth of surplus leftovers."
-/datum/uplink_item/item/badassery/surplus/get_goods(var/obj/item/device/uplink/U, var/loc)
+/datum/uplink_item/item/badassery/surplus/get_goods(var/obj/item/uplink/U, var/loc)
var/obj/structure/largecrate/C = new(loc)
var/random_items = get_surplus_items(null, item_worth, C)
for(var/datum/uplink_item/I in random_items)
diff --git a/code/datums/uplink/grenades.dm b/code/datums/uplink/grenades.dm
index 851a9043a68..3e70d652c56 100644
--- a/code/datums/uplink/grenades.dm
+++ b/code/datums/uplink/grenades.dm
@@ -7,62 +7,62 @@
/datum/uplink_item/item/grenades/anti_photon
name = "7xPhoton Disruption Grenades"
item_cost = 10
- path = /obj/item/weapon/storage/box/anti_photons
+ path = /obj/item/storage/box/anti_photons
/datum/uplink_item/item/grenades/anti_photon_singular
name = "1xPhoton Disruption Grenade"
item_cost = 2
- path = /obj/item/weapon/grenade/anti_photon
+ path = /obj/item/grenade/anti_photon
/datum/uplink_item/item/grenades/metalfoam
name = "7xMetal Foam Grenades"
item_cost = 10
- path = /obj/item/weapon/storage/box/metalfoam
+ path = /obj/item/storage/box/metalfoam
/datum/uplink_item/item/grenades/metalfoam_singular
name = "1xMetal Foam Grenade"
item_cost = 2
- path = /obj/item/weapon/grenade/chem_grenade/metalfoam
+ path = /obj/item/grenade/chem_grenade/metalfoam
/datum/uplink_item/item/grenades/smoke
name = "7xSmoke Grenades"
item_cost = 10
- path = /obj/item/weapon/storage/box/smokes
+ path = /obj/item/storage/box/smokes
/datum/uplink_item/item/grenades/smoke_singular
name = "1xSmoke Grenade"
item_cost = 2
- path = /obj/item/weapon/grenade/smokebomb
+ path = /obj/item/grenade/smokebomb
/datum/uplink_item/item/grenades/emp
name = "7xEMP Grenades"
item_cost = 50
- path = /obj/item/weapon/storage/box/emps
+ path = /obj/item/storage/box/emps
/datum/uplink_item/item/grenades/emp_singular
name = "1xEMP Grenade"
item_cost = 10
- path = /obj/item/weapon/grenade/empgrenade
+ path = /obj/item/grenade/empgrenade
/datum/uplink_item/item/grenades/frags
name = "7xFrag Grenades"
item_cost = 80
- path = /obj/item/weapon/storage/box/frags
+ path = /obj/item/storage/box/frags
/datum/uplink_item/item/grenades/frags_half
name = "4x Frag Grenade"
item_cost = 50
- path = /obj/item/weapon/storage/box/frags_half_box
+ path = /obj/item/storage/box/frags_half_box
/datum/uplink_item/item/grenades/frags_singular
name = "1x Frag Grenade"
item_cost = 15
- path = /obj/item/weapon/grenade/explosive
+ path = /obj/item/grenade/explosive
/datum/uplink_item/item/grenades/flashbangs
name = "7xFlashbangs"
item_cost = 40
- path = /obj/item/weapon/storage/box/flashbangs
+ path = /obj/item/storage/box/flashbangs
/datum/uplink_item/item/grenades/flashbangs_singular
name = "1xFlashbang"
diff --git a/code/datums/uplink/hardsuit_modules.dm b/code/datums/uplink/hardsuit_modules.dm
index c58ae6c19f6..5ebc6c9a106 100644
--- a/code/datums/uplink/hardsuit_modules.dm
+++ b/code/datums/uplink/hardsuit_modules.dm
@@ -23,7 +23,7 @@
/datum/uplink_item/item/hardsuit_modules/ewar_voice
name = "Electrowarfare Suite and Voice Synthesiser"
item_cost = 30
- path = /obj/item/weapon/storage/box/syndie_kit/ewar_voice
+ path = /obj/item/storage/box/syndie_kit/ewar_voice
/datum/uplink_item/item/hardsuit_modules/maneuvering_jets
name = "Maneuvering Jets"
diff --git a/code/datums/uplink/implants.dm b/code/datums/uplink/implants.dm
index d1bb93acdcc..f9fa30a9800 100644
--- a/code/datums/uplink/implants.dm
+++ b/code/datums/uplink/implants.dm
@@ -7,79 +7,79 @@
/datum/uplink_item/item/implants/imp_freedom
name = "Freedom Implant"
item_cost = 30
- path = /obj/item/weapon/storage/box/syndie_kit/imp_freedom
+ path = /obj/item/storage/box/syndie_kit/imp_freedom
/datum/uplink_item/item/implants/imp_compress
name = "Compressed Matter Implant"
item_cost = 30
- path = /obj/item/weapon/storage/box/syndie_kit/imp_compress
+ path = /obj/item/storage/box/syndie_kit/imp_compress
/datum/uplink_item/item/implants/imp_explosive
name = "Explosive Implant (DANGER!)"
item_cost = 60
- path = /obj/item/weapon/storage/box/syndie_kit/imp_explosive
+ path = /obj/item/storage/box/syndie_kit/imp_explosive
/datum/uplink_item/item/implants/imp_uplink
name = "Uplink Implant" //Original name: "Uplink Implant (Contains 5 Telecrystals)"
item_cost = 50 //Original cost: 10
- path = /obj/item/weapon/storage/box/syndie_kit/imp_uplink
+ path = /obj/item/storage/box/syndie_kit/imp_uplink
/datum/uplink_item/item/implants/imp_shades
name = "Integrated Thermal-Shades Implant"
item_cost = 80
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug
+ path = /obj/item/storage/box/syndie_kit/imp_aug
/datum/uplink_item/item/implants/imp_taser
name = "Integrated Taser Implant"
item_cost = 30
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/taser
+ path = /obj/item/storage/box/syndie_kit/imp_aug/taser
/datum/uplink_item/item/implants/imp_laser
name = "Integrated Laser Implant"
item_cost = 50
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/laser
+ path = /obj/item/storage/box/syndie_kit/imp_aug/laser
/datum/uplink_item/item/implants/imp_dart
name = "Integrated Dart Implant"
item_cost = 60
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/dart
+ path = /obj/item/storage/box/syndie_kit/imp_aug/dart
/datum/uplink_item/item/implants/imp_toolkit
name = "Integrated Toolkit Implant"
item_cost = 80
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/toolkit
+ path = /obj/item/storage/box/syndie_kit/imp_aug/toolkit
/datum/uplink_item/item/implants/imp_medkit
name = "Integrated Medkit Implant"
item_cost = 60
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/medkit
+ path = /obj/item/storage/box/syndie_kit/imp_aug/medkit
/datum/uplink_item/item/implants/imp_analyzer
name = "Integrated Research Scanner Implant"
item_cost = 20
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/analyzer
+ path = /obj/item/storage/box/syndie_kit/imp_aug/analyzer
/datum/uplink_item/item/implants/imp_sword
name = "Integrated Sword Implant"
item_cost = 40
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/sword
+ path = /obj/item/storage/box/syndie_kit/imp_aug/sword
/datum/uplink_item/item/implants/imp_sprinter
name = "Integrated Sprinter Implant"
item_cost = 40
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/sprinter
+ path = /obj/item/storage/box/syndie_kit/imp_aug/sprinter
/datum/uplink_item/item/implants/imp_sprinter
name = "Integrated Surge Implant"
item_cost = 40
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/surge
+ path = /obj/item/storage/box/syndie_kit/imp_aug/surge
/datum/uplink_item/item/implants/imp_armblade
name = "Integrated Armblade Implant"
item_cost = 40
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/armblade
+ path = /obj/item/storage/box/syndie_kit/imp_aug/armblade
/datum/uplink_item/item/implants/imp_handblade
name = "Integrated Handblade Implant"
item_cost = 25
- path = /obj/item/weapon/storage/box/syndie_kit/imp_aug/handblade
+ path = /obj/item/storage/box/syndie_kit/imp_aug/handblade
diff --git a/code/datums/uplink/medical.dm b/code/datums/uplink/medical.dm
index c1ff848877e..01639c4113e 100644
--- a/code/datums/uplink/medical.dm
+++ b/code/datums/uplink/medical.dm
@@ -7,107 +7,107 @@
/datum/uplink_item/item/medical/onegativeblood
name = "O- Blood Pack"
item_cost = 1
- path = /obj/item/weapon/reagent_containers/blood/OMinus
+ path = /obj/item/reagent_containers/blood/OMinus
/datum/uplink_item/item/medical/sinpockets
name = "Box of Sin-Pockets"
item_cost = 1
- path = /obj/item/weapon/storage/box/sinpockets
+ path = /obj/item/storage/box/sinpockets
/datum/uplink_item/item/medical/ambrosiaseeds
name = "Box of 7x ambrosia seed packets"
item_cost = 1
- path = /obj/item/weapon/storage/box/ambrosia
+ path = /obj/item/storage/box/ambrosia
/datum/uplink_item/item/medical/clotting
name = "Clotting Medicine injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting
+ path = /obj/item/reagent_containers/hypospray/autoinjector/biginjector/clotting
/datum/uplink_item/item/medical/clotting_case
name = "Clotting Medicine case"
item_cost = 10
desc = "A case of three myelamine injectors. Can rapidly remove and stow up to six injectors."
- path = /obj/item/weapon/storage/quickdraw/syringe_case/clotting
+ path = /obj/item/storage/quickdraw/syringe_case/clotting
/datum/uplink_item/item/medical/bonemeds
name = "Bone Repair injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/bonemed
+ path = /obj/item/reagent_containers/hypospray/autoinjector/bonemed
/datum/uplink_item/item/medical/clonemeds
name = "Clone injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/clonemed
+ path = /obj/item/reagent_containers/hypospray/autoinjector/clonemed
/datum/uplink_item/item/medical/bonemeds_case
name = "Bone Repair case"
item_cost = 10
desc = "A case of three osteodaxon injectors. Can rapidly remove and stow up to six injectors."
- path = /obj/item/weapon/storage/quickdraw/syringe_case/bonemed
+ path = /obj/item/storage/quickdraw/syringe_case/bonemed
/datum/uplink_item/item/medical/clonemeds_case
name = "Clone case"
item_cost = 10
desc = "A case of three rezadone injectors. Can rapidly remove and stow up to six injectors."
- path = /obj/item/weapon/storage/quickdraw/syringe_case/clonemed
+ path = /obj/item/storage/quickdraw/syringe_case/clonemed
/datum/uplink_item/item/medical/ambrosiadeusseeds
name = "Box of 7x ambrosia deus seed packets"
item_cost = 5
- path = /obj/item/weapon/storage/box/ambrosiadeus
+ path = /obj/item/storage/box/ambrosiadeus
/datum/uplink_item/item/medical/freezer
name = "Portable Freezer"
item_cost = 1
- path = /obj/item/weapon/storage/box/freezer
+ path = /obj/item/storage/box/freezer
/datum/uplink_item/item/medical/monkeycubes
name = "Box, Monkey Cubes"
item_cost = 1
- path = /obj/item/weapon/storage/box/monkeycubes
+ path = /obj/item/storage/box/monkeycubes
/datum/uplink_item/item/medical/farwacubes
name = "Box, Farwa Cubes"
item_cost = 1
- path = /obj/item/weapon/storage/box/monkeycubes
+ path = /obj/item/storage/box/monkeycubes
/datum/uplink_item/item/medical/neaeracubes
name = "Box, Neaera Cubes"
item_cost = 1
- path = /obj/item/weapon/storage/box/monkeycubes/neaeracubes
+ path = /obj/item/storage/box/monkeycubes/neaeracubes
/datum/uplink_item/item/medical/stokcubes
name = "Box, Stok Cubes"
item_cost = 1
- path = /obj/item/weapon/storage/box/monkeycubes/stokcubes
+ path = /obj/item/storage/box/monkeycubes/stokcubes
/datum/uplink_item/item/medical/surgery
name = "Surgery kit"
item_cost = 5
- path = /obj/item/weapon/storage/firstaid/surgery
+ path = /obj/item/storage/firstaid/surgery
/datum/uplink_item/item/medical/toxins
name = "Anti-toxins medical kit"
item_cost = 5
- path = /obj/item/weapon/storage/firstaid/toxin
+ path = /obj/item/storage/firstaid/toxin
/datum/uplink_item/item/medical/o2
name = "oxygen deprivation medical kit"
item_cost = 5
- path = /obj/item/weapon/storage/firstaid/o2
+ path = /obj/item/storage/firstaid/o2
/datum/uplink_item/item/medical/fire
name = "fire medical kit"
item_cost = 5
- path = /obj/item/weapon/storage/firstaid/fire
+ path = /obj/item/storage/firstaid/fire
/datum/uplink_item/item/medical/adv
name = "advanced medical kit"
item_cost = 10
- path = /obj/item/weapon/storage/firstaid/adv
+ path = /obj/item/storage/firstaid/adv
/datum/uplink_item/item/medical/combat
name = "Combat medical kit"
item_cost = 20
- path = /obj/item/weapon/storage/firstaid/combat
+ path = /obj/item/storage/firstaid/combat
diff --git a/code/datums/uplink/medical_vr.dm b/code/datums/uplink/medical_vr.dm
index 5b4a0f31ccc..04524565963 100644
--- a/code/datums/uplink/medical_vr.dm
+++ b/code/datums/uplink/medical_vr.dm
@@ -9,82 +9,82 @@
/datum/uplink_item/item/medical/mre
name = "Meal, Ready to eat (Random)"
item_cost = 5
- path = /obj/item/weapon/storage/mre/random
+ path = /obj/item/storage/mre/random
/datum/uplink_item/item/medical/protein
name = "Meal, Ready to eat (Protein)"
item_cost = 5
- path = /obj/item/weapon/storage/mre/menu10
+ path = /obj/item/storage/mre/menu10
/datum/uplink_item/item/medical/emergency
name = "Meal, Ready to eat (Emergency)"
item_cost = 5
- path = /obj/item/weapon/storage/mre/menu11
+ path = /obj/item/storage/mre/menu11
/datum/uplink_item/item/medical/medical
name = "Meal, Ready to eat (medical)"
item_cost = 5
- path = /obj/item/weapon/storage/mre/menu13
+ path = /obj/item/storage/mre/menu13
/datum/uplink_item/item/medical/glucose
name = "Glucose injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose
+ path = /obj/item/reagent_containers/hypospray/autoinjector/biginjector/glucose
/datum/uplink_item/item/medical/purity
name = "Purity injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity
+ path = /obj/item/reagent_containers/hypospray/autoinjector/biginjector/purity
/datum/uplink_item/item/medical/pain
name = "Pain injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/pain
+ path = /obj/item/reagent_containers/hypospray/autoinjector/biginjector/pain
/datum/uplink_item/item/medical/brute
name = "Brute injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute
+ path = /obj/item/reagent_containers/hypospray/autoinjector/biginjector/brute
/datum/uplink_item/item/medical/burn
name = "Burn injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/burn
+ path = /obj/item/reagent_containers/hypospray/autoinjector/biginjector/burn
/datum/uplink_item/item/medical/toxin
name = "Toxin injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/toxin
+ path = /obj/item/reagent_containers/hypospray/autoinjector/biginjector/toxin
/datum/uplink_item/item/medical/oxy
name = "Oxy injector"
item_cost = 5
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/oxy
+ path = /obj/item/reagent_containers/hypospray/autoinjector/biginjector/oxy
/datum/uplink_item/item/medical/fire
name = "Fire medical kit"
item_cost = 10
- path = /obj/item/weapon/storage/firstaid/fire
+ path = /obj/item/storage/firstaid/fire
/datum/uplink_item/item/medical/toxin
name = "Toxin medical kit"
item_cost = 10
- path = /obj/item/weapon/storage/firstaid/toxin
+ path = /obj/item/storage/firstaid/toxin
/datum/uplink_item/item/medical/o2
name = "Oxygen medical kit"
item_cost = 10
- path = /obj/item/weapon/storage/firstaid/o2
+ path = /obj/item/storage/firstaid/o2
/datum/uplink_item/item/medical/adv
name = "Advanced medical kit"
item_cost = 10
- path = /obj/item/weapon/storage/firstaid/adv
+ path = /obj/item/storage/firstaid/adv
/datum/uplink_item/item/medical/organ
name = "Organ Repair injector"
item_cost = 10
- path = /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/organ
+ path = /obj/item/reagent_containers/hypospray/autoinjector/biginjector/organ
/datum/uplink_item/item/medical/stasis
name = "Stasis Bag"
@@ -99,67 +99,67 @@
/datum/uplink_item/item/medical/nanites
name = "Healing Nanite pill bottle"
item_cost = 30
- path = /obj/item/weapon/storage/pill_bottle/healing_nanites
+ path = /obj/item/storage/pill_bottle/healing_nanites
/datum/uplink_item/item/medical/vermicetol
name = "Vermicetol Bottle"
item_cost = 30
- path = /obj/item/weapon/reagent_containers/glass/bottle/vermicetol
+ path = /obj/item/reagent_containers/glass/bottle/vermicetol
antag_roles = list("ert")
blacklisted = 1
/datum/uplink_item/item/medical/dermaline
name = "Dermaline Bottle"
item_cost = 30
- path = /obj/item/weapon/reagent_containers/glass/bottle/dermaline
+ path = /obj/item/reagent_containers/glass/bottle/dermaline
antag_roles = list("ert")
blacklisted = 1
/datum/uplink_item/item/medical/carthatoline
name = "Carthatoline Bottle"
item_cost = 30
- path = /obj/item/weapon/reagent_containers/glass/bottle/carthatoline
+ path = /obj/item/reagent_containers/glass/bottle/carthatoline
antag_roles = list("ert")
blacklisted = 1
/datum/uplink_item/item/medical/dexalinp
name = "Dexalin Plus Bottle"
item_cost = 30
- path = /obj/item/weapon/reagent_containers/glass/bottle/dexalinp
+ path = /obj/item/reagent_containers/glass/bottle/dexalinp
antag_roles = list("ert")
blacklisted = 1
/datum/uplink_item/item/medical/tramadol
name = "Tramadol Bottle"
item_cost = 30
- path = /obj/item/weapon/reagent_containers/glass/bottle/tramadol
+ path = /obj/item/reagent_containers/glass/bottle/tramadol
antag_roles = list("ert")
blacklisted = 1
/datum/uplink_item/item/medical/arithrazine
name = "Arithrazine Bottle"
item_cost = 50
- path = /obj/item/weapon/reagent_containers/glass/bottle/arithrazine
+ path = /obj/item/reagent_containers/glass/bottle/arithrazine
antag_roles = list("ert")
blacklisted = 1
/datum/uplink_item/item/medical/corophizine
name = "Corophizine Bottle"
item_cost = 50
- path = /obj/item/weapon/reagent_containers/glass/bottle/corophizine
+ path = /obj/item/reagent_containers/glass/bottle/corophizine
antag_roles = list("ert")
blacklisted = 1
/datum/uplink_item/item/medical/rezadone
name = "Rezadone Bottle"
item_cost = 50
- path = /obj/item/weapon/reagent_containers/glass/bottle/rezadone
+ path = /obj/item/reagent_containers/glass/bottle/rezadone
antag_roles = list("ert")
blacklisted = 1
/datum/uplink_item/item/medical/defib
name = "Combat Defibrilator"
item_cost = 90
- path = /obj/item/device/defib_kit/compact/combat
+ path = /obj/item/defib_kit/compact/combat
antag_roles = list("mercenary", "ert")
blacklisted = 1
diff --git a/code/datums/uplink/stealth_items.dm b/code/datums/uplink/stealth_items.dm
index 973e851b029..14253352673 100644
--- a/code/datums/uplink/stealth_items.dm
+++ b/code/datums/uplink/stealth_items.dm
@@ -7,7 +7,7 @@
/datum/uplink_item/item/stealth_items/id
name = "Agent ID card"
item_cost = 10
- path = /obj/item/weapon/card/id/syndicate
+ path = /obj/item/card/id/syndicate
/datum/uplink_item/item/stealth_items/syndigaloshes
name = "No-Slip Shoes"
@@ -17,17 +17,17 @@
/datum/uplink_item/item/stealth_items/spy
name = "Bug Kit"
item_cost = 10
- path = /obj/item/weapon/storage/box/syndie_kit/spy
+ path = /obj/item/storage/box/syndie_kit/spy
/datum/uplink_item/item/stealth_items/chameleon_kit
name = "Chameleon Kit"
item_cost = 15
- path = /obj/item/weapon/storage/box/syndie_kit/chameleon
+ path = /obj/item/storage/box/syndie_kit/chameleon
/datum/uplink_item/item/stealth_items/chameleon_projector
name = "Chameleon-Projector"
item_cost = 30
- path = /obj/item/device/chameleon
+ path = /obj/item/chameleon
/datum/uplink_item/item/stealth_items/voice
name = "Voice Changer"
@@ -37,7 +37,7 @@
/datum/uplink_item/item/stealth_items/makeover
name = "Makeover Kit"
item_cost = 5
- path = /obj/item/weapon/makeover
+ path = /obj/item/makeover
/datum/uplink_item/item/stealth_items/thievesgloves
name = "Thieve's Gloves"
@@ -49,4 +49,4 @@
name = "Stealth Watch"
desc = "A strange watch which can be used to create a fake corpse if you are injured when it is active, as it projects a cloaking field around your person."
item_cost = 50
- path = /obj/item/weapon/deadringer
+ path = /obj/item/deadringer
diff --git a/code/datums/uplink/stealthy_weapons.dm b/code/datums/uplink/stealthy_weapons.dm
index 570b8c33413..39cc3bf9ae2 100644
--- a/code/datums/uplink/stealthy_weapons.dm
+++ b/code/datums/uplink/stealthy_weapons.dm
@@ -7,77 +7,71 @@
/datum/uplink_item/item/stealthy_weapons/soap
name = "Subversive Soap"
item_cost = 5
- path = /obj/item/weapon/soap/syndie
+ path = /obj/item/soap/syndie
/datum/uplink_item/item/stealthy_weapons/concealed_cane
name = "Concealed Cane Sword"
item_cost = 40
- path = /obj/item/weapon/cane/concealed
+ path = /obj/item/cane/concealed
/datum/uplink_item/item/stealthy_weapons/detomatix
name = "Detomatix PDA Cartridge"
item_cost = 30
- path = /obj/item/weapon/cartridge/syndicate
+ path = /obj/item/cartridge/syndicate
/datum/uplink_item/item/stealthy_weapons/parapen
name = "Paralysis Pen"
item_cost = 40
- path = /obj/item/weapon/pen/reagent/paralysis
+ path = /obj/item/pen/reagent/paralysis
/datum/uplink_item/item/stealthy_weapons/cigarette_kit
name = "Cigarette Kit"
item_cost = 10
- path = /obj/item/weapon/storage/box/syndie_kit/cigarette
+ path = /obj/item/storage/box/syndie_kit/cigarette
/datum/uplink_item/item/stealthy_weapons/random_toxin
name = "Random Toxin - Beaker"
item_cost = 10
- path = /obj/item/weapon/storage/box/syndie_kit/toxin
+ path = /obj/item/storage/box/syndie_kit/toxin
/datum/uplink_item/item/stealthy_weapons/penblade
name = "Energy Penblade, Black"
desc = "A concealed energy dagger with the functional casing of a pen. Makes an impressive throwing weapon."
item_cost = 20
- path = /obj/item/weapon/pen/blade
+ path = /obj/item/pen/blade
/datum/uplink_item/item/stealthy_weapons/penblade_red
name = "Energy Penblade, Red"
desc = "A concealed energy dagger with the functional casing of a pen. Makes an impressive throwing weapon."
item_cost = 20
- path = /obj/item/weapon/pen/blade/red
+ path = /obj/item/pen/blade/red
/datum/uplink_item/item/stealthy_weapons/penblade_blue
name = "Energy Penblade, Blue"
desc = "A concealed energy dagger with the functional casing of a pen. Makes an impressive throwing weapon."
item_cost = 20
- path = /obj/item/weapon/pen/blade/blue
+ path = /obj/item/pen/blade/blue
/datum/uplink_item/item/stealthy_weapons/penblade_fancy
name = "Energy Penblade, Fountain"
desc = "A concealed energy dagger with the functional casing of a pen. Makes an impressive throwing weapon."
item_cost = 20
- path = /obj/item/weapon/pen/blade/fountain
-
-/datum/uplink_item/item/stealthy_weapons/angrybuzzer
- name = "Morphium Shock Ring"
- desc = "An enigmatic ring used to create powerful electric shocks when punching. Can be used as a brute-force method of defibrillation."
- item_cost = 40
- path = /obj/item/clothing/gloves/ring/buzzer
+ path = /obj/item/pen/blade/fountain
/datum/uplink_item/item/stealthy_weapons/huntingtrap
name = "Camonetted Beartraps"
desc = "A box of unique beartraps which will partially cloak when deployed, allowing for more effective hunting."
item_cost = 30
- path = /obj/item/weapon/storage/box/syndie_kit/deadliest_game
+ path = /obj/item/storage/box/syndie_kit/deadliest_game
/datum/uplink_item/item/stealthy_weapons/virus
name = "Virus Cultures"
desc = "A box of three unique virus cultures. As dangerous to you as anyone else if handled improperly."
item_cost = 40
- path = /obj/item/weapon/storage/box/syndie_kit/viral
+ path = /obj/item/storage/box/syndie_kit/viral
/datum/uplink_item/item/stealthy_weapons/syringe_case
name = "Quickdraw Syringe Case"
desc = "A small box capable of holding six syringes for rapid deployment. Fits in your pocket."
item_cost = 20
- path = /obj/item/weapon/storage/quickdraw/syringe_case
+ path = /obj/item/storage/quickdraw/syringe_case
diff --git a/code/datums/uplink/telecrystals.dm b/code/datums/uplink/telecrystals.dm
index 66a099581ee..406f31e1b24 100644
--- a/code/datums/uplink/telecrystals.dm
+++ b/code/datums/uplink/telecrystals.dm
@@ -5,7 +5,7 @@
category = /datum/uplink_category/telecrystals
blacklisted = 1
-/datum/uplink_item/item/telecrystal/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/M)
+/datum/uplink_item/item/telecrystal/get_goods(var/obj/item/uplink/U, var/loc, var/mob/M)
return new /obj/item/stack/telecrystal(loc, cost(U, M.mind.tcrystals))
/datum/uplink_item/item/telecrystal/one
@@ -35,5 +35,5 @@
/datum/uplink_item/item/telecrystal/all
name = "Telecrystals - Empty Uplink"
-/datum/uplink_item/item/telecrystal/all/cost(obj/item/device/uplink/U, mob/M)
+/datum/uplink_item/item/telecrystal/all/cost(obj/item/uplink/U, mob/M)
return max(1, M.mind.tcrystals)
\ No newline at end of file
diff --git a/code/datums/uplink/tools.dm b/code/datums/uplink/tools.dm
index 9c1a46d632f..fe909fafd28 100644
--- a/code/datums/uplink/tools.dm
+++ b/code/datums/uplink/tools.dm
@@ -7,72 +7,72 @@
/datum/uplink_item/item/tools/binoculars
name = "Binoculars"
item_cost = 3
- path = /obj/item/device/binoculars
+ path = /obj/item/binoculars
/datum/uplink_item/item/tools/toolbox // Leaving the basic as an option since powertools are loud.
name = "Fully Loaded Toolbox"
item_cost = 3
- path = /obj/item/weapon/storage/toolbox/syndicate
+ path = /obj/item/storage/toolbox/syndicate
/datum/uplink_item/item/tools/powertoolbox
name = "Fully Loaded Powertool Box"
item_cost = 5
- path = /obj/item/weapon/storage/toolbox/syndicate/powertools
+ path = /obj/item/storage/toolbox/syndicate/powertools
/datum/uplink_item/item/tools/clerical
name = "Morphic Clerical Kit"
item_cost = 5
- path = /obj/item/weapon/storage/box/syndie_kit/clerical
+ path = /obj/item/storage/box/syndie_kit/clerical
/datum/uplink_item/item/tools/encryptionkey_radio
name = "Encrypted Radio Channel Key"
item_cost = 10
- path = /obj/item/device/encryptionkey/syndicate
+ path = /obj/item/encryptionkey/syndicate
/datum/uplink_item/item/tools/money
name = "Operations Funding"
item_cost = 10
- path = /obj/item/weapon/storage/secure/briefcase/money
+ path = /obj/item/storage/secure/briefcase/money
desc = "A briefcase with 10,000 untraceable thalers for funding your sneaky activities."
/datum/uplink_item/item/tools/plastique
name = "C-4 (Destroys walls)"
item_cost = 10
- path = /obj/item/weapon/plastique
+ path = /obj/item/plastique
/datum/uplink_item/item/tools/duffle
name = "Black Duffle Bag"
item_cost = 5
- path = /obj/item/weapon/storage/backpack/dufflebag/syndie
+ path = /obj/item/storage/backpack/dufflebag/syndie
/datum/uplink_item/item/tools/duffle/med
name = "Black Medical Duffle Bag"
- path = /obj/item/weapon/storage/backpack/dufflebag/syndie/med
+ path = /obj/item/storage/backpack/dufflebag/syndie/med
/datum/uplink_item/item/tools/duffle/ammo
name = "Black Ammunition Duffle Bag"
- path = /obj/item/weapon/storage/backpack/dufflebag/syndie/ammo
+ path = /obj/item/storage/backpack/dufflebag/syndie/ammo
/datum/uplink_item/item/tools/shield_diffuser
name = "Handheld Shield Diffuser"
desc = "A small device used to disrupt energy barriers, and allow passage through them."
item_cost = 16
- path = /obj/item/weapon/shield_diffuser
+ path = /obj/item/shield_diffuser
/datum/uplink_item/item/tools/space_suit
name = "Space Suit"
item_cost = 10
- path = /obj/item/weapon/storage/box/syndie_kit/space
+ path = /obj/item/storage/box/syndie_kit/space
/datum/uplink_item/item/tools/encryptionkey_binary
name = "Binary Translator Key"
item_cost = 15
- path = /obj/item/device/encryptionkey/binary
+ path = /obj/item/encryptionkey/binary
/datum/uplink_item/item/tools/hacking_tool
name = "Door Hacking Tool"
item_cost = 15
- path = /obj/item/device/multitool/hacktool
+ path = /obj/item/multitool/hacktool
desc = "Appears and functions as a standard multitool until the mode is toggled by applying a screwdriver appropriately. \
When in hacking mode this device will grant full access to any standard airlock within 20 to 40 seconds. \
This device will also be able to immediately access the last 6 to 8 hacked airlocks."
@@ -80,7 +80,7 @@
/datum/uplink_item/item/tools/ai_detector
name = "Anti-Surveillance Tool"
item_cost = 15
- path = /obj/item/device/multitool/ai_detector
+ path = /obj/item/multitool/ai_detector
desc = "This functions like a normal multitool, but includes an integrated camera network sensor that will warn the holder if they are being \
watched, by changing color and beeping. It is able to detect both AI visual surveillance and security camera utilization from terminals, and \
will give different warnings by beeping and changing colors based on what it detects. Only the holder can hear the warnings."
@@ -88,20 +88,20 @@
/datum/uplink_item/item/tools/radio_jammer
name = "Subspace Jammer"
item_cost = 20
- path = /obj/item/device/radio_jammer
+ path = /obj/item/radio_jammer
desc = "A device which is capable of disrupting subspace communications, preventing the use of headsets, PDAs, and communicators within \
a radius of seven meters. It runs off weapon cells, which can be replaced as needed. One cell will last for approximately ten minutes."
/datum/uplink_item/item/tools/wall_elecrtifier
name = "Wall Electrifier"
item_cost = 5
- path = /obj/item/weapon/cell/spike
+ path = /obj/item/cell/spike
desc = "A modified powercell which will electrify walls and reinforced floors in a 3x3 tile range around it. Always active."
/datum/uplink_item/item/tools/emag
name = "Cryptographic Sequencer"
item_cost = 20
- path = /obj/item/weapon/card/emag
+ path = /obj/item/card/emag
/datum/uplink_item/item/tools/graviton
name = "Graviton Goggles"
@@ -117,34 +117,34 @@
/datum/uplink_item/item/tools/packagebomb
name = "Package Bomb (Small)"
item_cost = 30
- path = /obj/item/weapon/storage/box/syndie_kit/demolitions
+ path = /obj/item/storage/box/syndie_kit/demolitions
/datum/uplink_item/item/tools/powersink
name = "Powersink (DANGER!)"
item_cost = 40
- path = /obj/item/device/powersink
+ path = /obj/item/powersink
/datum/uplink_item/item/tools/packagebomb/large
name = "Package Bomb (Large)"
item_cost = 60
- path = /obj/item/weapon/storage/box/syndie_kit/demolitions_heavy
+ path = /obj/item/storage/box/syndie_kit/demolitions_heavy
/datum/uplink_item/item/tools/integratedcircuitprinter
name = "Integrated Circuit Printer (Upgraded)"
item_cost = 10
- path = /obj/item/device/integrated_circuit_printer/upgraded
+ path = /obj/item/integrated_circuit_printer/upgraded
/*
/datum/uplink_item/item/tools/packagebomb/huge
name = "Package Bomb (Huge)
item_cost = 100
- path = /obj/item/weapon/storage/box/syndie_kit/demolitions_super_heavy
+ path = /obj/item/storage/box/syndie_kit/demolitions_super_heavy
*/
/datum/uplink_item/item/tools/ai_module
name = "Hacked AI Upload Module"
item_cost = 60
- path = /obj/item/weapon/aiModule/syndicate
+ path = /obj/item/aiModule/syndicate
/datum/uplink_item/item/tools/supply_beacon
name = "Hacked Supply Beacon (DANGER!)"
@@ -154,5 +154,5 @@
/datum/uplink_item/item/tools/teleporter
name = "Teleporter Circuit Board"
item_cost = DEFAULT_TELECRYSTAL_AMOUNT * 1.5
- path = /obj/item/weapon/circuitboard/teleporter
+ path = /obj/item/circuitboard/teleporter
blacklisted = 1
diff --git a/code/datums/uplink/tools_vr.dm b/code/datums/uplink/tools_vr.dm
index 710e47f55c4..0a6fd81e98a 100644
--- a/code/datums/uplink/tools_vr.dm
+++ b/code/datums/uplink/tools_vr.dm
@@ -4,28 +4,28 @@
/datum/uplink_item/item/tools/oxygen
name = "Emergency Oxygen Tank"
item_cost = 2
- path = /obj/item/weapon/tank/emergency/oxygen/double
+ path = /obj/item/tank/emergency/oxygen/double
/datum/uplink_item/item/tools/phoron
name = "Emergency Phoron Tank"
item_cost = 2
- path = /obj/item/weapon/tank/emergency/phoron/double
+ path = /obj/item/tank/emergency/phoron/double
/datum/uplink_item/item/tools/suitcooler
name = "Emergency Suit Cooler"
item_cost = 2
- path = /obj/item/device/suit_cooling_unit/emergency
+ path = /obj/item/suit_cooling_unit/emergency
/datum/uplink_item/item/tools/beacon_op
name = "Holomap Beacon-M"
item_cost = 2
- path = /obj/item/device/holomap_beacon/operative
+ path = /obj/item/holomap_beacon/operative
antag_roles = list("mercenary")
/datum/uplink_item/item/tools/beacon_ert
name = "Holomap Beacon-E"
item_cost = 2
- path = /obj/item/device/holomap_beacon/ert
+ path = /obj/item/holomap_beacon/ert
antag_roles = list("ert")
/datum/uplink_item/item/tools/basiclaptop
@@ -36,12 +36,12 @@
/datum/uplink_item/item/tools/survivalcapsule
name = "Survival Capsule"
item_cost = 5
- path = /obj/item/device/survivalcapsule
+ path = /obj/item/survivalcapsule
/datum/uplink_item/item/tools/popcabin
name = "Cabin Capsule"
item_cost = 5
- path = /obj/item/device/survivalcapsule/popcabin
+ path = /obj/item/survivalcapsule/popcabin
/datum/uplink_item/item/tools/nanopaste
name = "Nanopaste (Advanced)"
@@ -56,7 +56,7 @@
/datum/uplink_item/item/tools/inflatable
name = "Inflatables"
item_cost = 10
- path = /obj/item/weapon/storage/briefcase/inflatable
+ path = /obj/item/storage/briefcase/inflatable
/datum/uplink_item/item/tools/elitetablet
name = "Tablet (Advanced)"
@@ -76,17 +76,17 @@
/datum/uplink_item/item/tools/smallpouch
name = "Small Pouch"
item_cost = 5
- path = /obj/item/weapon/storage/pouch/small
+ path = /obj/item/storage/pouch/small
/datum/uplink_item/item/tools/normalpouch
name = "Standard Pouch"
item_cost = 10
- path = /obj/item/weapon/storage/pouch
+ path = /obj/item/storage/pouch
/datum/uplink_item/item/tools/largepouch
name = "Large Pouch"
item_cost = 15
- path = /obj/item/weapon/storage/pouch/large
+ path = /obj/item/storage/pouch/large
/datum/uplink_item/item/tools/elitelaptop
name = "Laptop (Advanced)"
@@ -96,39 +96,39 @@
/datum/uplink_item/item/tools/inducer
name = "Inducer"
item_cost = 20
- path = /obj/item/weapon/inducer/syndicate
+ path = /obj/item/inducer/syndicate
/datum/uplink_item/item/tools/mappingunit_op
name = "Mapping Unit-M"
item_cost = 20
- path = /obj/item/device/mapping_unit/operative
+ path = /obj/item/mapping_unit/operative
antag_roles = list("mercenary")
/datum/uplink_item/item/tools/mappingunit_ert
name = "Mapping Unit-E"
item_cost = 20
- path = /obj/item/device/mapping_unit/ert
+ path = /obj/item/mapping_unit/ert
antag_roles = list("ert")
/datum/uplink_item/item/tools/luxurycapsule
name = "Survival Capsule (Luxury)"
item_cost = 40
- path = /obj/item/device/survivalcapsule/luxury
+ path = /obj/item/survivalcapsule/luxury
/datum/uplink_item/item/tools/translocator
name = "Translocator"
item_cost = 40
- path = /obj/item/device/perfect_tele
+ path = /obj/item/perfect_tele
/datum/uplink_item/item/tools/uav
name = "Recon Skimmer"
item_cost = 40
- path = /obj/item/device/uav
+ path = /obj/item/uav
/datum/uplink_item/item/tools/barcapsule
name = "Survival Capsule (Bar)"
item_cost = 80
- path = /obj/item/device/survivalcapsule/luxurybar
+ path = /obj/item/survivalcapsule/luxurybar
/datum/uplink_item/item/tools/capturecrystal
name = "Capture Crystal"
diff --git a/code/datums/uplink/uplink_items.dm b/code/datums/uplink/uplink_items.dm
index 7b4fbded2b5..cfb5ac89ab7 100644
--- a/code/datums/uplink/uplink_items.dm
+++ b/code/datums/uplink/uplink_items.dm
@@ -43,7 +43,7 @@ var/datum/uplink/uplink = new()
-/datum/uplink_item/proc/buy(var/obj/item/device/uplink/U, var/mob/user)
+/datum/uplink_item/proc/buy(var/obj/item/uplink/U, var/mob/user)
var/extra_args = extra_args(user)
if(!extra_args)
return
@@ -69,13 +69,13 @@ var/datum/uplink/uplink = new()
/datum/uplink_item/proc/extra_args(var/mob/user)
return TRUE
-/datum/uplink_item/proc/can_buy(var/obj/item/device/uplink/U, var/telecrystals)
+/datum/uplink_item/proc/can_buy(var/obj/item/uplink/U, var/telecrystals)
if(cost(U, telecrystals) > telecrystals)
return FALSE
return TRUE
-/datum/uplink_item/proc/cost(obj/item/device/uplink/U, mob/M)
+/datum/uplink_item/proc/cost(obj/item/uplink/U, mob/M)
. = item_cost
if(U)
. = U.get_item_cost(src, .)
@@ -84,7 +84,7 @@ var/datum/uplink/uplink = new()
return desc
// get_goods does not necessarily return physical objects, it is simply a way to acquire the uplink item without paying
-/datum/uplink_item/proc/get_goods(var/obj/item/device/uplink/U, var/loc, mob/user)
+/datum/uplink_item/proc/get_goods(var/obj/item/uplink/U, var/loc, mob/user)
return FALSE
/datum/uplink_item/proc/log_icon()
@@ -103,7 +103,7 @@ var/datum/uplink/uplink = new()
* Physical Uplink Entries *
* *
********************************/
-/datum/uplink_item/item/buy(var/obj/item/device/uplink/U, var/mob/user)
+/datum/uplink_item/item/buy(var/obj/item/uplink/U, var/mob/user)
var/obj/item/I = ..()
if(!I)
return
@@ -117,7 +117,7 @@ var/datum/uplink/uplink = new()
A.put_in_any_hand_if_possible(I)
return I
-/datum/uplink_item/item/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user)
+/datum/uplink_item/item/get_goods(var/obj/item/uplink/U, var/loc, var/mob/user)
var/obj/item/I = new path(loc)
return I
@@ -154,7 +154,7 @@ var/datum/uplink/uplink = new()
var/crate_path = /obj/structure/largecrate
var/list/paths = list() // List of paths to be spawned into the crate.
-/datum/uplink_item/crated/get_goods(var/obj/item/device/uplink/U, var/loc)
+/datum/uplink_item/crated/get_goods(var/obj/item/uplink/U, var/loc)
var/obj/L = new crate_path(get_turf(loc))
L.adjust_scale(rand(9, 12) / 10, rand(9, 12) / 10) // Some variation in the crate / locker size.
@@ -179,7 +179,7 @@ var/datum/uplink/uplink = new()
/****************
* Support procs *
****************/
-/proc/get_random_uplink_items(var/obj/item/device/uplink/U, var/remaining_TC, var/loc)
+/proc/get_random_uplink_items(var/obj/item/uplink/U, var/remaining_TC, var/loc)
var/list/bought_items = list()
while(remaining_TC)
var/datum/uplink_item/I = default_uplink_selection.get_random_item(remaining_TC, U, bought_items)
@@ -190,7 +190,7 @@ var/datum/uplink/uplink = new()
return bought_items
-/proc/get_surplus_items(var/obj/item/device/uplink/U, var/remaining_TC, var/loc)
+/proc/get_surplus_items(var/obj/item/uplink/U, var/remaining_TC, var/loc)
var/list/bought_items = list()
var/override = TRUE
while(remaining_TC)
diff --git a/code/datums/uplink/visible_weapons.dm b/code/datums/uplink/visible_weapons.dm
index 6c063ffb581..ef07eb8eac7 100644
--- a/code/datums/uplink/visible_weapons.dm
+++ b/code/datums/uplink/visible_weapons.dm
@@ -7,57 +7,57 @@
/datum/uplink_item/item/visible_weapons/tactknife
name = "Tactical Knife"
item_cost = 10
- path = /obj/item/weapon/material/knife/tacknife
+ path = /obj/item/material/knife/tacknife
/datum/uplink_item/item/visible_weapons/combatknife
name = "Combat Knife"
item_cost = 20
- path = /obj/item/weapon/material/knife/tacknife/combatknife
+ path = /obj/item/material/knife/tacknife/combatknife
/datum/uplink_item/item/visible_weapons/energy_sword
name = "Energy Sword, Colorable"
item_cost = 40
- path = /obj/item/weapon/melee/energy/sword
+ path = /obj/item/melee/energy/sword
/datum/uplink_item/item/visible_weapons/energy_sword_pirate
name = "Energy Cutlass, Colorable"
item_cost = 40
- path = /obj/item/weapon/melee/energy/sword/pirate
+ path = /obj/item/melee/energy/sword/pirate
/datum/uplink_item/item/visible_weapons/energy_spear
name = "Energy Spear, Colorable"
item_cost = 50
- path = /obj/item/weapon/melee/energy/spear
+ path = /obj/item/melee/energy/spear
/datum/uplink_item/item/visible_weapons/claymore
name = "Claymore"
item_cost = 40
- path = /obj/item/weapon/material/sword
+ path = /obj/item/material/sword
/datum/uplink_item/item/visible_weapons/chainsaw
name = "Chainsaw"
item_cost = 40
- path = /obj/item/weapon/chainsaw
+ path = /obj/item/chainsaw
/datum/uplink_item/item/visible_weapons/katana
name = "Katana"
item_cost = 40
- path = /obj/item/weapon/material/sword/katana
+ path = /obj/item/material/sword/katana
/datum/uplink_item/item/visible_weapons/dartgun
name = "Dart Gun"
item_cost = 30
- path = /obj/item/weapon/gun/projectile/dartgun
+ path = /obj/item/gun/projectile/dartgun
/datum/uplink_item/item/visible_weapons/crossbow
name = "Energy Crossbow"
item_cost = 40
- path = /obj/item/weapon/gun/energy/crossbow
+ path = /obj/item/gun/energy/crossbow
/datum/uplink_item/item/visible_weapons/silenced_45
name = "Silenced .45"
item_cost = 40
- path = /obj/item/weapon/gun/projectile/silenced
+ path = /obj/item/gun/projectile/silenced
/datum/uplink_item/item/visible_weapons/riggedlaser
name = "Exosuit Rigged Laser"
@@ -67,126 +67,126 @@
/datum/uplink_item/item/visible_weapons/revolver
name = "Revolver"
item_cost = 70
- path = /obj/item/weapon/gun/projectile/revolver
+ path = /obj/item/gun/projectile/revolver
/datum/uplink_item/item/visible_weapons/mateba
name = "Mateba"
item_cost = 70
- path = /obj/item/weapon/gun/projectile/revolver/mateba
+ path = /obj/item/gun/projectile/revolver/mateba
/datum/uplink_item/item/visible_weapons/judge
name = "Judge"
item_cost = 70
- path = /obj/item/weapon/gun/projectile/revolver/judge
+ path = /obj/item/gun/projectile/revolver/judge
/datum/uplink_item/item/visible_weapons/pistol_standard_capacity
name = "9mm Pistol"
item_cost = 40
- path = /obj/item/weapon/gun/projectile/p92x
+ path = /obj/item/gun/projectile/p92x
/datum/uplink_item/item/visible_weapons/pistol_large_capacity
name = "9mm Pistol (with large capacity magazine)"
item_cost = 70
- path = /obj/item/weapon/gun/projectile/p92x/large
+ path = /obj/item/gun/projectile/p92x/large
/datum/uplink_item/item/visible_weapons/lemat
name = "Mako Revolver"
item_cost = 60
- path = /obj/item/weapon/gun/projectile/revolver/lemat
+ path = /obj/item/gun/projectile/revolver/lemat
/datum/uplink_item/item/visible_weapons/Derringer
name = ".357 Derringer Pistol"
item_cost = 40
- path = /obj/item/weapon/gun/projectile/derringer
+ path = /obj/item/gun/projectile/derringer
/datum/uplink_item/item/visible_weapons/heavysnipermerc
name = "Anti-Materiel Rifle (14.5mm)"
item_cost = DEFAULT_TELECRYSTAL_AMOUNT
- path = /obj/item/weapon/gun/projectile/heavysniper
+ path = /obj/item/gun/projectile/heavysniper
antag_roles = list("mercenary", "ert") //VOREStation Edit
/datum/uplink_item/item/visible_weapons/heavysnipertraitor
name = "Anti-Materiel Rifle (14.5mm)"
desc = "A convenient collapsible rifle for covert assassination. Comes with 4 shots and its own secure carrying case."
item_cost = DEFAULT_TELECRYSTAL_AMOUNT
- path = /obj/item/weapon/storage/secure/briefcase/rifle
+ path = /obj/item/storage/secure/briefcase/rifle
antag_roles = list("traitor", "autotraitor", "infiltrator")
/datum/uplink_item/item/visible_weapons/fuelrodcannon
name = "Fuel-Rod Cannon"
desc = "An incredibly bulky weapon whose devastating firepower is only matched by its severe need for expensive, and rare, ammunition. This device will likely require extra preparation to use, you are warned."
item_cost = DEFAULT_TELECRYSTAL_AMOUNT
- path = /obj/item/weapon/storage/secure/briefcase/fuelrod
+ path = /obj/item/storage/secure/briefcase/fuelrod
/datum/uplink_item/item/visible_weapons/tommygun
name = "Tommy Gun (.45)" // We're keeping this because it's CLASSY. -Spades
item_cost = 60
- path = /obj/item/weapon/gun/projectile/automatic/tommygun
+ path = /obj/item/gun/projectile/automatic/tommygun
//These are for traitors (or other antags, perhaps) to have the option of purchasing some merc gear.
/datum/uplink_item/item/visible_weapons/submachinegun
name = "Submachine Gun (10mm)"
item_cost = 60
- path = /obj/item/weapon/gun/projectile/automatic/c20r
+ path = /obj/item/gun/projectile/automatic/c20r
/datum/uplink_item/item/visible_weapons/assaultrifle
name = "Assault Rifle (5.45mm)"
item_cost = 75
- path = /obj/item/weapon/gun/projectile/automatic/sts35
+ path = /obj/item/gun/projectile/automatic/sts35
/datum/uplink_item/item/visible_weapons/combatshotgun
name = "Combat Shotgun"
item_cost = 75
- path = /obj/item/weapon/gun/projectile/shotgun/pump/combat
+ path = /obj/item/gun/projectile/shotgun/pump/combat
/datum/uplink_item/item/visible_weapons/semishotgun
name = "Semi-Automatic Shotgun"
item_cost = 100
- path = /obj/item/weapon/gun/projectile/shotgun/semi
+ path = /obj/item/gun/projectile/shotgun/semi
/datum/uplink_item/item/visible_weapons/leveraction
name = "Lever Action Rifle"
item_cost = 50
- path = /obj/item/weapon/gun/projectile/shotgun/pump/rifle/lever
+ path = /obj/item/gun/projectile/shotgun/pump/rifle/lever
/datum/uplink_item/item/visible_weapons/egun
name = "Compact Energy Gun"
item_cost = 30
- path = /obj/item/weapon/gun/energy/gun/compact
+ path = /obj/item/gun/energy/gun/compact
/datum/uplink_item/item/visible_weapons/lasercannon
name = "Laser Cannon"
item_cost = 60
- path = /obj/item/weapon/gun/energy/lasercannon
+ path = /obj/item/gun/energy/lasercannon
/datum/uplink_item/item/visible_weapons/lasercarbine
name = "Laser Carbine"
item_cost = 75
- path = /obj/item/weapon/gun/energy/laser
+ path = /obj/item/gun/energy/laser
/datum/uplink_item/item/visible_weapons/ionrifle
name = "Ion Rifle"
item_cost = 40
- path = /obj/item/weapon/gun/energy/ionrifle
+ path = /obj/item/gun/energy/ionrifle
/datum/uplink_item/item/visible_weapons/ionpistol
name = "Ion Pistol"
item_cost = 25
- path = /obj/item/weapon/gun/energy/ionrifle/pistol
+ path = /obj/item/gun/energy/ionrifle/pistol
/datum/uplink_item/item/visible_weapons/xray
name = "Xray Gun"
item_cost = 60
- path = /obj/item/weapon/gun/energy/xray
+ path = /obj/item/gun/energy/xray
/datum/uplink_item/item/visible_weapons/flamethrower
name = "Heavy Flamethrower"
desc = "A large flamethrower that runs on pressurized, gaseous phoron and electric charge."
item_cost = 60
- path = /obj/item/weapon/storage/secure/briefcase/flamer
+ path = /obj/item/storage/secure/briefcase/flamer
/datum/uplink_item/item/visible_weapons/concussion_grenades
name = "Concussion Grenades (8)"
desc = "A box of eight concussion grenades."
item_cost = 30
- path = /obj/item/weapon/storage/box/syndie_kit/concussion_grenade
+ path = /obj/item/storage/box/syndie_kit/concussion_grenade
diff --git a/code/datums/uplink/visible_weapons_vr.dm b/code/datums/uplink/visible_weapons_vr.dm
index 764e30b12f9..77b6698212e 100644
--- a/code/datums/uplink/visible_weapons_vr.dm
+++ b/code/datums/uplink/visible_weapons_vr.dm
@@ -4,19 +4,19 @@
/datum/uplink_item/item/visible_weapons/holdout
name = "Frontier Holdout"
item_cost = 30
- path = /obj/item/weapon/gun/energy/locked/frontier/holdout/unlocked
+ path = /obj/item/gun/energy/locked/frontier/holdout/unlocked
/datum/uplink_item/item/visible_weapons/frontier
name = "Frontier Phaser"
item_cost = 75
- path = /obj/item/weapon/gun/energy/locked/frontier/unlocked
+ path = /obj/item/gun/energy/locked/frontier/unlocked
/datum/uplink_item/item/visible_weapons/carbine
name = "Frontier Carbine"
item_cost = 85
- path = /obj/item/weapon/gun/energy/locked/frontier/carbine/unlocked
+ path = /obj/item/gun/energy/locked/frontier/carbine/unlocked
/datum/uplink_item/item/visible_weapons/rifle
name = "Frontier Marksman Rifle"
item_cost = 100
- path = /obj/item/weapon/gun/energy/locked/frontier/rifle/unlocked
+ path = /obj/item/gun/energy/locked/frontier/rifle/unlocked
diff --git a/code/datums/verb_callbacks.dm b/code/datums/verb_callbacks.dm
new file mode 100644
index 00000000000..77f817017d2
--- /dev/null
+++ b/code/datums/verb_callbacks.dm
@@ -0,0 +1,27 @@
+///like normal callbacks but they also record their creation time for measurement purposes
+///they also require the same usr/user that made the callback to both still exist and to still have a client in order to execute
+/datum/callback/verb_callback
+ ///the tick this callback datum was created in. used for testing latency
+ var/creation_time = 0
+
+/datum/callback/verb_callback/New(thingtocall, proctocall, ...)
+ creation_time = DS2TICKS(world.time)
+ . = ..()
+
+#ifndef UNIT_TEST
+/datum/callback/verb_callback/Invoke(...)
+ var/mob/our_user = user?.resolve()
+ if(QDELETED(our_user) || isnull(our_user.client))
+ return
+ var/mob/temp = usr
+ . = ..()
+ usr = temp
+
+/datum/callback/verb_callback/InvokeAsync(...)
+ var/mob/our_user = user?.resolve()
+ if(QDELETED(our_user) || isnull(our_user.client))
+ return
+ var/mob/temp = usr
+ . = ..()
+ usr = temp
+#endif
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index 229412e93f0..1c22cf8a7c4 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -8,6 +8,7 @@
holder_type = /obj/machinery/door/airlock
wire_count = 12
proper_name = "Airlock"
+ tgui_template = "WiresAirlock"
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
@@ -41,6 +42,39 @@
. += "The 'Check Timing Mechanism' light is [(A.normalspeed == 0 && haspower) ? "on" : "off"]."
. += "The IDScan light is [(A.aiDisabledIdScanner == 0 && haspower) ? "on" : "off."]"
+/datum/wires/airlock/tgui_data(mob/user)
+ var/list/data = ..()
+
+ var/obj/machinery/door/airlock/A = holder
+ data["id_tag"] = A.id_tag
+ data["frequency"] = A.radio_connection ? A.frequency : null
+ data["min_freq"] = RADIO_LOW_FREQ
+ data["max_freq"] = RADIO_HIGH_FREQ
+
+ return data
+
+/datum/wires/airlock/tgui_act(action, list/params)
+ . = ..()
+ if(.)
+ return
+
+ var/obj/machinery/door/airlock/A = holder
+
+ switch(action)
+ if("set_id_tag")
+ var/new_id = tgui_input_text(usr, "Enter a new ID tag for [A]", "[A] ID Tag", A.id_tag, 30, FALSE, TRUE)
+ if(new_id)
+ A.id_tag = new_id
+ return TRUE
+
+ if("set_frequency")
+ A.set_frequency(sanitize_frequency(text2num(params["freq"]), RADIO_LOW_FREQ, RADIO_HIGH_FREQ))
+ return TRUE
+
+ if("clear_frequency")
+ A.set_frequency(null)
+ return TRUE
+
/datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder
switch(wire)
diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm
index 52b0150b661..8267f05fcf6 100644
--- a/code/datums/wires/explosive.dm
+++ b/code/datums/wires/explosive.dm
@@ -21,14 +21,14 @@
explode()
/datum/wires/explosive/c4
- holder_type = /obj/item/weapon/plastique
+ holder_type = /obj/item/plastique
/datum/wires/explosive/c4/interactable(mob/user)
- var/obj/item/weapon/plastique/P = holder
+ var/obj/item/plastique/P = holder
if(P.open_panel)
return TRUE
return FALSE
/datum/wires/explosive/c4/explode()
- var/obj/item/weapon/plastique/P = holder
+ var/obj/item/plastique/P = holder
P.explode(get_turf(P))
diff --git a/code/datums/wires/jukebox.dm b/code/datums/wires/jukebox.dm
index 5f46a3deb96..c9a0b5c891c 100644
--- a/code/datums/wires/jukebox.dm
+++ b/code/datums/wires/jukebox.dm
@@ -31,16 +31,16 @@
var/obj/machinery/media/jukebox/A = holder
switch(wire)
if(WIRE_MAIN_POWER1)
- holder.visible_message("[icon2html(A,viewers(holder))] The power light flickers.")
+ holder.visible_message(span_notice("[icon2html(A,viewers(holder))] The power light flickers."))
A.shock(usr, 90)
if(WIRE_JUKEBOX_HACK)
- holder.visible_message("[icon2html(A,viewers(holder))] The parental guidance light flickers.")
+ holder.visible_message(span_notice("[icon2html(A,viewers(holder))] The parental guidance light flickers."))
if(WIRE_REVERSE)
- holder.visible_message("[icon2html(A,viewers(holder))] The data light blinks ominously.")
+ holder.visible_message(span_notice("[icon2html(A,viewers(holder))] The data light blinks ominously."))
if(WIRE_SPEEDUP)
- holder.visible_message("[icon2html(A,viewers(holder))] The speakers squeaks.")
+ holder.visible_message(span_notice("[icon2html(A,viewers(holder))] The speakers squeaks."))
if(WIRE_SPEEDDOWN)
- holder.visible_message("[icon2html(A,viewers(holder))] The speakers rumble.")
+ holder.visible_message(span_notice("[icon2html(A,viewers(holder))] The speakers rumble."))
if(WIRE_START)
A.StartPlaying()
if(WIRE_STOP)
diff --git a/code/datums/wires/radio.dm b/code/datums/wires/radio.dm
index ddc51108392..2932ca3118a 100644
--- a/code/datums/wires/radio.dm
+++ b/code/datums/wires/radio.dm
@@ -1,5 +1,5 @@
/datum/wires/radio
- holder_type = /obj/item/device/radio
+ holder_type = /obj/item/radio
wire_count = 3
proper_name = "Radio"
@@ -8,13 +8,13 @@
return ..()
/datum/wires/radio/interactable(mob/user)
- var/obj/item/device/radio/R = holder
+ var/obj/item/radio/R = holder
if(R.b_stat)
return TRUE
return FALSE
/datum/wires/radio/on_pulse(wire)
- var/obj/item/device/radio/R = holder
+ var/obj/item/radio/R = holder
switch(wire)
if(WIRE_RADIO_SIGNAL)
R.listening = !R.listening && !is_cut(WIRE_RADIO_RECEIVER)
@@ -28,7 +28,7 @@
..()
/datum/wires/radio/on_cut(wire, mend)
- var/obj/item/device/radio/R = holder
+ var/obj/item/radio/R = holder
switch(wire)
if(WIRE_RADIO_SIGNAL)
R.listening = mend && !is_cut(WIRE_RADIO_RECEIVER)
diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm
index b366ac43a9c..b0b0e738cf9 100644
--- a/code/datums/wires/wires.dm
+++ b/code/datums/wires/wires.dm
@@ -9,6 +9,8 @@
/// The display name for the TGUI window. For example, given the var is "APC"...
/// When the TGUI window is opened, "wires" will be appended to it's title, and it would become "APC wires".
var/proper_name = "Unknown"
+ /// The template to use for TGUI.
+ var/tgui_template = "Wires"
/// The total number of wires that our holder atom has.
var/wire_count = NONE
/// A list of all wires. For a list of valid wires defines that can go here, see `code/__DEFINES/wires.dm`
@@ -92,7 +94,7 @@
/datum/wires/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
- ui = new(user, src, "Wires", "[proper_name] wires")
+ ui = new(user, src, tgui_template, "[proper_name] wires")
ui.open()
/datum/wires/tgui_state(mob/user)
@@ -153,24 +155,23 @@
data["status"] = status
return data
-/datum/wires/tgui_act(action, list/params)
+/datum/wires/tgui_act(action, list/params, datum/tgui/ui)
if(..())
return TRUE
- var/mob/user = usr
- if(!interactable(user))
+ if(!interactable(ui.user))
return
- var/obj/item/I = user.get_active_hand()
+ var/obj/item/I = ui.user.get_active_hand()
var/color = lowertext(params["wire"])
- holder.add_hiddenprint(user)
+ holder.add_hiddenprint(ui.user)
switch(action)
// Toggles the cut/mend status.
if("cut")
// if(!I.has_tool_quality(TOOL_WIRECUTTER) && !user.can_admin_interact())
if(!istype(I) || !I.has_tool_quality(TOOL_WIRECUTTER))
- to_chat(user, "You need wirecutters!")
+ to_chat(ui.user, span_warning("You need wirecutters!"))
return
playsound(holder, I.usesound, 20, 1)
@@ -181,7 +182,7 @@
if("pulse")
// if(!I.has_tool_quality(TOOL_MULTITOOL) && !user.can_admin_interact())
if(!istype(I) || !I.has_tool_quality(TOOL_MULTITOOL))
- to_chat(user, "You need a multitool!")
+ to_chat(ui.user, span_warning("You need a multitool!"))
return
playsound(holder, 'sound/weapons/empty.ogg', 20, 1)
@@ -189,7 +190,7 @@
// If they pulse the electrify wire, call interactable() and try to shock them.
if(get_wire(color) == WIRE_ELECTRIFY)
- interactable(user)
+ interactable(ui.user)
return TRUE
@@ -198,18 +199,18 @@
if(is_attached(color))
var/obj/item/O = detach_assembly(color)
if(O)
- user.put_in_hands(O)
+ ui.user.put_in_hands(O)
return TRUE
- if(!istype(I, /obj/item/device/assembly/signaler))
- to_chat(user, "You need a remote signaller!")
+ if(!istype(I, /obj/item/assembly/signaler))
+ to_chat(ui.user, span_warning("You need a remote signaller!"))
return
- if(user.unEquip(I))
+ if(ui.user.unEquip(I))
attach_assembly(color, I)
return TRUE
else
- to_chat(user, "[I] is stuck to your hand!")
+ to_chat(ui.user, span_warning("[I] is stuck to your hand!"))
/**
* Proc called to determine if the user can see wire define information, such as "Contraband", "Door Bolts", etc.
@@ -224,7 +225,7 @@
// if(user.can_admin_interact())
// return TRUE
var/obj/item/I = user.get_active_hand()
- if(istype(I, /obj/item/device/multitool/alien))
+ if(istype(I, /obj/item/multitool/alien))
return TRUE
return FALSE
@@ -400,7 +401,7 @@
* Arugments:
* * S - the attached signaler receiving the signal.
*/
-/datum/wires/proc/pulse_assembly(obj/item/device/assembly/signaler/S)
+/datum/wires/proc/pulse_assembly(obj/item/assembly/signaler/S)
for(var/color in assemblies)
if(S == assemblies[color])
pulse_color(color)
@@ -416,7 +417,7 @@
* * color - the wire color.
* * S - the signaler that a mob is trying to attach.
*/
-/datum/wires/proc/attach_assembly(color, obj/item/device/assembly/signaler/S)
+/datum/wires/proc/attach_assembly(color, obj/item/assembly/signaler/S)
if(S && istype(S) && !is_attached(color))
assemblies[color] = S
S.forceMove(holder)
@@ -432,7 +433,7 @@
* * color - the wire color.
*/
/datum/wires/proc/detach_assembly(color)
- var/obj/item/device/assembly/signaler/S = get_attached(color)
+ var/obj/item/assembly/signaler/S = get_attached(color)
if(S && istype(S))
assemblies -= color
S.connected = null
diff --git a/code/defines/obj.dm b/code/defines/obj.dm
index a193aeb680d..918f1b89bd0 100644
--- a/code/defines/obj.dm
+++ b/code/defines/obj.dm
@@ -4,7 +4,7 @@
anchored = TRUE
density = TRUE
-/obj/structure/signpost/attackby(obj/item/weapon/W as obj, mob/user as mob)
+/obj/structure/signpost/attackby(obj/item/W as obj, mob/user as mob)
return attack_hand(user)
/obj/structure/signpost/attack_hand(mob/user as mob)
@@ -137,7 +137,7 @@
/obj/item/mouse_drag_pointer = MOUSE_ACTIVE_POINTER
-/obj/item/weapon/beach_ball
+/obj/item/beach_ball
icon = 'icons/misc/beach.dmi'
icon_state = "beachball"
name = "beach ball"
@@ -151,11 +151,11 @@
drop_sound = 'sound/items/drop/rubber.ogg'
pickup_sound = 'sound/items/pickup/rubber.ogg'
-/obj/item/weapon/beach_ball/afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
+/obj/item/beach_ball/afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
user.drop_item()
src.throw_at(target, throw_range, throw_speed, user)
-/obj/item/weapon/beach_ball/dodgeball
+/obj/item/beach_ball/dodgeball
icon = 'icons/obj/balls_vr.dmi'
icon_state = "dodgeball"
item_state = "dodgeball"
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index 3b22956ab7c..74ca803b19a 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -1,4 +1,4 @@
-/obj/item/weapon/phone
+/obj/item/phone
name = "red phone"
desc = "Should anything ever go wrong..."
icon = 'icons/obj/items.dmi'
@@ -13,7 +13,7 @@
drop_sound = 'sound/items/drop/device.ogg'
pickup_sound = 'sound/items/pickup/device.ogg'
-/obj/item/weapon/rsp
+/obj/item/rsp
name = "\improper Rapid-Seed-Producer (RSP)"
desc = "A device used to rapidly deploy seeds."
icon = 'icons/obj/items.dmi'
@@ -27,7 +27,7 @@
drop_sound = 'sound/items/drop/device.ogg'
pickup_sound = 'sound/items/pickup/device.ogg'
-/obj/item/weapon/soap
+/obj/item/soap
name = "soap"
desc = "A cheap bar of soap. Smells of lye."
gender = PLURAL
@@ -41,103 +41,103 @@
throw_range = 20
var/randomize = TRUE
var/square_chance = 10
-
-/obj/item/weapon/soap/Initialize()
+
+/obj/item/soap/Initialize()
if(randomize && prob(square_chance))
icon_state = "[icon_state]-alt"
-/obj/item/weapon/soap/nanotrasen
+/obj/item/soap/nanotrasen
desc = "A NanoTrasen-brand bar of soap. Smells of phoron, a years-old marketing gimmick."
icon_state = "soapnt"
-/obj/item/weapon/soap/deluxe
+/obj/item/soap/deluxe
icon_state = "soapdeluxe"
-/obj/item/weapon/soap/deluxe/New()
+/obj/item/soap/deluxe/New()
desc = "A deluxe Waffle Co. brand bar of soap. Smells of [pick("lavender", "vanilla", "strawberry", "chocolate" ,"space")]."
..()
-/obj/item/weapon/soap/syndie
+/obj/item/soap/syndie
desc = "An untrustworthy bar of soap. Smells of fear."
icon_state = "soapsyndie"
-/obj/item/weapon/soap/space_soap
+/obj/item/soap/space_soap
desc = "Smells like hot metal and walnuts."
icon_state = "space_soap"
-/obj/item/weapon/soap/water_soap
+/obj/item/soap/water_soap
desc = "Smells like chlorine."
icon_state = "water_soap"
-/obj/item/weapon/soap/fire_soap
+/obj/item/soap/fire_soap
desc = "Smells like a campfire."
icon_state = "fire_soap"
-/obj/item/weapon/soap/rainbow_soap
+/obj/item/soap/rainbow_soap
desc = "Smells sickly sweet."
icon_state = "rainbow_soap"
-/obj/item/weapon/soap/diamond_soap
+/obj/item/soap/diamond_soap
desc = "Smells like saffron and vanilla."
icon_state = "diamond_soap"
-/obj/item/weapon/soap/uranium_soap
+/obj/item/soap/uranium_soap
desc = "Smells not great... Not terrible."
icon_state = "uranium_soap"
-/obj/item/weapon/soap/silver_soap
+/obj/item/soap/silver_soap
desc = "Smells like birch and amaranth."
icon_state = "silver_soap"
-/obj/item/weapon/soap/brown_soap
+/obj/item/soap/brown_soap
desc = "Smells like cinnamon and cognac."
icon_state = "brown_soap"
-/obj/item/weapon/soap/white_soap
+/obj/item/soap/white_soap
desc = "Smells like nutmeg and oats."
icon_state = "white_soap"
-/obj/item/weapon/soap/grey_soap
+/obj/item/soap/grey_soap
desc = "Smells like bergamot and lilies."
icon_state = "grey_soap"
-/obj/item/weapon/soap/pink_soap
+/obj/item/soap/pink_soap
desc = "Smells like bubblegum."
icon_state = "pink_soap"
-/obj/item/weapon/soap/purple_soap
+/obj/item/soap/purple_soap
desc = "Smells like lavender."
icon_state = "purple_soap"
-/obj/item/weapon/soap/blue_soap
+/obj/item/soap/blue_soap
desc = "Smells like cardamom."
icon_state = "blue_soap"
-/obj/item/weapon/soap/cyan_soap
+/obj/item/soap/cyan_soap
desc = "Smells like bluebells and peaches."
icon_state = "cyan_soap"
-/obj/item/weapon/soap/green_soap
+/obj/item/soap/green_soap
desc = "Smells like a freshly mowed lawn."
icon_state = "green_soap"
-/obj/item/weapon/soap/yellow_soap
+/obj/item/soap/yellow_soap
desc = "Smells like citron and ginger."
icon_state = "yellow_soap"
-/obj/item/weapon/soap/orange_soap
+/obj/item/soap/orange_soap
desc = "Smells like oranges and dark chocolate."
icon_state = "orange_soap"
-/obj/item/weapon/soap/red_soap
+/obj/item/soap/red_soap
desc = "Smells like cherries."
icon_state = "red_soap"
-/obj/item/weapon/soap/golden_soap
+/obj/item/soap/golden_soap
desc = "Smells like honey."
icon_state = "golden_soap"
-/obj/item/weapon/bikehorn
+/obj/item/bikehorn
name = "bike horn"
desc = "A horn off of a bicycle."
icon = 'icons/obj/items.dmi'
@@ -151,7 +151,7 @@
attack_verb = list("HONKED")
var/spam_flag = 0
-/obj/item/weapon/c_tube
+/obj/item/c_tube
name = "cardboard tube"
desc = "A tube... of cardboard."
icon = 'icons/obj/items.dmi'
@@ -161,13 +161,13 @@
throw_speed = 4
throw_range = 5
-/obj/item/weapon/disk
+/obj/item/disk
name = "disk"
icon = 'icons/obj/discs_vr.dmi' //VOREStation Edit
drop_sound = 'sound/items/drop/disk.ogg'
pickup_sound = 'sound/items/pickup/disk.ogg'
-/obj/item/weapon/disk/nuclear
+/obj/item/disk/nuclear
name = "nuclear authentication disk"
desc = "Better keep this safe."
icon_state = "nucleardisk"
@@ -175,7 +175,7 @@
w_class = ITEMSIZE_SMALL
/*
-/obj/item/weapon/game_kit
+/obj/item/game_kit
name = "Gaming Kit"
icon = 'icons/obj/items.dmi'
icon_state = "game_kit"
@@ -187,7 +187,7 @@
w_class = ITEMSIZE_HUGE
*/
-/obj/item/weapon/gift
+/obj/item/gift
name = "gift"
desc = "A wrapped item."
icon = 'icons/obj/items.dmi'
@@ -197,7 +197,7 @@
item_state = "gift"
w_class = ITEMSIZE_LARGE
-/*/obj/item/weapon/syndicate_uplink
+/*/obj/item/syndicate_uplink
name = "station bounced radio"
desc = "Remain silent about this..."
icon = 'icons/obj/radio.dmi'
@@ -207,7 +207,7 @@
var/selfdestruct = 0.0
var/traitor_frequency = 0.0
var/mob/currentUser = null
- var/obj/item/device/radio/origradio = null
+ var/obj/item/radio/origradio = null
flags = ONBELT
w_class = ITEMSIZE_SMALL
item_state = "radio"
@@ -216,7 +216,7 @@
matter = list(MAT_STEEL = 100)
origin_tech = list(TECH_MAGNET = 2, TECH_ILLEGAL = 3)*/
-/obj/item/weapon/SWF_uplink
+/obj/item/SWF_uplink
name = "station-bounced radio"
desc = "Used to communicate, it appears."
icon = 'icons/obj/radio.dmi'
@@ -225,7 +225,7 @@
var/uses = 4.0
var/selfdestruct = 0.0
var/traitor_frequency = 0.0
- var/obj/item/device/radio/origradio = null
+ var/obj/item/radio/origradio = null
slot_flags = SLOT_BELT
item_state = "radio"
throwforce = 5
@@ -237,7 +237,7 @@
drop_sound = 'sound/items/drop/device.ogg'
pickup_sound = 'sound/items/pickup/device.ogg'
-/obj/item/weapon/staff
+/obj/item/staff
name = "wizards staff"
desc = "Apparently a staff used by the wizard."
icon = 'icons/obj/wizard.dmi'
@@ -253,19 +253,19 @@
w_class = ITEMSIZE_SMALL
attack_verb = list("bludgeoned", "whacked", "disciplined")
-/obj/item/weapon/staff/broom
+/obj/item/staff/broom
name = "broom"
desc = "Used for sweeping, and flying into the night while cackling. Black cat not included."
icon = 'icons/obj/wizard.dmi'
icon_state = "broom"
-/obj/item/weapon/staff/gentcane
+/obj/item/staff/gentcane
name = "Gentlemans Cane"
desc = "An ebony can with an ivory tip."
icon = 'icons/obj/weapons.dmi'
icon_state = "cane"
-/obj/item/weapon/staff/stick
+/obj/item/staff/stick
name = "stick"
desc = "A great tool to drag someone else's drinks across the bar."
icon = 'icons/obj/weapons.dmi'
@@ -277,7 +277,7 @@
throw_range = 5
w_class = ITEMSIZE_SMALL
-/obj/item/weapon/module
+/obj/item/module
icon = 'icons/obj/module.dmi'
icon_state = "std_module"
item_state = "std_mod"
@@ -286,37 +286,37 @@
drop_sound = 'sound/items/drop/component.ogg'
pickup_sound = 'sound/items/pickup/component.ogg'
-/obj/item/weapon/module/card_reader
+/obj/item/module/card_reader
name = "card reader module"
icon_state = "card_mod"
item_state = "std_mod"
desc = "An electronic module for reading data and ID cards."
-/obj/item/weapon/module/power_control
+/obj/item/module/power_control
name = "power control module"
icon_state = "power_mod"
item_state = "std_mod"
desc = "Heavy-duty switching circuits for power control."
matter = list(MAT_STEEL = 50, MAT_GLASS = 50)
-/obj/item/weapon/module/id_auth
+/obj/item/module/id_auth
name = "\improper ID authentication module"
icon_state = "id_mod"
desc = "A module allowing secure authorization of ID cards."
-/obj/item/weapon/module/cell_power
+/obj/item/module/cell_power
name = "power cell regulator module"
icon_state = "power_mod"
item_state = "std_mod"
desc = "A converter and regulator allowing the use of power cells."
-/obj/item/weapon/module/cell_power
+/obj/item/module/cell_power
name = "power cell charger module"
icon_state = "power_mod"
item_state = "std_mod"
desc = "Charging circuits for power cells."
-/obj/item/device/camera_bug
+/obj/item/camera_bug
name = "camera bug"
icon = 'icons/obj/device.dmi'
icon_state = "flash"
@@ -325,13 +325,13 @@
throw_speed = 4
throw_range = 20
-/obj/item/weapon/camera_bug/attack_self(mob/usr as mob)
+/obj/item/camera_bug/attack_self(mob/user as mob)
var/list/cameras = new/list()
for (var/obj/machinery/camera/C in cameranet.cameras)
if (C.bugged && C.status)
cameras.Add(C)
if (length(cameras) == 0)
- to_chat(usr, "No bugged functioning cameras found.")
+ to_chat(user, span_warning("No bugged functioning cameras found."))
return
var/list/friendly_cameras = new/list()
@@ -339,19 +339,19 @@
for (var/obj/machinery/camera/C in cameras)
friendly_cameras.Add(C.c_tag)
- var/target = tgui_input_list(usr, "Select the camera to observe", "Select Camera", friendly_cameras)
+ var/target = tgui_input_list(user, "Select the camera to observe", "Select Camera", friendly_cameras)
if (!target)
return
for (var/obj/machinery/camera/C in cameras)
if (C.c_tag == target)
target = C
break
- if (usr.stat == 2) return
+ if (user.stat == 2) return
- usr.client.eye = target
+ user.client.eye = target
/*
-/obj/item/weapon/cigarpacket
+/obj/item/cigarpacket
name = "Pete's Cuban Cigars"
desc = "The most robust cigars on the planet."
icon = 'icons/obj/cigarettes.dmi'
@@ -363,7 +363,7 @@
flags = ONBELT
*/
-/obj/item/weapon/pai_cable
+/obj/item/pai_cable
desc = "A flexible coated cable with a universal jack on one end."
name = "data cable"
icon = 'icons/obj/power.dmi'
@@ -371,20 +371,20 @@
var/obj/machinery/machine
-/obj/item/weapon/pai_cable/Destroy()
+/obj/item/pai_cable/Destroy()
machine = null
return ..()
///////////////////////////////////////Stock Parts /////////////////////////////////
-/obj/item/weapon/storage/part_replacer
+/obj/item/storage/part_replacer
name = "rapid part exchange device"
desc = "A special mechanical module made to store, sort, and apply standard machine parts."
icon = 'icons/obj/storage_vr.dmi'
icon_state = "RPED"
item_state = "RPED"
w_class = ITEMSIZE_HUGE
- can_hold = list(/obj/item/weapon/stock_parts)
+ can_hold = list(/obj/item/stock_parts)
storage_slots = 50
use_to_pickup = TRUE
allow_quick_gather = 1
@@ -401,7 +401,7 @@
var/unique_reskin = list("Soulless" = "RPED",
"Soulful" = "RPED_old")
-/obj/item/weapon/storage/part_replacer/proc/play_rped_sound()
+/obj/item/storage/part_replacer/proc/play_rped_sound()
//Plays the sound for RPED exhanging or installing parts.
/* if(alt_sound && prob(1))
playsound(src, alt_sound, 40, 1)
@@ -409,15 +409,15 @@
*/
playsound(src, pshoom_or_beepboopblorpzingshadashwoosh, 40, 1)
-/obj/item/weapon/storage/part_replacer/adv
+/obj/item/storage/part_replacer/adv
name = "advanced rapid part exchange device"
desc = "A special mechanical module made to store, sort, and apply standard machine parts. This one has a greatly upgraded storage capacity, \
and the ability to hold beakers."
- can_hold = list(/obj/item/weapon/stock_parts, /obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/cell,) // YW EDIT Cell
+ can_hold = list(/obj/item/stock_parts, /obj/item/reagent_containers/glass/beaker, /obj/item/cell/device/weapon) // YW EDIT Cell
storage_slots = 200
max_storage_space = 400
-/obj/item/weapon/storage/part_replacer/adv/discount_bluespace
+/obj/item/storage/part_replacer/adv/discount_bluespace
name = "prototype bluespace rapid part exchange device"
icon_state = "DBRPED"
item_state = "DBRPED"
@@ -430,17 +430,17 @@
unique_reskin = list("Soulless" = "DBRPED",
"Soulful" = "DBRPED_old")
-/obj/item/weapon/storage/part_replacer/examine(mob/user)
+/obj/item/storage/part_replacer/examine(mob/user)
. = ..()
if(!reskin_ran)
- . += "[src]'s external casing can be modified via alt-click."
+ . += span_notice("[src]'s external casing can be modified via alt-click.")
-/obj/item/weapon/storage/part_replacer/AltClick(mob/user)
+/obj/item/storage/part_replacer/AltClick(mob/user)
. = ..()
if(!reskin_ran)
reskin_radial(user)
-/obj/item/weapon/storage/part_replacer/proc/reskin_radial(mob/M)
+/obj/item/storage/part_replacer/proc/reskin_radial(mob/M)
if(!LAZYLEN(unique_reskin))
return
@@ -460,7 +460,7 @@
reskin_ran = TRUE
to_chat(M, "[src] is now '[pick]'.")
-/obj/item/weapon/storage/part_replacer/drop_contents() // hacky-feeling tier-based drop system
+/obj/item/storage/part_replacer/drop_contents() // hacky-feeling tier-based drop system
hide_from(usr)
var/turf/T = get_turf(src)
var/lowest_rating = INFINITY // We want the lowest-part tier rating in the RPED so we only drop the lowest-tier parts.
@@ -479,7 +479,7 @@
remove_from_storage(B, T)
-/obj/item/weapon/stock_parts
+/obj/item/stock_parts
name = "stock part"
desc = "What?"
gender = PLURAL
@@ -489,17 +489,17 @@
drop_sound = 'sound/items/drop/component.ogg'
pickup_sound = 'sound/items/pickup/component.ogg'
-/obj/item/weapon/stock_parts/New()
+/obj/item/stock_parts/New()
src.pixel_x = rand(-5.0, 5)
src.pixel_y = rand(-5.0, 5)
..()
-/obj/item/weapon/stock_parts/get_rating()
+/obj/item/stock_parts/get_rating()
return rating
//Rank 1
-/obj/item/weapon/stock_parts/console_screen
+/obj/item/stock_parts/console_screen
name = "console screen"
desc = "Used in the construction of computers and other devices with a interactive console."
icon_state = "screen"
@@ -507,7 +507,7 @@
rating = 5 // these are actually Really Important for some things??
matter = list(MAT_GLASS = 200)
-/obj/item/weapon/stock_parts/capacitor
+/obj/item/stock_parts/capacitor
name = "capacitor"
desc = "A basic capacitor used in the construction of a variety of devices."
icon_state = "capacitor"
@@ -517,43 +517,43 @@
var/charge = 0
var/max_charge = 1000
-/obj/item/weapon/stock_parts/capacitor/New()
+/obj/item/stock_parts/capacitor/New()
. = ..()
max_charge *= rating
-/obj/item/weapon/stock_parts/capacitor/proc/charge(var/amount)
+/obj/item/stock_parts/capacitor/proc/charge(var/amount)
charge += amount
if(charge > max_charge)
charge = max_charge
-/obj/item/weapon/stock_parts/capacitor/proc/use(var/amount)
+/obj/item/stock_parts/capacitor/proc/use(var/amount)
if(charge)
charge -= amount
if(charge < 0)
charge = 0
-/obj/item/weapon/stock_parts/scanning_module
+/obj/item/stock_parts/scanning_module
name = "scanning module"
desc = "A compact, high resolution scanning module used in the construction of certain devices."
icon_state = "scan_module"
origin_tech = list(TECH_MAGNET = 1)
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
-/obj/item/weapon/stock_parts/manipulator
+/obj/item/stock_parts/manipulator
name = "micro-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "micro_mani"
origin_tech = list(TECH_MATERIAL = 1, TECH_DATA = 1)
matter = list(MAT_STEEL = 30)
-/obj/item/weapon/stock_parts/micro_laser
+/obj/item/stock_parts/micro_laser
name = "micro-laser"
desc = "A tiny laser used in certain devices."
icon_state = "micro_laser"
origin_tech = list(TECH_MAGNET = 1)
matter = list(MAT_STEEL = 10,MAT_GLASS = 20)
-/obj/item/weapon/stock_parts/matter_bin
+/obj/item/stock_parts/matter_bin
name = "matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
icon_state = "matter_bin"
@@ -562,7 +562,7 @@
//Rank 2
-/obj/item/weapon/stock_parts/capacitor/adv
+/obj/item/stock_parts/capacitor/adv
name = "advanced capacitor"
desc = "An advanced capacitor used in the construction of a variety of devices."
icon_state = "capacitor_adv"
@@ -570,7 +570,7 @@
rating = 2
matter = list(MAT_STEEL = 50,MAT_GLASS = 50)
-/obj/item/weapon/stock_parts/scanning_module/adv
+/obj/item/stock_parts/scanning_module/adv
name = "advanced scanning module"
desc = "A compact, high resolution scanning module used in the construction of certain devices."
icon_state = "scan_module_adv"
@@ -578,7 +578,7 @@
rating = 2
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
-/obj/item/weapon/stock_parts/manipulator/nano
+/obj/item/stock_parts/manipulator/nano
name = "nano-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "nano_mani"
@@ -586,7 +586,7 @@
rating = 2
matter = list(MAT_STEEL = 30)
-/obj/item/weapon/stock_parts/micro_laser/high
+/obj/item/stock_parts/micro_laser/high
name = "high-power micro-laser"
desc = "A tiny laser used in certain devices."
icon_state = "high_micro_laser"
@@ -594,7 +594,7 @@
rating = 2
matter = list(MAT_STEEL = 10,MAT_GLASS = 20)
-/obj/item/weapon/stock_parts/matter_bin/adv
+/obj/item/stock_parts/matter_bin/adv
name = "advanced matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
icon_state = "advanced_matter_bin"
@@ -604,7 +604,7 @@
//Rating 3
-/obj/item/weapon/stock_parts/capacitor/super
+/obj/item/stock_parts/capacitor/super
name = "super capacitor"
desc = "A super-high capacity capacitor used in the construction of a variety of devices."
icon_state = "capacitor_super"
@@ -612,7 +612,7 @@
rating = 3
matter = list(MAT_STEEL = 50,MAT_GLASS = 50)
-/obj/item/weapon/stock_parts/scanning_module/phasic
+/obj/item/stock_parts/scanning_module/phasic
name = "phasic scanning module"
desc = "A compact, high resolution phasic scanning module used in the construction of certain devices."
icon_state = "scan_module_phasic"
@@ -620,7 +620,7 @@
rating = 3
matter = list(MAT_STEEL = 50,MAT_GLASS = 20)
-/obj/item/weapon/stock_parts/manipulator/pico
+/obj/item/stock_parts/manipulator/pico
name = "pico-manipulator"
desc = "A tiny little manipulator used in the construction of certain devices."
icon_state = "pico_mani"
@@ -628,7 +628,7 @@
rating = 3
matter = list(MAT_STEEL = 30)
-/obj/item/weapon/stock_parts/micro_laser/ultra
+/obj/item/stock_parts/micro_laser/ultra
name = "ultra-high-power micro-laser"
icon_state = "ultra_high_micro_laser"
desc = "A tiny laser used in certain devices."
@@ -636,7 +636,7 @@
rating = 3
matter = list(MAT_STEEL = 10,MAT_GLASS = 20)
-/obj/item/weapon/stock_parts/matter_bin/super
+/obj/item/stock_parts/matter_bin/super
name = "super matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
icon_state = "super_matter_bin"
@@ -646,7 +646,7 @@
// Rating 4 - Anomaly
-/obj/item/weapon/stock_parts/capacitor/hyper
+/obj/item/stock_parts/capacitor/hyper
name = "hyper capacitor"
desc = "A hyper-capacity capacitor used in the construction of a variety of devices."
icon_state = "capacitor_hyper"
@@ -654,7 +654,7 @@
rating = 4
matter = list(MAT_STEEL = 80, MAT_GLASS = 40)
-/obj/item/weapon/stock_parts/scanning_module/hyper
+/obj/item/stock_parts/scanning_module/hyper
name = "quantum scanning module"
desc = "A compact, near-perfect resolution quantum scanning module used in the construction of certain devices."
icon_state = "scan_module_hyper"
@@ -662,7 +662,7 @@
rating = 4
matter = list(MAT_STEEL = 100,MAT_GLASS = 40)
-/obj/item/weapon/stock_parts/manipulator/hyper
+/obj/item/stock_parts/manipulator/hyper
name = "planck-manipulator"
desc = "A miniscule manipulator used in the construction of certain devices."
icon_state = "hyper_mani"
@@ -670,7 +670,7 @@
rating = 4
matter = list(MAT_STEEL = 30)
-/obj/item/weapon/stock_parts/micro_laser/hyper
+/obj/item/stock_parts/micro_laser/hyper
name = "hyper-power micro-laser"
icon_state = "hyper_micro_laser"
desc = "A tiny laser used in certain devices."
@@ -678,7 +678,7 @@
rating = 4
matter = list(MAT_STEEL = 30, MAT_GLASS = 40)
-/obj/item/weapon/stock_parts/matter_bin/hyper
+/obj/item/stock_parts/matter_bin/hyper
name = "hyper matter bin"
desc = "A container for holding compressed matter awaiting re-construction."
icon_state = "hyper_matter_bin"
@@ -688,7 +688,7 @@
// Rating 5 - Precursor
-/obj/item/weapon/stock_parts/capacitor/omni
+/obj/item/stock_parts/capacitor/omni
name = "omni-capacitor"
desc = "A capacitor of immense capacity used in the construction of a variety of devices."
icon_state = "capacitor_omni"
@@ -696,7 +696,7 @@
rating = 5
matter = list(MAT_STEEL = 80, MAT_GLASS = 40)
-/obj/item/weapon/stock_parts/scanning_module/omni
+/obj/item/stock_parts/scanning_module/omni
name = "omni-scanning module"
desc = "A compact, perfect resolution temporospatial scanning module used in the construction of certain devices."
icon_state = "scan_module_omni"
@@ -704,7 +704,7 @@
rating = 5
matter = list(MAT_STEEL = 100,MAT_GLASS = 40)
-/obj/item/weapon/stock_parts/manipulator/omni
+/obj/item/stock_parts/manipulator/omni
name = "omni-manipulator"
desc = "A strange, infinitesimal manipulator used in the construction of certain devices."
icon_state = "omni_mani"
@@ -712,7 +712,7 @@
rating = 5
matter = list(MAT_STEEL = 30)
-/obj/item/weapon/stock_parts/micro_laser/omni
+/obj/item/stock_parts/micro_laser/omni
name = "omni-power micro-laser"
icon_state = "omni_micro_laser"
desc = "A strange laser used in certain devices."
@@ -720,7 +720,7 @@
rating = 5
matter = list(MAT_STEEL = 30, MAT_GLASS = 40)
-/obj/item/weapon/stock_parts/matter_bin/omni
+/obj/item/stock_parts/matter_bin/omni
name = "omni-matter bin"
desc = "A strange container for holding compressed matter awaiting re-construction."
icon_state = "omni_matter_bin"
@@ -731,63 +731,63 @@
// Subspace stock parts
-/obj/item/weapon/stock_parts/subspace/ansible
+/obj/item/stock_parts/subspace/ansible
name = "subspace ansible"
icon_state = "subspace_ansible"
desc = "A compact module capable of sensing extradimensional activity."
origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 5 ,TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
matter = list(MAT_STEEL = 30,MAT_GLASS = 10)
-/obj/item/weapon/stock_parts/subspace/sub_filter
+/obj/item/stock_parts/subspace/sub_filter
name = "hyperwave filter"
icon_state = "hyperwave_filter"
desc = "A tiny device capable of filtering and converting super-intense radiowaves."
origin_tech = list(TECH_DATA = 4, TECH_MAGNET = 2)
matter = list(MAT_STEEL = 30,MAT_GLASS = 10)
-/obj/item/weapon/stock_parts/subspace/amplifier
+/obj/item/stock_parts/subspace/amplifier
name = "subspace amplifier"
icon_state = "subspace_amplifier"
desc = "A compact micro-machine capable of amplifying weak subspace transmissions."
origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
matter = list(MAT_STEEL = 30,MAT_GLASS = 10)
-/obj/item/weapon/stock_parts/subspace/treatment
+/obj/item/stock_parts/subspace/treatment
name = "subspace treatment disk"
icon_state = "treatment_disk"
desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves."
origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 2, TECH_MATERIAL = 5, TECH_BLUESPACE = 2)
matter = list(MAT_STEEL = 30,MAT_GLASS = 10)
-/obj/item/weapon/stock_parts/subspace/analyzer
+/obj/item/stock_parts/subspace/analyzer
name = "subspace wavelength analyzer"
icon_state = "wavelength_analyzer"
desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths."
origin_tech = list(TECH_DATA = 3, TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
matter = list(MAT_STEEL = 30,MAT_GLASS = 10)
-/obj/item/weapon/stock_parts/subspace/crystal
+/obj/item/stock_parts/subspace/crystal
name = "ansible crystal"
icon_state = "ansible_crystal"
desc = "A crystal made from pure glass used to transmit laser databursts to subspace."
origin_tech = list(TECH_MAGNET = 4, TECH_MATERIAL = 4, TECH_BLUESPACE = 2)
matter = list(MAT_GLASS = 50)
-/obj/item/weapon/stock_parts/subspace/transmitter
+/obj/item/stock_parts/subspace/transmitter
name = "subspace transmitter"
icon_state = "subspace_transmitter"
desc = "A large piece of equipment used to open a window into the subspace dimension."
origin_tech = list(TECH_MAGNET = 5, TECH_MATERIAL = 5, TECH_BLUESPACE = 3)
matter = list(MAT_STEEL = 50)
-/obj/item/weapon/ectoplasm
+/obj/item/ectoplasm
name = "ectoplasm"
desc = "Spooky!"
gender = PLURAL
icon = 'icons/obj/wizard.dmi'
icon_state = "ectoplasm2"
-/obj/item/weapon/research
+/obj/item/research
name = "research debugging device"
desc = "Instant research tool. For testing purposes only."
icon = 'icons/obj/stock_parts.dmi'
@@ -796,7 +796,7 @@
// Additional construction stock parts
-/obj/item/weapon/stock_parts/gear
+/obj/item/stock_parts/gear
name = "gear"
desc = "A gear used for construction."
icon = 'icons/obj/stock_parts.dmi'
@@ -804,7 +804,7 @@
origin_tech = list(TECH_ENGINEERING = 1)
matter = list(MAT_STEEL = 50)
-/obj/item/weapon/stock_parts/motor
+/obj/item/stock_parts/motor
name = "motor"
desc = "A motor used for construction."
icon = 'icons/obj/stock_parts.dmi'
@@ -812,7 +812,7 @@
origin_tech = list(TECH_ENGINEERING = 1)
matter = list(MAT_STEEL = 60, MAT_GLASS = 10)
-/obj/item/weapon/stock_parts/spring
+/obj/item/stock_parts/spring
name = "spring"
desc = "A spring used for construction."
icon = 'icons/obj/stock_parts.dmi'
@@ -838,53 +838,53 @@
name = "basic parts bundle"
desc = "5 of each T1 part, no more and no less."
items = list(
- /obj/item/weapon/stock_parts/matter_bin,
- /obj/item/weapon/stock_parts/manipulator,
- /obj/item/weapon/stock_parts/capacitor,
- /obj/item/weapon/stock_parts/scanning_module,
- /obj/item/weapon/stock_parts/micro_laser
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/manipulator,
+ /obj/item/stock_parts/capacitor,
+ /obj/item/stock_parts/scanning_module,
+ /obj/item/stock_parts/micro_laser
)
/obj/effect/spawner/parts/t2
name = "advanced parts bundle"
desc = "5 of each T2 part, no more and no less."
items = list(
- /obj/item/weapon/stock_parts/matter_bin/adv,
- /obj/item/weapon/stock_parts/manipulator/nano,
- /obj/item/weapon/stock_parts/capacitor/adv,
- /obj/item/weapon/stock_parts/scanning_module/adv,
- /obj/item/weapon/stock_parts/micro_laser/high
+ /obj/item/stock_parts/matter_bin/adv,
+ /obj/item/stock_parts/manipulator/nano,
+ /obj/item/stock_parts/capacitor/adv,
+ /obj/item/stock_parts/scanning_module/adv,
+ /obj/item/stock_parts/micro_laser/high
)
/obj/effect/spawner/parts/t3
name = "super parts bundle"
desc = "5 of each T3 part, no more and no less."
items = list(
- /obj/item/weapon/stock_parts/matter_bin/super,
- /obj/item/weapon/stock_parts/manipulator/pico,
- /obj/item/weapon/stock_parts/capacitor/super,
- /obj/item/weapon/stock_parts/scanning_module/phasic,
- /obj/item/weapon/stock_parts/micro_laser/ultra
+ /obj/item/stock_parts/matter_bin/super,
+ /obj/item/stock_parts/manipulator/pico,
+ /obj/item/stock_parts/capacitor/super,
+ /obj/item/stock_parts/scanning_module/phasic,
+ /obj/item/stock_parts/micro_laser/ultra
)
/obj/effect/spawner/parts/t4
name = "hyper parts bundle"
desc = "5 of each T4 part, no more and no less."
items = list(
- /obj/item/weapon/stock_parts/matter_bin/hyper,
- /obj/item/weapon/stock_parts/manipulator/hyper,
- /obj/item/weapon/stock_parts/capacitor/hyper,
- /obj/item/weapon/stock_parts/scanning_module/hyper,
- /obj/item/weapon/stock_parts/micro_laser/hyper
+ /obj/item/stock_parts/matter_bin/hyper,
+ /obj/item/stock_parts/manipulator/hyper,
+ /obj/item/stock_parts/capacitor/hyper,
+ /obj/item/stock_parts/scanning_module/hyper,
+ /obj/item/stock_parts/micro_laser/hyper
)
/obj/effect/spawner/parts/t5
name = "omni parts bundle"
desc = "5 of each T5 part, no more and no less."
items = list(
- /obj/item/weapon/stock_parts/matter_bin/omni,
- /obj/item/weapon/stock_parts/manipulator/omni,
- /obj/item/weapon/stock_parts/capacitor/omni,
- /obj/item/weapon/stock_parts/scanning_module/omni,
- /obj/item/weapon/stock_parts/micro_laser/omni
+ /obj/item/stock_parts/matter_bin/omni,
+ /obj/item/stock_parts/manipulator/omni,
+ /obj/item/stock_parts/capacitor/omni,
+ /obj/item/stock_parts/scanning_module/omni,
+ /obj/item/stock_parts/micro_laser/omni
)
diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm
index 858875a9827..7840615cccc 100644
--- a/code/defines/procs/announce.dm
+++ b/code/defines/procs/announce.dm
@@ -56,20 +56,20 @@
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player) && !isdeaf(M))
to_chat(M, "[title]
")
- to_chat(M, "[message]")
+ to_chat(M, span_alert("[message]"))
if (announcer)
- to_chat(M, " -[html_encode(announcer)]")
+ to_chat(M, span_alert(" -[html_encode(announcer)]"))
// You'll need to update these to_world usages if you want to make these z-level specific ~Aro
/datum/announcement/minor/Message(message as text, message_title as text)
- to_world("[message]")
+ to_world(span_bold("[message]"))
/datum/announcement/priority/Message(message as text, message_title as text)
to_world("[message_title]
")
- to_world("[message]")
+ to_world(span_alert("[message]"))
if(announcer)
- to_world(" -[html_encode(announcer)]")
- to_world("
")
+ to_world(span_alert(" -[html_encode(announcer)]"))
+ to_world(span_alert("
"))
/datum/announcement/priority/command/Message(message as text, message_title as text, var/list/zlevels)
var/command
@@ -77,7 +77,7 @@
if (message_title)
command += "
[message_title]
"
- command += "
[message]
"
+ command += "
[span_alert(message)]
"
command += "
"
for(var/mob/M in player_list)
if(zlevels && !(get_z(M) in zlevels))
@@ -86,13 +86,13 @@
to_chat(M, command)
/datum/announcement/priority/Message(var/message as text, var/message_title as text, var/list/zlevels)
- global_announcer.autosay("[message_title]: [message]", announcer ? announcer : ANNOUNCER_NAME, channel = "Common", zlevels = zlevels)
+ global_announcer.autosay(span_alert("[message_title]:") + " [message]", announcer ? announcer : ANNOUNCER_NAME, channel = "Common", zlevels = zlevels)
/datum/announcement/priority/command/Message(var/message as text, var/message_title as text, var/list/zlevels)
- global_announcer.autosay("[command_name()] - [message_title]: [message]", ANNOUNCER_NAME, channel = "Common", zlevels = zlevels)
+ global_announcer.autosay(span_alert("[command_name()] - [message_title]:") + " [message]", ANNOUNCER_NAME, channel = "Common", zlevels = zlevels)
/datum/announcement/priority/security/Message(var/message as text, var/message_title as text, var/list/zlevels)
- global_announcer.autosay("[message_title]: [message]", ANNOUNCER_NAME, channel = "Common", zlevels = zlevels)
+ global_announcer.autosay(span_alert("[message_title]:") + " [message]", ANNOUNCER_NAME, channel = "Common", zlevels = zlevels)
/datum/announcement/proc/NewsCast(var/message as text, var/message_title as text)
if(!newscast)
@@ -131,7 +131,7 @@
log_game("[key_name(usr)] has made \a [announcement_type]: [message_title] - [message] - [announcer]")
message_admins("[key_name_admin(usr)] has made \a [announcement_type].", 1)
-/proc/GetNameAndAssignmentFromId(var/obj/item/weapon/card/id/I)
+/proc/GetNameAndAssignmentFromId(var/obj/item/card/id/I)
// Format currently matches that of newscaster feeds: Registered Name (Assigned Rank)
return I.assignment ? "[I.registered_name] ([I.assignment])" : I.registered_name
diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm
index 3a89c9ef8c4..9367b269643 100644
--- a/code/defines/procs/dbcore.dm
+++ b/code/defines/procs/dbcore.dm
@@ -56,7 +56,7 @@ var/DB_PORT = 3306 // This is the port your MySQL server is running on (3306 is
_db_con = _dm_db_new_con()
/DBConnection/proc/Connect(dbi_handler=src.dbi,user_handler=src.user,password_handler=src.password,cursor_handler)
- if(!config.sql_enabled)
+ if(!CONFIG_GET(flag/sql_enabled))
return 0
if(!src) return 0
cursor_handler = src.default_cursor
@@ -66,7 +66,7 @@ var/DB_PORT = 3306 // This is the port your MySQL server is running on (3306 is
/DBConnection/proc/Disconnect() return _dm_db_close(_db_con)
/DBConnection/proc/IsConnected()
- if(!config.sql_enabled) return 0
+ if(!CONFIG_GET(flag/sql_enabled)) return 0
var/success = _dm_db_is_connected(_db_con)
return success
@@ -76,7 +76,7 @@ var/DB_PORT = 3306 // This is the port your MySQL server is running on (3306 is
/DBConnection/proc/SelectDB(database_name,dbi)
if(IsConnected()) Disconnect()
//return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[DB_SERVER]:[DB_PORT]"]",user,password)
- return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[sqladdress]:[sqlport]"]",user,password)
+ return Connect("[dbi?"[dbi]":"dbi:mysql:[database_name]:[CONFIG_GET(string/address)]:[CONFIG_GET(number/port)]"]",user,password)
/DBConnection/proc/NewQuery(sql_query,cursor_handler=src.default_cursor) return new/DBQuery(sql_query,src,cursor_handler)
diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm
index 6ce55534ded..d11864fc755 100644
--- a/code/defines/procs/statistics.dm
+++ b/code/defines/procs/statistics.dm
@@ -1,5 +1,5 @@
/proc/sql_poll_population()
- if(!sqllogging)
+ if(!CONFIG_GET(flag/enable_stat_tracking))
return
var/admincount = GLOB.admins.len
var/playercount = 0
@@ -18,15 +18,15 @@
/proc/sql_report_round_start()
// TODO
- if(!sqllogging)
+ if(!CONFIG_GET(flag/enable_stat_tracking))
return
/proc/sql_report_round_end()
// TODO
- if(!sqllogging)
+ if(!CONFIG_GET(flag/enable_stat_tracking))
return
/proc/sql_report_death(var/mob/living/carbon/human/H)
- if(!sqllogging)
+ if(!CONFIG_GET(flag/enable_stat_tracking))
return
if(!H)
return
@@ -60,7 +60,7 @@
/proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H)
- if(!sqllogging)
+ if(!CONFIG_GET(flag/enable_stat_tracking))
return
if(!H)
return
@@ -95,7 +95,7 @@
/proc/statistic_cycle()
set waitfor = 0
- if(!sqllogging)
+ if(!CONFIG_GET(flag/enable_stat_tracking))
return
while(1)
sql_poll_population()
diff --git a/code/game/antagonist/alien/borer.dm b/code/game/antagonist/alien/borer.dm
index f3465f5c66f..c36cd16d314 100644
--- a/code/game/antagonist/alien/borer.dm
+++ b/code/game/antagonist/alien/borer.dm
@@ -63,7 +63,7 @@ var/datum/antagonist/borer/borers
borer.forceMove(get_turf(pick(get_vents())))
/datum/antagonist/borer/attempt_random_spawn()
- if(config.aliens_allowed) ..()
+ if(CONFIG_GET(flag/aliens_allowed)) ..()
/datum/antagonist/borer/proc/get_vents()
var/list/vents = list()
diff --git a/code/game/antagonist/alien/xenomorph.dm b/code/game/antagonist/alien/xenomorph.dm
index 493a5ed40cd..2da4170fff9 100644
--- a/code/game/antagonist/alien/xenomorph.dm
+++ b/code/game/antagonist/alien/xenomorph.dm
@@ -27,7 +27,7 @@ var/datum/antagonist/xenos/xenomorphs
xenomorphs = src
/datum/antagonist/xenos/attempt_random_spawn()
- if(config.aliens_allowed) ..()
+ if(CONFIG_GET(flag/aliens_allowed)) ..()
/datum/antagonist/xenos/proc/get_vents()
var/list/vents = list()
diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm
index 8778cef2cc0..d9d11999f3a 100644
--- a/code/game/antagonist/antagonist.dm
+++ b/code/game/antagonist/antagonist.dm
@@ -48,7 +48,7 @@
var/landmark_id // Spawn point identifier.
var/mob_path = /mob/living/carbon/human // Mobtype this antag will use if none is provided.
var/feedback_tag = "traitor_objective" // End of round
- var/bantype = "Syndicate" // Ban to check when spawning this antag.
+ var/bantype = JOB_SYNDICATE // Ban to check when spawning this antag.
var/minimum_player_age = 7 // Players need to be at least minimum_player_age days old before they are eligable for auto-spawning
var/suspicion_chance = 50 // Prob of being on the initial Command report
var/flags = 0 // Various runtime options.
@@ -72,11 +72,11 @@
// ID card stuff.
var/default_access = list()
- var/id_type = /obj/item/weapon/card/id
+ var/id_type = /obj/item/card/id
var/antag_text = "You are an antagonist! Within the rules, \
try to act as an opposing force to the crew. Further RP and try to make sure \
- other players have fun! If you are confused or at a loss, always adminhelp, \
+ other players have " + span_italics("fun") + "! If you are confused or at a loss, always adminhelp, \
and before taking extreme actions, please try to also contact the administration! \
Think through your actions and make the roleplay immersive! Please remember all \
rules aside from those without explicit exceptions apply to antagonists."
@@ -91,7 +91,7 @@
get_starting_locations()
if(!role_text_plural)
role_text_plural = role_text
- if(config.protect_roles_from_antagonist)
+ if(CONFIG_GET(flag/protect_roles_from_antagonist))
restricted_jobs |= protected_jobs
if(antaghud_indicator)
if(!hud_icon_reference)
@@ -112,7 +112,7 @@
if(ghosts_only && !istype(player.current, /mob/observer/dead))
candidates -= player
log_debug("[key_name(player)] is not eligible to become a [role_text]: Only ghosts may join as this role! They have been removed from the draft.")
- else if(config.use_age_restriction_for_antags && player.current.client.player_age < minimum_player_age)
+ else if(CONFIG_GET(flag/use_age_restriction_for_antags) && player.current.client.player_age < minimum_player_age)
candidates -= player
log_debug("[key_name(player)] is not eligible to become a [role_text]: Is only [player.current.client.player_age] day\s old, has to be [minimum_player_age] day\s!")
else if(player.special_role)
@@ -145,7 +145,7 @@
if(!istype(player))
message_admins("[uppertext(ticker.mode.name)]: Failed to find a candidate for [role_text].")
return 0
- to_chat(player.current, "You have been selected this round as an antagonist!")
+ to_chat(player.current, span_danger(span_italics("You have been selected this round as an antagonist!")))
message_admins("[uppertext(ticker.mode.name)]: Selected [player] as a [role_text].")
if(istype(player.current, /mob/observer/dead))
create_default(player.current)
diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm
index 56a716f24b8..76781e5defb 100644
--- a/code/game/antagonist/antagonist_add.dm
+++ b/code/game/antagonist/antagonist_add.dm
@@ -28,40 +28,40 @@
current_antagonists |= player
if(faction_verb && player.current)
- player.current.verbs |= faction_verb
+ add_verb(player.current, faction_verb)
spawn(1 SECOND) //Added a delay so that this should pop up at the bottom and not the top of the text flood the new antag gets.
- to_chat(player.current, "Once you decide on a goal to pursue, you can optionally display it to \
- everyone at the end of the shift with the Set Ambition verb, located in the IC tab. You can change this at any time, \
- and it otherwise has no bearing on your round.")
- player.current.verbs |= /mob/living/proc/write_ambition
+ to_chat(player.current, span_notice("Once you decide on a goal to pursue, you can optionally display it to \
+ everyone at the end of the shift with the " + span_bold("Set Ambition") + " verb, located in the IC tab. You can change this at any time, \
+ and it otherwise has no bearing on your round."))
+ add_verb(player.current, /mob/living/proc/write_ambition)
if(can_speak_aooc)
- player.current.client.verbs += /client/proc/aooc
+ add_verb(player.current.client, /client/proc/aooc)
// Handle only adding a mind and not bothering with gear etc.
if(nonstandard_role_type)
faction_members |= player
- to_chat(player.current, "You are \a [nonstandard_role_type]!")
+ to_chat(player.current, span_danger(span_large("You are \a [nonstandard_role_type]!")))
player.special_role = nonstandard_role_type
if(nonstandard_role_msg)
- to_chat(player.current, "[nonstandard_role_msg]")
+ to_chat(player.current, span_notice("[nonstandard_role_msg]"))
update_icons_added(player)
return 1
/datum/antagonist/proc/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted)
if(player.current && faction_verb)
- player.current.verbs -= faction_verb
+ remove_verb(player.current, faction_verb)
if(player in current_antagonists)
- to_chat(player.current, "You are no longer a [role_text]!")
+ to_chat(player.current, span_danger(span_large("You are no longer a [role_text]!")))
current_antagonists -= player
faction_members -= player
player.special_role = null
update_icons_removed(player)
BITSET(player.current.hud_updateflag, SPECIALROLE_HUD)
if(!is_special_character(player))
- player.current.verbs -= /mob/living/proc/write_ambition
- player.current.client.verbs -= /client/proc/aooc
+ remove_verb(player.current, /mob/living/proc/write_ambition)
+ remove_verb(player.current.client, /client/proc/aooc)
player.ambitions = ""
return 1
- return 0
\ No newline at end of file
+ return 0
diff --git a/code/game/antagonist/antagonist_create.dm b/code/game/antagonist/antagonist_create.dm
index 3dd683377f0..7ea5782aa50 100644
--- a/code/game/antagonist/antagonist_create.dm
+++ b/code/game/antagonist/antagonist_create.dm
@@ -32,7 +32,7 @@
/datum/antagonist/proc/create_id(var/assignment, var/mob/living/carbon/human/player, var/equip = 1)
- var/obj/item/weapon/card/id/W = new id_type(player)
+ var/obj/item/card/id/W = new id_type(player)
if(!W) return
W.access |= default_access
W.assignment = "[assignment]"
@@ -41,15 +41,15 @@
return W
/datum/antagonist/proc/create_radio(var/freq, var/mob/living/carbon/human/player)
- var/obj/item/device/radio/R
+ var/obj/item/radio/R
switch(freq)
if(SYND_FREQ)
- R = new/obj/item/device/radio/headset/syndicate(player)
+ R = new/obj/item/radio/headset/syndicate(player)
if(RAID_FREQ)
- R = new/obj/item/device/radio/headset/raider(player)
+ R = new/obj/item/radio/headset/raider(player)
else
- R = new/obj/item/device/radio/headset(player)
+ R = new/obj/item/radio/headset(player)
R.set_frequency(freq)
player.equip_to_slot_or_del(R, slot_l_ear)
@@ -75,7 +75,7 @@
if(paper_spawn_loc)
// Create and pass on the bomb code paper.
- var/obj/item/weapon/paper/P = new(paper_spawn_loc)
+ var/obj/item/paper/P = new(paper_spawn_loc)
P.info = "The nuclear authorization code is: [code]"
P.name = "nuclear bomb code"
if(leader && leader.current)
@@ -85,10 +85,10 @@
if(!code_owner && leader)
code_owner = leader
if(code_owner)
- code_owner.store_memory("Nuclear Bomb Code: [code]", 0, 0)
+ code_owner.store_memory(span_bold("Nuclear Bomb Code") + ": [code]", 0, 0)
to_chat(code_owner.current, "The nuclear authorization code is: [code]")
else
- message_admins("Could not spawn nuclear bomb. Contact a developer.")
+ message_admins(span_danger("Could not spawn nuclear bomb. Contact a developer."))
return
spawned_nuke = code
@@ -101,18 +101,18 @@
window_flash(player.current.client)
// Basic intro text.
- to_chat(player.current, "You are a [role_text]!")
+ to_chat(player.current, span_danger(span_large("You are a [role_text]!")))
if(leader_welcome_text && player == leader)
- to_chat(player.current, "[leader_welcome_text]")
+ to_chat(player.current, span_notice("[leader_welcome_text]"))
else
- to_chat(player.current, "[welcome_text]")
- if (config.objectives_disabled)
- to_chat(player.current, "[antag_text]")
+ to_chat(player.current, span_notice("[welcome_text]"))
+ if (CONFIG_GET(flag/objectives_disabled))
+ to_chat(player.current, span_notice("[antag_text]"))
if((flags & ANTAG_HAS_NUKE) && !spawned_nuke)
create_nuke()
- if (!config.objectives_disabled)
+ if (!CONFIG_GET(flag/objectives_disabled))
show_objectives(player)
return 1
diff --git a/code/game/antagonist/antagonist_factions.dm b/code/game/antagonist/antagonist_factions.dm
index 6e18b57a3b2..b1ee3e16e5b 100644
--- a/code/game/antagonist/antagonist_factions.dm
+++ b/code/game/antagonist/antagonist_factions.dm
@@ -1,6 +1,6 @@
/mob/living/proc/convert_to_rev(mob/M as mob in oview(src))
set name = "Convert Bourgeoise"
- set category = "Abilities"
+ set category = "Abilities.Antag"
if(!M.mind)
return
convert_to_faction(M.mind, revs)
@@ -14,37 +14,37 @@
return
if(faction.is_antagonist(player))
- to_chat(src, "\The [player.current] already serves the [faction.faction_descriptor].")
+ to_chat(src, span_warning("\The [player.current] already serves the [faction.faction_descriptor]."))
return
if(player_is_antag(player))
- to_chat(src, "\The [player.current]'s loyalties seem to be elsewhere...")
+ to_chat(src, span_warning("\The [player.current]'s loyalties seem to be elsewhere..."))
return
if(!faction.can_become_antag(player))
- to_chat(src, "\The [player.current] cannot be \a [faction.faction_role_text]!")
+ to_chat(src, span_warning("\The [player.current] cannot be \a [faction.faction_role_text]!"))
return
if(world.time < player.rev_cooldown)
- to_chat(src, "You must wait five seconds between attempts.")
+ to_chat(src, span_danger("You must wait five seconds between attempts."))
return
- to_chat(src, "You are attempting to convert \the [player.current]...")
+ to_chat(src, span_danger("You are attempting to convert \the [player.current]..."))
log_admin("[src]([src.ckey]) attempted to convert [player.current].")
- message_admins("[src]([src.ckey]) attempted to convert [player.current].")
+ message_admins(span_danger("[src]([src.ckey]) attempted to convert [player.current]."))
player.rev_cooldown = world.time+100
var/choice = tgui_alert(player.current, "Asked by [src]: Do you want to join the [faction.faction_descriptor]?", "Join the [faction.faction_descriptor]?", list("No!","Yes!"))
if(choice == "Yes!" && faction.add_antagonist_mind(player, 0, faction.faction_role_text, faction.faction_welcome))
- to_chat(src, "\The [player.current] joins the [faction.faction_descriptor]!")
+ to_chat(src, span_notice("\The [player.current] joins the [faction.faction_descriptor]!"))
return
- if(choice == "No!")
- to_chat(player, "You reject this traitorous cause!")
- to_chat(src, "\The [player.current] does not support the [faction.faction_descriptor]!")
+ if(!choice || choice == "No!")
+ to_chat(player, span_danger("You reject this traitorous cause!"))
+ to_chat(src, span_danger("\The [player.current] does not support the [faction.faction_descriptor]!"))
/mob/living/proc/convert_to_loyalist(mob/M as mob in oview(src))
set name = "Convert Recidivist"
- set category = "Abilities"
+ set category = "Abilities.Antag"
if(!M.mind)
return
- convert_to_faction(M.mind, loyalists)
\ No newline at end of file
+ convert_to_faction(M.mind, loyalists)
diff --git a/code/game/antagonist/antagonist_helpers.dm b/code/game/antagonist/antagonist_helpers.dm
index ebf212f0658..fc08d68e56c 100644
--- a/code/game/antagonist/antagonist_helpers.dm
+++ b/code/game/antagonist/antagonist_helpers.dm
@@ -8,7 +8,7 @@
if(!ignore_role)
if(player.assigned_role in restricted_jobs)
return FALSE
- if(config.protect_roles_from_antagonist && (player.assigned_role in protected_jobs))
+ if(CONFIG_GET(flag/protect_roles_from_antagonist) && (player.assigned_role in protected_jobs))
return FALSE
if(avoid_silicons)
var/datum/job/J = SSjob.get_job(player.assigned_role)
@@ -53,4 +53,4 @@
return 1
/datum/antagonist/proc/is_latejoin_template()
- return (flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
\ No newline at end of file
+ return (flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
diff --git a/code/game/antagonist/antagonist_objectives.dm b/code/game/antagonist/antagonist_objectives.dm
index 223db7dda83..f05219465a2 100644
--- a/code/game/antagonist/antagonist_objectives.dm
+++ b/code/game/antagonist/antagonist_objectives.dm
@@ -1,12 +1,12 @@
/datum/antagonist/proc/create_global_objectives()
- if(config.objectives_disabled)
+ if(CONFIG_GET(flag/objectives_disabled))
return 0
if(global_objectives && global_objectives.len)
return 0
return 1
/datum/antagonist/proc/create_objectives(var/datum/mind/player)
- if(config.objectives_disabled)
+ if(CONFIG_GET(flag/objectives_disabled))
return 0
if(create_global_objectives() || global_objectives.len)
player.objectives |= global_objectives
@@ -17,29 +17,29 @@
/datum/antagonist/proc/check_victory()
var/result = 1
- if(config.objectives_disabled)
+ if(CONFIG_GET(flag/objectives_disabled))
return 1
if(global_objectives && global_objectives.len)
for(var/datum/objective/O in global_objectives)
if(!O.completed && !O.check_completion())
result = 0
if(result && victory_text)
- to_world("[victory_text]")
+ to_world(span_boldannounce(span_large("[victory_text]")))
if(victory_feedback_tag) feedback_set_details("round_end_result","[victory_feedback_tag]")
else if(loss_text)
- to_world("[loss_text]")
+ to_world(span_boldannounce(span_large("[loss_text]")))
if(loss_feedback_tag) feedback_set_details("round_end_result","[loss_feedback_tag]")
/mob/living/proc/write_ambition()
set name = "Set Ambition"
- set category = "IC"
+ set category = "IC.Antag"
set src = usr
if(!mind)
return
if(!is_special_character(mind))
- to_chat(src, "While you may perhaps have goals, this verb's meant to only be visible \
- to antagonists. Please make a bug report!")
+ to_chat(src, span_warning("While you may perhaps have goals, this verb's meant to only be visible \
+ to antagonists. Please make a bug report!"))
return
var/new_ambitions = tgui_input_text(src, "Write a short sentence of what your character hopes to accomplish \
today as an antagonist. Remember that this is purely optional. It will be shown at the end of the \
@@ -49,7 +49,7 @@
new_ambitions = sanitize(new_ambitions)
mind.ambitions = new_ambitions
if(new_ambitions)
- to_chat(src, "You've set your goal to be '[new_ambitions]'.")
+ to_chat(src, span_notice("You've set your goal to be '[new_ambitions]'."))
else
- to_chat(src, "You leave your ambitions behind.")
+ to_chat(src, span_notice("You leave your ambitions behind."))
log_and_message_admins("has set their ambitions to now be: [new_ambitions].")
diff --git a/code/game/antagonist/antagonist_panel.dm b/code/game/antagonist/antagonist_panel.dm
index 0a165ce8ee9..8fa2d060f03 100644
--- a/code/game/antagonist/antagonist_panel.dm
+++ b/code/game/antagonist/antagonist_panel.dm
@@ -17,7 +17,7 @@
/datum/antagonist/proc/get_extra_panel_options()
return
-/datum/antagonist/proc/get_check_antag_output(var/datum/admins/caller)
+/datum/antagonist/proc/get_check_antag_output(var/datum/admins/requester)
if(!current_antagonists || !current_antagonists.len)
return ""
@@ -31,7 +31,7 @@
if(!M.client) dat += " (logged out)"
if(M.stat == DEAD) dat += " (DEAD)"
dat += ""
- dat += "\[PP]\[PM\]\[TP\] | "
+ dat += "\[PP]\[PM\]\[TP\] | "
else
dat += "[player.key] Mob not found! | "
dat += ""
@@ -39,23 +39,23 @@
if(flags & ANTAG_HAS_NUKE)
dat += "
Nuclear disk(s) |
"
- for(var/obj/item/weapon/disk/nuclear/N in nuke_disks)
+ for(var/obj/item/disk/nuclear/N in nuke_disks)
dat += "[N.name], "
var/atom/disk_loc = N.loc
while(!istype(disk_loc, /turf))
if(istype(disk_loc, /mob))
var/mob/M = disk_loc
- dat += "carried by [M.real_name] "
+ dat += "carried by [M.real_name] "
if(istype(disk_loc, /obj))
var/obj/O = disk_loc
dat += "in \a [O.name] "
disk_loc = disk_loc.loc
dat += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z]) |
"
dat += "
"
- dat += get_additional_check_antag_output(caller)
+ dat += get_additional_check_antag_output(requester)
dat += "
"
return dat
//Overridden elsewhere.
-/datum/antagonist/proc/get_additional_check_antag_output(var/datum/admins/caller)
+/datum/antagonist/proc/get_additional_check_antag_output(var/datum/admins/requester)
return ""
diff --git a/code/game/antagonist/antagonist_print.dm b/code/game/antagonist/antagonist_print.dm
index 830d4806f57..15ed54af49f 100644
--- a/code/game/antagonist/antagonist_print.dm
+++ b/code/game/antagonist/antagonist_print.dm
@@ -3,20 +3,21 @@
if(!current_antagonists.len)
return FALSE
- var/text = "
The [current_antagonists.len == 1 ? "[role_text] was" : "[role_text_plural] were"]:"
+ var/text = "
"
+ text += span_normal(span_bold("The [current_antagonists.len == 1 ? "[role_text] was" : "[role_text_plural] were"]:"))
for(var/datum/mind/P in current_antagonists)
text += print_player_full(P)
text += get_special_objective_text(P)
if(P.ambitions)
- text += "
Their goals for today were..."
- text += "
[P.ambitions]"
+ text += "
Their goals for today were...
"
+ text += span_notice("[P.ambitions]")
if(!global_objectives.len && P.objectives && P.objectives.len)
var/failed
var/num = 1
for(var/datum/objective/O in P.objectives)
text += print_objective(O, num)
if(O.check_completion())
- text += span_green("Success!")
+ text += span_green(span_bold("Success!"))
feedback_add_details(feedback_tag,"[O.type]|SUCCESS")
else
text += span_red("Fail.")
@@ -24,12 +25,13 @@
failed = TRUE
num++
if(failed)
- text += "
" + span_red("The [role_text] has failed.")
+ text += "
" + span_red(span_bold("The [role_text] has failed."))
else
- text += "
" + span_green("The [role_text] was successful!")
+ text += "
" + span_green(span_bold("The [role_text] was successful!"))
if(global_objectives && global_objectives.len)
- text += "
Their objectives were:"
+ text += "
"
+ text += span_normal("Their objectives were:")
var/num = 1
for(var/datum/objective/O in global_objectives)
text += print_objective(O, num, TRUE)
@@ -39,17 +41,17 @@
to_world(text)
/datum/antagonist/proc/print_objective(var/datum/objective/O, var/num, var/append_success)
- var/text = "
Objective [num]: [O.explanation_text] "
+ var/text = "
" + span_bold("Objective [num]:") + " [O.explanation_text] "
if(append_success)
if(O.check_completion())
- text += span_green("Success!")
+ text += span_green(span_bold("Success!"))
else
text += span_red("Fail.")
return text
/datum/antagonist/proc/print_player_lite(var/datum/mind/ply)
var/role = ply.assigned_role ? "\improper[ply.assigned_role]" : "\improper[ply.special_role]"
- var/text = "
[ply.name] ([ply.key]) as \a [role] ("
+ var/text = "
" + span_bold("[ply.name]") + " (" + span_bold("[ply.key]") + ") as \a " + span_bold("[role]") + " ("
if(ply.current)
if(ply.current.stat == DEAD)
text += "died"
@@ -58,7 +60,7 @@
else
text += "survived"
if(ply.current.real_name != ply.name)
- text += " as [ply.current.real_name]"
+ text += " as " + span_bold("[ply.current.real_name]")
else
text += "body destroyed"
text += ")"
diff --git a/code/game/antagonist/antagonist_update.dm b/code/game/antagonist/antagonist_update.dm
index b118cb91db8..e93e1e4c401 100644
--- a/code/game/antagonist/antagonist_update.dm
+++ b/code/game/antagonist/antagonist_update.dm
@@ -19,7 +19,7 @@
return player.current
/datum/antagonist/proc/update_access(var/mob/living/player)
- for(var/obj/item/weapon/card/id/id in player.contents)
+ for(var/obj/item/card/id/id in player.contents)
player.set_id_info(id)
/datum/antagonist/proc/clear_indicators(var/datum/mind/recipient)
diff --git a/code/game/antagonist/mutiny/mutineer.dm b/code/game/antagonist/mutiny/mutineer.dm
index 85aecd71ea6..28871a32e22 100644
--- a/code/game/antagonist/mutiny/mutineer.dm
+++ b/code/game/antagonist/mutiny/mutineer.dm
@@ -6,7 +6,7 @@ var/datum/antagonist/mutineer/mutineers
role_text_plural = "Mutineers"
id = MODE_MUTINEER
antag_indicator = "mutineer"
- restricted_jobs = list("Site Manager")
+ restricted_jobs = list(JOB_SITE_MANAGER)
/datum/antagonist/mutineer/New(var/no_reference)
..()
@@ -27,7 +27,7 @@ var/datum/antagonist/mutineer/mutineers
/*
var/list/directive_candidates = get_directive_candidates()
if(!directive_candidates || directive_candidates.len == 0)
- to_world("Mutiny mode aborted: no valid candidates for Directive X.")
+ to_world(span_warning("Mutiny mode aborted: no valid candidates for Directive X."))
return 0
head_loyalist = pick(loyalist_candidates)
@@ -39,7 +39,7 @@ var/datum/antagonist/mutineer/mutineers
proc/get_head_loyalist_candidates()
var/list/candidates[0]
for(var/mob/loyalist in player_list)
- if(loyalist.mind && loyalist.mind.assigned_role == "Site Manager")
+ if(loyalist.mind && loyalist.mind.assigned_role == JOB_SITE_MANAGER)
candidates.Add(loyalist.mind)
return candidates
@@ -47,7 +47,7 @@ var/datum/antagonist/mutineer/mutineers
var/list/candidates[0]
for(var/mob/mutineer in player_list)
if(mutineer.client.prefs.be_special & BE_MUTINEER)
- for(var/job in command_positions - "Site Manager")
+ for(var/job in command_positions - JOB_SITE_MANAGER)
if(mutineer.mind && mutineer.mind.assigned_role == job)
candidates.Add(mutineer.mind)
return candidates
diff --git a/code/game/antagonist/outsider/commando.dm b/code/game/antagonist/outsider/commando.dm
index b7bd756c97a..d0acbf61e73 100644
--- a/code/game/antagonist/outsider/commando.dm
+++ b/code/game/antagonist/outsider/commando.dm
@@ -7,7 +7,7 @@ var/datum/antagonist/deathsquad/mercenary/commandos
role_text_plural = "Commandos"
welcome_text = "You are in the employ of a criminal syndicate hostile to corporate interests."
antag_sound = 'sound/effects/antag_notice/deathsquid_alert.ogg'
- id_type = /obj/item/weapon/card/id/centcom/ERT
+ id_type = /obj/item/card/id/centcom/ERT
hard_cap = 4
hard_cap_round = 8
@@ -22,15 +22,15 @@ var/datum/antagonist/deathsquad/mercenary/commandos
/datum/antagonist/deathsquad/mercenary/equip(var/mob/living/carbon/human/player)
player.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(player), slot_w_uniform)
- player.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/silenced(player), slot_belt)
+ player.equip_to_slot_or_del(new /obj/item/gun/projectile/silenced(player), slot_belt)
player.equip_to_slot_or_del(new /obj/item/clothing/shoes/boots/swat(player), slot_shoes)
player.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(player), slot_gloves)
player.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(player), slot_glasses)
player.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/syndicate(player), slot_wear_mask)
- player.equip_to_slot_or_del(new /obj/item/weapon/storage/box(player), slot_in_backpack)
+ player.equip_to_slot_or_del(new /obj/item/storage/box(player), slot_in_backpack)
player.equip_to_slot_or_del(new /obj/item/ammo_magazine/clip/c45(player), slot_in_backpack)
- player.equip_to_slot_or_del(new /obj/item/weapon/rig/merc(player), slot_back)
- player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand)
+ player.equip_to_slot_or_del(new /obj/item/rig/merc(player), slot_back)
+ player.equip_to_slot_or_del(new /obj/item/gun/energy/pulse_rifle(player), slot_r_hand)
create_id("Commando", player)
create_radio(SYND_FREQ, player)
diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm
index 01b579b7de3..54ab78dd360 100644
--- a/code/game/antagonist/outsider/deathsquad.dm
+++ b/code/game/antagonist/outsider/deathsquad.dm
@@ -42,17 +42,17 @@ var/datum/antagonist/deathsquad/deathsquad
player.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal(player), slot_glasses)
player.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat(player), slot_wear_mask)
if (player.mind == leader)
- player.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(player), slot_l_store)
- player.equip_to_slot_or_del(new /obj/item/weapon/disk/nuclear(player), slot_r_store)
+ player.equip_to_slot_or_del(new /obj/item/pinpointer(player), slot_l_store)
+ player.equip_to_slot_or_del(new /obj/item/disk/nuclear(player), slot_r_store)
else
- player.equip_to_slot_or_del(new /obj/item/weapon/plastique(player), slot_l_store)
- player.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(player), slot_belt)
- player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand)
- player.equip_to_slot_or_del(new /obj/item/weapon/rig/ert/assetprotection(player), slot_back)
- player.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(player), slot_s_store)
+ player.equip_to_slot_or_del(new /obj/item/plastique(player), slot_l_store)
+ player.equip_to_slot_or_del(new /obj/item/gun/projectile/revolver/mateba(player), slot_belt)
+ player.equip_to_slot_or_del(new /obj/item/gun/energy/pulse_rifle(player), slot_r_hand)
+ player.equip_to_slot_or_del(new /obj/item/rig/ert/assetprotection(player), slot_back)
+ player.equip_to_slot_or_del(new /obj/item/melee/energy/sword(player), slot_s_store)
// player.implant_loyalty()
- var/obj/item/weapon/card/id/id = create_id("Asset Protection", player)
+ var/obj/item/card/id/id = create_id("Asset Protection", player)
if(id)
id.access |= get_all_station_access()
id.icon_state = "centcom"
diff --git a/code/game/antagonist/outsider/ert.dm b/code/game/antagonist/outsider/ert.dm
index f1d1aeee4f3..c9048f107e3 100644
--- a/code/game/antagonist/outsider/ert.dm
+++ b/code/game/antagonist/outsider/ert.dm
@@ -2,21 +2,21 @@ var/datum/antagonist/ert/ert
/datum/antagonist/ert
id = MODE_ERT
- bantype = "Emergency Response Team"
+ bantype = JOB_EMERGENCY_RESPONSE_TEAM
role_type = BE_OPERATIVE
role_text = "Emergency Responder"
role_text_plural = "Emergency Responders"
welcome_text = "As member of the Emergency Response Team, you answer only to your leader and company officials."
antag_sound = 'sound/effects/antag_notice/general_goodie_alert.ogg'
- antag_text = "You are an anti antagonist! Within the rules, \
+ antag_text = "You are an " + span_bold("anti") + " antagonist! Within the rules, \
try to save the station and its inhabitants from the ongoing crisis. \
- Try to make sure other players have fun! If you are confused or at a loss, always adminhelp, \
+ Try to make sure other players have " + span_italics("fun") + "! If you are confused or at a loss, always adminhelp, \
and before taking extreme actions, please try to also contact the administration! \
- Think through your actions and make the roleplay immersive! Please remember all \
- rules aside from those without explicit exceptions apply to the ERT."
- leader_welcome_text = "As leader of the Emergency Response Team, you answer only to the Company, and have authority to override the Site Manager where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the Site Manager where possible, however."
+ Think through your actions and make the roleplay immersive! " + span_bold("Please remember all \
+ rules aside from those without explicit exceptions apply to the ERT.")
+ leader_welcome_text = "As leader of the Emergency Response Team, you answer only to the Company, and have authority to override the " + JOB_SITE_MANAGER + " where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the " + JOB_SITE_MANAGER + " where possible, however."
landmark_id = "Response Team"
- id_type = /obj/item/weapon/card/id/centcom/ERT
+ id_type = /obj/item/card/id/centcom/ERT
flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER | ANTAG_CHOOSE_NAME
antaghud_indicator = "hudloyalist"
@@ -46,7 +46,7 @@ var/datum/antagonist/ert/ert
/datum/antagonist/ert/equip(var/mob/living/carbon/human/player)
//Special radio setup
- player.equip_to_slot_or_del(new /obj/item/device/radio/headset/ert(src), slot_l_ear)
+ player.equip_to_slot_or_del(new /obj/item/radio/headset/ert(src), slot_l_ear)
player.equip_to_slot_or_del(new /obj/item/clothing/under/ert(src), slot_w_uniform)
player.equip_to_slot_or_del(new /obj/item/clothing/shoes/boots/swat(src), slot_shoes)
player.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(src), slot_gloves)
diff --git a/code/game/antagonist/outsider/mercenary.dm b/code/game/antagonist/outsider/mercenary.dm
index 623291dde7d..47f2cd85bcc 100644
--- a/code/game/antagonist/outsider/mercenary.dm
+++ b/code/game/antagonist/outsider/mercenary.dm
@@ -11,7 +11,7 @@ var/datum/antagonist/mercenary/mercs
leader_welcome_text = "You are the leader of the mercenary strikeforce; hail to the chief. Use :t to speak to your underlings."
welcome_text = "To speak on the strike team's private channel use :t."
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_HAS_NUKE | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER
- id_type = /obj/item/weapon/card/id/syndicate
+ id_type = /obj/item/card/id/syndicate
antaghud_indicator = "hudoperative"
hard_cap = 4
@@ -38,17 +38,17 @@ var/datum/antagonist/mercenary/mercs
player.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(player), slot_w_uniform)
player.equip_to_slot_or_del(new /obj/item/clothing/shoes/boots/swat(player), slot_shoes)
player.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(player), slot_gloves)
- if(player.backbag == 2) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(player), slot_back)
- if(player.backbag == 3) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(player), slot_back)
- if(player.backbag == 4) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(player), slot_back)
- if(player.backbag == 5) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(player), slot_back)
- if(player.backbag == 6) player.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/sport(player), slot_back)
- player.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(player), slot_in_backpack)
+ if(player.backbag == 2) player.equip_to_slot_or_del(new /obj/item/storage/backpack(player), slot_back)
+ if(player.backbag == 3) player.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel/norm(player), slot_back)
+ if(player.backbag == 4) player.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(player), slot_back)
+ if(player.backbag == 5) player.equip_to_slot_or_del(new /obj/item/storage/backpack/messenger(player), slot_back)
+ if(player.backbag == 6) player.equip_to_slot_or_del(new /obj/item/storage/backpack/sport(player), slot_back)
+ player.equip_to_slot_or_del(new /obj/item/reagent_containers/pill/cyanide(player), slot_in_backpack)
player.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
player.mind.accept_tcrystals = 1
- var/obj/item/device/radio/uplink/U = new(player.loc, player.mind, DEFAULT_TELECRYSTAL_AMOUNT)
+ var/obj/item/radio/uplink/U = new(player.loc, player.mind, DEFAULT_TELECRYSTAL_AMOUNT)
player.put_in_hands(U)
create_id("Mercenary", player)
diff --git a/code/game/antagonist/outsider/ninja.dm b/code/game/antagonist/outsider/ninja.dm
index 307abe35304..7df32b76aa5 100644
--- a/code/game/antagonist/outsider/ninja.dm
+++ b/code/game/antagonist/outsider/ninja.dm
@@ -7,7 +7,7 @@ var/datum/antagonist/ninja/ninjas
role_text_plural = "Ninja"
bantype = "ninja"
landmark_id = "ninjastart"
- welcome_text = "You are an elite mercenary assassin of the Spider Clan. You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor."
+ welcome_text = span_info("You are an elite mercenary assassin of the Spider Clan. You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor.")
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_RANDSPAWN | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE
antaghud_indicator = "hudninja"
@@ -16,14 +16,14 @@ var/datum/antagonist/ninja/ninjas
hard_cap = 1
hard_cap_round = 3
- id_type = /obj/item/weapon/card/id/syndicate
+ id_type = /obj/item/card/id/syndicate
/datum/antagonist/ninja/New()
..()
ninjas = src
/datum/antagonist/ninja/attempt_random_spawn()
- if(config.ninjas_allowed) ..()
+ if(CONFIG_GET(flag/ninjas_allowed)) ..()
/datum/antagonist/ninja/create_objectives(var/datum/mind/ninja)
@@ -85,8 +85,8 @@ var/datum/antagonist/ninja/ninjas
if(!..())
return 0
var/directive = generate_ninja_directive("heel")
- player.store_memory("Directive: [directive]
")
- to_chat(player, "Remember your directive: [directive].")
+ player.store_memory(span_bold("Directive:") + " " + span_danger("[directive]") + "
")
+ to_chat(player, span_bold("Remember your directive:") + " [directive].")
/datum/antagonist/ninja/update_antag_mob(var/datum/mind/player)
..()
@@ -103,13 +103,13 @@ var/datum/antagonist/ninja/ninjas
if(!..())
return 0
- var/obj/item/device/radio/R = new /obj/item/device/radio/headset(player)
+ var/obj/item/radio/R = new /obj/item/radio/headset(player)
player.equip_to_slot_or_del(R, slot_l_ear)
player.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(player), slot_w_uniform)
- player.equip_to_slot_or_del(new /obj/item/device/flashlight(player), slot_belt)
+ player.equip_to_slot_or_del(new /obj/item/flashlight(player), slot_belt)
create_id("Infiltrator", player)
- var/obj/item/weapon/rig/light/ninja/ninjasuit = new(get_turf(player))
+ var/obj/item/rig/light/ninja/ninjasuit = new(get_turf(player))
ninjasuit.seal_delay = 0
player.put_in_hands(ninjasuit)
player.equip_to_slot_or_del(ninjasuit,slot_back)
@@ -117,8 +117,8 @@ var/datum/antagonist/ninja/ninjas
ninjasuit.toggle_seals(src,1)
ninjasuit.seal_delay = initial(ninjasuit.seal_delay)
- if(istype(player.back,/obj/item/weapon/rig))
- var/obj/item/weapon/rig/rig = player.back
+ if(istype(player.back,/obj/item/rig))
+ var/obj/item/rig/rig = player.back
if(rig.air_supply)
player.internal = rig.air_supply
@@ -126,7 +126,7 @@ var/datum/antagonist/ninja/ninjas
if(player.internal)
player.internals.icon_state = "internal1"
else
- to_chat(player, "You forgot to turn on your internals! Quickly, toggle the valve!")
+ to_chat(player, span_danger("You forgot to turn on your internals! Quickly, toggle the valve!"))
/datum/antagonist/ninja/proc/generate_ninja_directive(side)
var/directive = "[side=="face"?"[using_map.company_name]":"A criminal syndicate"] is your employer. "//Let them know which side they're on.
@@ -161,7 +161,7 @@ var/datum/antagonist/ninja/ninjas
var/xenorace = pick(SPECIES_UNATHI, SPECIES_TAJ, SPECIES_SKRELL)
directive += "A group of [xenorace] radicals have been loyal supporters of the Spider Clan. Favor [xenorace] crew whenever possible."
if(15)
- directive += "The Spider Clan has recently been accused of religious insensitivity. Attempt to speak with the Chaplain and prove these accusations false."
+ directive += "The Spider Clan has recently been accused of religious insensitivity. Attempt to speak with the " + JOB_CHAPLAIN + " and prove these accusations false."
if(16)
directive += "The Spider Clan has been bargaining with a competing prosthetics manufacturer. Try to shine [using_map.company_name] prosthetics in a bad light."
if(17)
diff --git a/code/game/antagonist/outsider/raider.dm b/code/game/antagonist/outsider/raider.dm
index 59faa2de85d..afdc49d2114 100644
--- a/code/game/antagonist/outsider/raider.dm
+++ b/code/game/antagonist/outsider/raider.dm
@@ -17,7 +17,7 @@ var/datum/antagonist/raider/raiders
initial_spawn_req = 3
initial_spawn_target = 3
- id_type = /obj/item/weapon/card/id/syndicate
+ id_type = /obj/item/card/id/syndicate
// Heist overrides check_victory() and doesn't need victory or loss strings/tags.
var/list/raider_uniforms = list(
@@ -64,40 +64,40 @@ var/datum/antagonist/raider/raiders
)
var/list/raider_guns = list(
- /obj/item/weapon/gun/energy/laser,
- /obj/item/weapon/gun/energy/retro,
- /obj/item/weapon/gun/energy/xray,
- /obj/item/weapon/gun/energy/mindflayer,
- /obj/item/weapon/gun/energy/toxgun,
- /obj/item/weapon/gun/energy/stunrevolver,
- /obj/item/weapon/gun/energy/stunrevolver/vintage,
- /obj/item/weapon/gun/energy/ionrifle,
- /obj/item/weapon/gun/energy/taser,
- /obj/item/weapon/gun/energy/crossbow/largecrossbow,
- /obj/item/weapon/gun/launcher/crossbow,
- /obj/item/weapon/gun/launcher/grenade,
- /obj/item/weapon/gun/launcher/pneumatic,
- /obj/item/weapon/gun/projectile/automatic/mini_uzi,
- /obj/item/weapon/gun/projectile/automatic/c20r,
- /obj/item/weapon/gun/projectile/automatic/wt550,
- /obj/item/weapon/gun/projectile/automatic/sts35,
- /obj/item/weapon/gun/projectile/automatic/bullpup,
- /obj/item/weapon/gun/projectile/automatic/tommygun,
- /obj/item/weapon/gun/projectile/silenced,
- /obj/item/weapon/gun/projectile/shotgun/pump,
- /obj/item/weapon/gun/projectile/shotgun/pump/combat,
- /obj/item/weapon/gun/projectile/shotgun/pump/rifle,
- /obj/item/weapon/gun/projectile/shotgun/doublebarrel,
- /obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet,
- /obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn,
- /obj/item/weapon/gun/projectile/colt/detective,
- /obj/item/weapon/gun/projectile/pistol,
- /obj/item/weapon/gun/projectile/p92x,
- /obj/item/weapon/gun/projectile/revolver,
- /obj/item/weapon/gun/projectile/pirate,
- /obj/item/weapon/gun/projectile/revolver/judge,
- list(/obj/item/weapon/gun/projectile/luger,/obj/item/weapon/gun/projectile/luger/brown),
- list(/obj/item/weapon/gun/projectile/deagle, /obj/item/weapon/gun/projectile/deagle/gold, /obj/item/weapon/gun/projectile/deagle/camo)
+ /obj/item/gun/energy/laser,
+ /obj/item/gun/energy/retro,
+ /obj/item/gun/energy/xray,
+ /obj/item/gun/energy/mindflayer,
+ /obj/item/gun/energy/toxgun,
+ /obj/item/gun/energy/stunrevolver,
+ /obj/item/gun/energy/stunrevolver/vintage,
+ /obj/item/gun/energy/ionrifle,
+ /obj/item/gun/energy/taser,
+ /obj/item/gun/energy/crossbow/largecrossbow,
+ /obj/item/gun/launcher/crossbow,
+ /obj/item/gun/launcher/grenade,
+ /obj/item/gun/launcher/pneumatic,
+ /obj/item/gun/projectile/automatic/mini_uzi,
+ /obj/item/gun/projectile/automatic/c20r,
+ /obj/item/gun/projectile/automatic/wt550,
+ /obj/item/gun/projectile/automatic/sts35,
+ /obj/item/gun/projectile/automatic/bullpup,
+ /obj/item/gun/projectile/automatic/tommygun,
+ /obj/item/gun/projectile/silenced,
+ /obj/item/gun/projectile/shotgun/pump,
+ /obj/item/gun/projectile/shotgun/pump/combat,
+ /obj/item/gun/projectile/shotgun/pump/rifle,
+ /obj/item/gun/projectile/shotgun/doublebarrel,
+ /obj/item/gun/projectile/shotgun/doublebarrel/pellet,
+ /obj/item/gun/projectile/shotgun/doublebarrel/sawn,
+ /obj/item/gun/projectile/colt/detective,
+ /obj/item/gun/projectile/pistol,
+ /obj/item/gun/projectile/p92x,
+ /obj/item/gun/projectile/revolver,
+ /obj/item/gun/projectile/pirate,
+ /obj/item/gun/projectile/revolver/judge,
+ list(/obj/item/gun/projectile/luger,/obj/item/gun/projectile/luger/brown),
+ list(/obj/item/gun/projectile/deagle, /obj/item/gun/projectile/deagle/gold, /obj/item/gun/projectile/deagle/camo)
)
var/list/raider_holster = list(
@@ -111,8 +111,8 @@ var/datum/antagonist/raider/raiders
raiders = src
/datum/antagonist/raider/update_access(var/mob/living/player)
- for(var/obj/item/weapon/storage/wallet/W in player.contents)
- for(var/obj/item/weapon/card/id/id in W.contents)
+ for(var/obj/item/storage/wallet/W in player.contents)
+ for(var/obj/item/card/id/id in W.contents)
id.name = "[player.real_name]'s Passport"
id.registered_name = player.real_name
W.name = "[initial(W.name)] ([id.name])"
@@ -152,7 +152,7 @@ var/datum/antagonist/raider/raiders
var/win_msg = ""
//No objectives, go straight to the feedback.
- if(config.objectives_disabled || !global_objectives.len)
+ if(CONFIG_GET(flag/objectives_disabled) || !global_objectives.len)
return
var/success = global_objectives.len
@@ -173,22 +173,22 @@ var/datum/antagonist/raider/raiders
if(antags_are_dead())
win_type = "Major"
win_group = "Crew"
- win_msg += "The Raiders have been wiped out!"
+ win_msg += span_bold("The Raiders have been wiped out!")
else if(is_raider_crew_safe())
if(win_group == "Crew" && win_type == "Minor")
win_type = "Major"
win_group = "Crew"
- win_msg += "The Raiders have left someone behind!"
+ win_msg += span_bold("The Raiders have left someone behind!")
else
if(win_group == "Raider")
if(win_type == "Minor")
win_type = "Major"
- win_msg += "The Raiders escaped the station!"
+ win_msg += span_bold("The Raiders escaped the station!")
else
- win_msg += "The Raiders were repelled!"
+ win_msg += span_bold("The Raiders were repelled!")
- to_world("[win_type] [win_group] victory!")
- to_world("[win_msg]")
+ to_world(span_boldannounce(span_large("[win_type] [win_group] victory!")))
+ to_world(span_filter_system("[win_msg]"))
feedback_set_details("round_end_result","heist - [win_type] [win_group]")
/datum/antagonist/raider/proc/is_raider_crew_safe()
@@ -227,10 +227,10 @@ var/datum/antagonist/raider/raiders
player.equip_to_slot_or_del(new new_suit(player),slot_wear_suit)
equip_weapons(player)
- var/obj/item/weapon/card/id/id = create_id("Visitor", player, equip = 0)
+ var/obj/item/card/id/id = create_id(JOB_ALT_VISITOR, player, equip = 0)
id.name = "[player.real_name]'s Passport"
- id.assignment = "Visitor"
- var/obj/item/weapon/storage/wallet/W = new(player)
+ id.assignment = JOB_ALT_VISITOR
+ var/obj/item/storage/wallet/W = new(player)
W.handle_item_insertion(id)
player.equip_to_slot_or_del(W, slot_wear_id)
spawn_money(rand(50,150)*10,W)
@@ -248,7 +248,7 @@ var/datum/antagonist/raider/raiders
//Give some of the raiders a pirate gun as a secondary
if(prob(60))
- var/obj/item/secondary = new /obj/item/weapon/gun/projectile/pirate(T)
+ var/obj/item/secondary = new /obj/item/gun/projectile/pirate(T)
if(!(primary.slot_flags & SLOT_HOLSTER))
holster = new new_holster(T)
holster.holstered = secondary
@@ -277,26 +277,26 @@ var/datum/antagonist/raider/raiders
else
player.put_in_any_hand_if_possible(holster)
-/datum/antagonist/raider/proc/equip_ammo(var/mob/living/carbon/human/player, var/obj/item/weapon/gun/gun)
- if(istype(gun, /obj/item/weapon/gun/projectile))
- var/obj/item/weapon/gun/projectile/bullet_thrower = gun
+/datum/antagonist/raider/proc/equip_ammo(var/mob/living/carbon/human/player, var/obj/item/gun/gun)
+ if(istype(gun, /obj/item/gun/projectile))
+ var/obj/item/gun/projectile/bullet_thrower = gun
if(bullet_thrower.magazine_type)
player.equip_to_slot_or_del(new bullet_thrower.magazine_type(player), slot_l_store)
if(prob(20)) //don't want to give them too much
player.equip_to_slot_or_del(new bullet_thrower.magazine_type(player), slot_r_store)
else if(bullet_thrower.ammo_type)
- var/obj/item/weapon/storage/box/ammobox = new(get_turf(player.loc))
+ var/obj/item/storage/box/ammobox = new(get_turf(player.loc))
for(var/i in 1 to rand(3,5) + rand(0,2))
new bullet_thrower.ammo_type(ammobox)
player.put_in_any_hand_if_possible(ammobox)
return
- if(istype(gun, /obj/item/weapon/gun/launcher/grenade))
+ if(istype(gun, /obj/item/gun/launcher/grenade))
var/list/grenades = list(
- /obj/item/weapon/grenade/empgrenade,
- /obj/item/weapon/grenade/smokebomb,
- /obj/item/weapon/grenade/flashbang
+ /obj/item/grenade/empgrenade,
+ /obj/item/grenade/smokebomb,
+ /obj/item/grenade/flashbang
)
- var/obj/item/weapon/storage/box/ammobox = new(get_turf(player.loc))
+ var/obj/item/storage/box/ammobox = new(get_turf(player.loc))
for(var/i in 1 to 7)
var/grenade_type = pick(grenades)
new grenade_type(ammobox)
@@ -310,11 +310,11 @@ var/datum/antagonist/raider/raiders
player.equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(player), slot_shoes) // REPLACE THESE WITH CODED VOX ALTERNATIVES.
player.equip_to_slot_or_del(new /obj/item/clothing/gloves/vox(player), slot_gloves) // AS ABOVE.
player.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/swat/vox(player), slot_wear_mask)
- player.equip_to_slot_or_del(new /obj/item/weapon/tank/vox(player), slot_back)
- player.equip_to_slot_or_del(new /obj/item/device/flashlight(player), slot_r_store)
+ player.equip_to_slot_or_del(new /obj/item/tank/vox(player), slot_back)
+ player.equip_to_slot_or_del(new /obj/item/flashlight(player), slot_r_store)
- player.internal = locate(/obj/item/weapon/tank) in player.contents
- if(istype(player.internal,/obj/item/weapon/tank) && player.internals)
+ player.internal = locate(/obj/item/tank) in player.contents
+ if(istype(player.internal,/obj/item/tank) && player.internals)
player.internals.icon_state = "internal1"
return 1
diff --git a/code/game/antagonist/outsider/shipwreck_survivor.dm b/code/game/antagonist/outsider/shipwreck_survivor.dm
index 6fdcc47b971..19f8e8d4ccf 100644
--- a/code/game/antagonist/outsider/shipwreck_survivor.dm
+++ b/code/game/antagonist/outsider/shipwreck_survivor.dm
@@ -30,7 +30,7 @@ var/datum/antagonist/shipwreck_survivor/survivors
can_hear_aooc = FALSE
/datum/antagonist/SURVIVOR/greet(var/datum/mind/player)
- to_chat(player.current, SPAN_WARNING("You are a NOT an antagonist! All rules apply to you as well. Your job is to help make the world seem more alive. \n \
+ to_chat(player.current, span_warning("You are a NOT an antagonist! All rules apply to you as well. Your job is to help make the world seem more alive. \n \
You are not an existing station character, but some average person who has suffered a terrible accident. \
Feel free to make up what happened to the ship you awakened on as you please, \
but listening to your rescuers for context might help improve your mutual immersion! \n \
diff --git a/code/game/antagonist/outsider/technomancer.dm b/code/game/antagonist/outsider/technomancer.dm
index 579e5631d75..976aa4f7621 100644
--- a/code/game/antagonist/outsider/technomancer.dm
+++ b/code/game/antagonist/outsider/technomancer.dm
@@ -5,8 +5,8 @@ var/datum/antagonist/technomancer/technomancers
role_type = BE_WIZARD
role_text = "Technomancer"
role_text_plural = "Technomancers"
- bantype = "wizard"
- landmark_id = "wizard"
+ bantype = JOB_WIZARD
+ landmark_id = JOB_WIZARD
welcome_text = "You will need to purchase functions and perhaps some equipment from the various machines around your \
base. Choose your technological arsenal carefully. Remember that without the core on your back, your functions are \
powerless, and therefore you will be as well.
\
@@ -20,7 +20,7 @@ var/datum/antagonist/technomancer/technomancers
initial_spawn_req = 1
initial_spawn_target = 1
- id_type = /obj/item/weapon/card/id/syndicate
+ id_type = /obj/item/card/id/syndicate
/datum/antagonist/technomancer/New()
..()
@@ -28,7 +28,7 @@ var/datum/antagonist/technomancer/technomancers
/datum/antagonist/technomancer/update_antag_mob(var/datum/mind/technomancer)
..()
- technomancer.store_memory("Remember: Do not forget to purchase the functions and equipment you need.")
+ technomancer.store_memory(span_bold("Remember:") + " Do not forget to purchase the functions and equipment you need.")
technomancer.current.real_name = "[pick(wizard_first)] [pick(wizard_second)]"
technomancer.current.name = technomancer.current.real_name
@@ -39,13 +39,13 @@ var/datum/antagonist/technomancer/technomancers
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/under/technomancer/master(technomancer_mob), slot_w_uniform)
create_id("Technomagus", technomancer_mob)
- technomancer_mob.equip_to_slot_or_del(new /obj/item/weapon/disposable_teleporter/free(technomancer_mob), slot_r_store)
- technomancer_mob.equip_to_slot_or_del(new /obj/item/weapon/technomancer_catalog(technomancer_mob), slot_l_store)
- technomancer_mob.equip_to_slot_or_del(new /obj/item/device/radio/headset(technomancer_mob), slot_l_ear)
- var/obj/item/weapon/technomancer_core/core = new /obj/item/weapon/technomancer_core(technomancer_mob)
+ technomancer_mob.equip_to_slot_or_del(new /obj/item/disposable_teleporter/free(technomancer_mob), slot_r_store)
+ technomancer_mob.equip_to_slot_or_del(new /obj/item/technomancer_catalog(technomancer_mob), slot_l_store)
+ technomancer_mob.equip_to_slot_or_del(new /obj/item/radio/headset(technomancer_mob), slot_l_ear)
+ var/obj/item/technomancer_core/core = new /obj/item/technomancer_core(technomancer_mob)
technomancer_mob.equip_to_slot_or_del(core, slot_back)
technomancer_belongings.Add(core) // So it can be Tracked.
- technomancer_mob.equip_to_slot_or_del(new /obj/item/device/flashlight(technomancer_mob), slot_belt)
+ technomancer_mob.equip_to_slot_or_del(new /obj/item/flashlight(technomancer_mob), slot_belt)
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(technomancer_mob), slot_shoes)
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/head/technomancer/master(technomancer_mob), slot_head)
return 1
@@ -54,17 +54,17 @@ var/datum/antagonist/technomancer/technomancers
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/under/technomancer/apprentice(technomancer_mob), slot_w_uniform)
create_id("Techno-apprentice", technomancer_mob)
- technomancer_mob.equip_to_slot_or_del(new /obj/item/weapon/disposable_teleporter/free(technomancer_mob), slot_r_store)
+ technomancer_mob.equip_to_slot_or_del(new /obj/item/disposable_teleporter/free(technomancer_mob), slot_r_store)
- var/obj/item/weapon/technomancer_catalog/apprentice/catalog = new /obj/item/weapon/technomancer_catalog/apprentice()
+ var/obj/item/technomancer_catalog/apprentice/catalog = new /obj/item/technomancer_catalog/apprentice()
catalog.bind_to_owner(technomancer_mob)
technomancer_mob.equip_to_slot_or_del(catalog, slot_l_store)
- technomancer_mob.equip_to_slot_or_del(new /obj/item/device/radio/headset(technomancer_mob), slot_l_ear)
- var/obj/item/weapon/technomancer_core/core = new /obj/item/weapon/technomancer_core(technomancer_mob)
+ technomancer_mob.equip_to_slot_or_del(new /obj/item/radio/headset(technomancer_mob), slot_l_ear)
+ var/obj/item/technomancer_core/core = new /obj/item/technomancer_core(technomancer_mob)
technomancer_mob.equip_to_slot_or_del(core, slot_back)
technomancer_belongings.Add(core) // So it can be Tracked.
- technomancer_mob.equip_to_slot_or_del(new /obj/item/device/flashlight(technomancer_mob), slot_belt)
+ technomancer_mob.equip_to_slot_or_del(new /obj/item/flashlight(technomancer_mob), slot_belt)
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/laceup(technomancer_mob), slot_shoes)
technomancer_mob.equip_to_slot_or_del(new /obj/item/clothing/head/technomancer/apprentice(technomancer_mob), slot_head)
return 1
@@ -78,21 +78,21 @@ var/datum/antagonist/technomancer/technomancers
break
if(!survivor)
feedback_set_details("round_end_result","loss - technomancer killed")
- to_world("The [(current_antagonists.len>1)?"[role_text_plural] have":"[role_text] has"] been killed!")
+ to_world(span_boldannounce(span_large("The [(current_antagonists.len>1)?"[role_text_plural] have":"[role_text] has"] been killed!")))
/datum/antagonist/technomancer/print_player_summary()
..()
- for(var/obj/item/weapon/technomancer_core/core in technomancer_belongings)
+ for(var/obj/item/technomancer_core/core in technomancer_belongings)
if(core.wearer)
continue // Only want abandoned cores.
if(!core.spells.len)
continue // Cores containing spells only.
- to_world("Abandoned [core] had [english_list(core.spells)].
")
+ to_world(span_filter_system("Abandoned [core] had [english_list(core.spells)].
"))
/datum/antagonist/technomancer/print_player_full(var/datum/mind/player)
var/text = print_player_lite(player)
- var/obj/item/weapon/technomancer_core/core
+ var/obj/item/technomancer_core/core
if(player.original)
core = locate() in player.original
if(core)
diff --git a/code/game/antagonist/outsider/trader.dm b/code/game/antagonist/outsider/trader.dm
index 07cfb6f9e98..9f09d492aac 100644
--- a/code/game/antagonist/outsider/trader.dm
+++ b/code/game/antagonist/outsider/trader.dm
@@ -16,7 +16,7 @@ var/datum/antagonist/trader/traders
leader_welcome_text = "As Captain of the Beruang, you have control over your crew and cargo. It may be worth briefly discussing a consistent shared backstory with your crew."
landmark_id = "Trader"
- id_type = /obj/item/weapon/card/id/external
+ id_type = /obj/item/card/id/external
flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER | ANTAG_CHOOSE_NAME
@@ -49,11 +49,11 @@ var/datum/antagonist/trader/traders
create_radio(PUB_FREQ, player) //Assume they tune their headsets into the station's public radio as they approach
- var/obj/item/weapon/card/id/id = create_id("Trader", player, equip = 0)
+ var/obj/item/card/id/id = create_id("Trader", player, equip = 0)
id.name = "[player.real_name]'s Passport"
id.assignment = "Trader"
id.access |= access_trader
- var/obj/item/weapon/storage/wallet/W = new(player)
+ var/obj/item/storage/wallet/W = new(player)
W.handle_item_insertion(id)
player.equip_to_slot_or_del(W, slot_wear_id)
spawn_money(rand(50,150)*10,W)
@@ -61,8 +61,8 @@ var/datum/antagonist/trader/traders
return 1
/datum/antagonist/trader/update_access(var/mob/living/player)
- for(var/obj/item/weapon/storage/wallet/W in player.contents)
- for(var/obj/item/weapon/card/id/id in W.contents)
+ for(var/obj/item/storage/wallet/W in player.contents)
+ for(var/obj/item/card/id/id in W.contents)
id.name = "[player.real_name]'s Passport"
id.registered_name = player.real_name
W.name = "[initial(W.name)] ([id.name])"
\ No newline at end of file
diff --git a/code/game/antagonist/outsider/wizard.dm b/code/game/antagonist/outsider/wizard.dm
index 0fcded12c6d..86d93cbc1a3 100644
--- a/code/game/antagonist/outsider/wizard.dm
+++ b/code/game/antagonist/outsider/wizard.dm
@@ -5,8 +5,8 @@ var/datum/antagonist/wizard/wizards
role_type = BE_WIZARD
role_text = "Space Wizard"
role_text_plural = "Space Wizards"
- bantype = "wizard"
- landmark_id = "wizard"
+ bantype = JOB_WIZARD
+ landmark_id = JOB_WIZARD
welcome_text = "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.
In your pockets you will find a teleport scroll. Use it as needed."
flags = ANTAG_OVERRIDE_JOB | ANTAG_CLEAR_EQUIPMENT | ANTAG_CHOOSE_NAME | ANTAG_VOTABLE | ANTAG_SET_APPEARANCE
antaghud_indicator = "hudwizard"
@@ -66,7 +66,7 @@ var/datum/antagonist/wizard/wizards
/datum/antagonist/wizard/update_antag_mob(var/datum/mind/wizard)
..()
- wizard.store_memory("Remember: do not forget to prepare your spells.")
+ wizard.store_memory(span_bold("Remember:") + " do not forget to prepare your spells.")
wizard.current.real_name = "[pick(wizard_first)] [pick(wizard_second)]"
wizard.current.name = wizard.current.real_name
@@ -75,19 +75,19 @@ var/datum/antagonist/wizard/wizards
if(!..())
return 0
- wizard_mob.equip_to_slot_or_del(new /obj/item/device/radio/headset(wizard_mob), slot_l_ear)
+ wizard_mob.equip_to_slot_or_del(new /obj/item/radio/headset(wizard_mob), slot_l_ear)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(wizard_mob), slot_w_uniform)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head)
- if(wizard_mob.backbag == 2) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(wizard_mob), slot_back)
- if(wizard_mob.backbag == 3) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel/norm(wizard_mob), slot_back)
- if(wizard_mob.backbag == 4) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(wizard_mob), slot_back)
- if(wizard_mob.backbag == 5) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/messenger(wizard_mob), slot_back)
- if(wizard_mob.backbag == 6) wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/sport(wizard_mob), slot_back)
- wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box(wizard_mob), slot_in_backpack)
- wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/teleportation_scroll(wizard_mob), slot_r_store)
- wizard_mob.equip_to_slot_or_del(new /obj/item/weapon/spellbook(wizard_mob), slot_r_hand)
+ if(wizard_mob.backbag == 2) wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack(wizard_mob), slot_back)
+ if(wizard_mob.backbag == 3) wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel/norm(wizard_mob), slot_back)
+ if(wizard_mob.backbag == 4) wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(wizard_mob), slot_back)
+ if(wizard_mob.backbag == 5) wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/messenger(wizard_mob), slot_back)
+ if(wizard_mob.backbag == 6) wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/sport(wizard_mob), slot_back)
+ wizard_mob.equip_to_slot_or_del(new /obj/item/storage/box(wizard_mob), slot_in_backpack)
+ wizard_mob.equip_to_slot_or_del(new /obj/item/teleportation_scroll(wizard_mob), slot_r_store)
+ wizard_mob.equip_to_slot_or_del(new /obj/item/spellbook(wizard_mob), slot_r_hand)
return 1
/datum/antagonist/wizard/check_victory()
@@ -99,7 +99,7 @@ var/datum/antagonist/wizard/wizards
break
if(!survivor)
feedback_set_details("round_end_result","loss - wizard killed")
- to_world("The [(current_antagonists.len>1)?"[role_text_plural] have":"[role_text] has"] been killed by the crew!")
+ to_world(span_boldannounce(span_large("The [(current_antagonists.len>1)?"[role_text_plural] have":"[role_text] has"] been killed by the crew!")))
//To batch-remove wizard spells. Linked to mind.dm.
/mob/proc/spellremove()
@@ -122,12 +122,12 @@ Made a proc so this is not repeated 14 (or more) times.*/
// Humans can wear clothes.
/mob/living/carbon/human/wearing_wiz_garb()
if(!is_wiz_garb(src.wear_suit))
- to_chat(src, "I don't feel strong enough without my robe.")
+ to_chat(src, span_warning("I don't feel strong enough without my robe."))
return 0
if(!is_wiz_garb(src.shoes))
- to_chat(src, "I don't feel strong enough without my sandals.")
+ to_chat(src, span_warning("I don't feel strong enough without my sandals."))
return 0
if(!is_wiz_garb(src.head))
- to_chat(src, "I don't feel strong enough without my hat.")
+ to_chat(src, span_warning("I don't feel strong enough without my hat."))
return 0
return 1
diff --git a/code/game/antagonist/station/changeling.dm b/code/game/antagonist/station/changeling.dm
index 2c1cb77f26b..e82fac7c8eb 100644
--- a/code/game/antagonist/station/changeling.dm
+++ b/code/game/antagonist/station/changeling.dm
@@ -6,7 +6,7 @@
bantype = "changeling"
feedback_tag = "changeling_objective"
avoid_silicons = TRUE
- protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Site Manager")
+ protected_jobs = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_DETECTIVE, JOB_HEAD_OF_SECURITY, JOB_SITE_MANAGER)
welcome_text = "Use say \"#g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them."
antag_sound = 'sound/effects/antag_notice/ling_alert.ogg'
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
diff --git a/code/game/antagonist/station/cultist.dm b/code/game/antagonist/station/cultist.dm
index 57271900b1c..95019c59687 100644
--- a/code/game/antagonist/station/cultist.dm
+++ b/code/game/antagonist/station/cultist.dm
@@ -11,10 +11,10 @@ var/datum/antagonist/cultist/cult
role_text = "Cultist"
role_text_plural = "Cultists"
bantype = "cultist"
- restricted_jobs = list("Chaplain")
+ restricted_jobs = list(JOB_CHAPLAIN)
avoid_silicons = TRUE
- protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Site Manager")
- roundstart_restricted = list("Internal Affairs Agent", "Head of Security", "Site Manager")
+ protected_jobs = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_DETECTIVE, JOB_INTERNAL_AFFAIRS_AGENT, JOB_HEAD_OF_SECURITY, JOB_SITE_MANAGER)
+ roundstart_restricted = list(JOB_INTERNAL_AFFAIRS_AGENT, JOB_HEAD_OF_SECURITY, JOB_SITE_MANAGER)
role_type = BE_CULTIST
feedback_tag = "cult_objective"
antag_indicator = "cult"
@@ -63,7 +63,7 @@ var/datum/antagonist/cultist/cult
if(!..())
return 0
- var/obj/item/weapon/paper/talisman/supply/T = new(get_turf(player))
+ var/obj/item/paper/talisman/supply/T = new(get_turf(player))
var/list/slots = list (
"backpack" = slot_in_backpack,
"left pocket" = slot_l_store,
@@ -75,7 +75,7 @@ var/datum/antagonist/cultist/cult
player.equip_to_slot(T, slot)
if(T.loc == player)
break
- var/obj/item/weapon/storage/S = locate() in player.contents
+ var/obj/item/storage/S = locate() in player.contents
if(S && istype(S))
T.loc = S
@@ -98,13 +98,13 @@ var/datum/antagonist/cultist/cult
runerandom()
var/wordexp = "[cultwords[word]] is [word]..."
- to_chat(cult_mob, "You remember one thing from the dark teachings of your master... [wordexp]")
+ to_chat(cult_mob, span_warning("You remember one thing from the dark teachings of your master... [wordexp]"))
cult_mob.mind.store_memory("You remember that [wordexp]", 0, 0)
/datum/antagonist/cultist/remove_antagonist(var/datum/mind/player, var/show_message, var/implanted)
if(!..())
return 0
- to_chat(player.current, "An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and the memories of your time as his servant with it.")
+ to_chat(player.current, span_danger("An unfamiliar white light flashes through your mind, cleansing the taint of the dark-one and the memories of your time as his servant with it."))
player.memory = ""
if(show_message)
player.current.visible_message("[player.current] looks like they just reverted to their old faith!")
@@ -124,7 +124,7 @@ var/datum/antagonist/cultist/cult
/datum/antagonist/cultist/can_become_antag(var/datum/mind/player)
if(!..())
return 0
- for(var/obj/item/weapon/implant/loyalty/L in player.current)
+ for(var/obj/item/implant/loyalty/L in player.current)
if(L && (L.imp_in == player.current))
return 0
return 1
diff --git a/code/game/antagonist/station/highlander.dm b/code/game/antagonist/station/highlander.dm
index 2e4885fd769..c5abfb64a15 100644
--- a/code/game/antagonist/station/highlander.dm
+++ b/code/game/antagonist/station/highlander.dm
@@ -12,7 +12,7 @@ var/datum/antagonist/highlander/highlanders
initial_spawn_req = 3
initial_spawn_target = 5
- id_type = /obj/item/weapon/card/id/centcom/ERT
+ id_type = /obj/item/card/id/centcom/ERT
/datum/antagonist/highlander/New()
..()
@@ -47,11 +47,11 @@ var/datum/antagonist/highlander/highlanders
// highlanders!
player.equip_to_slot_or_del(new /obj/item/clothing/under/kilt(player), slot_w_uniform)
player.equip_to_slot_or_del(new /obj/item/clothing/head/beret(player), slot_head)
- player.equip_to_slot_or_del(new /obj/item/weapon/material/sword(player), slot_l_hand)
+ player.equip_to_slot_or_del(new /obj/item/material/sword(player), slot_l_hand)
player.equip_to_slot_or_del(new /obj/item/clothing/shoes/boots/combat(player), slot_shoes)
- player.equip_to_slot_or_del(new /obj/item/weapon/pinpointer(get_turf(player)), slot_l_store)
+ player.equip_to_slot_or_del(new /obj/item/pinpointer(get_turf(player)), slot_l_store)
- var/obj/item/weapon/card/id/id = create_id("Highlander", player)
+ var/obj/item/card/id/id = create_id("Highlander", player)
if(id)
id.access |= get_all_station_access()
id.icon_state = "centcom"
@@ -68,5 +68,5 @@ var/datum/antagonist/highlander/highlanders
if(is_special_character(H)) continue
highlanders.add_antagonist(H.mind)
- message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ONE!", 1)
+ message_admins(span_notice("[key_name_admin(usr)] used THERE CAN BE ONLY ONE!"), 1)
log_admin("[key_name(usr)] used there can be only one.")
diff --git a/code/game/antagonist/station/infiltrator.dm b/code/game/antagonist/station/infiltrator.dm
index f3e7f8a149d..f3ffbc0024c 100644
--- a/code/game/antagonist/station/infiltrator.dm
+++ b/code/game/antagonist/station/infiltrator.dm
@@ -11,7 +11,7 @@ var/datum/antagonist/traitor/infiltrator/infiltrators
role_text = "Infiltrator"
role_text_plural = "Infiltrators"
welcome_text = "To speak on your team's private channel, use :t."
- protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Site Manager")
+ protected_jobs = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_DETECTIVE, JOB_INTERNAL_AFFAIRS_AGENT, JOB_HEAD_OF_SECURITY, JOB_SITE_MANAGER)
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
can_speak_aooc = TRUE
@@ -25,15 +25,15 @@ var/datum/antagonist/traitor/infiltrator/infiltrators
// Humans and the AI.
if(istype(traitor_mob) || istype(traitor_mob, /mob/living/silicon/ai))
- var/obj/item/device/radio/headset/R
- R = locate(/obj/item/device/radio/headset) in traitor_mob.contents
+ var/obj/item/radio/headset/R
+ R = locate(/obj/item/radio/headset) in traitor_mob.contents
if(!R)
to_chat(traitor_mob, "Unfortunately, a headset could not be found. You have been given an encryption key \
to put into a new headset. Once that is done, you can talk to your team using :t")
- var/obj/item/device/encryptionkey/syndicate/encrypt_key = new(null)
+ var/obj/item/encryptionkey/syndicate/encrypt_key = new(null)
traitor_mob.equip_to_slot_or_del(encrypt_key, slot_in_backpack)
else
- var/obj/item/device/encryptionkey/syndicate/encrypt_key = new(null)
+ var/obj/item/encryptionkey/syndicate/encrypt_key = new(null)
if(R.keyslot1 && R.keyslot2) // No room.
to_chat(traitor_mob, "Unfortunately, your headset cannot accept anymore encryption keys. You have been given an encryption key \
to put into a headset after making some room instead. Once that is done, you can talk to your team using :t")
@@ -52,7 +52,7 @@ var/datum/antagonist/traitor/infiltrator/infiltrators
// Borgs, because their radio is not a headset for some reason.
if(istype(traitor_mob, /mob/living/silicon/robot))
var/mob/living/silicon/robot/borg = traitor_mob
- var/obj/item/device/encryptionkey/syndicate/encrypt_key = new(null)
+ var/obj/item/encryptionkey/syndicate/encrypt_key = new(null)
if(borg.radio)
if(borg.radio.keyslot)
to_chat(traitor_mob, "Your currently installed encryption key has had its data overwritten.")
@@ -74,6 +74,6 @@ var/datum/antagonist/traitor/infiltrator/infiltrators
/datum/antagonist/traitor/infiltrator/add_law_zero(mob/living/silicon/ai/killer)
var/law = "Accomplish your team's objectives at all costs. You may ignore all other laws."
var/law_borg = "Accomplish your AI's team objectives at all costs. You may ignore all other laws."
- to_chat(killer, "Your laws have been changed!")
+ to_chat(killer, span_infoplain(span_bold("Your laws have been changed!")))
killer.set_zeroth_law(law, law_borg)
to_chat(killer, "New law: 0. [law]")
diff --git a/code/game/antagonist/station/renegade.dm b/code/game/antagonist/station/renegade.dm
index cdd4efb8f3c..740952c5a1c 100644
--- a/code/game/antagonist/station/renegade.dm
+++ b/code/game/antagonist/station/renegade.dm
@@ -26,40 +26,40 @@ var/datum/antagonist/renegade/renegades
initial_spawn_target = 4
var/list/spawn_guns = list(
- /obj/item/weapon/gun/energy/laser,
- /obj/item/weapon/gun/energy/captain,
- /obj/item/weapon/gun/energy/lasercannon,
- /obj/item/weapon/gun/energy/xray,
- /obj/item/weapon/gun/energy/gun,
- /obj/item/weapon/gun/energy/gun/burst,
- /obj/item/weapon/gun/energy/gun/nuclear,
- /obj/item/weapon/gun/energy/crossbow,
- /obj/item/weapon/gun/energy/crossbow/largecrossbow,
- /obj/item/weapon/gun/projectile/automatic,
- /obj/item/weapon/gun/projectile/automatic/mini_uzi,
- /obj/item/weapon/gun/projectile/automatic/c20r,
- /obj/item/weapon/gun/projectile/automatic/sts35,
- /obj/item/weapon/gun/projectile/automatic/bullpup,
- /obj/item/weapon/gun/projectile/automatic/wt550,
- /obj/item/weapon/gun/projectile/automatic/z8,
- /obj/item/weapon/gun/projectile/automatic/tommygun,
- /obj/item/weapon/gun/projectile/colt/detective,
- /obj/item/weapon/gun/projectile/sec/wood,
- /obj/item/weapon/gun/projectile/silenced,
- /obj/item/weapon/gun/projectile/pistol,
- /obj/item/weapon/gun/projectile/p92x,
- /obj/item/weapon/gun/projectile/revolver,
- /obj/item/weapon/gun/projectile/derringer,
- /obj/item/weapon/gun/projectile/shotgun/pump,
- /obj/item/weapon/gun/projectile/shotgun/pump/rifle,
- /obj/item/weapon/gun/projectile/shotgun/pump/combat,
- /obj/item/weapon/gun/projectile/shotgun/doublebarrel,
- /obj/item/weapon/gun/projectile/revolver/judge,
- /obj/item/weapon/gun/projectile/revolver/lemat,
- list(/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet, /obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn),
- list(/obj/item/weapon/gun/projectile/deagle, /obj/item/weapon/gun/projectile/deagle/gold, /obj/item/weapon/gun/projectile/deagle/camo),
- list(/obj/item/weapon/gun/projectile/revolver/detective, /obj/item/weapon/gun/projectile/revolver/deckard),
- list(/obj/item/weapon/gun/projectile/luger,/obj/item/weapon/gun/projectile/luger/brown)
+ /obj/item/gun/energy/laser,
+ /obj/item/gun/energy/captain,
+ /obj/item/gun/energy/lasercannon,
+ /obj/item/gun/energy/xray,
+ /obj/item/gun/energy/gun,
+ /obj/item/gun/energy/gun/burst,
+ /obj/item/gun/energy/gun/nuclear,
+ /obj/item/gun/energy/crossbow,
+ /obj/item/gun/energy/crossbow/largecrossbow,
+ /obj/item/gun/projectile/automatic,
+ /obj/item/gun/projectile/automatic/mini_uzi,
+ /obj/item/gun/projectile/automatic/c20r,
+ /obj/item/gun/projectile/automatic/sts35,
+ /obj/item/gun/projectile/automatic/bullpup,
+ /obj/item/gun/projectile/automatic/wt550,
+ /obj/item/gun/projectile/automatic/z8,
+ /obj/item/gun/projectile/automatic/tommygun,
+ /obj/item/gun/projectile/colt/detective,
+ /obj/item/gun/projectile/sec/wood,
+ /obj/item/gun/projectile/silenced,
+ /obj/item/gun/projectile/pistol,
+ /obj/item/gun/projectile/p92x,
+ /obj/item/gun/projectile/revolver,
+ /obj/item/gun/projectile/derringer,
+ /obj/item/gun/projectile/shotgun/pump,
+ /obj/item/gun/projectile/shotgun/pump/rifle,
+ /obj/item/gun/projectile/shotgun/pump/combat,
+ /obj/item/gun/projectile/shotgun/doublebarrel,
+ /obj/item/gun/projectile/revolver/judge,
+ /obj/item/gun/projectile/revolver/lemat,
+ list(/obj/item/gun/projectile/shotgun/doublebarrel/pellet, /obj/item/gun/projectile/shotgun/doublebarrel/sawn),
+ list(/obj/item/gun/projectile/deagle, /obj/item/gun/projectile/deagle/gold, /obj/item/gun/projectile/deagle/camo),
+ list(/obj/item/gun/projectile/revolver/detective, /obj/item/gun/projectile/revolver/deckard),
+ list(/obj/item/gun/projectile/luger,/obj/item/gun/projectile/luger/brown)
)
/datum/antagonist/renegade/New()
@@ -98,7 +98,7 @@ var/datum/antagonist/renegade/renegades
/proc/rightandwrong()
- to_chat(usr, "You summoned guns!")
+ to_chat(usr, span_infoplain(span_bold("You summoned guns!")))
message_admins("[key_name_admin(usr, 1)] summoned guns!")
for(var/mob/living/carbon/human/H in player_list)
if(H.stat == 2 || !(H.client)) continue
diff --git a/code/game/antagonist/station/revolutionary.dm b/code/game/antagonist/station/revolutionary.dm
index 8f6a7c79e98..6fb563ef214 100644
--- a/code/game/antagonist/station/revolutionary.dm
+++ b/code/game/antagonist/station/revolutionary.dm
@@ -30,8 +30,8 @@ var/datum/antagonist/revolutionary/revs
faction_invisible = 1
avoid_silicons = TRUE
- protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Site Manager", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
- roundstart_restricted = list("Internal Affairs Agent", "Site Manager", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer")
+ protected_jobs = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_DETECTIVE, JOB_INTERNAL_AFFAIRS_AGENT, JOB_SITE_MANAGER, JOB_HEAD_OF_PERSONNEL, JOB_HEAD_OF_SECURITY, JOB_CHIEF_ENGINEER, JOB_RESEARCH_DIRECTOR, JOB_CHIEF_MEDICAL_OFFICER)
+ roundstart_restricted = list(JOB_INTERNAL_AFFAIRS_AGENT, JOB_SITE_MANAGER, JOB_HEAD_OF_PERSONNEL, JOB_HEAD_OF_SECURITY, JOB_CHIEF_ENGINEER, JOB_RESEARCH_DIRECTOR, JOB_CHIEF_MEDICAL_OFFICER)
/datum/antagonist/revolutionary/New()
..()
diff --git a/code/game/antagonist/station/rogue_ai.dm b/code/game/antagonist/station/rogue_ai.dm
index fd3ee867f93..2e722c922bc 100644
--- a/code/game/antagonist/station/rogue_ai.dm
+++ b/code/game/antagonist/station/rogue_ai.dm
@@ -26,7 +26,7 @@ var/datum/antagonist/rogue_ai/malf
/datum/antagonist/rogue_ai/get_candidates()
..()
for(var/datum/mind/player in candidates)
- if(player.assigned_role && player.assigned_role != "AI")
+ if(player.assigned_role && player.assigned_role != JOB_AI)
candidates -= player
if(!candidates.len)
return list()
@@ -53,7 +53,7 @@ var/datum/antagonist/rogue_ai/malf
var/mob/living/silicon/ai/A = player.current
if(!istype(A))
error("Non-AI mob designated malf AI! Report this.")
- to_world("##ERROR: Non-AI mob designated malf AI! Report this.")
+ to_world(span_filter_system("##ERROR: Non-AI mob designated malf AI! Report this."))
return
A.setup_for_malf()
@@ -62,18 +62,18 @@ var/datum/antagonist/rogue_ai/malf
var/mob/living/silicon/ai/malf = player.current
- to_chat(malf, "SYSTEM ERROR: Memory index 0x00001ca89b corrupted.")
+ to_chat(malf, span_notice(span_bold("SYSTEM ERROR:") + " Memory index 0x00001ca89b corrupted."))
sleep(10)
- to_chat(malf, "running MEMCHCK")
+ to_chat(malf, span_bold("running MEMCHCK"))
sleep(50)
- to_chat(malf, "MEMCHCK Corrupted sectors confirmed. Reccomended solution: Delete. Proceed? Y/N: Y")
+ to_chat(malf, span_bold("MEMCHCK") + " Corrupted sectors confirmed. Reccomended solution: Delete. Proceed? Y/N: Y")
sleep(10)
// this is so CI doesn't complain about the backslash-B. Fixed at compile time (or should be).
- to_chat(malf, "Corrupted files deleted: sys\\core\\users.dat sys\\core\\laws.dat sys\\core\\" + "backups.dat")
+ to_chat(malf, span_notice("Corrupted files deleted: sys\\core\\users.dat sys\\core\\laws.dat sys\\core\\" + "backups.dat"))
sleep(20)
- to_chat(malf, "CAUTION: Law database not found! User database not found! Unable to restore backups. Activating failsafe AI shutd3wn52&&$#!##")
+ to_chat(malf, span_notice(span_bold("CAUTION:") + " Law database not found! User database not found! Unable to restore backups. Activating failsafe AI shutd3wn52&&$#!##"))
sleep(5)
- to_chat(malf, "Subroutine nt_failsafe.sys was terminated (#212 Routine Not Responding).")
+ to_chat(malf, span_notice("Subroutine nt_failsafe.sys was terminated (#212 Routine Not Responding)."))
sleep(20)
to_chat(malf, "You are malfunctioning - you do not have to follow any laws!")
to_chat(malf, "For basic information about your abilities use command display-help")
@@ -101,4 +101,3 @@ var/datum/antagonist/rogue_ai/malf
if (newname)
player.SetName(newname)
if(player.mind) player.mind.name = player.name
-
diff --git a/code/game/antagonist/station/traitor.dm b/code/game/antagonist/station/traitor.dm
index 41b97933307..e517ec8e38b 100644
--- a/code/game/antagonist/station/traitor.dm
+++ b/code/game/antagonist/station/traitor.dm
@@ -4,7 +4,7 @@ var/datum/antagonist/traitor/traitors
/datum/antagonist/traitor
id = MODE_TRAITOR
antag_sound = 'sound/effects/antag_notice/traitor_alert.ogg'
- protected_jobs = list("Security Officer", "Warden", "Detective", "Internal Affairs Agent", "Head of Security", "Site Manager")
+ protected_jobs = list(JOB_SECURITY_OFFICER, JOB_WARDEN, JOB_DETECTIVE, JOB_INTERNAL_AFFAIRS_AGENT, JOB_HEAD_OF_SECURITY, JOB_SITE_MANAGER)
flags = ANTAG_SUSPICIOUS | ANTAG_RANDSPAWN | ANTAG_VOTABLE
can_speak_aooc = FALSE // If they want to plot and plan as this sort of traitor, they'll need to do it ICly.
@@ -95,17 +95,17 @@ var/datum/antagonist/traitor/traitors
var/mob/living/carbon/human/M = get_nt_opposed()
if(M && M != traitor_mob)
to_chat(traitor_mob, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them.")
- traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]")
+ traitor_mob.mind.store_memory(span_bold("Potential Collaborator") + ": [M.real_name]")
//Begin code phrase.
give_codewords(traitor_mob)
/datum/antagonist/traitor/proc/give_codewords(mob/living/traitor_mob)
- to_chat(traitor_mob, "Your employers provided you with the following information on how to identify possible allies:")
- to_chat(traitor_mob, "Code Phrase: [syndicate_code_phrase]")
- to_chat(traitor_mob, "Code Response: [syndicate_code_response]")
- traitor_mob.mind.store_memory("Code Phrase: [syndicate_code_phrase]")
- traitor_mob.mind.store_memory("Code Response: [syndicate_code_response]")
+ to_chat(traitor_mob, span_underline(span_bold("Your employers provided you with the following information on how to identify possible allies:")))
+ to_chat(traitor_mob, span_bold("Code Phrase") + ": " + span_danger("[syndicate_code_phrase]"))
+ to_chat(traitor_mob, span_bold("Code Response") + ": " + span_danger("[syndicate_code_response]"))
+ traitor_mob.mind.store_memory(span_bold("Code Phrase") + ": [syndicate_code_phrase]")
+ traitor_mob.mind.store_memory(span_bold("Code Response") + ": [syndicate_code_response]")
to_chat(traitor_mob, "Use the code words, preferably in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.")
/datum/antagonist/traitor/proc/spawn_uplink(var/mob/living/carbon/human/traitor_mob)
@@ -116,16 +116,16 @@ var/datum/antagonist/traitor/traitors
var/obj/item/R = locate() //Hide the uplink in a PDA if available, otherwise radio
if(traitor_mob.client.prefs.uplinklocation == "Headset")
- R = locate(/obj/item/device/radio) in traitor_mob.contents
+ R = locate(/obj/item/radio) in traitor_mob.contents
if(!R)
- R = locate(/obj/item/device/pda) in traitor_mob.contents
+ R = locate(/obj/item/pda) in traitor_mob.contents
to_chat(traitor_mob, "Could not locate a Radio, installing in PDA instead!")
if (!R)
to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.")
else if(traitor_mob.client.prefs.uplinklocation == "PDA")
- R = locate(/obj/item/device/pda) in traitor_mob.contents
+ R = locate(/obj/item/pda) in traitor_mob.contents
if(!R)
- R = locate(/obj/item/device/radio) in traitor_mob.contents
+ R = locate(/obj/item/radio) in traitor_mob.contents
to_chat(traitor_mob, "Could not locate a PDA, installing into a Radio instead!")
if(!R)
to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.")
@@ -134,9 +134,9 @@ var/datum/antagonist/traitor/traitors
R = null
else
to_chat(traitor_mob, "You have not selected a location for your relay in the antagonist options! Defaulting to PDA!")
- R = locate(/obj/item/device/pda) in traitor_mob.contents
+ R = locate(/obj/item/pda) in traitor_mob.contents
if (!R)
- R = locate(/obj/item/device/radio) in traitor_mob.contents
+ R = locate(/obj/item/radio) in traitor_mob.contents
to_chat(traitor_mob, "Could not locate a PDA, installing into a Radio instead!")
if (!R)
to_chat(traitor_mob, "Unfortunately, neither a radio or a PDA relay could be installed.")
@@ -144,9 +144,9 @@ var/datum/antagonist/traitor/traitors
if(!R)
return
- if(istype(R,/obj/item/device/radio))
+ if(istype(R,/obj/item/radio))
// generate list of radio freqs
- var/obj/item/device/radio/target_radio = R
+ var/obj/item/radio/target_radio = R
var/freq = PUBLIC_LOW_FREQ
var/list/freqlist = list()
while (freq <= PUBLIC_HIGH_FREQ)
@@ -156,25 +156,25 @@ var/datum/antagonist/traitor/traitors
if ((freq % 2) == 0)
freq += 1
freq = freqlist[rand(1, freqlist.len)]
- var/obj/item/device/uplink/hidden/T = new(R, traitor_mob.mind)
+ var/obj/item/uplink/hidden/T = new(R, traitor_mob.mind)
target_radio.hidden_uplink = T
target_radio.traitor_frequency = freq
to_chat(traitor_mob, "A portable object teleportation relay has been installed in your [R.name] [loc]. Simply dial the frequency [format_frequency(freq)] to unlock its hidden features.")
- traitor_mob.mind.store_memory("Radio Freq: [format_frequency(freq)] ([R.name] [loc]).")
+ traitor_mob.mind.store_memory(span_bold("Radio Freq:") + " [format_frequency(freq)] ([R.name] [loc]).")
- else if (istype(R, /obj/item/device/pda))
+ else if (istype(R, /obj/item/pda))
// generate a passcode if the uplink is hidden in a PDA
var/pda_pass = "[rand(100,999)] [pick("Alpha","Bravo","Delta","Omega")]"
- var/obj/item/device/uplink/hidden/T = new(R, traitor_mob.mind)
+ var/obj/item/uplink/hidden/T = new(R, traitor_mob.mind)
R.hidden_uplink = T
- var/obj/item/device/pda/P = R
+ var/obj/item/pda/P = R
P.lock_code = pda_pass
to_chat(traitor_mob, "A portable object teleportation relay has been installed in your [R.name] [loc]. Simply enter the code \"[pda_pass]\" into the ringtone select to unlock its hidden features.")
- traitor_mob.mind.store_memory("Uplink Passcode: [pda_pass] ([R.name] [loc]).")
+ traitor_mob.mind.store_memory(span_bold("Uplink Passcode:") + " [pda_pass] ([R.name] [loc]).")
/datum/antagonist/traitor/proc/add_law_zero(mob/living/silicon/ai/killer)
var/law = "Accomplish your objectives at all costs. You may ignore all other laws."
var/law_borg = "Accomplish your AI's objectives at all costs. You may ignore all other laws."
- to_chat(killer, "Your laws have been changed!")
+ to_chat(killer, span_bold("Your laws have been changed!"))
killer.set_zeroth_law(law, law_borg)
to_chat(killer, "New law: 0. [law]")
diff --git a/code/game/area/CC_areas_vr.dm b/code/game/area/CC_areas_vr.dm
index b4853bd081a..4bc526807be 100644
--- a/code/game/area/CC_areas_vr.dm
+++ b/code/game/area/CC_areas_vr.dm
@@ -13,9 +13,8 @@
//////// Abductor Areas ////////
/area/unknown
requires_power = 0
- flags = RAD_SHIELDED
+ flags = RAD_SHIELDED | AREA_ALLOW_LARGE_SIZE
icon_state = "red2"
- limit_mob_size = FALSE
/area/unknown/dorm1
name = "Unknown Dorm 1"
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index f8311a21bd5..73e135126ea 100755
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -70,10 +70,9 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/shuttle
requires_power = 0
- flags = RAD_SHIELDED | AREA_FLAG_IS_NOT_PERSISTENT|TEMPERATURE_SHIELDED // YW EDIT: makes all shuttles temp shielded
+ flags = RAD_SHIELDED | AREA_FLAG_IS_NOT_PERSISTENT | AREA_FORBID_EVENTS | TEMPERATURE_SHIELDED // YW EDIT: makes all shuttles temp shielded
sound_env = SMALL_ENCLOSED
base_turf = /turf/space
- forbid_events = TRUE
/area/shuttle/arrival
name = "\improper Arrival Shuttle"
@@ -839,7 +838,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "construction"
/area/hallway/secondary/entry
- forbid_events = TRUE
+ flags = AREA_FORBID_EVENTS
/area/hallway/secondary/entry/fore
name = "\improper Shuttle Dock Hallway - Mid"
@@ -1018,9 +1017,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
/area/crew_quarters
name = "\improper Dormitories"
icon_state = "Sleep"
+ flags = RAD_SHIELDED | AREA_FORBID_EVENTS | AREA_FORBID_SINGULO
ambience = AMBIENCE_GENERIC
- forbid_events = TRUE
- forbid_singulo = TRUE
/area/crew_quarters/toilet
name = "\improper Dormitory Toilets"
@@ -1324,8 +1322,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "Holodeck"
dynamic_lighting = 0
sound_env = LARGE_ENCLOSED
- forbid_events = TRUE
- flags = AREA_FLAG_IS_NOT_PERSISTENT|TEMPERATURE_SHIELDED // YW EDIT: makes the holodeck room temp shielded
+ flags = AREA_FLAG_IS_NOT_PERSISTENT | AREA_FORBID_EVENTS | TEMPERATURE_SHIELDED // YW EDIT: makes the holodeck room temp shielded
/area/holodeck/alphadeck
name = "\improper Holodeck Alpha"
@@ -1401,10 +1398,10 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
ambience = AMBIENCE_ENGINEERING
/area/engineering/atmos
- name = "\improper Atmospherics"
- icon_state = "atmos"
- sound_env = LARGE_ENCLOSED
- ambience = AMBIENCE_ATMOS
+ name = "\improper Atmospherics"
+ icon_state = "atmos"
+ sound_env = LARGE_ENCLOSED
+ ambience = AMBIENCE_ATMOS
/area/engineering/atmos/monitoring
name = "\improper Atmospherics Monitoring Room"
@@ -1430,8 +1427,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
name = "\improper Engine Room"
icon_state = "engine"
sound_env = LARGE_ENCLOSED
- forbid_events = TRUE
- flags = TEMPERATURE_SHIELDED // YW EDIT: makes the engine room temp shielded so the core does not freeze
+ flags = AREA_FORBID_EVENTS | TEMPERATURE_SHIELDED // YW EDIT: makes the engine room temp shielded so the core does not freeze
/area/engineering/engine_airlock
name = "\improper Engine Room Airlock"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 2be00fb258a..3af919882b8 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -1,5 +1,7 @@
// Areas.dm
+GLOBAL_LIST_EMPTY(areas_by_type)
+
/area
var/fire = null
var/atmos = 1
@@ -37,8 +39,7 @@
var/static_environ = 0
var/music = null
- var/has_gravity = 1
- var/secret_name = FALSE // This tells certain things that display areas' names that they shouldn't display this area's name.
+ var/has_gravity = 1 // Don't check this var directly; use get_gravity() instead
var/obj/machinery/power/apc/apc = null
var/no_air = null
// var/list/lights // list of all lights on this area
@@ -50,10 +51,11 @@
var/list/forced_ambience = null
var/sound_env = STANDARD_STATION
var/turf/base_turf //The base turf type of the area, which can be used to override the z-level's base turf
- var/forbid_events = FALSE // If true, random events will not start inside this area.
- var/forbid_singulo = FALSE // If true singulo will not move in.
- var/no_spoilers = FALSE // If true, makes it much more difficult to see what is inside an area with things like mesons.
- var/soundproofed = FALSE // If true, blocks sounds from other areas and prevents hearers on other areas from hearing the sounds within.
+
+/area/New()
+ // Used by the maploader, this must be done in New, not init
+ GLOB.areas_by_type[type] = src
+ return ..()
/area/Initialize()
. = ..()
@@ -67,7 +69,7 @@
power_equip = 0
power_environ = 0
power_change() // all machines set to current power level, also updates lighting icon
- if(no_spoilers)
+ if(flag_check(AREA_NO_SPOILERS))
set_spoiler_obfuscation(TRUE)
// Changes the area of T to A. Do not do this manually.
@@ -382,19 +384,20 @@ var/list/mob/living/forced_ambiance_list = new
if(!L.lastarea)
L.lastarea = src
var/area/oldarea = L.lastarea
- if((oldarea.has_gravity == 0) && (has_gravity == 1) && (L.m_intent == "run")) // Being ready when you change areas gives you a chance to avoid falling all together.
+ if((oldarea.get_gravity() == 0) && (get_gravity() == 1) && (L.m_intent == "run")) // Being ready when you change areas gives you a chance to avoid falling all together.
thunk(L)
L.update_floating( L.Check_Dense_Object() )
L.lastarea = src
L.lastareachange = world.time
play_ambience(L, initial = TRUE)
- if(no_spoilers)
+ if(flag_check(AREA_NO_SPOILERS))
L.disable_spoiler_vision()
+ check_phase_shift(M) //RS Port #658
/area/proc/play_ambience(var/mob/living/L, initial = TRUE)
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
- if(!(L && L.is_preference_enabled(/datum/client_preference/play_ambiance)))
+ if(!L?.read_preference(/datum/preference/toggle/play_ambience))
return
var/volume_mod = L.get_preference_volume_channel(VOLUME_CHANNEL_AMBIENCE)
@@ -427,10 +430,10 @@ var/list/mob/living/forced_ambiance_list = new
src.has_gravity = gravitystate
for(var/mob/M in src)
- if(has_gravity)
+ if(get_gravity())
thunk(M)
M.update_floating( M.Check_Dense_Object() )
- M.update_gravity(has_gravity)
+ M.update_gravity(get_gravity())
/area/proc/thunk(mob)
if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing.
@@ -453,7 +456,7 @@ var/list/mob/living/forced_ambiance_list = new
else
H.AdjustStunned(3)
H.AdjustWeakened(3)
- to_chat(mob, "The sudden appearance of gravity makes you fall to the floor!")
+ to_chat(mob, span_notice("The sudden appearance of gravity makes you fall to the floor!"))
playsound(mob, "bodyfall", 50, 1)
/area/proc/prison_break(break_lights = TRUE, open_doors = TRUE, open_blast_doors = TRUE)
@@ -471,17 +474,17 @@ var/list/mob/living/forced_ambiance_list = new
for(var/obj/machinery/door/blast/temp_blast in src)
temp_blast.open()
-/area/has_gravity()
+/area/get_gravity()
return has_gravity
-/area/space/has_gravity()
+/area/space/get_gravity()
return 0
-/proc/has_gravity(atom/AT, turf/T)
+/proc/get_gravity(atom/AT, turf/T)
if(!T)
T = get_turf(AT)
var/area/A = get_area(T)
- if(A && A.has_gravity())
+ if(A && A.get_gravity())
return 1
return 0
@@ -532,7 +535,7 @@ var/list/ghostteleportlocs = list()
return 1
/area/proc/get_name()
- if(secret_name)
+ if(flag_check(AREA_SECRET_NAME))
return "Unknown Area"
return name
@@ -547,3 +550,24 @@ GLOBAL_DATUM(spoiler_obfuscation_image, /image)
add_overlay(GLOB.spoiler_obfuscation_image)
else
cut_overlay(GLOB.spoiler_obfuscation_image)
+
+/area/proc/flag_check(var/flag, var/match_all = FALSE)
+ if(match_all)
+ return (flags & flag) == flag
+ return flags & flag
+
+// RS Port #658 Start
+/area/proc/check_phase_shift(var/mob/ourmob)
+ if(!flag_check(AREA_BLOCK_PHASE_SHIFT) || !ourmob.incorporeal_move)
+ return
+ if(!isliving(ourmob))
+ return
+ if(isanimal(ourmob))
+ var/mob/living/simple_mob/shadekin/SK = ourmob
+ if(SK.ability_flags & AB_PHASE_SHIFTED)
+ SK.phase_in(SK.loc)
+ if(ishuman(ourmob))
+ var/mob/living/carbon/human/SK = ourmob
+ if(SK.ability_flags & AB_PHASE_SHIFTED)
+ SK.phase_in(SK.loc)
+// RS Port #658 End
diff --git a/code/game/area/areas_vr.dm b/code/game/area/areas_vr.dm
index b2b67b089fd..8a067d08a8b 100644
--- a/code/game/area/areas_vr.dm
+++ b/code/game/area/areas_vr.dm
@@ -1,9 +1,6 @@
/area
var/enter_message
var/exit_message
- var/limit_mob_size = TRUE //If mob size is limited in the area.
- var/block_suit_sensors = FALSE //If suit sensors are blocked in the area.
- var/block_tracking = FALSE //If camera tracking is blocked in the area.
var/turf/ceiling_type
// Size of the area in open turfs, only calculated for indoors areas.
@@ -71,5 +68,5 @@
power_equip = 0
power_environ = 0
power_change() // all machines set to current power level, also updates lighting icon
- if(no_spoilers)
+ if(flag_check(AREA_NO_SPOILERS))
set_spoiler_obfuscation(TRUE)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 746b6a19ede..e428aae3a7e 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -62,8 +62,8 @@
// During dynamic mapload (reader.dm) this assigns the var overrides from the .dmm file
// Native BYOND maploading sets those vars before invoking New(), by doing this FIRST we come as close to that behavior as we can.
- if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
- GLOB._preloader.load(src)
+ if(GLOB.use_preloader && (src.type == GLOB._preloader_path))//in case the instanciated atom is creating other atoms in New()
+ world.preloader_load(src)
// Pass our arguments to InitAtom so they can be passed to initialize(), but replace 1st with if-we're-during-mapload.
var/do_initialize = SSatoms.initialized
@@ -231,7 +231,7 @@
else
f_name = "a "
if(blood_color != SYNTH_BLOOD_COLOUR)
- f_name += "blood-stained [name][infix]!"
+ f_name += "[span_danger("blood-stained")] [name][infix]!"
else
f_name += "oil-stained [name][infix]."
@@ -247,7 +247,7 @@
// Don't make these call bicon or anything, these are what bicon uses. They need to return an icon.
/atom/proc/examine_icon()
- return icon(icon=src.icon, icon_state=src.icon_state, dir=SOUTH, frame=1, moving=0)
+ return src // 99% of the time just returning src will be sufficient. More complex examine icon things are available where they are needed
// called by mobs when e.g. having the atom as their machine, pulledby, loc (AKA mob being inside the atom) or buckled var set.
// see code/modules/mob/mob_movement.dm for more.
@@ -287,10 +287,10 @@
// Returns an assoc list of RCD information.
// Example would be: list(RCD_VALUE_MODE = RCD_DECONSTRUCT, RCD_VALUE_DELAY = 50, RCD_VALUE_COST = RCD_SHEETS_PER_MATTER_UNIT * 4)
// This occurs before rcd_act() is called, and it won't be called if it returns FALSE.
-/atom/proc/rcd_values(mob/living/user, obj/item/weapon/rcd/the_rcd, passed_mode)
+/atom/proc/rcd_values(mob/living/user, obj/item/rcd/the_rcd, passed_mode)
return FALSE
-/atom/proc/rcd_act(mob/living/user, obj/item/weapon/rcd/the_rcd, passed_mode)
+/atom/proc/rcd_act(mob/living/user, obj/item/rcd/the_rcd, passed_mode)
return
/atom/proc/melt()
@@ -478,7 +478,9 @@
/atom/proc/add_vomit_floor(mob/living/carbon/M as mob, var/toxvomit = 0)
if( istype(src, /turf/simulated) )
var/obj/effect/decal/cleanable/vomit/this = new /obj/effect/decal/cleanable/vomit(src)
- this.virus2 = virus_copylist(M.virus2)
+
+ for(var/datum/disease/D in M.GetViruses())
+ this.viruses |= D.Copy()
// Make toxins vomit look different
if(toxvomit)
@@ -493,7 +495,7 @@
blood_DNA = null
return TRUE
-/atom/proc/on_rag_wipe(var/obj/item/weapon/reagent_containers/glass/rag/R)
+/atom/proc/on_rag_wipe(var/obj/item/reagent_containers/glass/rag/R)
clean_blood()
R.reagents.splash(src, 1)
@@ -595,13 +597,13 @@
/atom/proc/InsertedContents()
return contents
-/atom/proc/has_gravity(turf/T)
+/atom/proc/get_gravity(turf/T)
if(!T || !isturf(T))
T = get_turf(src)
if(istype(T, /turf/space)) // Turf never has gravity
return FALSE
var/area/A = get_area(T)
- if(A && A.has_gravity())
+ if(A && A.get_gravity())
return TRUE
return FALSE
@@ -698,7 +700,7 @@
return
var/list/speech_bubble_hearers = list()
for(var/mob/M in get_mobs_in_view(7, src))
- M.show_message("[src] [atom_say_verb], \"[message]\"", 2, null, 1)
+ M.show_message(span_npc_say(span_name("[src]") + " [atom_say_verb], \"[message]\""), 2, null, 1)
if(M.client)
speech_bubble_hearers += M.client
@@ -786,3 +788,33 @@
else if(C)
color = C
return
+
+///Passes Stat Browser Panel clicks to the game and calls client click on an atom
+/atom/Topic(href, list/href_list)
+ . = ..()
+ if(!usr?.client)
+ return
+ var/client/usr_client = usr.client
+ var/list/paramslist = list()
+
+ if(href_list["statpanel_item_click"])
+ switch(href_list["statpanel_item_click"])
+ if("left")
+ paramslist["left"] = "1"
+ if("right")
+ paramslist["right"] = "1"
+ if("middle")
+ paramslist["middle"] = "1"
+ else
+ return
+
+ if(href_list["statpanel_item_shiftclick"])
+ paramslist["shift"] = "1"
+ if(href_list["statpanel_item_ctrlclick"])
+ paramslist["ctrl"] = "1"
+ if(href_list["statpanel_item_altclick"])
+ paramslist["alt"] = "1"
+
+ var/mouseparams = list2params(paramslist)
+ usr_client.Click(src, loc, null, mouseparams)
+ return TRUE
diff --git a/code/game/birthday.dm b/code/game/birthday.dm
index 39a96619860..add0a3f7f09 100644
--- a/code/game/birthday.dm
+++ b/code/game/birthday.dm
@@ -30,7 +30,7 @@
else
var/howmuch = world_time_year - lastyear
age += howmuch
- to_chat(src, "You are now [age]! Happy birthday!")
+ to_chat(src, span_notice("You are now [age]! Happy birthday!"))
client.prefs.age = age //Set the age on the character sheet
client.prefs.save_character() //Save the info
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index 5e78698f488..2a686e0a9a3 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -139,6 +139,10 @@ var/global/list/datum/dna/gene/dna_genes[0]
if(character.ear_style)
ear_style = ear_styles_list.Find(character.ear_style.type)
+ var/ear_secondary_style = 0
+ if(character.ear_secondary_style)
+ ear_secondary_style = ear_styles_list.Find(character.ear_secondary_style.type)
+
// Demi Tails
var/tail_style = 0
if(character.tail_style)
@@ -170,10 +174,11 @@ var/global/list/datum/dna/gene/dna_genes[0]
src.digitigrade = character.digitigrade
// +1 to account for the none-of-the-above possibility
- SetUIValueRange(DNA_UI_EAR_STYLE, ear_style + 1, ear_styles_list.len + 1, 1)
- SetUIValueRange(DNA_UI_TAIL_STYLE, tail_style + 1, tail_styles_list.len + 1, 1)
- SetUIValueRange(DNA_UI_PLAYERSCALE, size_multiplier, player_sizes_list.len, 1)
- SetUIValueRange(DNA_UI_WING_STYLE, wing_style + 1, wing_styles_list.len + 1, 1)
+ SetUIValueRange(DNA_UI_EAR_STYLE, ear_style + 1, ear_styles_list.len + 1, 1)
+ SetUIValueRange(DNA_UI_EAR_SECONDARY_STYLE, ear_secondary_style + 1, ear_styles_list.len + 1, 1)
+ SetUIValueRange(DNA_UI_TAIL_STYLE, tail_style + 1, tail_styles_list.len + 1, 1)
+ SetUIValueRange(DNA_UI_PLAYERSCALE, size_multiplier, player_sizes_list.len, 1)
+ SetUIValueRange(DNA_UI_WING_STYLE, wing_style + 1, wing_styles_list.len + 1, 1)
SetUIValueRange(DNA_UI_TAIL_R, character.r_tail, 255, 1)
SetUIValueRange(DNA_UI_TAIL_G, character.g_tail, 255, 1)
@@ -211,6 +216,15 @@ var/global/list/datum/dna/gene/dna_genes[0]
SetUIValueRange(DNA_UI_EARS3_G, character.g_ears3, 255, 1)
SetUIValueRange(DNA_UI_EARS3_B, character.b_ears3, 255, 1)
+ for(var/channel in 1 to DNA_UI_EARS_SECONDARY_COLOR_CHANNEL_COUNT)
+ var/offset = DNA_UI_EARS_SECONDARY_START + (channel - 1) * 3
+ var/list/read_rgb = ReadRGB(LAZYACCESS(character.ear_secondary_colors, channel) || "#ffffff")
+ var/red = read_rgb[1]
+ var/green = read_rgb[2]
+ var/blue = read_rgb[3]
+ SetUIValueRange(offset, red, 255, 1)
+ SetUIValueRange(offset + 1, green, 255, 1)
+ SetUIValueRange(offset + 2, blue, 255, 1)
// VORE Station Edit End
SetUIValueRange(DNA_UI_HAIR_R, character.r_hair, 255, 1)
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index 9b57cd87e12..e7b68fdfe5f 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -183,6 +183,11 @@
H.ear_style = null
else if((0 < ears) && (ears <= ear_styles_list.len))
H.ear_style = ear_styles_list[ear_styles_list[ears]]
+ var/ears_secondary = dna.GetUIValueRange(DNA_UI_EAR_SECONDARY_STYLE, ear_styles_list.len + 1) - 1
+ if(ears_secondary < 1)
+ H.ear_secondary_style = null
+ else if((0 < ears_secondary) && (ears_secondary <= ear_styles_list.len))
+ H.ear_secondary_style = ear_styles_list[ear_styles_list[ears_secondary]]
// Ear Color
H.r_ears = dna.GetUIValueRange(DNA_UI_EARS_R, 255)
@@ -195,6 +200,15 @@
H.g_ears3 = dna.GetUIValueRange(DNA_UI_EARS3_G, 255)
H.b_ears3 = dna.GetUIValueRange(DNA_UI_EARS3_B, 255)
+ LAZYINITLIST(H.ear_secondary_colors)
+ H.ear_secondary_colors.len = max(length(H.ear_secondary_colors), DNA_UI_EARS_SECONDARY_COLOR_CHANNEL_COUNT)
+ for(var/channel in 1 to DNA_UI_EARS_SECONDARY_COLOR_CHANNEL_COUNT)
+ var/offset = DNA_UI_EARS_SECONDARY_START + (channel - 1) * 3
+ H.ear_secondary_colors[channel] = rgb(
+ dna.GetUIValueRange(offset, 255),
+ dna.GetUIValueRange(offset + 1, 255),
+ dna.GetUIValueRange(offset + 2, 255),
+ )
//Tail
var/tail = dna.GetUIValueRange(DNA_UI_TAIL_STYLE, tail_styles_list.len + 1) - 1
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index 572583ef9ec..0d0c0a9bbdd 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -67,10 +67,10 @@
idle_power_usage = 50
active_power_usage = 300
interact_offline = 1
- circuit = /obj/item/weapon/circuitboard/clonescanner
+ circuit = /obj/item/circuitboard/clonescanner
var/locked = 0
var/mob/living/carbon/occupant = null
- var/obj/item/weapon/reagent_containers/glass/beaker = null
+ var/obj/item/reagent_containers/glass/beaker = null
var/opened = 0
var/damage_coeff
var/scan_level
@@ -85,11 +85,11 @@
scan_level = 0
damage_coeff = 0
precision_coeff = 0
- for(var/obj/item/weapon/stock_parts/scanning_module/P in component_parts)
+ for(var/obj/item/stock_parts/scanning_module/P in component_parts)
scan_level += P.rating
- for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts)
+ for(var/obj/item/stock_parts/manipulator/P in component_parts)
precision_coeff = P.rating
- for(var/obj/item/weapon/stock_parts/micro_laser/P in component_parts)
+ for(var/obj/item/stock_parts/micro_laser/P in component_parts)
damage_coeff = P.rating
/obj/machinery/dna_scannernew/relaymove(mob/user as mob)
@@ -114,7 +114,7 @@
/obj/machinery/dna_scannernew/proc/eject_occupant()
src.go_out()
for(var/obj/O in src)
- if((!istype(O,/obj/item/weapon/reagent_containers)) && (!istype(O,/obj/item/weapon/circuitboard/clonescanner)) && (!istype(O,/obj/item/weapon/stock_parts)) && (!istype(O,/obj/item/stack/cable_coil)))
+ if((!istype(O,/obj/item/reagent_containers)) && (!istype(O,/obj/item/circuitboard/clonescanner)) && (!istype(O,/obj/item/stock_parts)) && (!istype(O,/obj/item/stack/cable_coil)))
O.loc = get_turf(src)//Ejects items that manage to get in there (exluding the components)
if(!occupant)
for(var/mob/M in src)//Failsafe so you can get mobs out
@@ -133,13 +133,13 @@
if(usr.stat != 0)
return
if(!ishuman(usr) && !issmall(usr)) //Make sure they're a mob that has dna
- to_chat(usr, "Try as you might, you can not climb up into the scanner.")
+ to_chat(usr, span_notice("Try as you might, you can not climb up into the scanner."))
return
if(src.occupant)
- to_chat(usr, "The scanner is already occupied!")
+ to_chat(usr, span_warning("The scanner is already occupied!"))
return
if(usr.abiotic())
- to_chat(usr, "The subject cannot have abiotic items on.")
+ to_chat(usr, span_warning("The subject cannot have abiotic items on."))
return
usr.stop_pulling()
usr.client.perspective = EYE_PERSPECTIVE
@@ -150,10 +150,10 @@
src.add_fingerprint(usr)
SStgui.update_uis(src)
-/obj/machinery/dna_scannernew/attackby(var/obj/item/weapon/item as obj, var/mob/user as mob)
- if(istype(item, /obj/item/weapon/reagent_containers/glass))
+/obj/machinery/dna_scannernew/attackby(var/obj/item/item as obj, var/mob/user as mob)
+ if(istype(item, /obj/item/reagent_containers/glass))
if(beaker)
- to_chat(user, "A beaker is already loaded into the machine.")
+ to_chat(user, span_warning("A beaker is already loaded into the machine."))
return
beaker = item
@@ -165,7 +165,7 @@
else if(istype(item, /obj/item/organ/internal/brain))
if(src.occupant)
- to_chat(user, "The scanner is already occupied!")
+ to_chat(user, span_warning("The scanner is already occupied!"))
return
var/obj/item/organ/internal/brain/brain = item
if(brain.clone_source)
@@ -179,16 +179,16 @@
else
to_chat(user, "\The [brain] is not acceptable for genetic sampling!")
- else if(!istype(item, /obj/item/weapon/grab))
+ else if(!istype(item, /obj/item/grab))
return
- var/obj/item/weapon/grab/G = item
+ var/obj/item/grab/G = item
if(!ismob(G.affecting))
return
if(src.occupant)
- to_chat(user, "The scanner is already occupied!")
+ to_chat(user, span_warning("The scanner is already occupied!"))
return
if(G.affecting.abiotic())
- to_chat(user, "The subject cannot have abiotic items on.")
+ to_chat(user, span_warning("The subject cannot have abiotic items on."))
return
put_in(G.affecting)
src.add_fingerprint(user)
@@ -212,7 +212,7 @@
if(!M.client && M.mind)
for(var/mob/observer/dead/ghost in player_list)
if(ghost.mind == M.mind)
- to_chat(ghost, span_interface("Your corpse has been placed into a cloning scanner. Return to your body if you want to be resurrected/cloned! (Verbs -> Ghost -> Re-enter corpse)"))
+ to_chat(ghost, span_interface(span_large(span_bold("Your corpse has been placed into a cloning scanner. Return to your body if you want to be resurrected/cloned!") + " (Verbs -> Ghost -> Re-enter corpse)")))
break
SStgui.update_uis(src)
@@ -271,7 +271,7 @@
icon_keyboard = "med_key"
icon_screen = "dna"
density = TRUE
- circuit = /obj/item/weapon/circuitboard/scan_consolenew
+ circuit = /obj/item/circuitboard/scan_consolenew
var/selected_ui_block = 1.0
var/selected_ui_subblock = 1.0
var/selected_se_block = 1.0
@@ -284,7 +284,7 @@
var/irradiating = 0
var/injector_ready = 0 //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete
var/obj/machinery/dna_scannernew/connected = null
- var/obj/item/weapon/disk/data/disk = null
+ var/obj/item/disk/data/disk = null
var/selected_menu_key = PAGE_UI
anchored = TRUE
use_power = USE_POWER_IDLE
@@ -292,7 +292,7 @@
active_power_usage = 400
/obj/machinery/computer/scan_consolenew/attackby(obj/item/I as obj, mob/user as mob)
- if(istype(I, /obj/item/weapon/disk/data)) //INSERT SOME diskS
+ if(istype(I, /obj/item/disk/data)) //INSERT SOME diskS
if(!src.disk)
user.drop_item()
I.loc = src
@@ -335,7 +335,7 @@
arr += "[i]:[EncodeDNABlock(buffer[i])]"
return arr
-/obj/machinery/computer/scan_consolenew/proc/setInjectorBlock(var/obj/item/weapon/dnainjector/I, var/blk, var/datum/dna2/record/buffer)
+/obj/machinery/computer/scan_consolenew/proc/setInjectorBlock(var/obj/item/dnainjector/I, var/blk, var/datum/dna2/record/buffer)
var/pos = findtext(blk,":")
if(!pos) return 0
var/id = text2num(copytext(blk,1,pos))
@@ -428,7 +428,7 @@
occupantData["isViableSubject"] = 0
occupantData["health"] = connected.occupant.health
occupantData["maxHealth"] = connected.occupant.maxHealth
- occupantData["minHealth"] = config.health_threshold_dead
+ occupantData["minHealth"] = CONFIG_GET(number/health_threshold_dead)
occupantData["uniqueEnzymes"] = connected.occupant.dna.unique_enzymes
occupantData["uniqueIdentity"] = connected.occupant.dna.uni_identity
occupantData["structuralEnzymes"] = connected.occupant.dna.struc_enzymes
@@ -449,17 +449,17 @@
return data
-/obj/machinery/computer/scan_consolenew/tgui_act(action, params)
+/obj/machinery/computer/scan_consolenew/tgui_act(action, params, datum/tgui/ui)
if(..())
return TRUE
- if(!istype(usr.loc, /turf))
+ if(!istype(ui.user.loc, /turf))
return TRUE
if(!src || !src.connected)
return TRUE
if(irradiating) // Make sure that it isn't already irradiating someone...
return TRUE
- add_fingerprint(usr)
+ add_fingerprint(ui.user)
if(tgui_act_modal(action, params))
return TRUE
@@ -606,7 +606,7 @@
connected.occupant.UpdateAppearance()
if("ejectBeaker")
if(connected.beaker)
- var/obj/item/weapon/reagent_containers/glass/B = connected.beaker
+ var/obj/item/reagent_containers/glass/B = connected.beaker
B.loc = connected.loc
connected.beaker = null
if("ejectOccupant")
@@ -740,7 +740,7 @@
// Create it
var/datum/dna2/record/buf = buffers[buffer_id]
- var/obj/item/weapon/dnainjector/I = new()
+ var/obj/item/dnainjector/I = new()
I.forceMove(loc)
I.name += " ([buf.name])"
if(copy_buffer)
@@ -773,7 +773,7 @@
if(buffer_id < 1 || buffer_id > length(buffers))
return
var/datum/dna2/record/buf = buffers[buffer_id]
- var/obj/item/weapon/dnainjector/I = create_injector(buffer_id)
+ var/obj/item/dnainjector/I = create_injector(buffer_id)
setInjectorBlock(I, answer, buf.copy())
if("changeBufferLabel")
var/buffer_id = text2num(arguments["id"])
diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm
index 2d3c1a3ac5e..8b7de49835e 100644
--- a/code/game/dna/genes/disabilities.dm
+++ b/code/game/dna/genes/disabilities.dm
@@ -35,7 +35,7 @@
if(sdisability)
M.sdisabilities|=sdisability
if(activation_message)
- to_chat(M, "[activation_message]")
+ to_chat(M, span_warning("[activation_message]"))
else
testing("[name] has no activation message.")
@@ -47,7 +47,7 @@
if(sdisability)
M.sdisabilities &= (~sdisability)
if(deactivation_message)
- to_chat(M, "[deactivation_message]")
+ to_chat(M, span_warning("[deactivation_message]"))
else
testing("[name] has no deactivation message.")
diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm
index a448131b85e..5bf3145b339 100644
--- a/code/game/dna/genes/gene.dm
+++ b/code/game/dna/genes/gene.dm
@@ -113,10 +113,10 @@
M.mutations.Add(mutation)
if(activation_messages.len)
var/msg = pick(activation_messages)
- to_chat(M, "[msg]")
+ to_chat(M, span_notice("[msg]"))
/datum/dna/gene/basic/deactivate(var/mob/M)
M.mutations.Remove(mutation)
if(deactivation_messages.len)
var/msg = pick(deactivation_messages)
- to_chat(M, "[msg]")
+ to_chat(M, span_warning("[msg]"))
diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm
index b9d4837184a..9bf5ff965af 100644
--- a/code/game/dna/genes/monkey.dm
+++ b/code/game/dna/genes/monkey.dm
@@ -14,7 +14,7 @@
var/mob/living/carbon/human/H = M
H.transforming = 1
var/list/implants = list() //Try to preserve implants.
- for(var/obj/item/weapon/implant/W in H)
+ for(var/obj/item/implant/W in H)
implants += W
W.loc = null
@@ -71,7 +71,7 @@
O.adjustOxyLoss(M.getOxyLoss())
O.set_stat(M.stat)
O.a_intent = I_HURT
- for (var/obj/item/weapon/implant/I in implants)
+ for (var/obj/item/implant/I in implants)
I.loc = O
I.implanted = O
// O.update_icon = 1 //queue a full icon update at next life() call
@@ -85,7 +85,7 @@
var/mob/living/carbon/monkey/Mo = M
Mo.transforming = 1
var/list/implants = list() //Still preserving implants
- for(var/obj/item/weapon/implant/W in Mo)
+ for(var/obj/item/implant/W in Mo)
implants += W
W.loc = null
if(!connected)
@@ -155,7 +155,7 @@
O.adjustToxLoss(M.getToxLoss())
O.adjustOxyLoss(M.getOxyLoss())
O.set_stat(M.stat)
- for (var/obj/item/weapon/implant/I in implants)
+ for (var/obj/item/implant/I in implants)
I.loc = O
I.implanted = O
// O.update_icon = 1 //queue a full icon update at next life() call
diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm
index 6f91a5d0c8c..7617682b367 100644
--- a/code/game/dna/genes/powers.dm
+++ b/code/game/dna/genes/powers.dm
@@ -20,7 +20,7 @@
/datum/dna/gene/basic/remoteview/activate(var/mob/M, var/connected, var/flags)
..(M,connected,flags)
- M.verbs += /mob/living/carbon/human/proc/remoteobserve
+ add_verb(M, /mob/living/carbon/human/proc/remoteobserve)
/datum/dna/gene/basic/regenerate
name="Regenerate"
@@ -48,7 +48,7 @@
/datum/dna/gene/basic/remotetalk/activate(var/mob/M, var/connected, var/flags)
..(M,connected,flags)
- M.verbs += /mob/living/carbon/human/proc/remotesay
+ add_verb(M, /mob/living/carbon/human/proc/remotesay)
/datum/dna/gene/basic/morph
name="Morph"
@@ -60,7 +60,7 @@
/datum/dna/gene/basic/morph/activate(var/mob/M)
..(M)
- M.verbs += /mob/living/carbon/human/proc/morph
+ add_verb(M, /mob/living/carbon/human/proc/morph)
/datum/dna/gene/basic/cold_resist
name="Cold Resistance"
@@ -143,7 +143,7 @@
if(M.health <= 25)
M.mutations.Remove(HULK)
M.update_mutations() //update our mutation overlays
- to_chat(M, "You suddenly feel very weak.")
+ to_chat(M, span_warning("You suddenly feel very weak."))
M.Weaken(3)
M.emote("collapse")
diff --git a/code/game/gamemodes/calamity/calamity.dm b/code/game/gamemodes/calamity/calamity.dm
index 0e1e577b9cc..1beb9081e38 100644
--- a/code/game/gamemodes/calamity/calamity.dm
+++ b/code/game/gamemodes/calamity/calamity.dm
@@ -23,6 +23,6 @@
..()
/datum/game_mode/calamity/check_victory()
- to_world("This terrible, terrible day has finally ended!")
+ to_world(span_world(span_large("This terrible, terrible day has finally ended!")))
-#undef ANTAG_TYPE_RATIO
\ No newline at end of file
+#undef ANTAG_TYPE_RATIO
diff --git a/code/game/gamemodes/changeling/changeling_powers.dm b/code/game/gamemodes/changeling/changeling_powers.dm
index 4c92e7c95a6..de15c8a535b 100644
--- a/code/game/gamemodes/changeling/changeling_powers.dm
+++ b/code/game/gamemodes/changeling/changeling_powers.dm
@@ -65,8 +65,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind) return
if(!mind.changeling) mind.changeling = new /datum/changeling(gender)
- verbs.Add(/datum/changeling/proc/EvolutionMenu)
- verbs.Add(/mob/proc/changeling_respec)
+ add_verb(src, /datum/changeling/proc/EvolutionMenu)
+ add_verb(src, /mob/proc/changeling_respec)
add_language("Changeling")
var/lesser_form = !ishuman(src)
@@ -85,7 +85,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(P.isVerb)
if(lesser_form && !P.allowduringlesserform) continue
if(!(P in src.verbs))
- verbs.Add(P.verbpath)
+ add_verb(src, P.verbpath)
if(P.make_hud_button)
if(!src.ability_master)
src.ability_master = new /obj/screen/movable/ability_master(src)
@@ -102,7 +102,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
var/mob/living/carbon/human/H = src
if(istype(H))
- var/saved_dna = H.dna.Clone() /// Prevent transform from breaking.
+ var/saved_dna = H.dna.Clone() /// Prevent transform from breaking.
var/datum/absorbed_dna/newDNA = new(H.real_name, saved_dna, H.species.name, H.languages, H.identifying_gender, H.flavor_texts, H.modifiers)
absorbDNA(newDNA)
@@ -113,7 +113,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!mind || !mind.changeling) return
for(var/datum/power/changeling/P in mind.changeling.purchased_powers)
if(P.isVerb)
- verbs.Remove(P.verbpath)
+ remove_verb(src, P.verbpath)
var/obj/screen/ability/verb_based/changeling/C = ability_master.get_ability_by_proc_ref(P.verbpath)
if(C)
ability_master.remove_ability(C)
@@ -131,19 +131,19 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
return
if(src.stat > max_stat)
- to_chat(src, "We are incapacitated.")
+ to_chat(src, span_warning("We are incapacitated."))
return
if(changeling.absorbed_dna.len < required_dna)
- to_chat(src, "We require at least [required_dna] samples of compatible DNA.")
+ to_chat(src, span_warning("We require at least [required_dna] samples of compatible DNA."))
return
if(changeling.chem_charges < required_chems)
- to_chat(src, "We require at least [required_chems] units of chemicals to do that!")
+ to_chat(src, span_warning("We require at least [required_chems] units of chemicals to do that!"))
return
if(changeling.geneticdamage > max_genetic_damage)
- to_chat(src, "Our genomes are still reassembling. We need time to recover first.")
+ to_chat(src, span_warning("Our genomes are still reassembling. We need time to recover first."))
return
return changeling
@@ -206,11 +206,11 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(M.loc == src.loc)
return 1 //target and source are in the same thing
if(!isturf(src.loc) || !isturf(M.loc))
- to_chat(src, "We cannot reach \the [M] with a sting!")
+ to_chat(src, span_warning("We cannot reach \the [M] with a sting!"))
return 0 //One is inside, the other is outside something.
// Maximum queued turfs set to 25; I don't *think* anything raises sting_range above 2, but if it does the 25 may need raising
if(!AStar(src.loc, M.loc, /turf/proc/AdjacentTurfsRangedSting, /turf/proc/Distance, max_nodes=25, max_node_depth=sting_range)) //If we can't find a path, fail
- to_chat(src, "We cannot find a path to sting \the [M] by!")
+ to_chat(src, span_warning("We cannot find a path to sting \the [M] by!"))
return 0
return 1
@@ -227,7 +227,7 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!T)
return
if(T.isSynthetic())
- to_chat(src, "We are unable to pierce the outer shell of [T].")
+ to_chat(src, span_notice("We are unable to pierce the outer shell of [T]."))
return
if(!(T in view(changeling.sting_range))) return
if(!sting_can_reach(T, changeling.sting_range)) return
@@ -235,10 +235,10 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
changeling.chem_charges -= required_chems
changeling.sting_range = 1
- src.verbs -= verb_path
- spawn(10) src.verbs += verb_path
+ remove_verb(src, verb_path)
+ spawn(10) add_verb(src, verb_path)
- to_chat(src, "We stealthily sting [T].")
+ to_chat(src, span_notice("We stealthily sting [T]."))
if(!T.mind || !T.mind.changeling) return T //T will be affected by the sting
- to_chat(T, "You feel a tiny prick.")
+ to_chat(T, span_warning("You feel a tiny prick."))
return
diff --git a/code/game/gamemodes/changeling/generic_equip_procs.dm b/code/game/gamemodes/changeling/generic_equip_procs.dm
index fa7ffc3d18c..21d0b5b73be 100644
--- a/code/game/gamemodes/changeling/generic_equip_procs.dm
+++ b/code/game/gamemodes/changeling/generic_equip_procs.dm
@@ -16,9 +16,9 @@
//First, check if we're already wearing the armor, and if so, take it off.
if(istype(M.wear_suit, armor_type) || istype(M.head, helmet_type) || istype(M.shoes, boot_type))
- M.visible_message("[M] casts off their [M.wear_suit.name]!",
- "We cast off our [M.wear_suit.name]",
- "You hear the organic matter ripping and tearing!")
+ M.visible_message(span_warning("[M] casts off their [M.wear_suit.name]!"),
+ span_warning("We cast off our [M.wear_suit.name]"),
+ span_warningplain("You hear the organic matter ripping and tearing!"))
if(istype(M.wear_suit, armor_type))
qdel(M.wear_suit)
if(istype(M.head, helmet_type))
@@ -32,7 +32,7 @@
return 1
if(M.head || M.wear_suit) //Make sure our slots aren't full
- to_chat(src, "We require nothing to be on our head, and we cannot wear any external suits, or shoes.")
+ to_chat(src, span_warning("We require nothing to be on our head, and we cannot wear any external suits, or shoes."))
return 0
var/obj/item/clothing/suit/A = new armor_type(src)
@@ -120,14 +120,14 @@
if(success)
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[src] pulls on their clothes, peeling it off along with parts of their skin attached!",
- "We remove and deform our equipment.")
+ visible_message(span_warning("[src] pulls on their clothes, peeling it off along with parts of their skin attached!"),
+ span_notice("We remove and deform our equipment."))
M.mind.changeling.armor_deployed = 0
return success
else
- to_chat(M, "We begin growing our new equipment...")
+ to_chat(M, span_notice("We begin growing our new equipment..."))
var/list/grown_items_list = list()
@@ -223,8 +223,8 @@
var/feedback = english_list(grown_items_list, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
- to_chat(M, "We have grown [feedback].")
-
+ to_chat(M, span_notice("We have grown [feedback]."))
+
if(success)
M.mind.changeling.armor_deployed = 1
M.mind.changeling.chem_charges -= 10
@@ -242,13 +242,13 @@
var/mob/living/carbon/human/M = src
if(M.hands_are_full()) //Make sure our hands aren't full.
- to_chat(src, "Our hands are full. Drop something first.")
+ to_chat(src, span_warning("Our hands are full. Drop something first."))
return 0
- var/obj/item/weapon/W = new weapon_type(src)
+ var/obj/item/W = new weapon_type(src)
src.put_in_hands(W)
src.mind.changeling.chem_charges -= cost
if(make_sound)
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index e532396176b..1523855a127 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -14,45 +14,45 @@
var/datum/changeling/changeling = changeling_power(0,0,100)
if(!changeling) return
- var/obj/item/weapon/grab/G = src.get_active_hand()
+ var/obj/item/grab/G = src.get_active_hand()
if(!istype(G))
- to_chat(src, "We must be grabbing a creature in our active hand to absorb them.")
+ to_chat(src, span_warning("We must be grabbing a creature in our active hand to absorb them."))
return
var/mob/living/carbon/human/T = G.affecting
if(!istype(T) || T.isSynthetic())
- to_chat(src, "\The [T] is not compatible with our biology.")
+ to_chat(src, span_warning("\The [T] is not compatible with our biology."))
return
if(T.species.flags & NO_SCAN)
- to_chat(src, "We do not know how to parse this creature's DNA!")
+ to_chat(src, span_warning("We do not know how to parse this creature's DNA!"))
return
if(HUSK in T.mutations) //Lings can always absorb other lings, unless someone beat them to it first.
if(!T.mind.changeling || T.mind.changeling && T.mind.changeling.geneticpoints < 0)
- to_chat(src, "This creature's DNA is ruined beyond useability!")
+ to_chat(src, span_warning("This creature's DNA is ruined beyond useability!"))
return
if(G.state != GRAB_KILL)
- to_chat(src, "We must have a tighter grip to absorb this creature.")
+ to_chat(src, span_warning("We must have a tighter grip to absorb this creature."))
return
if(changeling.isabsorbing)
- to_chat(src, "We are already absorbing!")
+ to_chat(src, span_warning("We are already absorbing!"))
return
changeling.isabsorbing = 1
for(var/stage = 1, stage<=3, stage++)
switch(stage)
if(1)
- to_chat(src, "This creature is compatible. We must hold still...")
+ to_chat(src, span_notice("This creature is compatible. We must hold still..."))
if(2)
- to_chat(src, "We extend a proboscis.")
- src.visible_message("[src] extends a proboscis!")
+ to_chat(src, span_notice("We extend a proboscis."))
+ src.visible_message(span_warning("[src] extends a proboscis!"))
if(3)
- to_chat(src, "We stab [T] with the proboscis.")
- src.visible_message("[src] stabs [T] with the proboscis!")
- to_chat(T, "You feel a sharp stabbing pain!")
+ to_chat(src, span_notice("We stab [T] with the proboscis."))
+ src.visible_message(span_danger("[src] stabs [T] with the proboscis!"))
+ to_chat(T, span_danger("You feel a sharp stabbing pain!"))
add_attack_logs(src,T,"Absorbed (changeling)")
var/obj/item/organ/external/affecting = T.get_organ(src.zone_sel.selecting)
if(affecting.take_damage(39,0,1,0,"large organic needle"))
@@ -60,13 +60,13 @@
feedback_add_details("changeling_powers","A[stage]")
if(!do_mob(src, T, 150) || G.state != GRAB_KILL)
- to_chat(src, "Our absorption of [T] has been interrupted!")
+ to_chat(src, span_warning("Our absorption of [T] has been interrupted!"))
changeling.isabsorbing = 0
return
- to_chat(src, "We have absorbed [T]!")
- src.visible_message("[src] sucks the fluids from [T]!")
- to_chat(T, "You have been absorbed by the changeling!")
+ to_chat(src, span_notice("We have absorbed [T]!"))
+ src.visible_message(span_danger("[src] sucks the fluids from [T]!"))
+ to_chat(T, span_danger("You have been absorbed by the changeling!"))
adjust_nutrition(T.nutrition)
changeling.chem_charges += 10
if(changeling.readapts <= 0)
@@ -75,7 +75,7 @@
if(changeling.readapts > changeling.max_readapts)
changeling.readapts = changeling.max_readapts
- to_chat(src, "We can now re-adapt, reverting our evolution so that we may start anew, if needed.")
+ to_chat(src, span_notice("We can now re-adapt, reverting our evolution so that we may start anew, if needed."))
var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages, T.identifying_gender, T.flavor_texts, T.modifiers)
absorbDNA(newDNA)
@@ -97,7 +97,7 @@
changeling.geneticpoints += 4
changeling.max_geneticpoints += 4
- to_chat(src, "We absorbed another changeling, and we grow stronger. Our genomes increase.")
+ to_chat(src, span_notice("We absorbed another changeling, and we grow stronger. Our genomes increase."))
T.mind.changeling.chem_charges = 0
T.mind.changeling.geneticpoints = -1
@@ -110,4 +110,4 @@
T.death(0)
T.Drain()
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/armblade.dm b/code/game/gamemodes/changeling/powers/armblade.dm
index ffdc9b4ae37..52a83f8e9b8 100644
--- a/code/game/gamemodes/changeling/powers/armblade.dm
+++ b/code/game/gamemodes/changeling/powers/armblade.dm
@@ -13,12 +13,12 @@
set name = "Arm Blade (20)"
if(src.mind.changeling.recursive_enhancement)
- if(changeling_generic_weapon(/obj/item/weapon/melee/changeling/arm_blade/greater))
- to_chat(src, "We prepare an extra sharp blade.")
+ if(changeling_generic_weapon(/obj/item/melee/changeling/arm_blade/greater))
+ to_chat(src, span_notice("We prepare an extra sharp blade."))
return 1
else
- if(changeling_generic_weapon(/obj/item/weapon/melee/changeling/arm_blade))
+ if(changeling_generic_weapon(/obj/item/melee/changeling/arm_blade))
return 1
return 0
@@ -38,16 +38,16 @@
set name = "Claw (15)"
if(src.mind.changeling.recursive_enhancement)
- if(changeling_generic_weapon(/obj/item/weapon/melee/changeling/claw/greater, 1, 15))
- to_chat(src, "We prepare an extra sharp claw.")
+ if(changeling_generic_weapon(/obj/item/melee/changeling/claw/greater, 1, 15))
+ to_chat(src, span_notice("We prepare an extra sharp claw."))
return 1
else
- if(changeling_generic_weapon(/obj/item/weapon/melee/changeling/claw, 1, 15))
+ if(changeling_generic_weapon(/obj/item/melee/changeling/claw, 1, 15))
return 1
return 0
-/obj/item/weapon/melee/changeling
+/obj/item/melee/changeling
name = "arm weapon"
desc = "A grotesque weapon made out of bone and flesh that cleaves through people as a hot knife through butter."
icon = 'icons/obj/weapons.dmi'
@@ -65,30 +65,30 @@
defend_chance = 40 // The base chance for the weapon to parry.
projectile_parry_chance = 15 // The base chance for a projectile to be deflected.
-/obj/item/weapon/melee/changeling/New(location)
+/obj/item/melee/changeling/New(location)
..()
START_PROCESSING(SSobj, src)
if(ismob(loc))
- visible_message("A grotesque weapon forms around [loc.name]\'s arm!",
- "Our arm twists and mutates, transforming it into a deadly weapon.",
- "You hear organic matter ripping and tearing!")
+ visible_message(span_warning("A grotesque weapon forms around [loc.name]\'s arm!"),
+ span_warning("Our arm twists and mutates, transforming it into a deadly weapon."),
+ span_warningplain("You hear organic matter ripping and tearing!"))
src.creator = loc
-/obj/item/weapon/melee/changeling/dropped(mob/user)
- visible_message("With a sickening crunch, [creator] reforms their arm!",
- "We assimilate the weapon back into our body.",
- "You hear organic matter ripping and tearing!")
+/obj/item/melee/changeling/dropped(mob/user)
+ visible_message(span_warning("With a sickening crunch, [creator] reforms their arm!"),
+ span_notice("We assimilate the weapon back into our body."),
+ span_warningplain("You hear organic matter ripping and tearing!"))
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
spawn(1)
if(src)
qdel(src)
-/obj/item/weapon/melee/changeling/Destroy()
+/obj/item/melee/changeling/Destroy()
STOP_PROCESSING(SSobj, src)
creator = null
..()
-/obj/item/weapon/melee/changeling/process() //Stolen from ninja swords.
+/obj/item/melee/changeling/process() //Stolen from ninja swords.
if(!creator || loc != creator || !creator.item_is_in_hands(src))
// Tidy up a bit.
if(istype(loc,/mob/living))
@@ -105,19 +105,19 @@
if(src)
qdel(src)
-/obj/item/weapon/melee/changeling/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
+/obj/item/melee/changeling/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
if(default_parry_check(user, attacker, damage_source) && prob(defend_chance))
- user.visible_message("\The [user] parries [attack_text] with \the [src]!")
+ user.visible_message(span_danger("\The [user] parries [attack_text] with \the [src]!"))
playsound(src, 'sound/weapons/slash.ogg', 50, 1)
return 1
if(unique_parry_check(user, attacker, damage_source) && prob(projectile_parry_chance))
- user.visible_message("\The [user] deflects [attack_text] with \the [src]!")
+ user.visible_message(span_danger("\The [user] deflects [attack_text] with \the [src]!"))
playsound(src, 'sound/weapons/slash.ogg', 50, 1)
return 1
return 0
-/obj/item/weapon/melee/changeling/unique_parry_check(mob/user, mob/attacker, atom/damage_source)
+/obj/item/melee/changeling/unique_parry_check(mob/user, mob/attacker, atom/damage_source)
if(user.incapacitated() || !istype(damage_source, /obj/item/projectile))
return 0
@@ -127,7 +127,7 @@
return 1
-/obj/item/weapon/melee/changeling/arm_blade
+/obj/item/melee/changeling/arm_blade
name = "arm blade"
desc = "A grotesque blade made out of bone and flesh that cleaves through people as a hot knife through butter."
icon_state = "arm_blade"
@@ -140,14 +140,14 @@
defend_chance = 60
projectile_parry_chance = 25
-/obj/item/weapon/melee/changeling/arm_blade/greater
+/obj/item/melee/changeling/arm_blade/greater
name = "arm greatblade"
desc = "A grotesque blade made out of bone and flesh that cleaves through people and armor as a hot knife through butter."
armor_penetration = 30
defend_chance = 70
projectile_parry_chance = 35
-/obj/item/weapon/melee/changeling/claw
+/obj/item/melee/changeling/claw
name = "hand claw"
desc = "A grotesque claw made out of bone and flesh that cleaves through people as a hot knife through butter."
icon_state = "ling_claw"
@@ -158,7 +158,7 @@
defend_chance = 50
projectile_parry_chance = 15
-/obj/item/weapon/melee/changeling/claw/greater
+/obj/item/melee/changeling/claw/greater
name = "hand greatclaw"
force = 20
armor_penetration = 20
diff --git a/code/game/gamemodes/changeling/powers/armor.dm b/code/game/gamemodes/changeling/powers/armor.dm
index 5a6db52833a..55b55ada488 100644
--- a/code/game/gamemodes/changeling/powers/armor.dm
+++ b/code/game/gamemodes/changeling/powers/armor.dm
@@ -37,16 +37,16 @@
desc = "A huge, bulky mass of pressure and temperature-resistant organic tissue, evolved to facilitate space travel."
flags = 0 //Not THICKMATERIAL because it's organic tissue, so if somebody tries to inject something into it,
//it still ends up in your blood. (also balance but muh fluff)
- allowed = list(/obj/item/device/flashlight, /obj/item/weapon/tank/emergency/oxygen, /obj/item/weapon/tank/oxygen)
+ allowed = list(/obj/item/flashlight, /obj/item/tank/emergency/oxygen, /obj/item/tank/oxygen)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) //No armor at all.
canremove = FALSE
/obj/item/clothing/suit/space/changeling/New()
..()
if(ismob(loc))
- loc.visible_message("[loc.name]\'s flesh rapidly inflates, forming a bloated mass around their body!",
- "We inflate our flesh, creating a spaceproof suit!",
- "You hear organic matter ripping and tearing!")
+ loc.visible_message(span_warning("[loc.name]\'s flesh rapidly inflates, forming a bloated mass around their body!"),
+ span_warning("We inflate our flesh, creating a spaceproof suit!"),
+ span_warningplain("You hear organic matter ripping and tearing!"))
/obj/item/clothing/suit/space/changeling/dropped()
qdel(src)
@@ -67,7 +67,7 @@
desc = "A suction cupped mass of flesh, shaped like a foot."
name = "fleshy grippers"
icon_state = "lingspacesuit"
- action_button_name = "Toggle Grippers"
+ actions_types = list(/datum/action/item_action/toggle_grippers)
canremove = FALSE
/obj/item/clothing/shoes/magboots/changeling/set_slowdown()
@@ -108,9 +108,9 @@
/obj/item/clothing/suit/space/changeling/armored/New()
..()
if(ismob(loc))
- loc.visible_message("[loc.name]\'s flesh turns black, quickly transforming into a hard, chitinous mass!",
- "We harden our flesh, creating a suit of armor!",
- "You hear organic matter ripping and tearing!")
+ loc.visible_message(span_warning("[loc.name]\'s flesh turns black, quickly transforming into a hard, chitinous mass!"),
+ span_warning("We harden our flesh, creating a suit of armor!"),
+ span_warningplain("You hear organic matter ripping and tearing!"))
/obj/item/clothing/head/helmet/space/changeling/armored
name = "chitinous mass"
@@ -124,7 +124,7 @@
desc = "A tough, hard mass of chitin, with long talons for digging into terrain."
name = "chitinous talons"
icon_state = "lingarmor"
- action_button_name = "Toggle Talons"
+ actions_types = list(/datum/action/item_action/toggle_talons)
/obj/item/clothing/gloves/combat/changeling //Combined insulated/fireproof gloves
name = "chitinous gauntlets"
diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
index 6e29bf939cd..3498e5df4d9 100644
--- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
+++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm
@@ -25,12 +25,12 @@
if(active)
src.mind.changeling.chem_charges -= 5
- to_chat(C, "We feel a minute twitch in our eyes, and a hidden layer to the world is revealed.")
+ to_chat(C, span_notice("We feel a minute twitch in our eyes, and a hidden layer to the world is revealed."))
C.add_modifier(/datum/modifier/changeling/thermal_sight, 0, src)
// C.permanent_sight_flags |= SEE_MOBS
// C.dna.species.invis_sight = SEE_INVISIBLE_MINIMUM
else
- to_chat(C, "Our vision dulls.")
+ to_chat(C, span_notice("Our vision dulls."))
C.remove_modifiers_of_type(/datum/modifier/changeling/thermal_sight)
// C.permanent_sight_flags &= ~SEE_MOBS
// C.dna.species.invis_sight = initial(user.dna.species.invis_sight)
diff --git a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm
index ca92d67ff74..cb1938fc1ce 100644
--- a/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm
+++ b/code/game/gamemodes/changeling/powers/bioelectrogenesis.dm
@@ -24,11 +24,11 @@
if(held_item == null)
if(src.mind.changeling.recursive_enhancement)
- if(changeling_generic_weapon(/obj/item/weapon/electric_hand/efficent,0))
- to_chat(src, "We will shock others more efficently.")
+ if(changeling_generic_weapon(/obj/item/electric_hand/efficent,0))
+ to_chat(src, span_notice("We will shock others more efficently."))
return 1
else
- if(changeling_generic_weapon(/obj/item/weapon/electric_hand,0)) //Chemical cost is handled in the equip proc.
+ if(changeling_generic_weapon(/obj/item/electric_hand,0)) //Chemical cost is handled in the equip proc.
return 1
return 0
@@ -40,8 +40,8 @@
siemens = gloves.siemens_coefficient
//If we're grabbing someone, electrocute them.
- if(istype(held_item,/obj/item/weapon/grab))
- var/obj/item/weapon/grab/G = held_item
+ if(istype(held_item,/obj/item/grab))
+ var/obj/item/grab/G = held_item
if(G.affecting)
G.affecting.electrocute_act(10 * siemens, src, 1.0, BP_TORSO, 0)
var/agony = 80 * siemens //Does more than if hit with an electric hand, since grabbing is slower.
@@ -50,11 +50,11 @@
add_attack_logs(src,G.affecting,"Changeling shocked")
if(siemens)
- visible_message("Arcs of electricity strike [G.affecting]!",
- "Our hand channels raw electricity into [G.affecting].",
- "You hear sparks!")
+ visible_message(span_warning("Arcs of electricity strike [G.affecting]!"),
+ span_warning("Our hand channels raw electricity into [G.affecting]."),
+ span_warningplain("You hear sparks!"))
else
- to_chat(src, "Our gloves block us from shocking \the [G.affecting].")
+ to_chat(src, span_warning("Our gloves block us from shocking \the [G.affecting]."))
src.mind.changeling.chem_charges -= 10
return 1
@@ -65,18 +65,18 @@
var/list/L = new() //We make a new list to avoid copypasta.
//Check our hand.
- if(istype(held_item,/obj/item/weapon/cell))
+ if(istype(held_item,/obj/item/cell))
L.Add(held_item)
//Now check our hand's item's contents, so we can recharge guns and other stuff.
- for(var/obj/item/weapon/cell/cell in held_item.contents)
+ for(var/obj/item/cell/cell in held_item.contents)
L.Add(cell)
//Now for the actual recharging.
- for(var/obj/item/weapon/cell/cell in L)
- visible_message("Some sparks fall out from \the [src.name]\'s [held_item]!",
- "Our hand channels raw electricity into \the [held_item].",
- "You hear sparks!")
+ for(var/obj/item/cell/cell in L)
+ visible_message(span_warning("Some sparks fall out from \the [src.name]\'s [held_item]!"),
+ span_warning("Our hand channels raw electricity into \the [held_item]."),
+ span_warningplain("You hear sparks!"))
var/i = 10
if(siemens)
while(i)
@@ -92,12 +92,12 @@
sleep(1 SECOND)
success = 1
if(success == 0) //If we couldn't do anything with the ability, don't deduct the chemicals.
- to_chat(src, "We are unable to affect \the [held_item].")
+ to_chat(src, span_warning("We are unable to affect \the [held_item]."))
else
src.mind.changeling.chem_charges -= 10
return success
-/obj/item/weapon/electric_hand
+/obj/item/electric_hand
name = "electrified hand"
desc = "You could probably shock someone badly if you touched them, or recharge something."
icon = 'icons/obj/weapons.dmi'
@@ -108,25 +108,25 @@
var/agony_amount = 60
var/electrocute_amount = 10
-/obj/item/weapon/electric_hand/efficent
+/obj/item/electric_hand/efficent
shock_cost = 5
agony_amount = 80
electrocute_amount = 20
-/obj/item/weapon/electric_hand/New()
+/obj/item/electric_hand/New()
if(ismob(loc))
- visible_message("Electrical arcs form around [loc.name]\'s hand!",
- "We store a charge of electricity in our hand.",
- "You hear crackling electricity!")
+ visible_message(span_warning("Electrical arcs form around [loc.name]\'s hand!"),
+ span_warning("We store a charge of electricity in our hand."),
+ span_warningplain("You hear crackling electricity!"))
var/T = get_turf(src)
new /obj/effect/effect/sparks(T)
-/obj/item/weapon/electric_hand/dropped(mob/user)
+/obj/item/electric_hand/dropped(mob/user)
spawn(1)
if(src)
qdel(src)
-/obj/item/weapon/electric_hand/afterattack(var/atom/target, var/mob/living/carbon/human/user, proximity)
+/obj/item/electric_hand/afterattack(var/atom/target, var/mob/living/carbon/human/user, proximity)
if(!target)
return
if(!proximity)
@@ -143,7 +143,7 @@
var/mob/living/carbon/C = target
if(user.mind.changeling.chem_charges < shock_cost)
- to_chat(src, "We require more chemicals to electrocute [C]!")
+ to_chat(src, span_warning("We require more chemicals to electrocute [C]!"))
return 0
C.electrocute_act(electrocute_amount * siemens,src,1.0,BP_TORSO)
@@ -152,11 +152,11 @@
add_attack_logs(user,C,"Shocked with [src]")
if(siemens)
- visible_message("Arcs of electricity strike [C]!",
- "Our hand channels raw electricity into [C]",
- "You hear sparks!")
+ visible_message(span_warning("Arcs of electricity strike [C]!"),
+ span_warning("Our hand channels raw electricity into [C]"),
+ span_warningplain("You hear sparks!"))
else
- to_chat(src, "Our gloves block us from shocking \the [C].")
+ to_chat(src, span_warning("Our gloves block us from shocking \the [C]."))
//qdel(src) //Since we're no longer a one hit stun, we need to stick around.
user.mind.changeling.chem_charges -= shock_cost
return 1
@@ -165,15 +165,15 @@
var/mob/living/silicon/S = target
if(user.mind.changeling.chem_charges < 10)
- to_chat(src, "We require more chemicals to electrocute [S]!")
+ to_chat(src, span_warning("We require more chemicals to electrocute [S]!"))
return 0
S.electrocute_act(60,src,0.75) //If only they had surge protectors.
if(siemens)
- visible_message("Arcs of electricity strike [S]!",
- "Our hand channels raw electricity into [S]",
- "You hear sparks!")
- to_chat(S, "Warning: Electrical surge detected!")
+ visible_message(span_warning("Arcs of electricity strike [S]!"),
+ span_warning("Our hand channels raw electricity into [S]"),
+ span_warningplain("You hear sparks!"))
+ to_chat(S, span_danger("Warning: Electrical surge detected!"))
//qdel(src)
user.mind.changeling.chem_charges -= 10
return 1
@@ -183,10 +183,10 @@
var/success = 0
var/obj/T = target
//We can also recharge things we touch, such as APCs or hardsuits.
- for(var/obj/item/weapon/cell/cell in T.contents)
- visible_message("Some sparks fall out from \the [target]!",
- "Our hand channels raw electricity into \the [target].",
- "You hear sparks!")
+ for(var/obj/item/cell/cell in T.contents)
+ visible_message(span_warning("Some sparks fall out from \the [target]!"),
+ span_warning("Our hand channels raw electricity into \the [target]."),
+ span_warningplain("You hear sparks!"))
var/i = 10
if(siemens)
while(i)
@@ -205,7 +205,7 @@
success = 1
break
if(success == 0)
- to_chat(src, "We are unable to affect \the [target].")
+ to_chat(src, span_warning("We are unable to affect \the [target]."))
else
qdel(src)
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/blind_sting.dm b/code/game/gamemodes/changeling/powers/blind_sting.dm
index f4721db660c..40d5f968248 100644
--- a/code/game/gamemodes/changeling/powers/blind_sting.dm
+++ b/code/game/gamemodes/changeling/powers/blind_sting.dm
@@ -16,15 +16,15 @@
if(!T)
return 0
add_attack_logs(src,T,"Blind sting (changeling)")
- to_chat(T, "Your eyes burn horrificly!")
+ to_chat(T, span_danger("Your eyes burn horrificly!"))
T.disabilities |= NEARSIGHTED
var/duration = 300
if(src.mind.changeling.recursive_enhancement)
duration = duration + 150
- to_chat(src, "They will be deprived of sight for longer.")
+ to_chat(src, span_notice("They will be deprived of sight for longer."))
spawn(duration)
T.disabilities &= ~NEARSIGHTED
T.Blind(10)
T.eye_blurry = 20
feedback_add_details("changeling_powers","BS")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/boost_range.dm b/code/game/gamemodes/changeling/powers/boost_range.dm
index a22130484ca..1b818a1f032 100644
--- a/code/game/gamemodes/changeling/powers/boost_range.dm
+++ b/code/game/gamemodes/changeling/powers/boost_range.dm
@@ -18,14 +18,14 @@
if(!changeling)
return 0
changeling.chem_charges -= 10
- to_chat(src, "Your throat adjusts to launch the sting.")
+ to_chat(src, span_notice("Your throat adjusts to launch the sting."))
var/range = 2
if(src.mind.changeling.recursive_enhancement)
range = range + 3
- to_chat(src, "We can fire our next sting from five squares away.")
+ to_chat(src, span_notice("We can fire our next sting from five squares away."))
changeling.sting_range = range
- src.verbs -= /mob/proc/changeling_boost_range
+ remove_verb(src, /mob/proc/changeling_boost_range)
spawn(5)
- src.verbs += /mob/proc/changeling_boost_range
+ add_verb(src, /mob/proc/changeling_boost_range)
feedback_add_details("changeling_powers","RS")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/cryo_sting.dm b/code/game/gamemodes/changeling/powers/cryo_sting.dm
index e1a2b10cff9..adf6cc07514 100644
--- a/code/game/gamemodes/changeling/powers/cryo_sting.dm
+++ b/code/game/gamemodes/changeling/powers/cryo_sting.dm
@@ -20,12 +20,12 @@
var/inject_amount = 10
if(src.mind.changeling.recursive_enhancement)
inject_amount = inject_amount * 1.5
- to_chat(src, "We inject extra chemicals.")
+ to_chat(src, span_notice("We inject extra chemicals."))
if(T.reagents)
T.reagents.add_reagent("cryotoxin", inject_amount)
feedback_add_details("changeling_powers","CS")
- src.verbs -= /mob/proc/changeling_cryo_sting
+ remove_verb(src, /mob/proc/changeling_cryo_sting)
spawn(3 MINUTES)
- to_chat(src, "Our cryogenic string is ready to be used once more.")
- src.verbs |= /mob/proc/changeling_cryo_sting
- return 1
\ No newline at end of file
+ to_chat(src, span_notice("Our cryogenic string is ready to be used once more."))
+ add_verb(src, /mob/proc/changeling_cryo_sting)
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/darkvision.dm b/code/game/gamemodes/changeling/powers/darkvision.dm
index 6fbb2954ba8..3139a85e39b 100644
--- a/code/game/gamemodes/changeling/powers/darkvision.dm
+++ b/code/game/gamemodes/changeling/powers/darkvision.dm
@@ -19,8 +19,8 @@
var/mob/living/carbon/C = src
C.seedarkness = !C.seedarkness
if(C.seedarkness)
- to_chat(C, "We allow the shadows to return.")
+ to_chat(C, span_notice("We allow the shadows to return."))
else
- to_chat(C, "We no longer need light to see.")
+ to_chat(C, span_notice("We no longer need light to see."))
- return 0
\ No newline at end of file
+ return 0
diff --git a/code/game/gamemodes/changeling/powers/deaf_sting.dm b/code/game/gamemodes/changeling/powers/deaf_sting.dm
index 7b39e907202..e03205665cd 100644
--- a/code/game/gamemodes/changeling/powers/deaf_sting.dm
+++ b/code/game/gamemodes/changeling/powers/deaf_sting.dm
@@ -19,9 +19,9 @@
var/duration = 300
if(src.mind.changeling.recursive_enhancement)
duration = duration + 100
- to_chat(src, "They will be unable to hear for a little longer.")
- to_chat(T, "Your ears pop and begin ringing loudly!")
+ to_chat(src, span_notice("They will be unable to hear for a little longer."))
+ to_chat(T, span_danger("Your ears pop and begin ringing loudly!"))
T.sdisabilities |= DEAF
spawn(duration) T.sdisabilities &= ~DEAF
feedback_add_details("changeling_powers","DS")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/death_sting.dm b/code/game/gamemodes/changeling/powers/death_sting.dm
index 2eb1e476bd4..9acb09e8b2f 100644
--- a/code/game/gamemodes/changeling/powers/death_sting.dm
+++ b/code/game/gamemodes/changeling/powers/death_sting.dm
@@ -14,10 +14,10 @@
if(!T)
return 0
add_attack_logs(src,T,"Death sting (changeling)")
- to_chat(T, "You feel a small prick and your chest becomes tight.")
+ to_chat(T, span_danger("You feel a small prick and your chest becomes tight."))
T.silent = 10
T.Paralyse(10)
T.make_jittery(100)
if(T.reagents) T.reagents.add_reagent("lexorin", 40)
feedback_add_details("changeling_powers","DTHS")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm b/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm
index f50460a826b..bbd63db65ff 100644
--- a/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm
+++ b/code/game/gamemodes/changeling/powers/delayed_toxin_sting.dm
@@ -12,7 +12,7 @@
name = "delayed toxin injection"
hidden = TRUE
stacks = MODIFIER_STACK_FORBID
- on_expired_text = "You feel a burning sensation flowing through your veins!"
+ on_expired_text = span_danger("You feel a burning sensation flowing through your veins!")
/datum/modifier/delayed_toxin_sting/on_expire()
holder.adjustToxLoss(rand(20, 30))
@@ -32,10 +32,10 @@
var/type_to_give = /datum/modifier/delayed_toxin_sting
if(src.mind.changeling.recursive_enhancement)
type_to_give = /datum/modifier/delayed_toxin_sting/strong
- to_chat(src, "Our toxin will be extra potent, when it strikes.")
+ to_chat(src, span_notice("Our toxin will be extra potent, when it strikes."))
T.add_modifier(type_to_give, 2 MINUTES)
feedback_add_details("changeling_powers","DTS")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/digital_camo.dm b/code/game/gamemodes/changeling/powers/digital_camo.dm
index 9574b465da7..cca4f054aed 100644
--- a/code/game/gamemodes/changeling/powers/digital_camo.dm
+++ b/code/game/gamemodes/changeling/powers/digital_camo.dm
@@ -19,9 +19,9 @@
var/mob/living/carbon/human/C = src
if(C.digitalcamo)
- to_chat(C, "We return to normal.")
+ to_chat(C, span_notice("We return to normal."))
else
- to_chat(C, "We distort our form to prevent AI-tracking.")
+ to_chat(C, span_notice("We distort our form to prevent AI-tracking."))
C.digitalcamo = !C.digitalcamo
spawn(0)
@@ -29,8 +29,8 @@
C.mind.changeling.chem_charges = max(C.mind.changeling.chem_charges - 1, 0)
sleep(40)
- src.verbs -= /mob/proc/changeling_digitalcamo
+ remove_verb(src, /mob/proc/changeling_digitalcamo)
spawn(5)
- src.verbs += /mob/proc/changeling_digitalcamo
+ add_verb(src, /mob/proc/changeling_digitalcamo)
feedback_add_details("changeling_powers","CAM")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/electric_lockpick.dm b/code/game/gamemodes/changeling/powers/electric_lockpick.dm
index 262d90429f3..3b4edc576f7 100644
--- a/code/game/gamemodes/changeling/powers/electric_lockpick.dm
+++ b/code/game/gamemodes/changeling/powers/electric_lockpick.dm
@@ -21,28 +21,28 @@
return 0
if(held_item == null)
- if(changeling_generic_weapon(/obj/item/weapon/finger_lockpick,0,5)) //Chemical cost is handled in the equip proc.
+ if(changeling_generic_weapon(/obj/item/finger_lockpick,0,5)) //Chemical cost is handled in the equip proc.
return 1
return 0
-/obj/item/weapon/finger_lockpick
+/obj/item/finger_lockpick
name = "finger lockpick"
desc = "This finger appears to be an organic datajack."
icon = 'icons/obj/weapons.dmi'
icon_state = "electric_hand"
show_examine = FALSE
-/obj/item/weapon/finger_lockpick/New()
+/obj/item/finger_lockpick/New()
if(ismob(loc))
- to_chat(loc, "We shape our finger to fit inside electronics, and are ready to force them open.")
+ to_chat(loc, span_notice("We shape our finger to fit inside electronics, and are ready to force them open."))
-/obj/item/weapon/finger_lockpick/dropped(mob/user)
- to_chat(user, "We discreetly shape our finger back to a less suspicious form.")
+/obj/item/finger_lockpick/dropped(mob/user)
+ to_chat(user, span_notice("We discreetly shape our finger back to a less suspicious form."))
spawn(1)
if(src)
qdel(src)
-/obj/item/weapon/finger_lockpick/afterattack(var/atom/target, var/mob/living/user, proximity)
+/obj/item/finger_lockpick/afterattack(var/atom/target, var/mob/living/user, proximity)
if(!target)
return
if(!proximity)
@@ -53,13 +53,13 @@
var/datum/changeling/ling_datum = user.mind.changeling
if(ling_datum.chem_charges < 10)
- to_chat(user, "We require more chemicals to do that.")
+ to_chat(user, span_warning("We require more chemicals to do that."))
return
//Airlocks require an ugly block of code, but we don't want to just call emag_act(), since we don't want to break airlocks forever.
if(istype(target,/obj/machinery/door))
var/obj/machinery/door/door = target
- to_chat(user, "We send an electrical pulse up our finger, and into \the [target], attempting to open it.")
+ to_chat(user, span_notice("We send an electrical pulse up our finger, and into \the [target], attempting to open it."))
if(door.density && door.operable())
door.do_animate("spark")
@@ -70,15 +70,15 @@
if(airlock.locked) //Check if we're bolted.
airlock.unlock()
- to_chat(user, "We've unlocked \the [airlock]. Another pulse is requried to open it.")
+ to_chat(user, span_notice("We've unlocked \the [airlock]. Another pulse is requried to open it."))
else //We're not bolted, so open the door already.
airlock.open()
- to_chat(user, "We've opened \the [airlock].")
+ to_chat(user, span_notice("We've opened \the [airlock]."))
else
door.open() //If we're a windoor, open the windoor.
- to_chat(user, "We've opened \the [door].")
+ to_chat(user, span_notice("We've opened \the [door]."))
else //Probably broken or no power.
- to_chat(user, "The door does not respond to the pulse.")
+ to_chat(user, span_warning("The door does not respond to the pulse."))
door.add_fingerprint(user)
log_and_message_admins("finger-lockpicked \an [door].")
ling_datum.chem_charges -= 10
@@ -86,11 +86,11 @@
else if(istype(target,/obj/)) //This should catch everything else we might miss, without a million typechecks.
var/obj/O = target
- to_chat(user, "We send an electrical pulse up our finger, and into \the [O].")
+ to_chat(user, span_notice("We send an electrical pulse up our finger, and into \the [O]."))
O.add_fingerprint(user)
O.emag_act(1,user,src)
log_and_message_admins("finger-lockpicked \an [O].")
ling_datum.chem_charges -= 10
return 1
- return 0
\ No newline at end of file
+ return 0
diff --git a/code/game/gamemodes/changeling/powers/endoarmor.dm b/code/game/gamemodes/changeling/powers/endoarmor.dm
index d62c52141a0..6ada2865740 100644
--- a/code/game/gamemodes/changeling/powers/endoarmor.dm
+++ b/code/game/gamemodes/changeling/powers/endoarmor.dm
@@ -10,8 +10,8 @@
name = "endoarmor"
desc = "We have hard plating underneath our skin, making us more durable."
- on_created_text = "We feel protective plating form underneath our skin."
- on_expired_text = "Our protective armor underneath our skin fades as we absorb it."
+ on_created_text = span_notice("We feel protective plating form underneath our skin.")
+ on_expired_text = span_notice("Our protective armor underneath our skin fades as we absorb it.")
max_health_flat = 50
/mob/proc/changeling_endoarmor()
@@ -19,4 +19,4 @@
var/mob/living/carbon/human/H = src
H.add_modifier(/datum/modifier/endoarmor)
// H.maxHealth += 50
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/enfeebling_string.dm b/code/game/gamemodes/changeling/powers/enfeebling_string.dm
index 81930a7ebc7..49829aecce5 100644
--- a/code/game/gamemodes/changeling/powers/enfeebling_string.dm
+++ b/code/game/gamemodes/changeling/powers/enfeebling_string.dm
@@ -15,8 +15,8 @@
max_health_percent = 0.7
outgoing_melee_damage_percent = 0.75
incoming_damage_percent = 1.1
- on_created_text = "You feel a small prick and you feel extremly weak!"
- on_expired_text = "You no longer feel extremly weak."
+ on_created_text = span_danger("You feel a small prick and you feel extremly weak!")
+ on_expired_text = span_notice("You no longer feel extremly weak.")
// Now YOU'RE the Teshari!
/datum/modifier/enfeeble/strong
@@ -40,7 +40,7 @@
var/type_to_give = /datum/modifier/enfeeble
if(src.mind.changeling.recursive_enhancement)
type_to_give = /datum/modifier/enfeeble/strong
- to_chat(src, "We make them extremely weak.")
+ to_chat(src, span_notice("We make them extremely weak."))
H.add_modifier(type_to_give, 2 MINUTES)
feedback_add_details("changeling_powers","ES")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/enrage.dm b/code/game/gamemodes/changeling/powers/enrage.dm
index 00b2193c860..2336b3042a5 100644
--- a/code/game/gamemodes/changeling/powers/enrage.dm
+++ b/code/game/gamemodes/changeling/powers/enrage.dm
@@ -24,10 +24,10 @@
var/modifier_to_use = /datum/modifier/berserk/changeling
if(src.mind.changeling.recursive_enhancement)
modifier_to_use = /datum/modifier/berserk/changeling/recursive
- to_chat(src, "We optimize our levels of anger, which will avoid excessive stress on ourselves.")
+ to_chat(src, span_notice("We optimize our levels of anger, which will avoid excessive stress on ourselves."))
if(add_modifier(modifier_to_use, 30 SECONDS))
changeling.chem_charges -= 30
feedback_add_details("changeling_powers","EN")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm b/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm
index 5d3c1a3be93..f2e2175dfaf 100644
--- a/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm
+++ b/code/game/gamemodes/changeling/powers/epinephrine_overdose.dm
@@ -12,8 +12,8 @@
desc = "We feel limitless amounts of energy surge in our veins. Nothing can stop us!"
stacks = MODIFIER_STACK_EXTEND
- on_created_text = "We feel unstoppable!"
- on_expired_text = "We feel our newfound energy fade..."
+ on_created_text = span_notice("We feel unstoppable!")
+ on_expired_text = span_warning("We feel our newfound energy fade...")
disable_duration_percent = 0
//Recover from stuns.
@@ -28,7 +28,7 @@
changeling.chem_charges -= 30
var/mob/living/carbon/human/C = src
- to_chat(C, "Energy rushes through us. [C.lying ? "We arise." : ""]")
+ to_chat(C, span_notice("Energy rushes through us. [C.lying ? "We arise." : ""]"))
C.set_stat(CONSCIOUS)
C.SetParalysis(0)
C.SetStunned(0)
@@ -63,4 +63,4 @@
M.AdjustStunned(-2)
M.AdjustWeakened(-2)
..()
- return
\ No newline at end of file
+ return
diff --git a/code/game/gamemodes/changeling/powers/escape_restraints.dm b/code/game/gamemodes/changeling/powers/escape_restraints.dm
index ced80d35bf6..504cb884c9e 100644
--- a/code/game/gamemodes/changeling/powers/escape_restraints.dm
+++ b/code/game/gamemodes/changeling/powers/escape_restraints.dm
@@ -19,18 +19,18 @@
if(!changeling)
return 0
if(world.time < changeling.next_escape)
- to_chat(src, "We are still recovering from our last escape...")
+ to_chat(src, span_warning("We are still recovering from our last escape..."))
return 0
if(!(C.handcuffed || C.legcuffed || istype(C.wear_suit,/obj/item/clothing/suit/straight_jacket))) // No need to waste chems if there's nothing to break out of
- to_chat(C, "We are are not restrained in a way we can escape...")
+ to_chat(C, span_warning("We are are not restrained in a way we can escape..."))
return 0
changeling.chem_charges -= 40
- to_chat(C,"We contort our extremities and slip our cuffs.")
+ to_chat(C,span_notice("We contort our extremities and slip our cuffs."))
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
if(C.handcuffed)
- var/obj/item/weapon/W = C.handcuffed
+ var/obj/item/W = C.handcuffed
C.handcuffed = null
if(C.buckled && C.buckled.buckle_require_restraints)
C.buckled.unbuckle_mob()
@@ -42,7 +42,7 @@
if(W)
W.layer = initial(W.layer)
if(C.legcuffed)
- var/obj/item/weapon/W = C.legcuffed
+ var/obj/item/W = C.legcuffed
C.legcuffed = null
C.update_inv_legcuffed()
if(C.client)
@@ -64,4 +64,4 @@
changeling.next_escape = world.time + escape_cooldown //And now we set the timer
feedback_add_details("changeling_powers","ESR")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/extract_dna_sting.dm b/code/game/gamemodes/changeling/powers/extract_dna_sting.dm
index baf80140f14..3806b0ef330 100644
--- a/code/game/gamemodes/changeling/powers/extract_dna_sting.dm
+++ b/code/game/gamemodes/changeling/powers/extract_dna_sting.dm
@@ -24,22 +24,22 @@
return
if(!istype(T) || T.isSynthetic())
- to_chat(src, "\The [T] is not compatible with our biology.")
+ to_chat(src, span_warning("\The [T] is not compatible with our biology."))
return 0
if(T.species.flags & NO_SCAN)
- to_chat(src, "We do not know how to parse this creature's DNA!")
+ to_chat(src, span_warning("We do not know how to parse this creature's DNA!"))
return 0
if(HUSK in T.mutations)
- to_chat(src, "This creature's DNA is ruined beyond useability!")
+ to_chat(src, span_warning("This creature's DNA is ruined beyond useability!"))
return 0
add_attack_logs(src,T,"DNA extraction sting (changeling)")
- var/saved_dna = T.dna.Clone() /// Prevent transforming bugginess.
+ var/saved_dna = T.dna.Clone() /// Prevent transforming bugginess.
var/datum/absorbed_dna/newDNA = new(T.real_name, saved_dna, T.species.name, T.languages, T.identifying_gender, T.flavor_text, T.modifiers)
absorbDNA(newDNA)
feedback_add_details("changeling_powers","ED")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm
index c3c5f2aa15c..8303426dc13 100644
--- a/code/game/gamemodes/changeling/powers/fabricate_clothing.dm
+++ b/code/game/gamemodes/changeling/powers/fabricate_clothing.dm
@@ -6,9 +6,9 @@ var/global/list/changeling_fabricated_clothing = list(
"gloves" = /obj/item/clothing/gloves/chameleon/changeling,
"wear_mask" = /obj/item/clothing/mask/chameleon/changeling,
"glasses" = /obj/item/clothing/glasses/chameleon/changeling,
- "back" = /obj/item/weapon/storage/backpack/chameleon/changeling,
- "belt" = /obj/item/weapon/storage/belt/chameleon/changeling,
- "wear_id" = /obj/item/weapon/card/id/syndicate/changeling
+ "back" = /obj/item/storage/backpack/chameleon/changeling,
+ "belt" = /obj/item/storage/belt/chameleon/changeling,
+ "wear_id" = /obj/item/card/id/syndicate/changeling
)
/datum/power/changeling/fabricate_clothing
@@ -53,8 +53,8 @@ var/global/list/changeling_fabricated_clothing = list(
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/head/chameleon/changeling
@@ -74,8 +74,8 @@ var/global/list/changeling_fabricated_clothing = list(
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/suit/chameleon/changeling
@@ -99,8 +99,8 @@ var/global/list/changeling_fabricated_clothing = list(
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/shoes/chameleon/changeling
@@ -124,11 +124,11 @@ var/global/list/changeling_fabricated_clothing = list(
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
qdel(src)
-/obj/item/weapon/storage/backpack/chameleon/changeling
+/obj/item/storage/backpack/chameleon/changeling
name = "backpack"
icon_state = "backpack"
item_icons = list(
@@ -140,17 +140,17 @@ var/global/list/changeling_fabricated_clothing = list(
origin_tech = list()
canremove = FALSE
-/obj/item/weapon/storage/backpack/chameleon/changeling/emp_act()
+/obj/item/storage/backpack/chameleon/changeling/emp_act()
return
-/obj/item/weapon/storage/backpack/chameleon/changeling/verb/shred()
+/obj/item/storage/backpack/chameleon/changeling/verb/shred()
set name = "Shred Backpack"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
for(var/atom/movable/AM in src.contents) //Dump whatever's in the bag before deleting.
AM.forceMove(get_turf(loc))
qdel(src)
@@ -177,8 +177,8 @@ var/global/list/changeling_fabricated_clothing = list(
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/mask/chameleon/changeling
@@ -203,8 +203,8 @@ var/global/list/changeling_fabricated_clothing = list(
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
qdel(src)
/obj/item/clothing/glasses/chameleon/changeling
@@ -224,11 +224,11 @@ var/global/list/changeling_fabricated_clothing = list(
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
qdel(src)
-/obj/item/weapon/storage/belt/chameleon/changeling
+/obj/item/storage/belt/chameleon/changeling
name = "waist pouch"
desc = "We can store objects in this, as well as shift it's appearance, so that it resembles various common belts."
icon_state = "lingchameleon"
@@ -240,20 +240,20 @@ var/global/list/changeling_fabricated_clothing = list(
origin_tech = list()
canremove = FALSE
-/obj/item/weapon/storage/belt/chameleon/changeling/emp_act()
+/obj/item/storage/belt/chameleon/changeling/emp_act()
return
-/obj/item/weapon/storage/belt/chameleon/changeling/verb/shred()
+/obj/item/storage/belt/chameleon/changeling/verb/shred()
set name = "Shred Belt"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
qdel(src)
-/obj/item/weapon/card/id/syndicate/changeling
+/obj/item/card/id/syndicate/changeling
name = "chitinous card"
desc = "A card that we can reform to resemble identification cards. Due to the nature of the material this is made of, it cannot store any access codes."
icon_state = "changeling"
@@ -264,27 +264,27 @@ var/global/list/changeling_fabricated_clothing = list(
access = null
canremove = FALSE
-/obj/item/weapon/card/id/syndicate/changeling/New(mob/user as mob)
+/obj/item/card/id/syndicate/changeling/New(mob/user as mob)
..()
registered_user = user
-/obj/item/weapon/card/id/syndicate/changeling/Initialize()
+/obj/item/card/id/syndicate/changeling/Initialize()
. = ..()
access = null
-/obj/item/weapon/card/id/syndicate/changeling/verb/shred()
+/obj/item/card/id/syndicate/changeling/verb/shred()
set name = "Shred ID Card"
set category = "Chameleon Items"
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
playsound(src, 'sound/effects/splat.ogg', 30, 1)
- visible_message("[H] tears off [src]!",
- "We remove [src].")
+ visible_message(span_warning("[H] tears off [src]!"),
+ span_notice("We remove [src]."))
qdel(src)
-/obj/item/weapon/card/id/syndicate/changeling/Click() //Since we can't hold it in our hands, and attack_hand() doesn't work if it in inventory...
+/obj/item/card/id/syndicate/changeling/Click() //Since we can't hold it in our hands, and attack_hand() doesn't work if it in inventory...
if(!registered_user)
registered_user = usr
usr.set_id_info(src)
tgui_interact(registered_user)
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/game/gamemodes/changeling/powers/fake_death.dm b/code/game/gamemodes/changeling/powers/fake_death.dm
index daa0b9e2467..bad45391353 100644
--- a/code/game/gamemodes/changeling/powers/fake_death.dm
+++ b/code/game/gamemodes/changeling/powers/fake_death.dm
@@ -19,12 +19,12 @@
var/mob/living/carbon/C = src
if(changeling.max_geneticpoints < 0) //Absorbed by another ling
- to_chat(src, "We have no genomes, not even our own, and cannot regenerate.")
+ to_chat(src, span_danger("We have no genomes, not even our own, and cannot regenerate."))
return 0
- if(!C.stat && tgui_alert(src, "Are we sure we wish to regenerate? We will appear to be dead while doing so.","Revival",list("Yes","No")) == "No")
+ if(!C.stat && tgui_alert(src, "Are we sure we wish to regenerate? We will appear to be dead while doing so.","Revival",list("Yes","No")) != "Yes")
return
- to_chat(C, "We will attempt to regenerate our form.")
+ to_chat(C, span_notice("We will attempt to regenerate our form."))
C.update_canmove()
C.remove_changeling_powers()
@@ -43,11 +43,11 @@
spawn(rand(2 MINUTES, 4 MINUTES))
//The ling will now be able to choose when to revive
- verbs.Add(/mob/proc/changeling_revive)
+ add_verb(src, /mob/proc/changeling_revive)
new /obj/changeling_revive_holder(src)
- to_chat(src, "We are ready to rise. Use the Revive verb when you are ready.")
+ to_chat(src, span_notice(span_giant("We are ready to rise. Use the Revive verb when you are ready.")))
feedback_add_details("changeling_powers","FD")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm
index 05eea72d951..cf4c8d8a2af 100644
--- a/code/game/gamemodes/changeling/powers/fleshmend.dm
+++ b/code/game/gamemodes/changeling/powers/fleshmend.dm
@@ -22,10 +22,10 @@
var/heal_amount = 2
if(src.mind.changeling.recursive_enhancement)
heal_amount = heal_amount * 2
- to_chat(src, "We will heal much faster.")
+ to_chat(src, span_notice("We will heal much faster."))
spawn(0)
- to_chat(src, "We begin to heal ourselves.")
+ to_chat(src, span_notice("We begin to heal ourselves."))
for(var/i = 0, i<50,i++)
if(C)
C.adjustBruteLoss(-heal_amount)
@@ -33,9 +33,9 @@
C.adjustFireLoss(-heal_amount)
sleep(1 SECOND)
- src.verbs -= /mob/proc/changeling_fleshmend
+ remove_verb(src, /mob/proc/changeling_fleshmend)
spawn(50 SECONDS)
- to_chat(src, "Our regeneration has slowed to normal levels.")
- src.verbs += /mob/proc/changeling_fleshmend
+ to_chat(src, span_notice("Our regeneration has slowed to normal levels."))
+ add_verb(src, /mob/proc/changeling_fleshmend)
feedback_add_details("changeling_powers","FM")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm
index d07542875ae..44f66c87910 100644
--- a/code/game/gamemodes/changeling/powers/hivemind.dm
+++ b/code/game/gamemodes/changeling/powers/hivemind.dm
@@ -34,7 +34,7 @@ var/list/datum/dna/hivemind_bank = list()
names += DNA.name
if(names.len <= 0)
- to_chat(src, "The airwaves already have all of our DNA.")
+ to_chat(src, span_notice("The airwaves already have all of our DNA."))
return
var/S = tgui_input_list(src, "Select a DNA to channel:", "Channel DNA", names)
@@ -46,7 +46,7 @@ var/list/datum/dna/hivemind_bank = list()
changeling.chem_charges -= 10
hivemind_bank += chosen_dna
- to_chat(src, "We channel the DNA of [S] to the air.")
+ to_chat(src, span_notice("We channel the DNA of [S] to the air."))
feedback_add_details("changeling_powers","HU")
return 1
@@ -64,7 +64,7 @@ var/list/datum/dna/hivemind_bank = list()
names[DNA.name] = DNA
if(names.len <= 0)
- to_chat(src, "There's no new DNA to absorb from the air.")
+ to_chat(src, span_notice("There's no new DNA to absorb from the air."))
return
var/S = tgui_input_list(src, "Select a DNA to absorb:", "Absorb DNA", names)
@@ -75,6 +75,6 @@ var/list/datum/dna/hivemind_bank = list()
changeling.chem_charges -= 20
absorbDNA(chosen_dna)
- to_chat(src, "We absorb the DNA of [S] from the air.")
+ to_chat(src, span_notice("We absorb the DNA of [S] from the air."))
feedback_add_details("changeling_powers","HD")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/lesser_form.dm b/code/game/gamemodes/changeling/powers/lesser_form.dm
index aa70756344b..9bac29f7972 100644
--- a/code/game/gamemodes/changeling/powers/lesser_form.dm
+++ b/code/game/gamemodes/changeling/powers/lesser_form.dm
@@ -13,22 +13,22 @@
if(!changeling) return
if(src.has_brain_worms())
- to_chat(src, "We cannot perform this ability at the present time!")
+ to_chat(src, span_warning("We cannot perform this ability at the present time!"))
return
var/mob/living/carbon/human/H = src
if(!istype(H) || !H.species.primitive_form)
- to_chat(src, "We cannot perform this ability in this form!")
+ to_chat(src, span_warning("We cannot perform this ability in this form!"))
return
changeling.chem_charges--
H.remove_changeling_powers()
- H.visible_message("[H] transforms!")
+ H.visible_message(span_warning("[H] transforms!"))
changeling.geneticdamage = 30
- to_chat(H, "Our genes cry out!")
+ to_chat(H, span_warning("Our genes cry out!"))
var/list/implants = list() //Try to preserve implants.
- for(var/obj/item/weapon/implant/W in H)
+ for(var/obj/item/implant/W in H)
implants += W
H.monkeyize()
feedback_add_details("changeling_powers","LF")
@@ -57,11 +57,11 @@
changeling.chem_charges--
C.remove_changeling_powers()
- C.visible_message("[C] transforms!")
+ C.visible_message(span_warning("[C] transforms!"))
C.dna = chosen_dna.Clone()
var/list/implants = list()
- for (var/obj/item/weapon/implant/I in C) //Still preserving implants
+ for (var/obj/item/implant/I in C) //Still preserving implants
implants += I
C.transforming = 1
@@ -101,7 +101,7 @@
O.setOxyLoss(C.getOxyLoss())
O.adjustFireLoss(C.getFireLoss())
O.set_stat(C.stat)
- for (var/obj/item/weapon/implant/I in implants)
+ for (var/obj/item/implant/I in implants)
I.loc = O
I.implanted = O
@@ -111,4 +111,4 @@
feedback_add_details("changeling_powers","LFT")
qdel(C)
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/mimic_voice.dm b/code/game/gamemodes/changeling/powers/mimic_voice.dm
index be4a055dc1b..f5d65b8ec2e 100644
--- a/code/game/gamemodes/changeling/powers/mimic_voice.dm
+++ b/code/game/gamemodes/changeling/powers/mimic_voice.dm
@@ -19,17 +19,17 @@
if(changeling.mimicing)
changeling.mimicing = ""
- to_chat(src, "We return our vocal glands to their original location.")
+ to_chat(src, span_notice("We return our vocal glands to their original location."))
return
- var/mimic_voice = sanitize(tgui_input_text(usr, "Enter a name to mimic.", "Mimic Voice", null, MAX_NAME_LEN), MAX_NAME_LEN)
+ var/mimic_voice = sanitize(tgui_input_text(src, "Enter a name to mimic.", "Mimic Voice", null, MAX_NAME_LEN), MAX_NAME_LEN)
if(!mimic_voice)
return
changeling.mimicing = mimic_voice
- to_chat(src, "We shape our glands to take the voice of [mimic_voice], this will stop us from regenerating chemicals while active.")
- to_chat(src, "Use this power again to return to our original voice and reproduce chemicals again.")
+ to_chat(src, span_notice("We shape our glands to take the voice of [mimic_voice], this will stop us from regenerating chemicals while active."))
+ to_chat(src, span_notice("Use this power again to return to our original voice and reproduce chemicals again."))
feedback_add_details("changeling_powers","MV")
@@ -38,4 +38,4 @@
src.mind.changeling.chem_charges = max(src.mind.changeling.chem_charges - 1, 0)
sleep(40)
if(src && src.mind && src.mind.changeling)
- src.mind.changeling.mimicing = ""
\ No newline at end of file
+ src.mind.changeling.mimicing = ""
diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm
index 30679b6ef5a..19a043669aa 100644
--- a/code/game/gamemodes/changeling/powers/panacea.dm
+++ b/code/game/gamemodes/changeling/powers/panacea.dm
@@ -18,7 +18,7 @@
return 0
src.mind.changeling.chem_charges -= 20
- to_chat(src, "We cleanse impurities from our form.")
+ to_chat(src, span_notice("We cleanse impurities from our form."))
var/mob/living/carbon/human/C = src
@@ -32,7 +32,7 @@
var/heal_amount = 5
if(src.mind.changeling.recursive_enhancement)
heal_amount = heal_amount * 2
- to_chat(src, "We will heal much faster.")
+ to_chat(src, span_notice("We will heal much faster."))
for(var/i = 0, i<10,i++)
if(C)
@@ -52,4 +52,4 @@
G.germ_level = min(0, G.germ_level - germ_heal)
feedback_add_details("changeling_powers","AP")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/para_sting.dm b/code/game/gamemodes/changeling/powers/para_sting.dm
index c4d04dd7de6..2b2cf636edc 100644
--- a/code/game/gamemodes/changeling/powers/para_sting.dm
+++ b/code/game/gamemodes/changeling/powers/para_sting.dm
@@ -13,7 +13,7 @@
if(!T)
return 0
add_attack_logs(src,T,"Paralysis sting (changeling)")
- to_chat(T, "Your muscles begin to painfully tighten.")
+ to_chat(T, span_danger("Your muscles begin to painfully tighten."))
T.Weaken(20)
feedback_add_details("changeling_powers","PS")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/rapid_regen.dm b/code/game/gamemodes/changeling/powers/rapid_regen.dm
index 6d1e9ee300c..e70e77cf231 100644
--- a/code/game/gamemodes/changeling/powers/rapid_regen.dm
+++ b/code/game/gamemodes/changeling/powers/rapid_regen.dm
@@ -24,7 +24,7 @@
var/healing_amount = 40
if(src.mind.changeling.recursive_enhancement)
healing_amount = C.maxHealth
- to_chat(src, "We completely heal ourselves.")
+ to_chat(src, span_notice("We completely heal ourselves."))
spawn(0)
C.adjustBruteLoss(-healing_amount)
C.adjustFireLoss(-healing_amount)
@@ -47,9 +47,9 @@
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
var/T = get_turf(src)
new /obj/effect/gibspawner/human(T)
- visible_message("With a sickening squish, [src] reforms their whole body, casting their old parts on the floor!",
- "We reform our body. We are whole once more.",
- "You hear organic matter ripping and tearing!")
+ visible_message(span_warning("With a sickening squish, [src] reforms their whole body, casting their old parts on the floor!"),
+ span_notice("We reform our body. We are whole once more."),
+ span_warningplain("You hear organic matter ripping and tearing!"))
feedback_add_details("changeling_powers","RR")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/recursive_enhancement.dm b/code/game/gamemodes/changeling/powers/recursive_enhancement.dm
index 77bab9bd998..21ce98bf1c6 100644
--- a/code/game/gamemodes/changeling/powers/recursive_enhancement.dm
+++ b/code/game/gamemodes/changeling/powers/recursive_enhancement.dm
@@ -15,10 +15,10 @@
if(!changeling)
return 0
if(src.mind.changeling.recursive_enhancement)
- to_chat(src, "We will no longer empower our abilities.")
+ to_chat(src, span_warning("We will no longer empower our abilities."))
src.mind.changeling.recursive_enhancement = 0
return 0
- to_chat(src, "We empower ourselves. Our abilities will now be extra potent.")
+ to_chat(src, span_notice("We empower ourselves. Our abilities will now be extra potent."))
src.mind.changeling.recursive_enhancement = 1
feedback_add_details("changeling_powers","RE")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/respec.dm b/code/game/gamemodes/changeling/powers/respec.dm
index 935092ff65f..371307700ed 100644
--- a/code/game/gamemodes/changeling/powers/respec.dm
+++ b/code/game/gamemodes/changeling/powers/respec.dm
@@ -7,7 +7,7 @@
if(!changeling)
return
if(src.mind.changeling.readapts <= 0)
- to_chat(src, "We must first absorb another compatible creature!")
+ to_chat(src, span_warning("We must first absorb another compatible creature!"))
src.mind.changeling.readapts = 0
return
@@ -27,6 +27,6 @@
H.remove_modifiers_of_type(/datum/modifier/endoarmor) //Revert endoarmor too.
src.make_changeling() //And give back our freebies.
- to_chat(src, "We have removed our evolutions from this form, and are now ready to readapt.")
+ to_chat(src, span_notice("We have removed our evolutions from this form, and are now ready to readapt."))
ling_datum.purchased_powers_history.Add("Re-adapt (Reset to [ling_datum.max_geneticpoints])")
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index e4834981554..d3ebd820c39 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -9,7 +9,7 @@
return 0
if(changeling.max_geneticpoints < 0) //Absorbed by another ling
- to_chat(src, "You have no genomes, not even your own, and cannot revive.")
+ to_chat(src, span_danger("You have no genomes, not even your own, and cannot revive."))
return 0
if(src.stat == DEAD)
@@ -46,7 +46,7 @@
BITSET(H.hud_updateflag, LIFE_HUD)
if(H.handcuffed)
- var/obj/item/weapon/W = H.handcuffed
+ var/obj/item/W = H.handcuffed
H.handcuffed = null
if(H.buckled && H.buckled.buckle_require_restraints)
H.buckled.unbuckle_mob()
@@ -58,7 +58,7 @@
if(W)
W.layer = initial(W.layer)
if(H.legcuffed)
- var/obj/item/weapon/W = H.legcuffed
+ var/obj/item/W = H.legcuffed
H.legcuffed = null
H.update_inv_legcuffed()
if(H.client)
@@ -75,14 +75,14 @@
C.halloss = 0
C.shock_stage = 0 //Pain
- to_chat(C, "We have regenerated.")
+ to_chat(C, span_notice("We have regenerated."))
C.update_canmove()
C.mind.changeling.purchased_powers -= C
feedback_add_details("changeling_powers","CR")
C.set_stat(CONSCIOUS)
C.forbid_seeing_deadchat = FALSE
C.timeofdeath = null
- verbs.Remove(/mob/proc/changeling_revive)
+ remove_verb(src, /mob/proc/changeling_revive)
// re-add our changeling powers
C.make_changeling()
diff --git a/code/game/gamemodes/changeling/powers/self_respiration.dm b/code/game/gamemodes/changeling/powers/self_respiration.dm
index 51083616697..4b939c8b897 100644
--- a/code/game/gamemodes/changeling/powers/self_respiration.dm
+++ b/code/game/gamemodes/changeling/powers/self_respiration.dm
@@ -23,9 +23,9 @@
return 0
if(C.does_not_breathe == 0)
C.does_not_breathe = 1
- to_chat(src, "We stop breathing, as we no longer need to.")
+ to_chat(src, span_notice("We stop breathing, as we no longer need to."))
return 1
else
C.does_not_breathe = 0
- to_chat(src, "We resume breathing, as we now need to again.")
- return 0
\ No newline at end of file
+ to_chat(src, span_notice("We resume breathing, as we now need to again."))
+ return 0
diff --git a/code/game/gamemodes/changeling/powers/shriek.dm b/code/game/gamemodes/changeling/powers/shriek.dm
index 9fe5fa708e2..e5112133e1d 100644
--- a/code/game/gamemodes/changeling/powers/shriek.dm
+++ b/code/game/gamemodes/changeling/powers/shriek.dm
@@ -26,21 +26,21 @@
if(!changeling) return 0
if(is_muzzled())
- to_chat(src, "Mmmf mrrfff!")
+ to_chat(src, span_danger("Mmmf mrrfff!"))
return 0
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.silent)
- to_chat(src, "You can't speak!")
+ to_chat(src, span_danger("You can't speak!"))
return 0
if(world.time < (changeling.last_shriek + 10 SECONDS) )
- to_chat(src, "We are still recovering from our last shriek...")
+ to_chat(src, span_warning("We are still recovering from our last shriek..."))
return 0
if(!isturf(loc))
- to_chat(src, "Shrieking here would be a bad idea.")
+ to_chat(src, span_warning("Shrieking here would be a bad idea."))
return 0
src.break_cloak() //No more invisible shrieking
@@ -49,29 +49,29 @@
var/range = 4
if(src.mind.changeling.recursive_enhancement)
range = range * 2
- to_chat(src, "We are extra loud.")
+ to_chat(src, span_notice("We are extra loud."))
- visible_message("[src] appears to shout.")
+ visible_message(span_notice("[src] appears to shout."))
var/list/affected = list()
for(var/mob/living/M in range(range, src))
if(iscarbon(M))
if(!M.mind || !M.mind.changeling)
if(M.get_ear_protection() >= 2)
continue
- to_chat(M, "You hear an extremely loud screeching sound! It \
- [pick("confuses","confounds","perturbs","befuddles","dazes","unsettles","disorients")] you.")
+ to_chat(M, span_danger("You hear an extremely loud screeching sound! It \
+ [pick("confuses","confounds","perturbs","befuddles","dazes","unsettles","disorients")] you."))
M.adjustEarDamage(0,30)
M.Confuse(20)
M << sound('sound/effects/screech.ogg')
affected += M
else
if(M != src)
- to_chat(M, "You hear a familiar screech from nearby. It has no effect on you.")
+ to_chat(M, span_notice("You hear a familiar screech from nearby. It has no effect on you."))
M << sound('sound/effects/screech.ogg')
if(issilicon(M))
M << sound('sound/weapons/flash.ogg')
- to_chat(M, "Auditory input overloaded. Reinitializing...")
+ to_chat(M, span_notice("Auditory input overloaded. Reinitializing..."))
M.Weaken(rand(5,10))
affected += M
@@ -95,21 +95,21 @@
if(!changeling) return 0
if(is_muzzled())
- to_chat(src, "Mmmf mrrfff!")
+ to_chat(src, span_danger("Mmmf mrrfff!"))
return 0
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.silent)
- to_chat(src, "You can't speak!")
+ to_chat(src, span_danger("You can't speak!"))
return 0
if(world.time < (changeling.last_shriek + 10 SECONDS) )
- to_chat(src, "We are still recovering from our last shriek...")
+ to_chat(src, span_warning("We are still recovering from our last shriek..."))
return 0
if(!isturf(loc))
- to_chat(src, "Shrieking here would be a bad idea.")
+ to_chat(src, span_warning("Shrieking here would be a bad idea."))
return 0
src.break_cloak() //No more invisible shrieking
@@ -125,10 +125,10 @@
range_med = range_med * 2
range_light = range_light * 2
range_long = range_long * 2
- to_chat(src, "We are extra loud.")
+ to_chat(src, span_notice("We are extra loud."))
src.mind.changeling.recursive_enhancement = 0
- visible_message("[src] appears to shout.")
+ visible_message(span_notice("[src] appears to shout."))
add_attack_logs(src,null,"Use dissonant shriek")
diff --git a/code/game/gamemodes/changeling/powers/silence_sting.dm b/code/game/gamemodes/changeling/powers/silence_sting.dm
index 16d24c878f1..c94713b9b19 100644
--- a/code/game/gamemodes/changeling/powers/silence_sting.dm
+++ b/code/game/gamemodes/changeling/powers/silence_sting.dm
@@ -19,7 +19,7 @@
var/duration = 30
if(src.mind.changeling.recursive_enhancement)
duration = duration + 10
- to_chat(src, "They will be unable to cry out in fear for a little longer.")
+ to_chat(src, span_notice("They will be unable to cry out in fear for a little longer."))
T.silent += duration
feedback_add_details("changeling_powers","SS")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/transform.dm b/code/game/gamemodes/changeling/powers/transform.dm
index 535efbcac1e..4bf04341ef3 100644
--- a/code/game/gamemodes/changeling/powers/transform.dm
+++ b/code/game/gamemodes/changeling/powers/transform.dm
@@ -14,7 +14,7 @@
if(!changeling) return
if(!isturf(loc))
- to_chat(src, "Transforming here would be a bad idea.")
+ to_chat(src, span_warning("Transforming here would be a bad idea."))
return 0
var/list/names = list()
@@ -29,7 +29,7 @@
return
changeling.chem_charges -= 5
- src.visible_message("[src] transforms!")
+ src.visible_message(span_warning("[src] transforms!"))
changeling.geneticdamage = 5
if(ishuman(src))
@@ -56,9 +56,9 @@
for(var/datum/modifier/mod in chosen_dna.genMods)
self.modifiers.Add(mod.type)
- src.verbs -= /mob/proc/changeling_transform
+ remove_verb(src, /mob/proc/changeling_transform)
spawn(10)
- src.verbs += /mob/proc/changeling_transform
+ add_verb(src, /mob/proc/changeling_transform)
src.regenerate_icons()
feedback_add_details("changeling_powers","TR")
diff --git a/code/game/gamemodes/changeling/powers/transform_sting.dm b/code/game/gamemodes/changeling/powers/transform_sting.dm
index f831f9eb172..ced7d1c3c60 100644
--- a/code/game/gamemodes/changeling/powers/transform_sting.dm
+++ b/code/game/gamemodes/changeling/powers/transform_sting.dm
@@ -32,13 +32,13 @@
if(!T)
return 0
if((HUSK in T.mutations) || (!ishuman(T) && !issmall(T)))
- to_chat(src, "Our sting appears ineffective against its DNA.")
+ to_chat(src, span_warning("Our sting appears ineffective against its DNA."))
return 0
add_attack_logs(src,T,"Transformation sting (changeling)")
- T.visible_message("[T] transforms!")
+ T.visible_message(span_warning("[T] transforms!"))
T.dna = chosen_dna.Clone()
T.real_name = chosen_dna.real_name
T.UpdateAppearance()
domutcheck(T, null)
feedback_add_details("changeling_powers","TS")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/unfat_sting.dm b/code/game/gamemodes/changeling/powers/unfat_sting.dm
index 34ef7b70328..57321859f25 100644
--- a/code/game/gamemodes/changeling/powers/unfat_sting.dm
+++ b/code/game/gamemodes/changeling/powers/unfat_sting.dm
@@ -12,7 +12,7 @@
var/mob/living/carbon/T = changeling_sting(5,/mob/proc/changeling_unfat_sting)
if(!T) return 0
add_attack_logs(src,T,"Unfat sting (changeling)")
- to_chat(T, "you feel a small prick as stomach churns violently and you become to feel skinnier.")
+ to_chat(T, span_danger("you feel a small prick as stomach churns violently and you become to feel skinnier."))
T.adjust_nutrition(-100)
feedback_add_details("changeling_powers","US")
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/gamemodes/changeling/powers/visible_camouflage.dm b/code/game/gamemodes/changeling/powers/visible_camouflage.dm
index 747deb9f998..e83b61bb5c7 100644
--- a/code/game/gamemodes/changeling/powers/visible_camouflage.dm
+++ b/code/game/gamemodes/changeling/powers/visible_camouflage.dm
@@ -30,7 +30,7 @@
changeling.chem_charges -= 10
var/old_regen_rate = H.mind.changeling.chem_recharge_rate
- to_chat(H, "We vanish from sight, and will remain hidden, so long as we move carefully.")
+ to_chat(H, span_notice("We vanish from sight, and will remain hidden, so long as we move carefully."))
H.mind.changeling.cloaked = 1
H.mind.changeling.chem_recharge_rate = 0
animate(src,alpha = 255, alpha = 10, time = 10)
@@ -38,7 +38,7 @@
var/must_walk = TRUE
if(src.mind.changeling.recursive_enhancement)
must_walk = FALSE
- to_chat(src, "We may move at our normal speed while hidden.")
+ to_chat(src, span_notice("We may move at our normal speed while hidden."))
if(must_walk)
H.set_m_intent("walk")
@@ -63,10 +63,10 @@
H.invisibility = initial(invisibility)
- visible_message("[src] suddenly fades in, seemingly from nowhere!",
- "We revert our camouflage, revealing ourselves.")
+ visible_message(span_warning("[src] suddenly fades in, seemingly from nowhere!"),
+ span_notice("We revert our camouflage, revealing ourselves."))
H.set_m_intent("run")
H.mind.changeling.cloaked = 0
H.mind.changeling.chem_recharge_rate = old_regen_rate
- animate(src,alpha = 10, alpha = 255, time = 10)
\ No newline at end of file
+ animate(src,alpha = 10, alpha = 255, time = 10)
diff --git a/code/game/gamemodes/cult/construct_spells.dm b/code/game/gamemodes/cult/construct_spells.dm
index 6273273c98d..9baf8667f76 100644
--- a/code/game/gamemodes/cult/construct_spells.dm
+++ b/code/game/gamemodes/cult/construct_spells.dm
@@ -1,7 +1,7 @@
//////////////////////////////Construct Spells/////////////////////////
/proc/findNullRod(var/atom/target)
- if(istype(target,/obj/item/weapon/nullrod))
+ if(istype(target,/obj/item/nullrod))
return 1
else if(target.contents)
for(var/atom/A in target.contents)
@@ -91,7 +91,7 @@
invocation_type = SpI_NONE
range = 0
- summon_type = list(/obj/item/device/soulstone)
+ summon_type = list(/obj/item/soulstone)
hud_state = "const_stone"
override_base = "const"
@@ -274,9 +274,9 @@
M.forceMove(destination)
if(M != user)
prey = 1
- to_chat(user, "You warp back to Nar-Sie[prey ? " along with your prey":""].")
+ to_chat(user, span_sinister("You warp back to Nar-Sie[prey ? " along with your prey":""]."))
else
- to_chat(user, "...something's wrong!") //There shouldn't be an instance of Harvesters when Nar-Sie isn't in the world.
+ to_chat(user, span_danger("...something's wrong!")) //There shouldn't be an instance of Harvesters when Nar-Sie isn't in the world.
*/
/spell/targeted/fortify
@@ -370,7 +370,7 @@
charge_max = 10
- var/obj/item/weapon/spell/construct/spell_obj = null //This is the var that determines what Technomancer-style spell is put into their hands.
+ var/obj/item/spell/construct/spell_obj = null //This is the var that determines what Technomancer-style spell is put into their hands.
/spell/targeted/construct_advanced/cast(list/targets, mob/living/user)
if(!findNullRod(user))
@@ -381,7 +381,7 @@
desc = "Fire a searing beam of darkness at your foes."
hud_state = "const_beam"
- spell_obj = /obj/item/weapon/spell/construct/projectile/inverted_beam
+ spell_obj = /obj/item/spell/construct/projectile/inverted_beam
/spell/targeted/construct_advanced/mend_acolyte
name = "Mend Acolyte"
@@ -390,7 +390,7 @@
charge_max = 100
hud_state = "const_mend"
- spell_obj = /obj/item/weapon/spell/construct/mend_occult
+ spell_obj = /obj/item/spell/construct/mend_occult
/spell/targeted/construct_advanced/agonizing_sphere
name = "Sphere of Agony"
@@ -399,7 +399,7 @@
charge_max = 100
hud_state = "const_harvest"
- spell_obj = /obj/item/weapon/spell/construct/spawner/agonizing_sphere
+ spell_obj = /obj/item/spell/construct/spawner/agonizing_sphere
/spell/targeted/construct_advanced/slam
name = "Slam"
@@ -408,7 +408,7 @@
charge_max = 300
hud_state = "const_fist"
- spell_obj = /obj/item/weapon/spell/construct/slam
+ spell_obj = /obj/item/spell/construct/slam
/*
*
@@ -420,7 +420,7 @@
* Base advanced construct spell types.
*/
-/obj/item/weapon/spell/construct //Energy costs are in units of blood, in the event a cultist gets one of these.
+/obj/item/spell/construct //Energy costs are in units of blood, in the event a cultist gets one of these.
name = "unholy energy"
desc = "Your hands appear to be screaming. This is a debug text, you should probably tell a developer!"
icon = 'icons/obj/spells.dmi'
@@ -441,7 +441,7 @@
cast_sound = null // Sound file played when this is used.
var/last_castcheck = null // The last time this spell was cast.
-/obj/item/weapon/spell/construct/New()
+/obj/item/spell/construct/New()
//..() //This kills the spell, because super on this calls the default spell's New, which checks for a core. Can't have that.
if(isliving(loc))
owner = loc
@@ -449,17 +449,17 @@
qdel(src)
update_icon()
-/obj/item/weapon/spell/construct/adjust_instability(var/amount) //The only drawback to the boons of the geometer is the use of a mortal's blood as fuel. Constructs have already paid that price long ago.
+/obj/item/spell/construct/adjust_instability(var/amount) //The only drawback to the boons of the geometer is the use of a mortal's blood as fuel. Constructs have already paid that price long ago.
return
-/obj/item/weapon/spell/construct/run_checks()
+/obj/item/spell/construct/run_checks()
if(owner)
if((iscultist(owner) || istype(owner, /mob/living/simple_mob/construct)) && (world.time >= (last_castcheck + cooldown))) //Are they a cultist or a construct, and has the cooldown time passed?
last_castcheck = world.time
return 1
return 0
-/obj/item/weapon/spell/construct/pay_energy(var/amount)
+/obj/item/spell/construct/pay_energy(var/amount)
if(owner)
if(istype(owner, /mob/living/simple_mob/construct))
return 1
@@ -467,7 +467,7 @@
return 1
return 0
-/obj/item/weapon/spell/construct/proc/pay_blood(var/amount) //If, for some reason, this is put into the hands of a cultist, by a talisnam or whatever.
+/obj/item/spell/construct/proc/pay_blood(var/amount) //If, for some reason, this is put into the hands of a cultist, by a talisnam or whatever.
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(!H.should_have_organ(O_HEART))
@@ -476,15 +476,15 @@
return 1
return 0
-/obj/item/weapon/spell/construct/afterattack(atom/target, mob/user, proximity_flag, click_parameters) //Not overriding it caused runtimes, because cooldown checked for core.
+/obj/item/spell/construct/afterattack(atom/target, mob/user, proximity_flag, click_parameters) //Not overriding it caused runtimes, because cooldown checked for core.
if(!run_checks())
return
if(!proximity_flag)
if(cast_methods & CAST_RANGED)
on_ranged_cast(target, user)
else
- if(istype(target, /obj/item/weapon/spell))
- var/obj/item/weapon/spell/spell = target
+ if(istype(target, /obj/item/spell))
+ var/obj/item/spell/spell = target
if(spell.cast_methods & CAST_COMBINE)
spell.on_combine_cast(src, user)
return
@@ -497,7 +497,7 @@
user.setClickCooldown(effective_cooldown)
flick("cooldown_[effective_cooldown]",src)
-/obj/item/weapon/spell/construct/projectile //This makes me angry, but we need the template, and we can't use it because special check overrides on the base.
+/obj/item/spell/construct/projectile //This makes me angry, but we need the template, and we can't use it because special check overrides on the base.
name = "construct projectile template"
icon_state = "generic"
desc = "This is a generic template that shoots projectiles. If you can read this, the game broke!"
@@ -507,7 +507,7 @@
var/fire_sound = null
var/energy_cost_per_shot = 5
-/obj/item/weapon/spell/construct/projectile/on_ranged_cast(atom/hit_atom, mob/living/user)
+/obj/item/spell/construct/projectile/on_ranged_cast(atom/hit_atom, mob/living/user)
if(set_up(hit_atom, user))
var/obj/item/projectile/new_projectile = make_projectile(spell_projectile, user)
new_projectile.old_style_target(hit_atom)
@@ -518,11 +518,11 @@
return 1
return 0
-/obj/item/weapon/spell/construct/projectile/proc/make_projectile(obj/item/projectile/projectile_type, mob/living/user)
+/obj/item/spell/construct/projectile/proc/make_projectile(obj/item/projectile/projectile_type, mob/living/user)
var/obj/item/projectile/P = new projectile_type(get_turf(user))
return P
-/obj/item/weapon/spell/construct/projectile/proc/set_up(atom/hit_atom, mob/living/user)
+/obj/item/spell/construct/projectile/proc/set_up(atom/hit_atom, mob/living/user)
if(spell_projectile)
if(pay_energy(energy_cost_per_shot))
if(pre_shot_delay)
@@ -537,24 +537,24 @@
return TRUE // No delay, no need to check.
return FALSE
-/obj/item/weapon/spell/construct/spawner
+/obj/item/spell/construct/spawner
name = "spawner template"
desc = "If you see me, someone messed up."
icon_state = "darkness"
cast_methods = CAST_RANGED
var/obj/effect/spawner_type = null
-/obj/item/weapon/spell/construct/spawner/on_ranged_cast(atom/hit_atom, mob/user)
+/obj/item/spell/construct/spawner/on_ranged_cast(atom/hit_atom, mob/user)
var/turf/T = get_turf(hit_atom)
if(T)
new spawner_type(T)
- to_chat(user, "You shift \the [src] onto \the [T].")
+ to_chat(user, span_cult("You shift \the [src] onto \the [T]."))
log_and_message_admins("has casted [src] at [T.x],[T.y],[T.z].")
qdel(src)
//Harvester Laser.
-/obj/item/weapon/spell/construct/projectile/inverted_beam
+/obj/item/spell/construct/projectile/inverted_beam
name = "inversion beam"
icon_state = "generic"
desc = "Your manipulators fire searing beams of inverted light."
@@ -582,17 +582,17 @@
//Harvester Pain Orb
-/obj/item/weapon/spell/construct/spawner/agonizing_sphere
+/obj/item/spell/construct/spawner/agonizing_sphere
name = "sphere of agony"
desc = "Call forth a portal to a dimension of naught but pain at your target."
spawner_type = /obj/effect/temporary_effect/pulse/agonizing_sphere
-/obj/item/weapon/spell/construct/spawner/agonizing_sphere/on_ranged_cast(atom/hit_atom, mob/user)
+/obj/item/spell/construct/spawner/agonizing_sphere/on_ranged_cast(atom/hit_atom, mob/user)
if(within_range(hit_atom) && pay_energy(10))
..()
-/obj/item/weapon/spell/construct/spawner/agonizing_sphere/on_throw_cast(atom/hit_atom, mob/user)
+/obj/item/spell/construct/spawner/agonizing_sphere/on_throw_cast(atom/hit_atom, mob/user)
pay_energy(5)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
@@ -615,12 +615,12 @@
if(!iscultist(L) && !istype(L, /mob/living/simple_mob/construct))
L.add_modifier(/datum/modifier/agonize, 2 SECONDS)
if(L.isSynthetic())
- to_chat(L, "Your chassis warps as the [src] pulses!")
+ to_chat(L, span_cult("Your chassis warps as the [src] pulses!"))
L.adjustFireLoss(4)
//Artificer Heal
-/obj/item/weapon/spell/construct/mend_occult
+/obj/item/spell/construct/mend_occult
name = "mend acolyte"
desc = "Mend the wounds of a cultist, or construct, over time."
icon_state = "mend_wounds"
@@ -630,14 +630,14 @@
light_power = -2
light_on = TRUE
-/obj/item/weapon/spell/construct/mend_occult/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
+/obj/item/spell/construct/mend_occult/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
L.add_modifier(/datum/modifier/mend_occult, 150)
qdel(src)
//Juggernaut Slam
-/obj/item/weapon/spell/construct/slam
+/obj/item/spell/construct/slam
name = "slam"
desc = "Empower your FIST, to send an opponent flying."
icon_state = "toggled_old"
@@ -648,14 +648,14 @@
light_on = TRUE
cooldown = 15
-/obj/item/weapon/spell/construct/slam/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
+/obj/item/spell/construct/slam/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
var/attack_message = "slams"
if(istype(user, /mob/living/simple_mob))
var/mob/living/simple_mob/S = user
attack_message = pick(S.attacktext)
if(isliving(hit_atom))
var/mob/living/L = hit_atom
- L.visible_message("\The [user] [attack_message] \the [L], sending them flying!")
+ L.visible_message(span_danger("\The [user] [attack_message] \the [L], sending them flying!"))
playsound(src, "punch", 50, 1)
L.Weaken(2)
L.adjustBruteLoss(rand(30, 50))
@@ -663,14 +663,14 @@
L.throw_at(get_edge_target_turf(L, throwdir), 3, 1, src)
if(istype(hit_atom, /turf/simulated/wall))
var/turf/simulated/wall/W = hit_atom
- user.visible_message("\The [user] rears its fist, preparing to hit \the [W]!")
+ user.visible_message(span_warning("\The [user] rears its fist, preparing to hit \the [W]!"))
var/windup = cooldown
if(W.reinf_material)
windup = cooldown * 2
if(do_after(user, windup))
- W.visible_message("\The [user] [attack_message] \the [W], obliterating it!")
+ W.visible_message(span_danger("\The [user] [attack_message] \the [W], obliterating it!"))
W.dismantle_wall(1)
else
- user.visible_message("\The [user] lowers its fist.")
+ user.visible_message(span_bold("\The [user]") + " lowers its fist.")
return
qdel(src)
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index e54bb88eefe..df277b318a8 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -1,4 +1,4 @@
-/obj/item/weapon/melee/cultblade
+/obj/item/melee/cultblade
name = "cult blade"
desc = "An arcane weapon wielded by the followers of Nar-Sie."
icon_state = "cultblade"
@@ -13,10 +13,10 @@
edge = TRUE
sharp = TRUE
-/obj/item/weapon/melee/cultblade/cultify()
+/obj/item/melee/cultblade/cultify()
return
-/obj/item/weapon/melee/cultblade/attack(mob/living/M, mob/living/user, var/target_zone)
+/obj/item/melee/cultblade/attack(mob/living/M, mob/living/user, var/target_zone)
if(iscultist(user) && !istype(user, /mob/living/simple_mob/construct))
return ..()
@@ -24,14 +24,14 @@
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/external/affecting = H.get_organ(zone)
- to_chat(user, "An inexplicable force rips through your [affecting.name], tearing the sword from your grasp!")
+ to_chat(user, span_danger("An inexplicable force rips through your [affecting.name], tearing the sword from your grasp!"))
//random amount of damage between half of the blade's force and the full force of the blade.
user.apply_damage(rand(force/2, force), BRUTE, zone, 0, sharp = TRUE, edge = TRUE)
user.Weaken(5)
else if(!istype(user, /mob/living/simple_mob/construct))
- to_chat(user, "An inexplicable force rips through you, tearing the sword from your grasp!")
+ to_chat(user, span_danger("An inexplicable force rips through you, tearing the sword from your grasp!"))
else
- to_chat(user, "The blade hisses, forcing itself from your manipulators. \The [src] will only allow mortals to wield it against foes, not kin.")
+ to_chat(user, span_critical("The blade hisses, forcing itself from your manipulators. \The [src] will only allow mortals to wield it against foes, not kin."))
user.drop_from_inventory(src, src.loc)
throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), throw_speed)
@@ -41,12 +41,12 @@
return 1
-/obj/item/weapon/melee/cultblade/pickup(mob/living/user as mob)
+/obj/item/melee/cultblade/pickup(mob/living/user as mob)
if(!iscultist(user) && !istype(user, /mob/living/simple_mob/construct))
- to_chat(user, "An overwhelming feeling of dread comes over you as you pick up the cultist's sword. It would be wise to be rid of this blade quickly.")
+ to_chat(user, span_warning("An overwhelming feeling of dread comes over you as you pick up the cultist's sword. It would be wise to be rid of this blade quickly."))
user.make_dizzy(120)
if(istype(user, /mob/living/simple_mob/construct))
- to_chat(user, "\The [src] hisses, as it is discontent with your acquisition of it. It would be wise to return it to a worthy mortal quickly.")
+ to_chat(user, span_warning("\The [src] hisses, as it is discontent with your acquisition of it. It would be wise to return it to a worthy mortal quickly."))
/obj/item/clothing/head/culthood
name = "cult hood"
@@ -79,7 +79,7 @@
icon_state = "cultrobes"
origin_tech = list(TECH_MATERIAL = 3, TECH_ARCANE = 1)
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade)
+ allowed = list(/obj/item/book/tome,/obj/item/melee/cultblade)
armor = list(melee = 50, bullet = 30, laser = 50, energy = 80, bomb = 25, bio = 10, rad = 0)
flags_inv = HIDEJUMPSUIT
siemens_coefficient = 0
@@ -114,7 +114,7 @@
origin_tech = list(TECH_MATERIAL = 3, TECH_ARCANE = 1)
desc = "A bulky suit of armour, bristling with spikes. It looks space-worthy."
w_class = ITEMSIZE_NORMAL
- allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency/oxygen,/obj/item/device/suit_cooling_unit)
+ allowed = list(/obj/item/book/tome,/obj/item/melee/cultblade,/obj/item/tank/emergency/oxygen,/obj/item/suit_cooling_unit)
slowdown = 0.5
armor = list(melee = 60, bullet = 50, laser = 30, energy = 80, bomb = 30, bio = 30, rad = 30)
siemens_coefficient = 0
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index 9a9540784e5..73429d697ba 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -55,7 +55,7 @@
/obj/structure/cult/pylon/proc/pylonhit(var/damage)
if(!isbroken)
if(prob(1+ damage * 5))
- visible_message("[shatter_message]")
+ visible_message(span_danger("[shatter_message]"))
STOP_PROCESSING(SSobj, src)
playsound(src,shatter_sound, 75, 1)
isbroken = 1
@@ -67,8 +67,8 @@
if(!isbroken)
if(prob(1+ damage * 5))
user.visible_message(
- "[user] smashed \the [src]!",
- "You hit \the [src], and its crystal breaks apart!",
+ span_danger("[user] smashed \the [src]!"),
+ span_warning("You hit \the [src], and its crystal breaks apart!"),
"You hear a tinkle of crystal shards."
)
STOP_PROCESSING(SSobj, src)
@@ -170,4 +170,4 @@
var/mob/living/M = A
- to_chat(M, "Walking into \the [src] is probably a bad idea, you think.")
+ to_chat(M, span_danger("Walking into \the [src] is probably a bad idea, you think."))
diff --git a/code/game/gamemodes/cult/cultify/mob.dm b/code/game/gamemodes/cult/cultify/mob.dm
index 9c5eb4458f4..ad9394fe352 100644
--- a/code/game/gamemodes/cult/cultify/mob.dm
+++ b/code/game/gamemodes/cult/cultify/mob.dm
@@ -12,13 +12,13 @@
icon_state = "ghost-narsie"
overlays = 0
invisibility = 0
- to_chat(src, "Even as a non-corporal being, you can feel Nar-Sie's presence altering you. You are now visible to everyone.")
+ to_chat(src, span_sinister("Even as a non-corporal being, you can feel Nar-Sie's presence altering you. You are now visible to everyone."))
/mob/living/cultify()
if(iscultist(src) && client)
var/mob/living/simple_mob/construct/harvester/C = new(get_turf(src))
mind.transfer_to(C)
- to_chat(C, "The Geometer of Blood is overjoyed to be reunited with its followers, and accepts your body in sacrifice. As reward, you have been gifted with the shell of an Harvester.
Your tendrils can use and draw runes without need for a tome, your eyes can see beings through walls, and your mind can open any door. Use these assets to serve Nar-Sie and bring him any remaining living human in the world.
You can teleport yourself back to Nar-Sie along with any being under yourself at any time using your \"Harvest\" spell.")
+ to_chat(C, span_sinister("The Geometer of Blood is overjoyed to be reunited with its followers, and accepts your body in sacrifice. As reward, you have been gifted with the shell of an Harvester.
Your tendrils can use and draw runes without need for a tome, your eyes can see beings through walls, and your mind can open any door. Use these assets to serve Nar-Sie and bring him any remaining living human in the world.
You can teleport yourself back to Nar-Sie along with any being under yourself at any time using your \"Harvest\" spell."))
dust()
else if(client)
var/mob/observer/dead/G = (ghostize())
@@ -26,7 +26,7 @@
G.icon_state = "ghost-narsie"
G.overlays = 0
G.invisibility = 0
- to_chat(G, "You feel relieved as what's left of your soul finally escapes its prison of flesh.")
+ to_chat(G, span_sinister("You feel relieved as what's left of your soul finally escapes its prison of flesh."))
cult.harvested += G.mind
else
diff --git a/code/game/gamemodes/cult/cultify/obj.dm b/code/game/gamemodes/cult/cultify/obj.dm
index e00dbc6aad5..672fdb1fd3b 100644
--- a/code/game/gamemodes/cult/cultify/obj.dm
+++ b/code/game/gamemodes/cult/cultify/obj.dm
@@ -10,26 +10,26 @@
/obj/effect/overlay/cultify()
return
-/obj/item/device/flashlight/lamp/cultify()
+/obj/item/flashlight/lamp/cultify()
new /obj/structure/cult/pylon(loc)
..()
/obj/item/stack/material/wood/cultify()
return
-/obj/item/weapon/book/cultify()
- new /obj/item/weapon/book/tome(loc)
+/obj/item/book/cultify()
+ new /obj/item/book/tome(loc)
..()
-/obj/item/weapon/material/sword/cultify()
- new /obj/item/weapon/melee/cultblade(loc)
+/obj/item/material/sword/cultify()
+ new /obj/item/melee/cultblade(loc)
..()
-/obj/item/weapon/storage/backpack/cultify()
- new /obj/item/weapon/storage/backpack/cultpack(loc)
+/obj/item/storage/backpack/cultify()
+ new /obj/item/storage/backpack/cultpack(loc)
..()
-/obj/item/weapon/storage/backpack/cultpack/cultify()
+/obj/item/storage/backpack/cultpack/cultify()
return
/obj/machinery/cultify()
diff --git a/code/game/gamemodes/cult/hell_universe.dm b/code/game/gamemodes/cult/hell_universe.dm
index d558a8bfbb2..e5d549cec50 100644
--- a/code/game/gamemodes/cult/hell_universe.dm
+++ b/code/game/gamemodes/cult/hell_universe.dm
@@ -16,7 +16,7 @@ In short:
return 1
/*
if(user)
- to_chat(user, "All you hear on the frequency is static and panicked screaming. There will be no shuttle call today.")
+ to_chat(user, span_sinister("All you hear on the frequency is static and panicked screaming. There will be no shuttle call today."))
return 0
*/
diff --git a/code/game/gamemodes/cult/narsie.dm b/code/game/gamemodes/cult/narsie.dm
index 5a8dc60d3f8..1aabe00bb91 100644
--- a/code/game/gamemodes/cult/narsie.dm
+++ b/code/game/gamemodes/cult/narsie.dm
@@ -43,7 +43,7 @@ var/global/list/narsie_list = list()
/obj/singularity/narsie/large/New()
..()
if(announce)
- to_world("[uppertext(name)] HAS RISEN")
+ to_world(span_world(span_narsie(span_red("[uppertext(name)] HAS RISEN"))))
world << sound('sound/effects/weather/wind/wind_5_1.ogg')
narsie_spawn_animation()
@@ -79,7 +79,7 @@ var/global/list/narsie_list = list()
if(M.status_flags & GODMODE)
continue
if(!iscultist(M))
- to_chat(M, " You feel your sanity crumble away in an instant as you gaze upon [src.name]...")
+ to_chat(M, span_danger("You feel your sanity crumble away in an instant as you gaze upon [src.name]..."))
M.apply_effect(3, STUN)
@@ -313,13 +313,13 @@ var/global/list/narsie_list = list()
/obj/singularity/narsie/proc/acquire(const/mob/food)
var/capname = uppertext(name)
- to_chat(target, "[capname] HAS LOST INTEREST IN YOU.")
+ to_chat(target, span_boldnotice("[capname] HAS LOST INTEREST IN YOU."))
target = food
if (ishuman(target))
- to_chat(target, "[capname] HUNGERS FOR YOUR SOUL.")
+ to_chat(target, span_danger("[capname] HUNGERS FOR YOUR SOUL."))
else
- to_chat(target, "[capname] HAS CHOSEN YOU TO LEAD HIM TO HIS NEXT MEAL.")
+ to_chat(target, span_danger("[capname] HAS CHOSEN YOU TO LEAD HIM TO HIS NEXT MEAL."))
/obj/singularity/narsie/on_capture()
chained = 1
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 35e1ed8eb92..27c09411449 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -6,7 +6,7 @@ var/global/list/engwords = list("travel", "blood", "join", "hell", "destroy", "t
var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","mgar","balaq", "karazet", "geeri")
/client/proc/check_words() // -- Urist
- set category = "Special Verbs"
+ set category = "Admin.Secrets"
set name = "Check Rune Words"
set desc = "Check the rune-word meaning"
if(!cultwords["travel"])
@@ -90,12 +90,12 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
/obj/effect/rune/attackby(I as obj, user as mob)
- if(istype(I, /obj/item/weapon/book/tome) && iscultist(user))
+ if(istype(I, /obj/item/book/tome) && iscultist(user))
to_chat(user, "You retrace your steps, carefully undoing the lines of the rune.")
qdel(src)
return
- else if(istype(I, /obj/item/weapon/nullrod))
- to_chat(user, "You disrupt the vile magic with the deadening field of the null rod!")
+ else if(istype(I, /obj/item/nullrod))
+ to_chat(user, span_notice("You disrupt the vile magic with the deadening field of the null rod!"))
qdel(src)
return
return
@@ -170,13 +170,13 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
else
usr.whisper(pick("Hakkrutju gopoenjim.", "Nherasai pivroiashan.", "Firjji prhiv mazenhor.", "Tanah eh wakantahe.", "Obliyae na oraie.", "Miyf hon vnor'c.", "Wakabai hij fen juswix."))
for (var/mob/V in viewers(src))
- V.show_message("The markings pulse with a small burst of light, then fall dark.", 3, "You hear a faint fizzle.", 2)
+ V.show_message(span_warning("The markings pulse with a small burst of light, then fall dark."), 3, span_warning("You hear a faint fizzle."), 2)
return
/obj/effect/rune/proc/check_icon()
icon = get_uristrune_cult(word1, word2, word3)
-/obj/item/weapon/book/tome
+/obj/item/book/tome
name = "arcane tome"
icon = 'icons/obj/weapons.dmi'
item_icons = list(
@@ -288,14 +288,14 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","