mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-23 04:51:32 +01:00
Merge remote-tracking branch 'Aurora/master' into beach_episode
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# This action is a wrapper around `oven-sh/setup-bun` to use the version specified in
|
||||
# `dependencies.sh`.
|
||||
name: Setup Bun
|
||||
description: Install Bun using the version specified in `dependencies.sh`
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Configure Bun version
|
||||
shell: bash
|
||||
run: |
|
||||
source dependencies.sh
|
||||
echo "BUN_VERSION_REQUIRED=$BUN_VERSION" >> $GITHUB_ENV
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: ${{ env.BUN_VERSION_REQUIRED }}
|
||||
@@ -0,0 +1,26 @@
|
||||
# This action is a wrapper around `actions/setup-node`, to use the version specified in
|
||||
# `dependencies.sh`.
|
||||
name: Setup Node
|
||||
description: Install Node using the version specified in `dependencies.sh`; additionally, restores the Yarn cache if one exists
|
||||
|
||||
inputs:
|
||||
restore-yarn-cache:
|
||||
description: "If `true`, restores the Yarn cache alongside installing node."
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Configure Node version
|
||||
shell: bash
|
||||
run: |
|
||||
source dependencies.sh
|
||||
echo "NODE_VERSION_REQUIRED=$NODE_VERSION_LTS" >> $GITHUB_ENV
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION_REQUIRED }}
|
||||
cache: ${{ fromJSON(inputs.restore-yarn-cache) && 'yarn' || '' }}
|
||||
cache-dependency-path: ${{ fromJSON(inputs.restore-yarn-cache) && 'tgui/yarn.lock' || '' }}
|
||||
@@ -69,6 +69,7 @@ jobs:
|
||||
bash tools/ci/check_filedirs.sh aurorastation.dme
|
||||
bash tools/ci/check_changelogs.sh
|
||||
bash tools/ci/check_grep.sh $PWD
|
||||
bash tools/ci/check_shell_scripts.sh
|
||||
awk -f tools/indentation.awk **/*.dm
|
||||
|
||||
- name: "Check if running CI"
|
||||
@@ -281,18 +282,14 @@ jobs:
|
||||
- name: Set ENV variables
|
||||
run: bash dependencies.sh
|
||||
|
||||
#Setup NodeJS using YARN as cache
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION_LTS }}
|
||||
cache: "yarn"
|
||||
cache-dependency-path: tgui/yarn.lock
|
||||
#Setup bun
|
||||
- name: Setup Bun
|
||||
uses: ./.github/actions/setup_bun
|
||||
|
||||
#Lint TGUI
|
||||
- name: Check Tgui
|
||||
run: |
|
||||
tools/build/build --ci lint tgui-test
|
||||
tools/build/build.sh --ci lint tgui-test
|
||||
|
||||
###########################################
|
||||
############### MISC LINTING ##############
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
name: "Build TGUI"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-tgui:
|
||||
concurrency: tgui
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Install Bun
|
||||
uses: ./.github/actions/setup_bun
|
||||
|
||||
- name: Update TGUI
|
||||
run: |
|
||||
tools/bootstrap/javascript tools/build/build.sh tgui
|
||||
|
||||
- name: Commit TGUI
|
||||
run: |
|
||||
git pull origin master
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "AuroraBuildBot"
|
||||
git add --force tgui/public/*
|
||||
git commit -m "Automatic TGUI compile [ci skip]" -a || true
|
||||
|
||||
- name: Push
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
github_token: ${{ secrets.BOT_TOKEN_AURORA }}
|
||||
@@ -73,3 +73,6 @@ define_sanity_output.txt
|
||||
|
||||
# Tracy dumps
|
||||
*.utracy
|
||||
|
||||
# JavaScript tools
|
||||
**/node_modules
|
||||
|
||||
Vendored
+4
-2
@@ -6,7 +6,9 @@
|
||||
"dbaeumer.vscode-eslint",
|
||||
"vscode.typescript-language-features",
|
||||
"redhat.vscode-yaml",
|
||||
"esbenp.prettier-vscode",
|
||||
"rome.rome"
|
||||
"rome.rome",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"editorconfig.editorconfig",
|
||||
"biomejs.biome"
|
||||
]
|
||||
}
|
||||
|
||||
Vendored
+10
-8
@@ -1,25 +1,27 @@
|
||||
{
|
||||
"eslint.nodePath": "./tgui/.yarn/sdks",
|
||||
"eslint.workingDirectories": ["./tgui"],
|
||||
"prettier.prettierPath": "./tgui/.yarn/sdks/prettier/index.cjs",
|
||||
"typescript.tsdk": "./tgui/.yarn/sdks/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"search.exclude": {
|
||||
"**/.yarn": true,
|
||||
"**/.pnp.*": true
|
||||
},
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
"source.organizeImports.biome": "explicit",
|
||||
"source.fixAll.biome": "explicit"
|
||||
},
|
||||
"editor.insertSpaces": false,
|
||||
"files.eol": "\n",
|
||||
"files.insertFinalNewline": true,
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"gitlens.advanced.blame.customArguments": ["-w"],
|
||||
"[javascript][typescript][typescriptreact][javascriptreact][html][scss][css][json][jsonc][markdown][yaml]": {
|
||||
"editor.rulers": [80],
|
||||
"[javascript][typescript][javascriptreact][typescriptreact][css][json][jsonc]": {
|
||||
"editor.defaultFormatter": "biomejs.biome",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.rulers": [80]
|
||||
},
|
||||
"[yaml][markdown][html][scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true
|
||||
"editor.formatOnSave": true,
|
||||
"editor.rulers": [80]
|
||||
},
|
||||
"workbench.editorAssociations": {
|
||||
"*.dmi": "dmiEditor.dmiEditor"
|
||||
|
||||
Vendored
+4
-34
@@ -16,8 +16,7 @@
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$dreammaker",
|
||||
"$tsc",
|
||||
"$eslint-stylish"
|
||||
"$tsc"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
@@ -61,8 +60,7 @@
|
||||
"command": ".\\bin\\tgui-build.cmd"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc",
|
||||
"$eslint-stylish"
|
||||
"$tsc"
|
||||
],
|
||||
"group": "build",
|
||||
"label": "tgui: build"
|
||||
@@ -74,38 +72,11 @@
|
||||
"command": ".\\bin\\tgui-dev.cmd"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc",
|
||||
"$eslint-stylish"
|
||||
"$tsc"
|
||||
],
|
||||
"group": "build",
|
||||
"label": "tgui: dev server"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"command": "bin/tgui-bench",
|
||||
"windows": {
|
||||
"command": ".\\bin\\tgui-bench.cmd"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc",
|
||||
"$eslint-stylish"
|
||||
],
|
||||
"group": "build",
|
||||
"label": "tgui: bench"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"command": "bin/tgui-sonar",
|
||||
"windows": {
|
||||
"command": ".\\bin\\tgui-sonar.cmd"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc",
|
||||
"$eslint-stylish"
|
||||
],
|
||||
"group": "build",
|
||||
"label": "tgui: sonar"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"command": "bin/tgfont",
|
||||
@@ -113,8 +84,7 @@
|
||||
"command": ".\\bin\\tgfont.cmd"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc",
|
||||
"$eslint-stylish"
|
||||
"$tsc"
|
||||
],
|
||||
"group": "build",
|
||||
"label": "tgui: rebuild tgfont"
|
||||
|
||||
+10
-9
@@ -155,6 +155,7 @@
|
||||
#include "code\__DEFINES\targeting.dm"
|
||||
#include "code\__DEFINES\technomancer.dm"
|
||||
#include "code\__DEFINES\text.dm"
|
||||
#include "code\__DEFINES\tgs.config.dm"
|
||||
#include "code\__DEFINES\tgs.dm"
|
||||
#include "code\__DEFINES\tgui.dm"
|
||||
#include "code\__DEFINES\time.dm"
|
||||
@@ -184,6 +185,7 @@
|
||||
#include "code\__DEFINES\dcs\signals\signals_record.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_spatial_grid.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_subsystem.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_tgui.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_tools.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_turf.dm"
|
||||
#include "code\__DEFINES\dcs\signals\signals_weather.dm"
|
||||
@@ -404,6 +406,7 @@
|
||||
#include "code\controllers\subsystems\stickyban.dm"
|
||||
#include "code\controllers\subsystems\sun.dm"
|
||||
#include "code\controllers\subsystems\sunlight.dm"
|
||||
#include "code\controllers\subsystems\tgui.dm"
|
||||
#include "code\controllers\subsystems\throwing.dm"
|
||||
#include "code\controllers\subsystems\ticker.dm"
|
||||
#include "code\controllers\subsystems\time_track.dm"
|
||||
@@ -448,7 +451,6 @@
|
||||
#include "code\controllers\subsystems\processing\electronics.dm"
|
||||
#include "code\controllers\subsystems\processing\fast_process.dm"
|
||||
#include "code\controllers\subsystems\processing\modifiers.dm"
|
||||
#include "code\controllers\subsystems\processing\nanoui.dm"
|
||||
#include "code\controllers\subsystems\processing\ntsl2.dm"
|
||||
#include "code\controllers\subsystems\processing\obj_tab_items.dm"
|
||||
#include "code\controllers\subsystems\processing\odyssey.dm"
|
||||
@@ -457,7 +459,6 @@
|
||||
#include "code\controllers\subsystems\processing\projectiles.dm"
|
||||
#include "code\controllers\subsystems\processing\psi.dm"
|
||||
#include "code\controllers\subsystems\processing\shuttle.dm"
|
||||
#include "code\controllers\subsystems\processing\tgui.dm"
|
||||
#include "code\datums\ai_law_sets.dm"
|
||||
#include "code\datums\ai_laws.dm"
|
||||
#include "code\datums\beam.dm"
|
||||
@@ -465,6 +466,7 @@
|
||||
#include "code\datums\callback.dm"
|
||||
#include "code\datums\cargo.dm"
|
||||
#include "code\datums\category.dm"
|
||||
#include "code\datums\chat_payload.dm"
|
||||
#include "code\datums\computerfiles.dm"
|
||||
#include "code\datums\datum.dm"
|
||||
#include "code\datums\datumvars.dm"
|
||||
@@ -616,6 +618,7 @@
|
||||
#include "code\datums\outfits\event\outfit_killers.dm"
|
||||
#include "code\datums\outfits\event\outfit_megacorps.dm"
|
||||
#include "code\datums\outfits\event\outfit_nanotrasen.dm"
|
||||
#include "code\datums\outfits\event\outfit_oe.dm"
|
||||
#include "code\datums\outfits\event\outfit_scc.dm"
|
||||
#include "code\datums\outfits\event\outfit_siib.dm"
|
||||
#include "code\datums\outfits\event\outfit_tfcl.dm"
|
||||
@@ -3166,13 +3169,6 @@
|
||||
#include "code\modules\multiz\zmimic\mimic_common.dm"
|
||||
#include "code\modules\multiz\zmimic\mimic_movable.dm"
|
||||
#include "code\modules\multiz\zmimic\mimic_turf.dm"
|
||||
#include "code\modules\nano\nanoexternal.dm"
|
||||
#include "code\modules\nano\nanomapgen.dm"
|
||||
#include "code\modules\nano\nanoui.dm"
|
||||
#include "code\modules\nano\modules\follow_menu.dm"
|
||||
#include "code\modules\nano\modules\human_appearance.dm"
|
||||
#include "code\modules\nano\modules\nano_module.dm"
|
||||
#include "code\modules\nano\modules\narrate_panel.dm"
|
||||
#include "code\modules\ntsl2\guide.dm"
|
||||
#include "code\modules\ntsl2\ntsl2_program.dm"
|
||||
#include "code\modules\ntsl2\ntsl2_types.dm"
|
||||
@@ -3935,8 +3931,11 @@
|
||||
#include "code\modules\tgui\modules\armor_values.dm"
|
||||
#include "code\modules\tgui\modules\faction_select.dm"
|
||||
#include "code\modules\tgui\modules\flavor_text.dm"
|
||||
#include "code\modules\tgui\modules\follow_menu.dm"
|
||||
#include "code\modules\tgui\modules\hivenet_manifest.dm"
|
||||
#include "code\modules\tgui\modules\human_appearance.dm"
|
||||
#include "code\modules\tgui\modules\ipc_diagnostic.dm"
|
||||
#include "code\modules\tgui\modules\narrate_panel.dm"
|
||||
#include "code\modules\tgui\modules\neural_configuration.dm"
|
||||
#include "code\modules\tgui\states\admin.dm"
|
||||
#include "code\modules\tgui\states\always.dm"
|
||||
@@ -3959,6 +3958,8 @@
|
||||
#include "code\modules\tgui\states\self.dm"
|
||||
#include "code\modules\tgui\states\zlevel.dm"
|
||||
#include "code\modules\tgui_input\alert.dm"
|
||||
#include "code\modules\tgui_input\checkboxes.dm"
|
||||
#include "code\modules\tgui_input\keycombo.dm"
|
||||
#include "code\modules\tgui_input\list.dm"
|
||||
#include "code\modules\tgui_input\number.dm"
|
||||
#include "code\modules\tgui_input\text.dm"
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.1.2/schema.json",
|
||||
"assist": {
|
||||
"actions": {
|
||||
"source": {
|
||||
"organizeImports": "on"
|
||||
}
|
||||
},
|
||||
"enabled": true
|
||||
},
|
||||
"css": {
|
||||
"formatter": {
|
||||
"quoteStyle": "double"
|
||||
}
|
||||
},
|
||||
"files": {
|
||||
"ignoreUnknown": false,
|
||||
"includes": [
|
||||
"**",
|
||||
"!**/node_modules",
|
||||
"!tgui/public",
|
||||
"tgui/public/tgui.html",
|
||||
"!tgui/packages/tgui-setup/helpers.js"
|
||||
]
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "tab",
|
||||
"lineEnding": "lf"
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"indentStyle": "space",
|
||||
"quoteStyle": "single"
|
||||
}
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
"a11y": "off",
|
||||
"correctness": {
|
||||
"noUnusedImports": "warn",
|
||||
"noUnusedVariables": "off",
|
||||
"useExhaustiveDependencies": "off",
|
||||
"noUnusedFunctionParameters": "off",
|
||||
"useHookAtTopLevel": "off"
|
||||
},
|
||||
"security": {
|
||||
"noDangerouslySetInnerHtml": "off"
|
||||
},
|
||||
"style": {
|
||||
"noNonNullAssertion": "off",
|
||||
"useSelfClosingElements": "error",
|
||||
"useTemplate": "off",
|
||||
"useNodejsImportProtocol": "off"
|
||||
},
|
||||
"suspicious": {
|
||||
"noArrayIndexKey": "off",
|
||||
"noExplicitAny": "off",
|
||||
"noImplicitAnyLet": "off",
|
||||
"noShadowRestrictedNames": "off"
|
||||
},
|
||||
"complexity": {
|
||||
"noImportantStyles": "off",
|
||||
"useOptionalChain": "off"
|
||||
}
|
||||
}
|
||||
},
|
||||
"vcs": {
|
||||
"clientKind": "git",
|
||||
"enabled": false,
|
||||
"useIgnoreFile": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^2.1.2",
|
||||
"prettier": "^3.6.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@biomejs/biome": ["@biomejs/biome@2.4.15", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.15", "@biomejs/cli-darwin-x64": "2.4.15", "@biomejs/cli-linux-arm64": "2.4.15", "@biomejs/cli-linux-arm64-musl": "2.4.15", "@biomejs/cli-linux-x64": "2.4.15", "@biomejs/cli-linux-x64-musl": "2.4.15", "@biomejs/cli-win32-arm64": "2.4.15", "@biomejs/cli-win32-x64": "2.4.15" }, "bin": { "biome": "bin/biome" } }, "sha512-j5VH3a/h/HXTKBM50MDMxRCzkeLv9S2XJcW2WgnZT1+xyisi+0bISrXR82gCX+8S9lvK0skEvHJRN+3Ktr2hlw=="],
|
||||
|
||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.15", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rF3PPqLq1yoST79zaQbDjVJwsuIeci/O+9bgNmC5QpgOqz6aqYuzA4abyAGx+mgyiDXn4A049xAN8gijbuR1Qg=="],
|
||||
|
||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.4.15", "", { "os": "darwin", "cpu": "x64" }, "sha512-/5KHXYMfSJs1fNXiX30xFtI8JcCFV6zaVVLxOa0M2sfqBKHkpQhRTv94yxQWxeTY2lzo2OuTlNvPC+hDQt2wcQ=="],
|
||||
|
||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.4.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-owaAMZD/T4LrD0ELNCk0Km3qrRHuM0X6EAyVE1FSqGY0rbLoiDLrO4Us2tllm6cAeB2Ioa9C2C08NZPdr8+0Ug=="],
|
||||
|
||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.4.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZPcxznxm0pogHBLZhYntyR3sR+MrZjqJIKEr7ZqVen0Rl+P/4upVmfYXjftizi9RoqZntg33fv/1fbdhbYXpEQ=="],
|
||||
|
||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.4.15", "", { "os": "linux", "cpu": "x64" }, "sha512-0jj7THz12GbUOLmMibktK6DZjqz2zV64KFxyBtcFTKPiiOIY0a7vns1elpO1dERvxpsZ5ik0oFfz0oGwFde1+g=="],
|
||||
|
||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.4.15", "", { "os": "linux", "cpu": "x64" }, "sha512-CNq/9W38SYSH023lfcQ4KKU8K0YX8T//FZUhcgtMMRABDojx5XsMV7jlweAvGSl389wJQB29Qo6Zb/a+jdvt+w=="],
|
||||
|
||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.4.15", "", { "os": "win32", "cpu": "arm64" }, "sha512-ouhkYdlhp/1GghEJPdWwD/Vi3gQ1nFxuSpMolWsbq3Lsq3QUR4jl6UdhhscdCugKU5vOEuMiJhvKj66O0OCq+w=="],
|
||||
|
||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.15", "", { "os": "win32", "cpu": "x64" }, "sha512-zBrGq5mx5wwpnow4+2BxUvleDM+GNd4sLbPaMapsSLQLD0NGRCquqPBTgN+7XkUteHvj7M+BstuI8tmnV7+HgQ=="],
|
||||
|
||||
"prettier": ["prettier@3.8.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw=="],
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
Contains helper procs for airflow, handled in /connection_group.
|
||||
*/
|
||||
|
||||
/mob/var/tmp/last_airflow_stun = 0
|
||||
/mob/proc/airflow_stun()
|
||||
if(stat == 2)
|
||||
return 0
|
||||
@@ -60,11 +59,6 @@ Contains helper procs for airflow, handled in /connection_group.
|
||||
if(4,5)
|
||||
if(n < GLOB.vsc.airflow_medium_pressure) return 0
|
||||
|
||||
/atom/movable/var/tmp/turf/airflow_dest
|
||||
/atom/movable/var/tmp/airflow_speed = 0
|
||||
/atom/movable/var/tmp/airflow_time = 0
|
||||
/atom/movable/var/tmp/last_airflow = 0
|
||||
|
||||
/atom/movable/proc/AirflowCanMove(n)
|
||||
return 1
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ GLOBAL_DATUM_INIT(contamination_overlay, /image, image('icons/effects/contaminat
|
||||
///Does being in sleeping gas cause you to hallucinate?
|
||||
var/N2O_HALLUCINATION = TRUE
|
||||
|
||||
/obj/var/contaminated = 0
|
||||
|
||||
/obj/item/proc/can_contaminate()
|
||||
if(item_flags & ITEM_FLAG_PHORON_GUARD)
|
||||
return FALSE
|
||||
|
||||
@@ -56,6 +56,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
#define PASSDOORHATCH (1<<15)
|
||||
#define PASSTRACE (1<<16) //Used by turrets in the check_trajectory proc to target mobs hiding behind certain things (such as closets)
|
||||
#define PASSRAILING (1<<17)
|
||||
/// Allows you to pass over energy shields, these also have additional handling for blocking projectiles in their on_hit().
|
||||
#define PASSSHIELD (1<<18)
|
||||
|
||||
//Movement Types
|
||||
#define GROUND (1<<0)
|
||||
|
||||
@@ -32,3 +32,24 @@
|
||||
#define BULLET_ACT_FORCE_PIERCE "PIERCE" //It pierces through the object regardless of the bullet being piercing by default.
|
||||
|
||||
#define NICE_SHOT_RICOCHET_BONUS 10 //if the shooter has the NICE_SHOT trait and they fire a ricocheting projectile, add this to the ricochet chance and auto aim angle
|
||||
|
||||
//attack visual effects
|
||||
#define ATTACK_EFFECT_PUNCH "punch"
|
||||
#define ATTACK_EFFECT_KICK "kick"
|
||||
#define ATTACK_EFFECT_SMASH "smash"
|
||||
#define ATTACK_EFFECT_CLAW "claw"
|
||||
#define ATTACK_EFFECT_SLASH "slash"
|
||||
#define ATTACK_EFFECT_DISARM "disarm"
|
||||
#define ATTACK_EFFECT_BITE "bite"
|
||||
#define ATTACK_EFFECT_MECHFIRE "mech_fire"
|
||||
#define ATTACK_EFFECT_MECHTOXIN "mech_toxin"
|
||||
#define ATTACK_EFFECT_BOOP "boop" //Honk
|
||||
#define ATTACK_EFFECT_VOID "void"
|
||||
#define ATTACK_EFFECT_CPR "cpr"
|
||||
|
||||
/// Attack animation for sharp items
|
||||
#define ATTACK_ANIMATION_SLASH "slash"
|
||||
/// Attack animation for pointy items
|
||||
#define ATTACK_ANIMATION_PIERCE "pierce"
|
||||
/// Animation for blunt attacks
|
||||
#define ATTACK_ANIMATION_BLUNT "blunt"
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON "atom_init_success_on"
|
||||
///from base of atom/examine(): (/mob, list/examine_text)
|
||||
#define COMSIG_ATOM_EXAMINE "atom_examine"
|
||||
///from base of atom/examine_tags(): (/mob, list/examine_tags)
|
||||
#define COMSIG_ATOM_EXAMINE_TAGS "atom_examine_tags"
|
||||
///from base of atom/Entered(): (atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
#define COMSIG_ATOM_ENTERED "atom_entered"
|
||||
/// Sent from the atom that just Entered src. From base of atom/Entered(): (/atom/destination, atom/old_loc, list/atom/old_locs)
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
/// Sent when a mob rests.
|
||||
#define COMSIG_MOB_RESTED "mob_rested"
|
||||
|
||||
/// Sent from /mob/proc/update_canmove() when the mob transitions into lying down.
|
||||
#define COMSIG_MOB_LYING_DOWN "mob_lying_down"
|
||||
|
||||
/// From /obj/item/organ/external/take_damage. Updates the limb's colour matrix. Very laggy, so we do it on reaction to stuff.
|
||||
#define COMSIG_UPDATE_LIMB_IMAGE "update_limb_image"
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#define COMSIG_ITEM_ATTACK_SELF "item_attack_self"
|
||||
//from base of obj/item/attack_self_secondary(): (/mob)
|
||||
#define COMSIG_ITEM_ATTACK_SELF_SECONDARY "item_attack_self_secondary"
|
||||
/// Sent from /obj/item/proc/animate_attack() : (atom/movable/attacker, atom/attacked_atom, animation_type, list/image_override, list/animation_override, list/angle_override)
|
||||
#define COMSIG_ITEM_ATTACK_ANIMATION "item_attack_animation"
|
||||
|
||||
///from base of [obj/item/attack()]: (atom/target, mob/user, proximity_flag, click_parameters)
|
||||
#define COMSIG_ITEM_AFTERATTACK "item_afterattack"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/// Window is fully visible and we can make fragile calls
|
||||
#define COMSIG_TGUI_WINDOW_VISIBLE "tgui_window_visible"
|
||||
@@ -51,8 +51,6 @@
|
||||
#define LEFT 1
|
||||
#define RIGHT 2
|
||||
|
||||
#define FIST_ATTACK_ANIMATION -1
|
||||
|
||||
// Pulse levels, very simplified.
|
||||
#define PULSE_NONE 0 // So !M.pulse checks would be possible.
|
||||
#define PULSE_SLOW 1 // <60 bpm
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
///The maximum improvement that can be applied to a weapon component.
|
||||
#define IMPROVEMENT_CAP 100
|
||||
///The maximum increase an individual variable can recieve over it's initial value.
|
||||
#define INCREASE_CAP 2
|
||||
#define INCREASE_CAP 1.5
|
||||
///The maximum decrease an individual variable can recieve under it's initial value.
|
||||
#define DECREASE_CAP 0.2
|
||||
#define DECREASE_CAP 0.5
|
||||
///All improvements are multiplied by this value, tweak down if they are too strong, up if they are too weak.
|
||||
#define IMPROVEMENT_MULTIPLIER 1
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
*/
|
||||
#define COMSIG_GRAVITY_WEAKNESS_EVENT "gravity_weakness_event"
|
||||
|
||||
/// Raised external organ (a limb) takes damage. Used for the synthetic endoskeleton at the moment. Must supply damage.
|
||||
#define COMSIG_EXTERNAL_ORGAN_DAMAGE "machine_internal_damage"
|
||||
/// This is raised when you want to send damage to the synthetic endoskeleton. Must supply a damage number.
|
||||
#define COMSIG_DAMAGE_TO_ENDOSKELETON "machine_internal_damage"
|
||||
|
||||
/// Sent when the burst damage is cleared by the posibrain.
|
||||
#define COMSIG_SYNTH_EMP_DAMAGE_CLEARED "emp_damage_cleared"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#define SHIP_AMMO_IMPACT_HE "high explosive"
|
||||
#define SHIP_AMMO_IMPACT_PROBE "sensor probe"
|
||||
#define SHIP_AMMO_IMPACT_FMJ "full metal jacket"
|
||||
#define SHIP_AMMO_IMPACT_FRAG "fragmentation"
|
||||
#define SHIP_AMMO_IMPACT_AP "armour-piercing"
|
||||
#define SHIP_AMMO_IMPACT_LASER "laser"
|
||||
#define SHIP_AMMO_IMPACT_BUNKERBUSTER "bunker-buster"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define SPAN_COLOR(color, str) SPAN_STYLE("color: [color]", "[str]")
|
||||
#define SPAN_CAUTION(str) ("<span class='caution'>" + str + "</span>")
|
||||
#define SPAN_STORYTELLER(str) ("<span class='storyteller'>" + str + "</span>")
|
||||
#define SPAN_BOLDANNOUNCE(str) ("<span class='boldannounce'>" + str + "</span>")
|
||||
|
||||
#define SPAN_MACHINE_WARNING(str) ("<span class='machine-warning'>" + str + "</span>")
|
||||
#define SPAN_MACHINE_DANGER(str) ("<span class='machine-danger'>" + str + "</span>")
|
||||
@@ -42,6 +43,9 @@
|
||||
#define SPAN_BOLDNOTICE(str) ("<span class='boldnotice'>" + str + "</span>")
|
||||
#define SPAN_BOLDWARNING(X) "<span class='boldwarning'>[X]</span>"
|
||||
|
||||
// Spans that use embedded tgui components:
|
||||
#define SPAN_TOOLTIP(tip, main_text) ("<span data-component=\"Tooltip\" data-content=\"" + tip + "\" class=\"tooltip\">" + main_text + "</span>")
|
||||
|
||||
/*
|
||||
#####################
|
||||
Font sizes
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#define SS_PRIORITY_STATPANELS 25 // Statpanels.
|
||||
#define SS_PRIORITY_LIGHTING 25 // Queued lighting engine updates.
|
||||
#define SS_PRIORITY_MACHINERY 25 // Machinery + powernet ticks.
|
||||
#define SS_PRIORITY_NANOUI 25 // UI updates.
|
||||
#define SS_PRIORITY_ELECTRONICS 20 // Integrated Electronics processing.
|
||||
#define SS_PRIORITY_CALAMITY 20 // Singularity, Tesla, Nar'sie, blob, etc.
|
||||
#define SS_PRIORITY_EVENT 20
|
||||
|
||||
@@ -277,6 +277,7 @@
|
||||
#define FIRE_PRIORITY_SPACEDRIFT 30
|
||||
#define FIRE_PRIORITY_DEFAULT 50
|
||||
#define FIRE_PRIORITY_MOBS 100
|
||||
#define FIRE_PRIORITY_TGUI 110
|
||||
#define FIRE_PRIORITY_STATPANEL 390
|
||||
#define FIRE_PRIORITY_CHAT 400
|
||||
#define FIRE_PRIORITY_RUNECHAT 410
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#define CHAT_MESSAGE_WIDTH 112
|
||||
|
||||
// Setting this much higher than 1024 could allow spammers to DOS the server easily.
|
||||
#define MAX_MESSAGE_LEN 1024
|
||||
#define MAX_MESSAGE_LEN 4096
|
||||
#define MAX_PAPER_MESSAGE_LEN 3072
|
||||
#define MAX_BOOK_MESSAGE_LEN 9216
|
||||
#define MAX_LNAME_LEN 64
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#define TGS_EXTERNAL_CONFIGURATION
|
||||
#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, SPAN_BOLDANNOUNCE("[html_encode(##message)]"))
|
||||
#define TGS_INFO_LOG(message) log_world("TGS Info: [##message]")
|
||||
#define TGS_WARNING_LOG(message) log_world("TGS Warn: [##message]")
|
||||
#define TGS_ERROR_LOG(message) stack_trace("TGS Error: [##message]")
|
||||
#define TGS_NOTIFY_ADMINS(event) message_admins(##event)
|
||||
#define TGS_CLIENT_COUNT GLOB.clients.len
|
||||
#define TGS_PROTECT_DATUM(Path) GENERAL_PROTECT_DATUM(##Path)
|
||||
+132
-44
@@ -1,55 +1,68 @@
|
||||
// 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 "6.6.2"
|
||||
#define TGS_DMAPI_VERSION "7.3.3"
|
||||
|
||||
// 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.
|
||||
//#error TGS API unconfigured
|
||||
// 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
|
||||
|
||||
// Required interfaces (fill in with your codebase equivalent):
|
||||
|
||||
/// Create a global variable named `Name` and set it to `Value`.
|
||||
#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) var/global/##Name = ##Value
|
||||
#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value)
|
||||
|
||||
/// Read the value in the global variable `Name`.
|
||||
#define TGS_READ_GLOBAL(Name) global.##Name
|
||||
#define TGS_READ_GLOBAL(Name)
|
||||
|
||||
/// Set the value in the global variable `Name` to `Value`.
|
||||
#define TGS_WRITE_GLOBAL(Name, Value) global.##Name = ##Value
|
||||
#define TGS_WRITE_GLOBAL(Name, Value)
|
||||
|
||||
/// Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities.
|
||||
#define TGS_PROTECT_DATUM(Path)
|
||||
|
||||
/// Display an announcement `message` from the server to all players.
|
||||
#define TGS_WORLD_ANNOUNCE(message) world << "<b>TGS Notification</b>: [html_encode(##message)]"
|
||||
#define TGS_WORLD_ANNOUNCE(message)
|
||||
|
||||
/// Notify current in-game administrators of a string `event`.
|
||||
#define TGS_NOTIFY_ADMINS(event) message_admins(##event)
|
||||
#define TGS_NOTIFY_ADMINS(event)
|
||||
|
||||
/// Write an info `message` to a server log.
|
||||
#define TGS_INFO_LOG(message) log_tgs("[##message]")
|
||||
#define TGS_INFO_LOG(message)
|
||||
|
||||
/// Write an warning `message` to a server log.
|
||||
#define TGS_WARNING_LOG(message) log_tgs("[##message]", SEVERITY_WARNING)
|
||||
#define TGS_WARNING_LOG(message)
|
||||
|
||||
/// Write an error `message` to a server log.
|
||||
#define TGS_ERROR_LOG(message) log_tgs("[##message]", SEVERITY_ERROR)
|
||||
#define TGS_ERROR_LOG(message)
|
||||
|
||||
/// Get the number of connected /clients.
|
||||
#define TGS_CLIENT_COUNT clients.len
|
||||
#define TGS_CLIENT_COUNT
|
||||
|
||||
#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
|
||||
|
||||
// SpacemanDMM compatibility
|
||||
#ifndef CAN_BE_REDEFINED
|
||||
#define CAN_BE_REDEFINED(X)
|
||||
#endif
|
||||
|
||||
// EVENT CODES
|
||||
|
||||
/// Before a reboot mode change, extras parameters are the current and new reboot mode enums.
|
||||
@@ -73,12 +86,12 @@
|
||||
#define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3
|
||||
/// Before the repository makes a sychronize operation. Parameters: Absolute repostiory path.
|
||||
#define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4
|
||||
/// Before a BYOND install operation begins. Parameters: [/datum/tgs_version] of the installing BYOND.
|
||||
#define TGS_EVENT_BYOND_INSTALL_START 5
|
||||
/// When a BYOND install operation fails. Parameters: Error message
|
||||
#define TGS_EVENT_BYOND_INSTALL_FAIL 6
|
||||
/// When the active BYOND version changes. Parameters: (Nullable) [/datum/tgs_version] of the current BYOND, [/datum/tgs_version] of the new BYOND.
|
||||
#define TGS_EVENT_BYOND_ACTIVE_VERSION_CHANGE 7
|
||||
/// Before a engine install operation begins. Parameters: Version string of the installing engine.
|
||||
#define TGS_EVENT_ENGINE_INSTALL_START 5
|
||||
/// When a engine install operation fails. Parameters: Error message
|
||||
#define TGS_EVENT_ENGINE_INSTALL_FAIL 6
|
||||
/// When the active engine version changes. Parameters: (Nullable) Version string of the current engine, version string of the new engine.
|
||||
#define TGS_EVENT_ENGINE_ACTIVE_VERSION_CHANGE 7
|
||||
/// When the compiler starts running. Parameters: Game directory path, origin commit SHA.
|
||||
#define TGS_EVENT_COMPILE_START 8
|
||||
/// When a compile is cancelled. No parameters.
|
||||
@@ -108,7 +121,7 @@
|
||||
// #define TGS_EVENT_DREAM_DAEMON_LAUNCH 22
|
||||
/// After a single submodule update is performed. Parameters: Updated submodule name.
|
||||
#define TGS_EVENT_REPO_SUBMODULE_UPDATE 23
|
||||
/// After CodeModifications are applied, before DreamMaker is run. Parameters: Game directory path, origin commit sha, byond version.
|
||||
/// After CodeModifications are applied, before DreamMaker is run. Parameters: Game directory path, origin commit sha, version string of the used engine.
|
||||
#define TGS_EVENT_PRE_DREAM_MAKER 24
|
||||
/// Whenever a deployment folder is deleted from disk. Parameters: Game directory path.
|
||||
#define TGS_EVENT_DEPLOYMENT_CLEANUP 25
|
||||
@@ -122,6 +135,7 @@
|
||||
/// The watchdog will restart on reboot.
|
||||
#define TGS_REBOOT_MODE_RESTART 2
|
||||
|
||||
// Note that security levels are currently meaningless in OpenDream
|
||||
/// DreamDaemon Trusted security level.
|
||||
#define TGS_SECURITY_TRUSTED 0
|
||||
/// DreamDaemon Safe security level.
|
||||
@@ -136,20 +150,26 @@
|
||||
/// DreamDaemon invisible visibility level.
|
||||
#define TGS_VISIBILITY_INVISIBLE 2
|
||||
|
||||
/// The Build Your Own Net Dream engine.
|
||||
#define TGS_ENGINE_TYPE_BYOND 0
|
||||
/// The OpenDream engine.
|
||||
#define TGS_ENGINE_TYPE_OPENDREAM 1
|
||||
|
||||
//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)
|
||||
CAN_BE_REDEFINED(TRUE)
|
||||
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
|
||||
@@ -159,12 +179,10 @@
|
||||
CAN_BE_REDEFINED(TRUE)
|
||||
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
|
||||
|
||||
/**
|
||||
* 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()
|
||||
CAN_BE_REDEFINED(TRUE)
|
||||
return
|
||||
@@ -261,7 +279,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
|
||||
@@ -275,7 +293,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 = ""
|
||||
@@ -288,29 +340,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
|
||||
@@ -322,13 +381,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
|
||||
@@ -337,7 +396,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
|
||||
@@ -345,48 +404,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!")
|
||||
|
||||
@@ -429,6 +498,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.
|
||||
@@ -439,6 +509,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.
|
||||
@@ -449,6 +520,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.
|
||||
@@ -462,6 +534,11 @@
|
||||
CAN_BE_REDEFINED(TRUE)
|
||||
return
|
||||
|
||||
/// Returns the running engine type
|
||||
/world/proc/TgsEngine()
|
||||
CAN_BE_REDEFINED(TRUE)
|
||||
return
|
||||
|
||||
/// Returns the current [/datum/tgs_version] of the DMAPI being used if it was activated, null otherwise. This function may sleep if the call to [/world/proc/TgsNew] is sleeping!
|
||||
/world/proc/TgsApiVersion()
|
||||
CAN_BE_REDEFINED(TRUE)
|
||||
@@ -497,10 +574,21 @@
|
||||
CAN_BE_REDEFINED(TRUE)
|
||||
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)
|
||||
CAN_BE_REDEFINED(TRUE)
|
||||
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
|
||||
|
||||
@@ -24,6 +24,16 @@
|
||||
/// Window is free and ready to receive data
|
||||
#define TGUI_WINDOW_READY 2
|
||||
|
||||
/// Though not the maximum renderable ByondUis within tgui, this is the maximum that the server will manage per-UI
|
||||
#define TGUI_MANAGED_BYONDUI_LIMIT 10
|
||||
|
||||
// These are defines instead of being inline, as they're being sent over
|
||||
// from tgui-core, so can't be easily played with
|
||||
#define TGUI_MANAGED_BYONDUI_TYPE_RENDER "renderByondUi"
|
||||
#define TGUI_MANAGED_BYONDUI_TYPE_UNMOUNT "unmountByondUi"
|
||||
|
||||
#define TGUI_MANAGED_BYONDUI_PAYLOAD_ID "renderByondUi"
|
||||
|
||||
/// Get a window id based on the provided pool index
|
||||
#define TGUI_WINDOW_ID(index) "tgui-window-[index]"
|
||||
/// Get a pool index of the provided window id
|
||||
|
||||
@@ -94,6 +94,9 @@
|
||||
/proc/is_shuttle_area(var/area/A)
|
||||
. = istype(A,/area/horizon/shuttle)
|
||||
|
||||
/proc/is_shieldless_exterior(var/area/A)
|
||||
. = istype(A,/area/horizon/exterior/no_shields)
|
||||
|
||||
/proc/is_area_with_turf(var/area/A)
|
||||
. = isnum(A.x)
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
/**
|
||||
* Blend atoms
|
||||
*/
|
||||
/atom/proc/handle_blending(adjacencies, var/list/dir_mods)
|
||||
/atom/proc/handle_blending(adjacencies, list/dir_mods)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
LAZYINITLIST(dir_mods)
|
||||
@@ -282,10 +282,10 @@
|
||||
var/walls_found = 0
|
||||
for(var/adjacency in list(N_NORTH, N_EAST, N_SOUTH, N_WEST))
|
||||
if(adjacencies & adjacency)
|
||||
var/turf/T = get_step(src, REVERSE_DIR(adjacency))
|
||||
var/turf/T = get_step(src, GLOB.ndir_to_dir[adjacency]) // get_step() expects byond native directions, so we convert N_* bitfields
|
||||
if(is_type_in_list(T, can_blend_with))
|
||||
if(attach_overlay)
|
||||
AddOverlays("[REVERSE_DIR(adjacency)]_[attach_overlay]")
|
||||
AddOverlays("[GLOB.ndir_to_dir[adjacency]]_[attach_overlay]")
|
||||
walls_found |= adjacency
|
||||
dir_mods["[adjacency]"] = "-[blend_overlay]"
|
||||
for(var/adjacency in list(N_NORTH, N_SOUTH))
|
||||
@@ -297,7 +297,7 @@
|
||||
|
||||
var/has_adjacency = walls_found & adjacency
|
||||
var/has_diagonal = walls_found & diagonal
|
||||
if(((adjacencies & adjacency) && (adjacencies && diagonal)) && (has_adjacency || has_diagonal))
|
||||
if(((adjacencies & adjacency) && (adjacencies & diagonal)) && (has_adjacency || has_diagonal))
|
||||
dir_mods["[adjacency][diagonal]"] = "-[prefix][has_adjacency ? "wall" : "win"]-[suffix][has_diagonal ? "wall" : "win"]"
|
||||
if(attach_overlay)
|
||||
AddOverlays("[prefix][suffix]_[attach_overlay]")
|
||||
@@ -305,10 +305,15 @@
|
||||
|
||||
#undef ndir_to_initial
|
||||
|
||||
/atom/proc/cardinal_smooth(adjacencies)
|
||||
/atom/proc/cardinal_smooth(adjacencies, list/dir_mods)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
/**
|
||||
* Below here we evaluate an object by their 4 corners and tell them how they're supposed to smooth depending on its adjacencies.
|
||||
* The adjacencies we care about is the things that the atom can smooth with, determined in 'calculate_adjacencies()'.
|
||||
* Think this as mapping an icon, every 16x16 corner counts.
|
||||
*/
|
||||
|
||||
//NW CORNER
|
||||
// NW CORNER
|
||||
var/nw = "1-i"
|
||||
if((adjacencies & N_NORTH) && (adjacencies & N_WEST))
|
||||
if(adjacencies & N_NORTHWEST)
|
||||
@@ -321,7 +326,7 @@
|
||||
else if(adjacencies & N_WEST)
|
||||
nw = "1-w"
|
||||
|
||||
//NE CORNER
|
||||
// NE CORNER
|
||||
var/ne = "2-i"
|
||||
if((adjacencies & N_NORTH) && (adjacencies & N_EAST))
|
||||
if(adjacencies & N_NORTHEAST)
|
||||
@@ -334,7 +339,7 @@
|
||||
else if(adjacencies & N_EAST)
|
||||
ne = "2-e"
|
||||
|
||||
//SW CORNER
|
||||
// SW CORNER
|
||||
var/sw = "3-i"
|
||||
if((adjacencies & N_SOUTH) && (adjacencies & N_WEST))
|
||||
if(adjacencies & N_SOUTHWEST)
|
||||
@@ -347,7 +352,7 @@
|
||||
else if(adjacencies & N_WEST)
|
||||
sw = "3-w"
|
||||
|
||||
//SE CORNER
|
||||
// SE CORNER
|
||||
var/se = "4-i"
|
||||
if((adjacencies & N_SOUTH) && (adjacencies & N_EAST))
|
||||
if(adjacencies & N_SOUTHEAST)
|
||||
@@ -360,6 +365,36 @@
|
||||
else if(adjacencies & N_EAST)
|
||||
se = "4-e"
|
||||
|
||||
/**
|
||||
* Here we handle blend overlays. This is an extra step if we want our icons to take account whatever is defined in their 'can_blend_with' list
|
||||
* and apply a different smooth overlay for them. An example to this is windows, they'll smooth regularly among themselves but if there's
|
||||
* a wall next to them they'll apply a junction part. See 'handle_blending()' for blending direction modifiers (dir_mods).
|
||||
*/
|
||||
if(length(dir_mods))
|
||||
|
||||
nw += LAZYACCESS(dir_mods, "[N_NORTH][N_WEST][N_NORTHWEST]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_NORTH][N_WEST]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_NORTH]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_WEST]")
|
||||
|
||||
ne += LAZYACCESS(dir_mods, "[N_NORTH][N_EAST][N_NORTHEAST]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_NORTH][N_EAST]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_NORTH]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_EAST]")
|
||||
|
||||
sw += LAZYACCESS(dir_mods, "[N_SOUTH][N_WEST][N_SOUTHWEST]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_SOUTH][N_WEST]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_SOUTH]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_WEST]")
|
||||
|
||||
se += LAZYACCESS(dir_mods, "[N_SOUTH][N_EAST][N_SOUTHEAST]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_SOUTH][N_EAST]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_SOUTH]") \
|
||||
|| LAZYACCESS(dir_mods, "[N_EAST]")
|
||||
|
||||
/**
|
||||
* Here we apply all the 4 corners we calculated and clean the cached corners.
|
||||
*/
|
||||
var/list/New
|
||||
var/list/Old
|
||||
var/cut_f = smoothing_hints & SMOOTHHINT_CUT_F
|
||||
|
||||
@@ -912,3 +912,31 @@
|
||||
/proc/endswith(input_text, ending)
|
||||
var/input_length = LAZYLEN(ending)
|
||||
return !!findtext(input_text, ending, -input_length)
|
||||
|
||||
///Returns a string based on the weight class define used as argument
|
||||
/proc/weight_class_to_text(w_class)
|
||||
switch(w_class)
|
||||
if(WEIGHT_CLASS_TINY)
|
||||
. = "tiny"
|
||||
if(WEIGHT_CLASS_SMALL)
|
||||
. = "small"
|
||||
if(WEIGHT_CLASS_NORMAL)
|
||||
. = "normal-sized"
|
||||
if(WEIGHT_CLASS_BULKY)
|
||||
. = "bulky"
|
||||
if(WEIGHT_CLASS_HUGE)
|
||||
. = "huge"
|
||||
if(WEIGHT_CLASS_GIGANTIC)
|
||||
. = "gigantic"
|
||||
else
|
||||
. = ""
|
||||
|
||||
/proc/weight_class_to_tooltip(w_class)
|
||||
switch(w_class)
|
||||
if(WEIGHT_CLASS_TINY to WEIGHT_CLASS_SMALL)
|
||||
return "This item can fit into pockets, boxes and backpacks."
|
||||
if(WEIGHT_CLASS_NORMAL)
|
||||
return "This item can fit into backpacks."
|
||||
if(WEIGHT_CLASS_BULKY to WEIGHT_CLASS_GIGANTIC)
|
||||
return "This item is too large to fit into any standard storage."
|
||||
return ""
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
turfs += T
|
||||
if(turfs.len)
|
||||
return pick(turfs)
|
||||
else
|
||||
return null
|
||||
|
||||
///Returns a turf based on text inputs, original turf and viewing client
|
||||
/proc/parse_caught_click_modifiers(list/modifiers, turf/origin, client/viewing_client)
|
||||
|
||||
@@ -623,11 +623,6 @@ Turf and target are seperate in case you want to teleport some distance from a t
|
||||
if (progbar)
|
||||
qdel(progbar)
|
||||
|
||||
/// Integer. Unique sequential ID from the `do_after` proc used to validate `DO_USER_UNIQUE_ACT` flag checks.
|
||||
/mob/var/do_unique_user_handle = 0
|
||||
/// The mob currently interacting with the atom during a `do_after` timer. Used to validate `DO_TARGET_UNIQUE_ACT` flag checks.
|
||||
/atom/var/mob/do_unique_target_user
|
||||
|
||||
/**
|
||||
* Timed actions involving one mob user and (optionally) one target.
|
||||
*
|
||||
|
||||
@@ -93,6 +93,18 @@ GLOBAL_LIST_INIT(alldirs, list(
|
||||
SOUTHWEST,
|
||||
))
|
||||
|
||||
/// Used in N_* directions (defined in \code\_DEFINES\icon_smoothing.dm) to Byond native conversions
|
||||
GLOBAL_LIST_INIT(ndir_to_dir, alist(
|
||||
N_NORTH = NORTH,
|
||||
N_SOUTH = SOUTH,
|
||||
N_EAST = EAST,
|
||||
N_WEST = WEST,
|
||||
N_NORTHEAST = NORTHEAST,
|
||||
N_NORTHWEST = NORTHWEST,
|
||||
N_SOUTHEAST = SOUTHEAST,
|
||||
N_SOUTHWEST = SOUTHWEST
|
||||
))
|
||||
|
||||
/// Just a list of all the area objects in the game
|
||||
/// Note, areas can have duplicate types
|
||||
GLOBAL_LIST_EMPTY(areas)
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
~Sayu
|
||||
*/
|
||||
|
||||
// 1 decisecond click delay (above and beyond mob/next_move)
|
||||
/mob/var/next_click = 0
|
||||
|
||||
|
||||
/**
|
||||
* Before anything else, defer these calls to a per-mobtype handler. This allows us to
|
||||
* remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
|
||||
|
||||
@@ -11,15 +11,6 @@ if(!click_handlers) { \
|
||||
click_handlers += new/datum/click_handler/default(src) \
|
||||
}
|
||||
|
||||
/**
|
||||
* LAZYLIST (Instances of `/datum/click_handler`). Click handlers for this mob that should intercept and handle click
|
||||
* calls.
|
||||
*
|
||||
* The 'topmost'/'active' click handler for the mob is the handler currently at index `1`. By default, this will be
|
||||
* `/datum/click_handler/default`.
|
||||
*/
|
||||
/mob/var/list/click_handlers
|
||||
|
||||
// In the mob code, because otherwise it's a redefinition
|
||||
// /mob/Destroy()
|
||||
// QDEL_LIST(click_handlers)
|
||||
|
||||
@@ -284,6 +284,22 @@
|
||||
check_flags = AB_CHECK_STUNNED|AB_CHECK_ALIVE|AB_CHECK_INSIDE
|
||||
button_icon_state = "night_eyes"
|
||||
|
||||
/datum/action/item_action/organ/night_eyes/Trigger()
|
||||
if(!Checks())
|
||||
return
|
||||
var/obj/item/organ/internal/eyes/night/target_eyes = target
|
||||
target_eyes.night_vision()
|
||||
|
||||
/datum/action/item_action/organ/extended_eyes
|
||||
check_flags = AB_CHECK_STUNNED|AB_CHECK_ALIVE|AB_CHECK_INSIDE
|
||||
button_icon_state = "night_eyes"
|
||||
|
||||
/datum/action/item_action/organ/extended_eyes/Trigger()
|
||||
if(!Checks())
|
||||
return
|
||||
var/obj/item/organ/internal/eyes/night/target_eyes = target
|
||||
target_eyes.extended_vision()
|
||||
|
||||
/datum/action/item_action/organ/night_eyes/rev
|
||||
check_flags = AB_CHECK_ALIVE|AB_CHECK_INSIDE
|
||||
button_icon_state = "rev_eyes"
|
||||
|
||||
+30
-26
@@ -5,11 +5,6 @@
|
||||
GLOBAL_DATUM_INIT(global_hud, /datum/global_hud, new)
|
||||
GLOBAL_LIST(global_huds)
|
||||
|
||||
/datum/hud/var/atom/movable/screen/grab_intent
|
||||
/datum/hud/var/atom/movable/screen/hurt_intent
|
||||
/datum/hud/var/atom/movable/screen/disarm_intent
|
||||
/datum/hud/var/atom/movable/screen/help_intent
|
||||
|
||||
/datum/global_hud
|
||||
var/atom/movable/screen/vr_control
|
||||
var/atom/movable/screen/druggy
|
||||
@@ -111,12 +106,11 @@ GLOBAL_LIST(global_huds)
|
||||
O.layer = IMPAIRED_LAYER
|
||||
O.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
/*
|
||||
The hud datum
|
||||
Used to show and hide huds for all the different mob types,
|
||||
including inventories and item quick actions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The hud datum
|
||||
* Used to show and hide huds for all the different mob types,
|
||||
* including inventories and item quick actions.
|
||||
*/
|
||||
/datum/hud
|
||||
///The mob that possesses the HUD
|
||||
var/mob/mymob
|
||||
@@ -136,12 +130,21 @@ GLOBAL_LIST(global_huds)
|
||||
///Boolean, if the action buttons are hidden
|
||||
var/action_buttons_hidden = FALSE
|
||||
|
||||
/*
|
||||
STOP ADDING SNOWFLAKE HUD ELEMENTS LIKE /datum/hud/var/atom/movable/screen/help_intent
|
||||
IN DIFFERENT FILES ENTIRELY. IF YOU ARE ADDING A NEW HUD ELEMENT TO THIS, PUT IT IN THIS FILE UNDER THIS LIST,
|
||||
AND INCLUDE A QDEL_NULL() FOR IT IN THE DESTROY PROC.
|
||||
*/
|
||||
var/atom/movable/screen/blobpwrdisplay
|
||||
var/atom/movable/screen/blobhealthdisplay
|
||||
var/atom/movable/screen/r_hand_hud_object
|
||||
var/atom/movable/screen/l_hand_hud_object
|
||||
var/atom/movable/screen/action_intent
|
||||
var/atom/movable/screen/movement_intent/move_intent
|
||||
var/atom/movable/screen/grab_intent
|
||||
var/atom/movable/screen/hurt_intent
|
||||
var/atom/movable/screen/disarm_intent
|
||||
var/atom/movable/screen/help_intent
|
||||
|
||||
var/list/adding
|
||||
var/list/other
|
||||
@@ -177,26 +180,27 @@ GLOBAL_LIST(global_huds)
|
||||
..()
|
||||
|
||||
/datum/hud/Destroy()
|
||||
grab_intent = null
|
||||
hurt_intent = null
|
||||
disarm_intent = null
|
||||
help_intent = null
|
||||
blobpwrdisplay = null
|
||||
blobhealthdisplay = null
|
||||
r_hand_hud_object = null
|
||||
l_hand_hud_object = null
|
||||
action_intent = null
|
||||
move_intent = null
|
||||
adding = null
|
||||
other = null
|
||||
hotkeybuttons = null
|
||||
// item_action_list = null // ?
|
||||
mymob = null
|
||||
QDEL_NULL(blobpwrdisplay)
|
||||
QDEL_NULL(blobhealthdisplay)
|
||||
QDEL_NULL(r_hand_hud_object)
|
||||
QDEL_NULL(l_hand_hud_object)
|
||||
QDEL_NULL(action_intent)
|
||||
QDEL_NULL(move_intent)
|
||||
QDEL_NULL(grab_intent)
|
||||
QDEL_NULL(hurt_intent)
|
||||
QDEL_NULL(disarm_intent)
|
||||
QDEL_NULL(help_intent)
|
||||
|
||||
adding?.Cut()
|
||||
other?.Cut()
|
||||
QDEL_LIST(hotkeybuttons)
|
||||
|
||||
QDEL_LIST_ASSOC_VAL(plane_masters)
|
||||
QDEL_LIST_ASSOC_VAL(plane_master_controllers)
|
||||
QDEL_NULL(hide_actions_toggle)
|
||||
|
||||
. = ..()
|
||||
return ..()
|
||||
|
||||
/datum/hud/proc/hidden_inventory_update()
|
||||
if(!mymob)
|
||||
|
||||
@@ -26,10 +26,10 @@
|
||||
/atom/movable/screen/Destroy(force = FALSE)
|
||||
master = null
|
||||
screen_loc = null
|
||||
if(hud?.mymob?.client)
|
||||
if(length(hud?.mymob?.client?.screen))
|
||||
hud.mymob.client.screen -= src
|
||||
hud = null
|
||||
. = ..()
|
||||
return ..()
|
||||
|
||||
/// Screen elements are always on top of the players screen and don't move so yes they are adjacent
|
||||
/atom/movable/screen/Adjacent(atom/neighbor, atom/target, atom/movable/mover)
|
||||
|
||||
@@ -150,7 +150,7 @@ This calls [atom/proc/tool_act], among others.
|
||||
return 0
|
||||
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
user.do_attack_animation(target_mob, src)
|
||||
user.do_attack_animation(target_mob, used_item = src)
|
||||
if(!user.aura_check(AURA_TYPE_WEAPON, src, user))
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -10,31 +10,82 @@ SUBSYSTEM_DEF(chat)
|
||||
flags = SS_TICKER | SS_NO_INIT
|
||||
wait = 1
|
||||
priority = FIRE_PRIORITY_CHAT
|
||||
init_order = INIT_ORDER_CHAT
|
||||
init_order = INITSTAGE_MAX
|
||||
|
||||
var/list/payload_by_client = list()
|
||||
/// Assosciates a ckey with a list of messages to send to them.
|
||||
var/list/list/datum/chat_payload/client_to_payloads = list()
|
||||
|
||||
/// Associates a ckey with an assosciative list of their last CHAT_RELIABILITY_HISTORY_SIZE messages.
|
||||
var/list/list/datum/chat_payload/client_to_reliability_history = list()
|
||||
|
||||
/// Assosciates a ckey with their next sequence number.
|
||||
var/list/client_to_sequence_number = list()
|
||||
|
||||
/datum/controller/subsystem/chat/proc/generate_payload(client/target, message_data)
|
||||
var/sequence = client_to_sequence_number[target.ckey]
|
||||
client_to_sequence_number[target.ckey] += 1
|
||||
|
||||
var/datum/chat_payload/payload = new
|
||||
payload.sequence = sequence
|
||||
payload.content = message_data
|
||||
|
||||
if(!(target.ckey in client_to_reliability_history))
|
||||
client_to_reliability_history[target.ckey] = list()
|
||||
var/list/client_history = client_to_reliability_history[target.ckey]
|
||||
client_history["[sequence]"] = payload
|
||||
|
||||
if(length(client_history) > 5)
|
||||
var/oldest = text2num(client_history[1])
|
||||
for(var/index in 2 to length(client_history))
|
||||
var/test = text2num(client_history[index])
|
||||
if(test < oldest)
|
||||
oldest = test
|
||||
client_history -= "[oldest]"
|
||||
return payload
|
||||
|
||||
/datum/controller/subsystem/chat/proc/send_payload_to_client(client/target, datum/chat_payload/payload)
|
||||
target.tgui_panel.window.send_message("chat/message", payload.into_message())
|
||||
SEND_TEXT(target, payload.get_content_as_html())
|
||||
|
||||
/datum/controller/subsystem/chat/fire()
|
||||
for(var/key in payload_by_client)
|
||||
var/client/client = key
|
||||
var/payload = payload_by_client[key]
|
||||
payload_by_client -= key
|
||||
if(client)
|
||||
// Send to tgchat
|
||||
client.tgui_panel?.window.send_message("chat/message", payload)
|
||||
// Send to old chat
|
||||
for(var/message in payload)
|
||||
to_target(client, message_to_html(message))
|
||||
for(var/ckey in client_to_payloads)
|
||||
var/client/target = GLOB.directory[ckey]
|
||||
if(isnull(target)) // verify client still exists
|
||||
LAZYREMOVE(client_to_payloads, ckey)
|
||||
continue
|
||||
|
||||
for(var/datum/chat_payload/payload as anything in client_to_payloads[ckey])
|
||||
send_payload_to_client(target, payload)
|
||||
LAZYREMOVE(client_to_payloads, ckey)
|
||||
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
/datum/controller/subsystem/chat/proc/queue(target, message)
|
||||
if(islist(target))
|
||||
for(var/_target in target)
|
||||
var/client/client = CLIENT_FROM_VAR(_target)
|
||||
if(client)
|
||||
LAZYADD(payload_by_client[client], list(message))
|
||||
/datum/controller/subsystem/chat/proc/queue(queue_target, list/message_data)
|
||||
var/list/targets = islist(queue_target) ? queue_target : list(queue_target)
|
||||
for(var/target in targets)
|
||||
var/client/client = CLIENT_FROM_VAR(target)
|
||||
if(isnull(client))
|
||||
continue
|
||||
LAZYADDASSOCLIST(client_to_payloads, client.ckey, generate_payload(client, message_data))
|
||||
|
||||
/datum/controller/subsystem/chat/proc/send_immediate(send_target, list/message_data)
|
||||
var/list/targets = islist(send_target) ? send_target : list(send_target)
|
||||
for(var/target in targets)
|
||||
var/client/client = CLIENT_FROM_VAR(target)
|
||||
if(isnull(client))
|
||||
continue
|
||||
send_payload_to_client(client, generate_payload(client, message_data))
|
||||
|
||||
/datum/controller/subsystem/chat/proc/handle_resend(client/client, sequence)
|
||||
var/list/client_history = client_to_reliability_history[client.ckey]
|
||||
sequence = "[sequence]"
|
||||
if(isnull(client_history) || !(sequence in client_history))
|
||||
return
|
||||
var/client/client = CLIENT_FROM_VAR(target)
|
||||
if(client)
|
||||
LAZYADD(payload_by_client[client], list(message))
|
||||
|
||||
var/datum/chat_payload/payload = client_history[sequence]
|
||||
if(payload.resends > 3)
|
||||
return // we tried but byond said no
|
||||
|
||||
payload.resends += 1
|
||||
send_payload_to_client(client, client_history[sequence])
|
||||
|
||||
@@ -306,6 +306,18 @@ SUBSYSTEM_DEF(garbage)
|
||||
|
||||
if (time > 0.1 SECONDS)
|
||||
postpone(time)
|
||||
|
||||
// Standard sentry logging for hard dels other than the two subsystems that will always hard del every round
|
||||
var/sentry_threshold = 0.25 SECONDS
|
||||
if (time > sentry_threshold && SSsentry)
|
||||
SSsentry.capture_message(
|
||||
"Hard delete: [type]",
|
||||
"warning",
|
||||
"garbage",
|
||||
tags = list("datum_type" = "[type]"),
|
||||
extra = list("ref_id" = refID, "time_ms" = tick_usage, "details" = detail)
|
||||
)
|
||||
|
||||
var/threshold = 0.5 // Used to be CONFIG_GET(number/hard_deletes_overrun_threshold)
|
||||
if (threshold && (time > threshold SECONDS))
|
||||
if (!(type_info.qdel_flags & QDEL_ITEM_ADMINS_WARNED))
|
||||
@@ -318,7 +330,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
"warning",
|
||||
"garbage",
|
||||
tags = list("datum_type" = "[type]"),
|
||||
extra = list("ref_id" = refID, "time_ms" = tick_usage)
|
||||
extra = list("ref_id" = refID, "time_ms" = tick_usage, "details" = detail)
|
||||
)
|
||||
type_info.hard_deletes_over_threshold++
|
||||
var/overrun_limit = 0 // Used to be CONFIG_GET(number/hard_deletes_overrun_limit)
|
||||
|
||||
@@ -23,37 +23,50 @@ SUBSYSTEM_DEF(atlas)
|
||||
/**
|
||||
* Note that the dirs here are REVERSE because they're used for entry points, so it'd be the dir facing starboard for example.
|
||||
* These are strings because otherwise the list indexes would be out of bounds. Thanks BYOND.
|
||||
*
|
||||
* SOUTH = 1, NORTH = 2, WEST = 4, EAST = 8,
|
||||
* NORTH-EAST = 5, SOUTH-EAST = 6, NORTH-WEST = 9, SOUTH-WEST = 10,
|
||||
*/
|
||||
var/list/naval_to_dir = list(
|
||||
"1" = list(
|
||||
"1" = list( //Ship Fore is facing North. (These are reversed, a shot travelling south would enter from the north.)
|
||||
"starboard" = WEST,
|
||||
"port" = EAST,
|
||||
"fore" = SOUTH,
|
||||
"aft" = NORTH
|
||||
"aft" = NORTH,
|
||||
"aft-starboard" = NORTH|WEST,
|
||||
"fore-starboard" = SOUTH|WEST,
|
||||
"aft-port" = NORTH|EAST,
|
||||
"fore-port" = SOUTH|EAST
|
||||
),
|
||||
"2" = list(
|
||||
"2" = list( //Ship Fore is facing South.
|
||||
"starboard" = EAST,
|
||||
"port" = WEST,
|
||||
"fore" = NORTH,
|
||||
"aft" = SOUTH
|
||||
"aft" = SOUTH,
|
||||
"aft-starboard" = SOUTH|EAST,
|
||||
"fore-starboard" = NORTH|EAST,
|
||||
"aft-port" = SOUTH|WEST,
|
||||
"fore-port" = NORTH|WEST
|
||||
),
|
||||
"4" = list(
|
||||
"4" = list( //Ship Fore is facing West.
|
||||
"starboard" = NORTH,
|
||||
"port" = SOUTH,
|
||||
"fore" = WEST,
|
||||
"aft" = EAST
|
||||
"aft" = EAST,
|
||||
"aft-starboard" = EAST|NORTH,
|
||||
"fore-starboard" = WEST|NORTH,
|
||||
"aft-port" = EAST|SOUTH,
|
||||
"fore-port" = WEST|SOUTH
|
||||
),
|
||||
"4" = list(
|
||||
"starboard" = NORTH,
|
||||
"port" = SOUTH,
|
||||
"fore" = WEST,
|
||||
"aft" = EAST
|
||||
),
|
||||
"8" = list(
|
||||
"8" = list( //Ship Fore is facing East.
|
||||
"starboard" = SOUTH,
|
||||
"port" = NORTH,
|
||||
"fore" = EAST,
|
||||
"aft" = WEST
|
||||
"aft" = WEST,
|
||||
"aft-starboard" = WEST|SOUTH,
|
||||
"fore-starboard" = EAST|SOUTH,
|
||||
"aft-port" = WEST|NORTH,
|
||||
"fore-port" = EAST|NORTH
|
||||
)
|
||||
)
|
||||
|
||||
@@ -62,49 +75,49 @@ SUBSYSTEM_DEF(atlas)
|
||||
"1" = "aft",
|
||||
"2" = "fore",
|
||||
"4" = "port",
|
||||
"5" = "port",
|
||||
"6" = "port",
|
||||
"5" = "aft-port",
|
||||
"6" = "fore-port",
|
||||
"8" = "starboard",
|
||||
"9" = "starboard",
|
||||
"10" = "starboard"
|
||||
"9" = "aft-starboard",
|
||||
"10" = "fore-starboard"
|
||||
),
|
||||
"2" = list(
|
||||
"1" = "fore",
|
||||
"2" = "aft",
|
||||
"4" = "starboard",
|
||||
"5" = "starboard",
|
||||
"6" = "starboard",
|
||||
"5" = "fore-starboard",
|
||||
"6" = "aft-starboard",
|
||||
"8" = "port",
|
||||
"9" = "port",
|
||||
"10" = "port"
|
||||
"9" = "fore-port",
|
||||
"10" = "aft-port"
|
||||
),
|
||||
"4" = list(
|
||||
"1" = "starboard",
|
||||
"2" = "port",
|
||||
"4" = "aft",
|
||||
"5" = "starboard",
|
||||
"6" = "port",
|
||||
"5" = "starboard-aft",
|
||||
"6" = "port-aft",
|
||||
"8" = "fore",
|
||||
"9" = "starboard",
|
||||
"10" = "port"
|
||||
"9" = "starboard-fore",
|
||||
"10" = "port-fore"
|
||||
),
|
||||
"5" = list( //northeast
|
||||
"1" = "starboard",
|
||||
"2" = "port",
|
||||
"4" = "port",
|
||||
"1" = "aft-starboard",
|
||||
"2" = "fore-port",
|
||||
"4" = "aft-port",
|
||||
"5" = "aft",
|
||||
"6" = "port",
|
||||
"8" = "starboard",
|
||||
"8" = "fore-starboard",
|
||||
"9" = "starboard",
|
||||
"10" = "fore"
|
||||
),
|
||||
"6" = list( //southeast
|
||||
"1" = "starboard",
|
||||
"2" = "port",
|
||||
"4" = "starboard",
|
||||
"1" = "fore-starboard",
|
||||
"2" = "aft-port",
|
||||
"4" = "aft-starboard",
|
||||
"5" = "starboard",
|
||||
"6" = "aft",
|
||||
"8" = "port",
|
||||
"8" = "fore-port",
|
||||
"9" = "fore",
|
||||
"10" = "port"
|
||||
),
|
||||
@@ -112,31 +125,31 @@ SUBSYSTEM_DEF(atlas)
|
||||
"1" = "port",
|
||||
"2" = "starboard",
|
||||
"4" = "fore",
|
||||
"5" = "port",
|
||||
"6" = "starboard",
|
||||
"5" = "port-fore",
|
||||
"6" = "starboard-fore",
|
||||
"8" = "aft",
|
||||
"9" = "port",
|
||||
"10" = "starboard"
|
||||
"9" = "port-aft",
|
||||
"10" = "starboard-aft"
|
||||
),
|
||||
"9" = list( //northwest
|
||||
"1" = "port",
|
||||
"2" = "starboard",
|
||||
"4" = "port",
|
||||
"1" = "aft-port",
|
||||
"2" = "fore-starboard",
|
||||
"4" = "fore-port",
|
||||
"5" = "port",
|
||||
"6" = "fore",
|
||||
"8" = "starboard",
|
||||
"6" = "aft-starboard",
|
||||
"8" = "fore",
|
||||
"9" = "aft",
|
||||
"10" = "starboard"
|
||||
),
|
||||
"10" = list( //southwest
|
||||
"1" = "port",
|
||||
"2" = "starboard",
|
||||
"4" = "starboard",
|
||||
"1" = "fore-port",
|
||||
"2" = "aft-starboard",
|
||||
"4" = "fore-starboard",
|
||||
"5" = "fore",
|
||||
"6" = "starboard",
|
||||
"8" = "port",
|
||||
"9" = "port",
|
||||
"10" = "aft"
|
||||
"8" = "aft-port",
|
||||
"9" = "aft",
|
||||
"10" = "port"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -410,9 +410,6 @@ SUBSYSTEM_DEF(jobs)
|
||||
Debug("ER/([H]): Completed.")
|
||||
return H
|
||||
|
||||
/mob/living/carbon/human
|
||||
var/tmp/centcomm_despawn_timer
|
||||
|
||||
/mob/living/proc/centcomm_timeout()
|
||||
if (!istype(get_area(src), /area/centcom/spawning))
|
||||
return FALSE
|
||||
|
||||
@@ -66,9 +66,6 @@ SUBSYSTEM_DEF(mob_ai)
|
||||
|
||||
mutexes -= mob_weakref
|
||||
|
||||
/mob
|
||||
var/thinking_enabled = FALSE
|
||||
|
||||
/**
|
||||
* Perform AI logic for a mob, called by the AI subsystem
|
||||
*
|
||||
|
||||
@@ -50,12 +50,16 @@ SUBSYSTEM_DEF(nightlight)
|
||||
/datum/controller/subsystem/nightlight/proc/get_apc_list(var/whitelisted_only = 1)
|
||||
var/list/obj/structure/machinery/power/apc/lighting_apcs = list()
|
||||
|
||||
for (var/A in get_sorted_areas())
|
||||
var/area/B = A
|
||||
if (B.no_light_control || (!(B.allow_nightmode) && whitelisted_only))
|
||||
for (var/obj/structure/machinery/power/apc/APC in SSmachinery.apc_units)
|
||||
if (QDELETED(APC) || APC.aidisabled)
|
||||
continue
|
||||
if (B.apc && !B.apc.aidisabled)
|
||||
lighting_apcs += B.apc
|
||||
|
||||
var/area/apc_area = APC.area || get_area(APC)
|
||||
if (!apc_area)
|
||||
continue
|
||||
if (apc_area.no_light_control || (!(apc_area.allow_nightmode) && whitelisted_only))
|
||||
continue
|
||||
lighting_apcs += APC
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ SUBSYSTEM_DEF(plants)
|
||||
var/list/seeds = list()
|
||||
/// Gene obfuscation for delicious trial and error goodness.
|
||||
var/list/gene_tag_masks = list()
|
||||
/// Reverse lookup for gene_tag_masks, keyed by real gene tag.
|
||||
var/list/gene_masks_by_tag = list()
|
||||
/// Stores images of growth, fruits and seeds.
|
||||
var/list/plant_icon_cache = list()
|
||||
/// List of all harvested product sprites.
|
||||
@@ -83,6 +85,7 @@ SUBSYSTEM_DEF(plants)
|
||||
used_masks += gene_mask
|
||||
plant_traits -= gene_tag
|
||||
gene_tag_masks[gene_mask] = gene_tag
|
||||
gene_masks_by_tag[gene_tag] = gene_mask
|
||||
plant_gene_datums[gene_mask] = G
|
||||
gene_masked_list += (list(list("tag" = gene_tag, "mask" = gene_mask)))
|
||||
|
||||
@@ -93,6 +96,7 @@ SUBSYSTEM_DEF(plants)
|
||||
src.product_descs = SSplants.product_descs
|
||||
src.seeds = SSplants.seeds
|
||||
src.gene_tag_masks = SSplants.gene_tag_masks
|
||||
src.gene_masks_by_tag = SSplants.gene_masks_by_tag
|
||||
src.plant_icon_cache = SSplants.plant_icon_cache
|
||||
src.plant_sprites = SSplants.plant_sprites
|
||||
src.plant_product_sprites = SSplants.plant_product_sprites
|
||||
@@ -146,6 +150,9 @@ SUBSYSTEM_DEF(plants)
|
||||
SET_SEED_TRAIT(seed, TRAIT_HIGHKPA_TOLERANCE, 200)
|
||||
return seed
|
||||
|
||||
/datum/controller/subsystem/plants/proc/get_gene_mask(var/gene_tag)
|
||||
return gene_masks_by_tag[gene_tag] || gene_tag
|
||||
|
||||
/// Debug for testing seed genes.
|
||||
/client/proc/show_plant_genes()
|
||||
set category = "Debug"
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
PROCESSING_SUBSYSTEM_DEF(nanoui)
|
||||
// Subsystem stuff.
|
||||
name = "NanoUI"
|
||||
flags = SS_NO_INIT
|
||||
priority = SS_PRIORITY_NANOUI
|
||||
stat_tag = "A"
|
||||
|
||||
// NanoUI stuff.
|
||||
var/list/open_nanouis = list()
|
||||
|
||||
/**
|
||||
* Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data
|
||||
*
|
||||
* * user - /mob The mob who opened/owns the ui
|
||||
* * src_object - /obj|/mob The obj or mob which the ui belongs to
|
||||
* * ui_key - A string key used for the ui
|
||||
* * data - List, the data to be passed to the ui, if it exists
|
||||
* * force_open - Boolean, the ui is being forced to (re)open, so close ui if it exists (instead of updating)
|
||||
*
|
||||
* Returns the `/nanoui` found ui, for null if none exists
|
||||
*/
|
||||
/datum/controller/subsystem/processing/nanoui/proc/try_update_ui(mob/user, src_object, ui_key, datum/nanoui/ui, data, force_open = FALSE)
|
||||
if (!ui) // no ui has been passed, so we'll search for one
|
||||
ui = get_open_ui(user, src_object, ui_key)
|
||||
|
||||
if (ui)
|
||||
// The UI is already open
|
||||
if (!force_open)
|
||||
ui.push_data(data)
|
||||
return ui
|
||||
else
|
||||
ui.reinitialise(new_initial_data=data)
|
||||
return ui
|
||||
|
||||
return null
|
||||
|
||||
/**
|
||||
* Get an open /nanoui ui for the current user, src_object and ui_key
|
||||
*
|
||||
* * user - The `/mob` who opened/owns the ui
|
||||
* * src_object - The `/obj` or `/mob` which the ui belongs to
|
||||
* * ui_key - A string key used for the ui
|
||||
*/
|
||||
/datum/controller/subsystem/processing/nanoui/proc/get_open_ui(mob/user, src_object, ui_key)
|
||||
var/src_object_key = REF(src_object)
|
||||
if (!LAZYLEN(open_nanouis[src_object_key]) || !LAZYLEN(open_nanouis[src_object_key][ui_key]))
|
||||
return null
|
||||
|
||||
for (var/datum/nanoui/ui in open_nanouis[src_object_key][ui_key])
|
||||
if (ui.user == user)
|
||||
return ui
|
||||
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found")
|
||||
return null
|
||||
|
||||
/**
|
||||
* Update all `/nanoui` uis attached to src_object
|
||||
*
|
||||
* * src_object - The `/obj` or `/mob` which the uis are attached to
|
||||
*
|
||||
* Returns the number of UIs updated
|
||||
*/
|
||||
/datum/controller/subsystem/processing/nanoui/proc/update_uis(src_object)
|
||||
var/src_object_key = REF(src_object)
|
||||
if (!LAZYLEN(open_nanouis[src_object_key]))
|
||||
return 0
|
||||
|
||||
. = 0
|
||||
var/list/obj_uis = open_nanouis[src_object_key]
|
||||
for (var/ui_key in obj_uis)
|
||||
for (var/thing in obj_uis[ui_key])
|
||||
var/datum/nanoui/ui = thing
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host())
|
||||
ui.process(1)
|
||||
.++
|
||||
|
||||
/**
|
||||
* Close all `/nanoui` uis attached to src_object
|
||||
*
|
||||
* * src_object - The `/obj` or `/mob` which the uis are attached to
|
||||
*
|
||||
* Returns the number of UIs closed
|
||||
*/
|
||||
/datum/controller/subsystem/processing/nanoui/proc/close_uis(src_object)
|
||||
var/src_object_key = REF(src_object)
|
||||
if (!open_nanouis[src_object_key] || !islist(open_nanouis[src_object_key]))
|
||||
return 0
|
||||
|
||||
. = 0
|
||||
var/list/obj_uis = open_nanouis[src_object_key]
|
||||
for (var/ui_key in obj_uis)
|
||||
for (var/thing in obj_uis[ui_key])
|
||||
var/datum/nanoui/ui = thing
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.ui_host())
|
||||
ui.close()
|
||||
.++
|
||||
|
||||
/**
|
||||
* Update /nanoui uis belonging to user
|
||||
*
|
||||
* * user - The `/mob` who owns the uis
|
||||
* * src_object - An `/obj` or `/mob` that, if is provided, only update uis which are attached to it (optional)
|
||||
* * ui_key - A string, if ui_key is provided, only update uis with a matching ui_key (optional)
|
||||
*
|
||||
* Returns the number of UIs updated
|
||||
*/
|
||||
/datum/controller/subsystem/processing/nanoui/proc/update_user_uis(mob/user, src_object, ui_key)
|
||||
if (!LAZYLEN(user.open_nanouis))
|
||||
return 0 // has no open uis
|
||||
|
||||
. = 0
|
||||
for (var/thing in user.open_nanouis)
|
||||
var/datum/nanoui/ui = thing
|
||||
if (NULL_OR_EQUAL(src_object, ui.src_object) && NULL_OR_EQUAL(ui_key, ui.ui_key))
|
||||
ui.process(1)
|
||||
.++
|
||||
|
||||
/datum/controller/subsystem/processing/nanoui/proc/close_user_uis(mob/user, src_object, ui_key)
|
||||
if (!LAZYLEN(user.open_nanouis))
|
||||
return 0
|
||||
|
||||
for (var/thing in user.open_nanouis)
|
||||
var/datum/nanoui/ui = thing
|
||||
if (NULL_OR_EQUAL(src_object, ui.src_object) && NULL_OR_EQUAL(ui_key, ui.ui_key))
|
||||
ui.close()
|
||||
.++
|
||||
|
||||
//testing("nanomanager/close_user_uis mob [user.name] closed [open_nanouis.len] of [.] uis")
|
||||
|
||||
/**
|
||||
* Add a /nanoui ui to the list of open uis
|
||||
* This is called by the /nanoui open() proc
|
||||
*
|
||||
* * ui - The `/nanoui` ui to add
|
||||
*/
|
||||
/datum/controller/subsystem/processing/nanoui/proc/ui_opened(datum/nanoui/ui)
|
||||
var/src_object_key = REF(ui.src_object)
|
||||
LAZYINITLIST(open_nanouis[src_object_key])
|
||||
|
||||
LAZYADD(ui.user.open_nanouis, ui)
|
||||
LAZYADD(open_nanouis[src_object_key][ui.ui_key], ui)
|
||||
START_PROCESSING(SSnanoui, ui)
|
||||
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_nanouis [ui.user.open_nanouis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
|
||||
|
||||
/**
|
||||
* Remove a /nanoui ui from the list of open uis
|
||||
* This is called by the /nanoui close() proc
|
||||
*
|
||||
* * ui - A `/nanoui` to remove
|
||||
*
|
||||
* Returns FALSE if no ui was removed, TRUE if removed successfully
|
||||
*/
|
||||
/datum/controller/subsystem/processing/nanoui/proc/ui_closed(datum/nanoui/ui)
|
||||
var/src_object_key = REF(ui.src_object)
|
||||
var/ui_key = ui.ui_key
|
||||
var/list/obj_uis = open_nanouis[src_object_key]
|
||||
|
||||
if (!LAZYLEN(obj_uis) || !obj_uis[ui_key])
|
||||
return 0 // Wasn't open.
|
||||
|
||||
STOP_PROCESSING(SSnanoui, ui)
|
||||
if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface)
|
||||
LAZYREMOVE(ui.user.open_nanouis, ui)
|
||||
|
||||
obj_uis[ui_key] -= ui
|
||||
|
||||
if (!LAZYLEN(obj_uis[ui_key]))
|
||||
obj_uis -= ui_key
|
||||
|
||||
if (!LAZYLEN(obj_uis))
|
||||
open_nanouis -= src_object_key
|
||||
|
||||
//testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_nanouis [ui.user.open_nanouis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
|
||||
|
||||
return 1
|
||||
|
||||
/**
|
||||
* This is called on user logout
|
||||
* Closes/clears all uis attached to the user's `/mob`
|
||||
*
|
||||
* * user - The user's `/mob`
|
||||
*/
|
||||
/datum/controller/subsystem/processing/nanoui/proc/user_logout(mob/user)
|
||||
return close_user_uis(user)
|
||||
|
||||
/**
|
||||
* This is called when a player transfers from one mob to another
|
||||
* Transfers all open UIs to the new mob
|
||||
*
|
||||
* * oldMob - The user's old `/mob`
|
||||
* * newMob - The user's new `/mob`
|
||||
*/
|
||||
/datum/controller/subsystem/processing/nanoui/proc/user_transferred(mob/oldMob, mob/newMob)
|
||||
//testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]")
|
||||
if (!oldMob || !LAZYLEN(oldMob.open_nanouis) || !LAZYLEN(open_nanouis))
|
||||
//testing("nanomanager/user_transferred mob [oldMob.name] has no open uis")
|
||||
return 0 // has no open uis
|
||||
|
||||
for (var/thing in oldMob.open_nanouis)
|
||||
var/datum/nanoui/ui = thing
|
||||
ui.user = newMob
|
||||
LAZYADD(newMob.open_nanouis, ui)
|
||||
|
||||
oldMob.open_nanouis = null
|
||||
|
||||
return 1 // success
|
||||
|
||||
/datum/asset/nanoui
|
||||
var/list/common = list()
|
||||
|
||||
var/list/common_dirs = list(
|
||||
"nano/css/",
|
||||
"nano/js/",
|
||||
"nano/images/",
|
||||
"nano/images/status_icons/",
|
||||
"nano/templates/"
|
||||
)
|
||||
var/list/uncommon_dirs = list()
|
||||
|
||||
/datum/asset/nanoui/register()
|
||||
// Crawl the directories to find files.
|
||||
for (var/path in common_dirs)
|
||||
var/list/filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // Ignore directories.
|
||||
if(fexists(path + filename))
|
||||
common[filename] = fcopy_rsc(path + filename)
|
||||
SSassets.transport.register_asset(filename, common[filename])
|
||||
for (var/path in uncommon_dirs)
|
||||
var/list/filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // Ignore directories.
|
||||
if(fexists(path + filename))
|
||||
SSassets.transport.register_asset(filename, fcopy_rsc(path + filename))
|
||||
|
||||
/datum/asset/nanoui/send(client, uncommon)
|
||||
if(!islist(uncommon))
|
||||
uncommon = list(uncommon)
|
||||
|
||||
SSassets.transport.send_assets(client, uncommon)
|
||||
SSassets.transport.send_assets(client, common)
|
||||
@@ -213,7 +213,7 @@ SUBSYSTEM_DEF(records)
|
||||
return GLOB.always_state
|
||||
|
||||
/datum/controller/subsystem/records/ui_status(mob/user, datum/ui_state/state)
|
||||
return (isnewplayer(user) || isghost(user) || issilicon(user)) ? UI_INTERACTIVE : UI_CLOSE
|
||||
return (isnewplayer(user) || isghost(user) || tgui_silicon_user(user)) ? UI_INTERACTIVE : UI_CLOSE
|
||||
|
||||
/datum/controller/subsystem/records/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
|
||||
@@ -186,6 +186,11 @@ SUBSYSTEM_DEF(statpanels)
|
||||
atoms_to_display += turf_content
|
||||
|
||||
/// Set the atoms we're meant to display
|
||||
// Lazy-init: SSstatpanels can fire for a client whose obj_window was never
|
||||
// created (mob transfer / relogin) or was nulled by /datum/object_window_info/Destroy()
|
||||
// while mob.listed_turf survived. Without this guard we'd null-deref atoms_to_show.
|
||||
if(!target.obj_window)
|
||||
target.obj_window = new /datum/object_window_info(target)
|
||||
var/datum/object_window_info/obj_window = target.obj_window
|
||||
obj_window.atoms_to_show = atoms_to_display
|
||||
START_PROCESSING(SSobj_tab_items, obj_window)
|
||||
@@ -210,6 +215,9 @@ SUBSYSTEM_DEF(statpanels)
|
||||
// No turf? go away
|
||||
if(!load_from.mob?.listed_turf)
|
||||
return list()
|
||||
// Lazy-init for the same lifecycle reasons as set_turf_examine_tab
|
||||
if(!load_from.obj_window)
|
||||
load_from.obj_window = new /datum/object_window_info(load_from)
|
||||
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
|
||||
|
||||
+36
-53
@@ -10,11 +10,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
SUBSYSTEM_DEF(tgui)
|
||||
name = "tgui"
|
||||
wait = 9
|
||||
flags = SS_NO_INIT
|
||||
priority = SS_PRIORITY_NANOUI
|
||||
priority = FIRE_PRIORITY_TGUI
|
||||
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
|
||||
|
||||
/// A list of UIs scheduled to process
|
||||
@@ -24,54 +24,39 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
/// The HTML base used for all UIs.
|
||||
var/basehtml
|
||||
|
||||
/datum/controller/subsystem/processing/tgui/PreInit()
|
||||
basehtml = file2text('tgui/public/tgui.html')
|
||||
// Inject inline polyfills
|
||||
var/polyfill = file2text('tgui/public/tgui-polyfill.min.js')
|
||||
polyfill = "<script>\n[polyfill]\n</script>"
|
||||
basehtml = replacetextEx(basehtml, "<!-- tgui:inline-polyfill -->", polyfill)
|
||||
basehtml = replacetextEx(basehtml, "<!-- tgui:nt-copyright -->", "NanoTrasen © 2457-[text2num(time2text(world.realtime, "YYYY")) + 442]")
|
||||
/datum/controller/subsystem/tgui/PreInit()
|
||||
basehtml = file2text("tgui/public/tgui.html")
|
||||
|
||||
basehtml = replacetext(basehtml, "tgui:stylesheet", MAP_STYLESHEET)
|
||||
// Inject inline helper functions
|
||||
var/helpers = file2text("tgui/public/helpers.min.js")
|
||||
helpers = "<script type='text/javascript'>\n[helpers]\n</script>"
|
||||
basehtml = replacetextEx(basehtml, "<!-- tgui:helpers -->", helpers)
|
||||
|
||||
/datum/controller/subsystem/processing/tgui/OnConfigLoad()
|
||||
var/storage_iframe = GLOB.config.storage_cdn_iframe
|
||||
if(storage_iframe && storage_iframe != /datum/configuration::storage_cdn_iframe)
|
||||
basehtml = replacetextEx(basehtml, "tgui:storagecdn", storage_iframe)
|
||||
return
|
||||
// Inject inline ntos-error styles
|
||||
var/ntos_error = file2text("tgui/public/ntos-error.min.css")
|
||||
ntos_error = "<style type='text/css'>\n[ntos_error]\n</style>"
|
||||
basehtml = replacetextEx(basehtml, "<!-- tgui:ntos-error -->", ntos_error)
|
||||
|
||||
if(GLOB.config.asset_transport == "webroot")
|
||||
var/datum/asset_transport/webroot/webroot = SSassets.transport
|
||||
basehtml = replacetextEx(basehtml, "<!-- tgui:nt-copyright -->", "Nanotrasen (c) 2395-[num2text(GLOB.game_year)]")
|
||||
|
||||
var/datum/asset_cache_item/item = webroot.register_asset("iframe.html", file("tgui/public/iframe.html"))
|
||||
basehtml = replacetext(basehtml, "tgui:storagecdn", webroot.get_asset_url("iframe.html", item))
|
||||
return
|
||||
|
||||
if(!storage_iframe)
|
||||
return
|
||||
|
||||
basehtml = replacetextEx(basehtml, "tgui:storagecdn", storage_iframe)
|
||||
|
||||
/datum/controller/subsystem/processing/tgui/Shutdown()
|
||||
/datum/controller/subsystem/tgui/Shutdown()
|
||||
close_all_uis()
|
||||
|
||||
/datum/controller/subsystem/processing/tgui/stat_entry(msg)
|
||||
/datum/controller/subsystem/tgui/stat_entry(msg)
|
||||
msg = "P:[length(all_uis)]"
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/processing/tgui/fire(resumed = FALSE)
|
||||
CAN_BE_REDEFINED(TRUE)
|
||||
/datum/controller/subsystem/tgui/fire(resumed = FALSE)
|
||||
if(!resumed)
|
||||
src.current_run = all_uis.Copy()
|
||||
// Cache for sanic speed (lists are references anyways)
|
||||
var/list/current_run = src.current_run
|
||||
var/seconds_per_tick = wait * 0.1
|
||||
while(current_run.len)
|
||||
var/datum/tgui/ui = current_run[current_run.len]
|
||||
current_run.len--
|
||||
// TODO: Move user/src_object check to process()
|
||||
if(ui?.user && ui.src_object)
|
||||
ui.process(seconds_per_tick)
|
||||
ui.process(wait * 0.1)
|
||||
else
|
||||
ui.close(0)
|
||||
if(MC_TICK_CHECK)
|
||||
@@ -84,9 +69,9 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
* Returns null if pool was exhausted.
|
||||
*
|
||||
* required user mob
|
||||
* return datum/tgui
|
||||
* return datum/tgui_window
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/request_pooled_window(mob/user)
|
||||
/datum/controller/subsystem/tgui/proc/request_pooled_window(mob/user)
|
||||
if(!user.client)
|
||||
return null
|
||||
var/list/windows = user.client.tgui_windows
|
||||
@@ -122,7 +107,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* required user mob
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/force_close_all_windows(mob/user)
|
||||
/datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user)
|
||||
log_tgui(user, context = "SStgui/force_close_all_windows")
|
||||
if(user.client)
|
||||
user.client.tgui_windows = list()
|
||||
@@ -138,14 +123,12 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
* required user mob
|
||||
* required window_id string
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/force_close_window(mob/user, window_id)
|
||||
/datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id)
|
||||
log_tgui(user, context = "SStgui/force_close_window")
|
||||
// Close all tgui datums based on window_id.
|
||||
for(var/datum/tgui/ui in user.tgui_open_uis)
|
||||
if(ui.window && ui.window.id == window_id)
|
||||
ui.close(can_be_suspended = FALSE)
|
||||
// Unset machine just to be sure.
|
||||
user.unset_machine()
|
||||
// Close window directly just to be sure.
|
||||
user << browse(null, "window=[window_id]")
|
||||
|
||||
@@ -161,7 +144,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return datum/tgui The found UI.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/try_update_ui(
|
||||
/datum/controller/subsystem/tgui/proc/try_update_ui(
|
||||
mob/user,
|
||||
datum/src_object,
|
||||
datum/tgui/ui)
|
||||
@@ -191,7 +174,8 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return datum/tgui The found UI.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/get_open_ui(mob/user, datum/src_object)
|
||||
/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object)
|
||||
// No UIs opened for this src_object
|
||||
if(!LAZYLEN(src_object?.open_uis))
|
||||
return null
|
||||
for(var/datum/tgui/ui in src_object.open_uis)
|
||||
@@ -209,15 +193,15 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return int The number of UIs updated.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/update_uis(datum/src_object)
|
||||
/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object)
|
||||
// No UIs opened for this src_object
|
||||
if(!LAZYLEN(src_object?.open_uis))
|
||||
return 0
|
||||
var/count = 0
|
||||
var/seconds_per_tick = wait * 0.1
|
||||
for(var/datum/tgui/ui in src_object.open_uis)
|
||||
// Check if UI is valid.
|
||||
if(ui?.src_object && ui.user && ui.src_object.ui_host(ui.user))
|
||||
INVOKE_ASYNC(ui, TYPE_PROC_REF(/datum/tgui, process), seconds_per_tick, TRUE)
|
||||
INVOKE_ASYNC(ui, TYPE_PROC_REF(/datum/tgui, process), wait * 0.1, TRUE)
|
||||
count++
|
||||
return count
|
||||
|
||||
@@ -230,7 +214,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/close_uis(datum/src_object)
|
||||
/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object)
|
||||
// No UIs opened for this src_object
|
||||
if(!LAZYLEN(src_object?.open_uis))
|
||||
return 0
|
||||
@@ -249,7 +233,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/close_all_uis()
|
||||
/datum/controller/subsystem/tgui/proc/close_all_uis()
|
||||
var/count = 0
|
||||
for(var/datum/tgui/ui in all_uis)
|
||||
// Check if UI is valid.
|
||||
@@ -268,14 +252,13 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return int The number of UIs updated.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/update_user_uis(mob/user, datum/src_object)
|
||||
/datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object)
|
||||
var/count = 0
|
||||
if(length(user?.tgui_open_uis) == 0)
|
||||
return count
|
||||
var/seconds_per_tick = wait * 0.1
|
||||
for(var/datum/tgui/ui in user.tgui_open_uis)
|
||||
if(isnull(src_object) || ui.src_object == src_object)
|
||||
ui.process(seconds_per_tick, force = 1)
|
||||
ui.process(wait * 0.1, force = 1)
|
||||
count++
|
||||
return count
|
||||
|
||||
@@ -289,7 +272,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/close_user_uis(mob/user, datum/src_object)
|
||||
/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object)
|
||||
var/count = 0
|
||||
if(length(user?.tgui_open_uis) == 0)
|
||||
return count
|
||||
@@ -306,7 +289,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* required ui datum/tgui The UI to be added.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/on_open(datum/tgui/ui)
|
||||
/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui)
|
||||
ui.user?.tgui_open_uis |= ui
|
||||
LAZYOR(ui.src_object.open_uis, ui)
|
||||
all_uis |= ui
|
||||
@@ -320,7 +303,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return bool If the UI was removed or not.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/on_close(datum/tgui/ui)
|
||||
/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui)
|
||||
// Remove it from the list of processing UIs.
|
||||
all_uis -= ui
|
||||
current_run -= ui
|
||||
@@ -340,7 +323,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return int The number of UIs closed.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/on_logout(mob/user)
|
||||
/datum/controller/subsystem/tgui/proc/on_logout(mob/user)
|
||||
close_user_uis(user)
|
||||
|
||||
/**
|
||||
@@ -353,7 +336,7 @@ PROCESSING_SUBSYSTEM_DEF(tgui)
|
||||
*
|
||||
* return bool If the UIs were transferred.
|
||||
*/
|
||||
/datum/controller/subsystem/processing/tgui/proc/on_transfer(mob/source, mob/target)
|
||||
/datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target)
|
||||
// The old mob had no open UIs.
|
||||
if(length(source?.tgui_open_uis) == 0)
|
||||
return FALSE
|
||||
@@ -55,11 +55,6 @@ SUBSYSTEM_DEF(virtualreality)
|
||||
if(bound && network)
|
||||
bounded[network].Remove(bound)
|
||||
|
||||
|
||||
/mob
|
||||
var/mob/living/vr_mob = null // In which mob is our mind
|
||||
var/mob/living/old_mob = null // Which mob is our old mob
|
||||
|
||||
/// Return to original body
|
||||
/mob/proc/body_return()
|
||||
set name = "Return to Body"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/// Stores information about a chat payload
|
||||
/datum/chat_payload
|
||||
/// Sequence number of this payload
|
||||
var/sequence = 0
|
||||
/// Message we are sending
|
||||
var/list/content
|
||||
/// Resend count
|
||||
var/resends = 0
|
||||
|
||||
/// Converts the chat payload into a JSON string
|
||||
/datum/chat_payload/proc/into_message()
|
||||
return "{\"sequence\":[sequence],\"content\":[json_encode(content)]}"
|
||||
|
||||
/// Returns an HTML-encoded message from our contents.
|
||||
/datum/chat_payload/proc/get_content_as_html()
|
||||
return message_to_html(content)
|
||||
@@ -23,7 +23,7 @@
|
||||
var/key = get_armor_key(damage_type, damage_flags)
|
||||
var/damage_taken
|
||||
if(blocked)
|
||||
damage_taken = round(damage * blocked)
|
||||
damage_taken = damage * (1 - blocked)
|
||||
else
|
||||
damage_taken = damage
|
||||
var/new_armor = max(0, get_value(key) - armor_degradation_coef * damage_taken)
|
||||
|
||||
@@ -95,7 +95,9 @@
|
||||
shift_pixel_x = 10
|
||||
animate(src, pixel_x = shift_pixel_x, pixel_y = shift_pixel_y, time = 1)
|
||||
if(direction == NORTH)
|
||||
src.add_filter("cutout", 1, alpha_mask_filter(icon = icon('icons/effects/effects.dmi', "cutout")))
|
||||
src.appearance_flags |= KEEP_TOGETHER
|
||||
src.add_filter("cutout", 1, alpha_mask_filter(y = 0, icon = icon('icons/effects/effects.dmi', "white")))
|
||||
animate(src.get_filter("cutout"), y = 10, time = 1, flags = ANIMATION_PARALLEL)
|
||||
if(direction == SOUTH)
|
||||
src.layer = ABOVE_DOOR_LAYER
|
||||
set_density(FALSE)
|
||||
@@ -105,7 +107,7 @@
|
||||
SPAN_NOTICE("[src] leans against [lean_target]."),
|
||||
SPAN_NOTICE("You lean against [lean_target]."),
|
||||
)
|
||||
RegisterSignals(src, list(COMSIG_MOVABLE_MOVED, COMSIG_MOB_RESISTED), PROC_REF(stop_leaning), src)
|
||||
RegisterSignals(src, list(COMSIG_MOVABLE_MOVED, COMSIG_MOB_RESISTED, COMSIG_MOB_LYING_DOWN), PROC_REF(stop_leaning), src)
|
||||
|
||||
/mob/living/proc/stop_leaning()
|
||||
SIGNAL_HANDLER
|
||||
@@ -116,11 +118,13 @@
|
||||
UnregisterSignal(src, list(
|
||||
COMSIG_MOVABLE_MOVED,
|
||||
COMSIG_MOB_RESISTED,
|
||||
COMSIG_MOB_LYING_DOWN,
|
||||
))
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_STOPPED_LEANING)
|
||||
to_chat(src, SPAN_NOTICE("You stop leaning on the wall."))
|
||||
REMOVE_TRAIT(src, TRAIT_UNDENSE, TRAIT_SOURCE_WALL_LEANING)
|
||||
REMOVE_TRAIT(src, TRAIT_LEANING, TRAIT_SOURCE_WALL_LEANING)
|
||||
appearance_flags &= ~KEEP_TOGETHER
|
||||
remove_filter("cutout")
|
||||
|
||||
/datum/component/leanable/proc/stopped_leaning(datum/source)
|
||||
|
||||
@@ -47,11 +47,6 @@
|
||||
lan = null
|
||||
return lan
|
||||
|
||||
/datum/component/local_network_member/nano_host()
|
||||
if(parent)
|
||||
return parent.nano_host()
|
||||
. = ..()
|
||||
|
||||
/datum/component/local_network_member/proc/get_new_tag(mob/user)
|
||||
var/new_ident = input(user, "Enter a new ident tag.", "[parent]", id_tag) as null|text
|
||||
if(new_ident && parent && user.Adjacent(parent) && CanInteract(user, GLOB.physical_state))
|
||||
|
||||
@@ -84,6 +84,15 @@
|
||||
reagent_results = list()
|
||||
return TRUE
|
||||
|
||||
/datum/component/health_analyzer/ui_status(mob/user, datum/ui_state/state)
|
||||
var/obj/item/rig_module/containing_rig_module = owner?.loc
|
||||
if(!containing_rig_module)
|
||||
return ..()
|
||||
else if(containing_rig_module)
|
||||
return UI_INTERACTIVE
|
||||
|
||||
return UI_CLOSE
|
||||
|
||||
/datum/component/health_analyzer/proc/attack(mob/living/target_mob, mob/living/user, target_zone)
|
||||
sound_scan = TRUE
|
||||
|
||||
@@ -104,6 +113,8 @@
|
||||
user.visible_message("\The [user] stops scanning \the [target_mob].")
|
||||
|
||||
/datum/component/health_analyzer/proc/attack_self(mob/user)
|
||||
if(scan_title == "" || scan_title == null)
|
||||
health_scan_mob(user, user, FALSE, sound_scan = sound_scan)
|
||||
ui_interact(user)
|
||||
|
||||
owner.add_fingerprint(user)
|
||||
|
||||
@@ -39,8 +39,8 @@ ABSTRACT_TYPE(/singleton/overhead_emote)
|
||||
var/self_message = SPAN_NOTICE("You lift your hand to meet [original]'s, delivering a stunning [emote_description]!")
|
||||
reciprocator.visible_message(others_message, self_message)
|
||||
|
||||
INVOKE_ASYNC(reciprocator, TYPE_PROC_REF(/atom/movable, do_attack_animation), original, FIST_ATTACK_ANIMATION)
|
||||
INVOKE_ASYNC(original, TYPE_PROC_REF(/atom/movable, do_attack_animation), reciprocator, FIST_ATTACK_ANIMATION)
|
||||
INVOKE_ASYNC(reciprocator, TYPE_PROC_REF(/atom/movable, do_attack_animation), original)
|
||||
INVOKE_ASYNC(original, TYPE_PROC_REF(/atom/movable, do_attack_animation), reciprocator)
|
||||
|
||||
if(emote_sound)
|
||||
playsound(reciprocator.loc, emote_sound, 30, 1)
|
||||
@@ -54,8 +54,8 @@ ABSTRACT_TYPE(/singleton/overhead_emote)
|
||||
var/self_message = SPAN_NOTICE("You lift your hand to meet [original]'s, who was expecting a [original_emote.emote_description], but received a [fail_emote.emote_description] instead.")
|
||||
reciprocator.visible_message(others_message, self_message)
|
||||
|
||||
INVOKE_ASYNC(reciprocator, TYPE_PROC_REF(/atom/movable, do_attack_animation), original, FIST_ATTACK_ANIMATION)
|
||||
INVOKE_ASYNC(original, TYPE_PROC_REF(/atom/movable, do_attack_animation), reciprocator, FIST_ATTACK_ANIMATION)
|
||||
INVOKE_ASYNC(reciprocator, TYPE_PROC_REF(/atom/movable, do_attack_animation), original)
|
||||
INVOKE_ASYNC(original, TYPE_PROC_REF(/atom/movable, do_attack_animation), reciprocator)
|
||||
|
||||
playsound(reciprocator.loc, SFX_PUNCH_MISS, 30, 1)
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
return
|
||||
|
||||
to_chat(minister, SPAN_BAD("Why should you care how [ministree] feels?"))
|
||||
*moodlet_value = 0
|
||||
*moodlet_value = *moodlet_value * 0.5
|
||||
|
||||
/datum/component/timed_life/psiblock_drugs/proc/modify_ministry_receiving(ministree, minister, moodlet_value)
|
||||
SIGNAL_HANDLER
|
||||
@@ -71,7 +71,7 @@
|
||||
return
|
||||
|
||||
to_chat(ministree, SPAN_BAD("You feel nothing from [minister]'s words."))
|
||||
*moodlet_value = 0
|
||||
*moodlet_value = *moodlet_value * 0.5
|
||||
|
||||
/datum/component/timed_life/psiblock_drugs/proc/modify_leadership_empathy(leader, moodlet_value)
|
||||
SIGNAL_HANDLER
|
||||
@@ -79,7 +79,7 @@
|
||||
return
|
||||
|
||||
to_chat(leader, SPAN_BAD("Why should you care about how others feel?"))
|
||||
*moodlet_value = 0
|
||||
*moodlet_value = *moodlet_value * 0.5
|
||||
|
||||
|
||||
/datum/component/timed_life/psiblock_drugs/process(seconds_per_tick)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
log_debug("Synthetic endoskeleton component spawned on non-IPC. Deleting.")
|
||||
qdel_self()
|
||||
|
||||
RegisterSignal(owner, COMSIG_EXTERNAL_ORGAN_DAMAGE, PROC_REF(receive_damage))
|
||||
RegisterSignal(owner, COMSIG_DAMAGE_TO_ENDOSKELETON, PROC_REF(receive_damage))
|
||||
RegisterSignal(owner, COMSIG_SYNTH_ENDOSKELETON_REPAIR, PROC_REF(heal_damage))
|
||||
RegisterSignal(owner, COMSIG_SYNTH_ENDOSKELETON_FULL_REPAIR, PROC_REF(full_repair))
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/endoskeleton, multiplicative_slowdown = 1)
|
||||
if(0.75 to 1)
|
||||
owner.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/endoskeleton, multiplicative_slowdown = 1.5)
|
||||
SEND_SIGNAL(owner, COMSIG_SYNTH_SET_SELF_PRESERVATION, FALSE)
|
||||
if(!damage)
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
|
||||
|
||||
@@ -27,17 +27,6 @@
|
||||
|
||||
#define langchat_client_enabled(M) (M && M.client && M.client.prefs && (M.client.prefs.toggles_secondary & FLOATING_MESSAGES))
|
||||
|
||||
/*
|
||||
* Duplicate vars and logic created for untranslated images for the sake of getting an untranslated langchat to display for listeners who do not understand
|
||||
* the language being spoken. Someone could certainly think of cleaner ways to do this, but for want of a better solution right now, it has been implemented
|
||||
* in this rote manner to make it easier to strip out in future if it needs replaced.
|
||||
*/
|
||||
|
||||
/atom/var/image/langchat_image
|
||||
/atom/var/image/langchat_image_untranslated
|
||||
/atom/var/list/mob/langchat_listeners
|
||||
/atom/var/list/mob/langchat_listeners_untranslated
|
||||
|
||||
/// Hides the images, if they exist. Do not null the langchat images; they are rotated when the mob is buckled or proned to maintain text orientation.
|
||||
/atom/proc/langchat_drop_images()
|
||||
if(langchat_listeners)
|
||||
|
||||
@@ -94,7 +94,6 @@
|
||||
current.remove_vampire_powers()
|
||||
current.mind = null
|
||||
|
||||
SSnanoui.user_transferred(current, new_character)
|
||||
SStgui.on_transfer(current, new_character)
|
||||
if(current.client && GLOB.ticket_panels[current.client])
|
||||
var/datum/ticket_panel/tp = GLOB.ticket_panels[current.client]
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/obj/outfit/admin/oe_enforcer
|
||||
name = "Outer Eyes Enforcer"
|
||||
|
||||
uniform = /obj/item/clothing/under/color/purple
|
||||
shoes = /obj/item/clothing/shoes/jackboots
|
||||
gloves = /obj/item/clothing/gloves/black
|
||||
suit = /obj/item/clothing/suit/space/void/outereyes
|
||||
suit_store = /obj/item/gun/projectile/automatic/rifle/dnac
|
||||
mask = /obj/item/clothing/mask/balaclava
|
||||
belt = /obj/item/storage/belt/military
|
||||
l_ear = /obj/item/radio/headset/raider
|
||||
head = /obj/item/clothing/head/helmet/space/void/outereyes
|
||||
r_pocket = /obj/item/melee/energy/sword/knife
|
||||
l_pocket = /obj/item/coin/phoron
|
||||
|
||||
accessory = /obj/item/clothing/accessory/holster/hip
|
||||
accessory_contents = list(/obj/item/gun/projectile/xanupistol = 1)
|
||||
|
||||
belt_contents = list(
|
||||
/obj/item/grenade/flashbang = 2,
|
||||
/obj/item/ammo_magazine/a65 = 3,
|
||||
/obj/item/ammo_magazine/c46m/extended = 2
|
||||
)
|
||||
@@ -69,12 +69,38 @@
|
||||
|
||||
/singleton/skill/anatomy
|
||||
name = "Anatomy"
|
||||
description = "Not currently implemented."
|
||||
description = "Governs the speed at which you can check yourself for injuries, as well as the quality of the information obtained when doing so."
|
||||
maximum_level = SKILL_LEVEL_PROFESSIONAL
|
||||
uneducated_skill_cap = SKILL_LEVEL_TRAINED
|
||||
uneducated_skill_cap = SKILL_LEVEL_PROFESSIONAL
|
||||
category = /singleton/skill_category/occupational
|
||||
subcategory = SKILL_SUBCATEGORY_MEDICAL
|
||||
component_type = ANATOMY_SKILL_COMPONENT
|
||||
skill_level_descriptions = alist(
|
||||
SKILL_LEVEL_UNFAMILIAR = "You have zero training or knowledge of anatomy.<br>" \
|
||||
+ " - You can only distinguish visible damage like cuts and burns.",
|
||||
SKILL_LEVEL_FAMILIAR = "You have minimal training on the basics of anatomy.<br>" \
|
||||
+ "You can diagnose the following conditions: <br>" \
|
||||
+ " - External injuries.<br>" \
|
||||
+ " - Limb dislocation.<br>" \
|
||||
+ " - Simple bleeds.",
|
||||
SKILL_LEVEL_TRAINED = "You have years of formal training and experience with anatomy.<br>" \
|
||||
+ "You can diagnose the following conditions: <br>" \
|
||||
+ " - External injuries at a high level of detail.<br>" \
|
||||
+ " - Limb dislocation.<br>" \
|
||||
+ " - Broken bones.<br>" \
|
||||
+ " - Distinguish between simple bleeds and severed arteries.<br>" \
|
||||
+ " - Limb necrosis.<br>" \
|
||||
+ " - Tag injuries by triage priority.",
|
||||
SKILL_LEVEL_PROFESSIONAL = "You have extensive training and experience with anatomy.<br>" \
|
||||
+ "You can diagnose the following conditions at the highest level of detail: <br>" \
|
||||
+ " - External injuries at a high level of detail.<br>" \
|
||||
+ " - Limb dislocation.<br>" \
|
||||
+ " - Broken bones.<br>" \
|
||||
+ " - Distinguish between simple bleeds and severed arteries.<br>" \
|
||||
+ " - Limb necrosis.<br>" \
|
||||
+ " - Tag injuries by triage priority."
|
||||
)
|
||||
required = TRUE
|
||||
|
||||
/singleton/skill/forensics
|
||||
name = "Forensics"
|
||||
|
||||
@@ -38,11 +38,6 @@
|
||||
icon_state = "tank_midriff"
|
||||
has_color = TRUE
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_midriff_short
|
||||
name = "Tank Top, Midriff Short"
|
||||
icon_state = "tank_midriff_short"
|
||||
has_color = TRUE
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_expedition
|
||||
name = "Tank Top, Expedition"
|
||||
icon_state = "tank_expedition"
|
||||
@@ -59,14 +54,6 @@
|
||||
name = "Tank Top, Fleet Feminine"
|
||||
icon_state = "tank_fleet_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_fire
|
||||
name = "Tank Top, Fire"
|
||||
icon_state = "tank_fire"
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_fire_fem
|
||||
name = "Tank Top, Fire Feminine"
|
||||
icon_state = "tank_fire_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_stripes
|
||||
name = "Tank Top, Stripes"
|
||||
icon_state = "tank_stripes"
|
||||
@@ -83,22 +70,6 @@
|
||||
name = "Tank Top, Stripes Alt Feminine"
|
||||
icon_state = "tank_stripes_alt_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_sun
|
||||
name = "Tank Top, Sun"
|
||||
icon_state = "tank_sun"
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_sun_fem
|
||||
name = "Tank Top, Sun Feminine"
|
||||
icon_state = "tank_sun_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_sun_alt
|
||||
name = "Tank Top, Sun Alt"
|
||||
icon_state = "tank_sun_alt"
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_sun_alt_fem
|
||||
name = "Tank Top, Sun Alt Feminine"
|
||||
icon_state = "tank_sun_alt_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/tank_top_tight
|
||||
name = "Tank Top, Tight"
|
||||
icon_state = "tank_tight"
|
||||
@@ -137,95 +108,11 @@
|
||||
icon_state = "undershirt_fem"
|
||||
has_color = TRUE
|
||||
|
||||
/datum/category_item/underwear/undershirt/undershirt_heart
|
||||
name = "Undershirt, Heart"
|
||||
icon_state = "heart"
|
||||
|
||||
/datum/category_item/underwear/undershirt/undershirt_heart_fem
|
||||
name = "Undershirt, Heart Feminine"
|
||||
icon_state = "heart_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/undershirt_heart_echelon
|
||||
name = "Undershirt, Heart Echelon"
|
||||
icon_state = "heart_echelon"
|
||||
|
||||
/datum/category_item/underwear/undershirt/undershirt_heart_echelon_fem
|
||||
name = "Undershirt, Heart Echelon Feminine"
|
||||
icon_state = "heart_echelon_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_love_nt
|
||||
name = "Undershirt, I<3NT"
|
||||
icon_state = "ilovent"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_love_nt_fem
|
||||
name = "Undershirt, I<3NT Feminine"
|
||||
icon_state = "ilovent_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt
|
||||
name = "Shirt"
|
||||
icon_state = "shirt"
|
||||
has_color = TRUE
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_alien
|
||||
name = "Shirt, Alien"
|
||||
icon_state = "shirt_alien"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_band
|
||||
name = "Shirt, Band"
|
||||
icon_state = "shirt_band"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_clown
|
||||
name = "Shirt, Clown"
|
||||
icon_state = "shirt_clown"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_ian
|
||||
name = "Shirt, Ian"
|
||||
icon_state = "shirt_ian"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_jersey
|
||||
name = "Shirt, Blue Jersey"
|
||||
icon_state = "shirt_jersey"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_jersey_red
|
||||
name = "Shirt, Red Jersey"
|
||||
icon_state = "shirt_jersey_red"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_meat
|
||||
name = "Shirt, Meat"
|
||||
icon_state = "shirt_meat"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_scc
|
||||
name = "Shirt, SCC"
|
||||
icon_state = "shirt_scc"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_scc_fem
|
||||
name = "Shirt, SCC feminine"
|
||||
icon_state = "shirt_scc_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_nt
|
||||
name = "Shirt, NT"
|
||||
icon_state = "shirt_nano"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_nt_red
|
||||
name = "Shirt, NT Red"
|
||||
icon_state = "shirt_nano_red"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_peace
|
||||
name = "Shirt, Peace"
|
||||
icon_state = "shirt_peace"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_question
|
||||
name = "Shirt, Question"
|
||||
icon_state = "shirt_question"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_skull
|
||||
name = "Shirt, Skull"
|
||||
icon_state = "shirt_skull"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_ss13
|
||||
name = "Shirt, SS13"
|
||||
icon_state = "shirt_ss13"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_blue_striped
|
||||
name = "Shirt, Blue Stripes"
|
||||
icon_state = "shirt_stripes"
|
||||
@@ -234,34 +121,10 @@
|
||||
name = "Shirt, Blue Stripes Alt"
|
||||
icon_state = "shirt_stripes_alt"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_tiedye
|
||||
name = "Shirt, Tiedye"
|
||||
icon_state = "shirt_tiedye"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_tight
|
||||
name = "Shirt, Tight"
|
||||
icon_state = "tight"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_wing
|
||||
name = "Shirt, Wing"
|
||||
icon_state = "wing_shirt"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_pinkblack
|
||||
name = "Shirt, Pink-Black"
|
||||
icon_state = "pinkblack_tshirt"
|
||||
|
||||
/datum/category_item/underwear/undershirt/sport_shirt_blue
|
||||
name = "Sport Shirt, Blue"
|
||||
icon_state = "sportblue"
|
||||
|
||||
/datum/category_item/underwear/undershirt/sport_shirt_green
|
||||
name = "Sport Shirt, Green"
|
||||
icon_state = "sportgreen"
|
||||
|
||||
/datum/category_item/underwear/undershirt/sport_shirt_red
|
||||
name = "Sport Shirt, Red"
|
||||
icon_state = "sportred"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_army
|
||||
name = "Shirt, Army"
|
||||
icon_state = "shirt_army"
|
||||
@@ -286,38 +149,6 @@
|
||||
name = "Shirt, Fleet Feminine"
|
||||
icon_state = "shirt_fleet_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_zavodskoi
|
||||
name = "Shirt, Zavodskoi Interstellar"
|
||||
icon_state = "shirt_necropolis"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_zavodskoi_fem
|
||||
name = "Shirt, Zavodskoi Interstellar Feminine"
|
||||
icon_state = "shirt_necropolis_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_epmc
|
||||
name = "Shirt, EPMC"
|
||||
icon_state = "shirt_epmc"
|
||||
|
||||
/datum/category_item/underwear/undershirt/shirt_epmc_fem
|
||||
name = "Shirt, EPMC Feminine"
|
||||
icon_state = "shirt_epmc_fem"
|
||||
|
||||
/datum/category_item/underwear/undershirt/bowlinga
|
||||
name = "Bowling Shirt, Aqua"
|
||||
icon_state = "bowlinga"
|
||||
|
||||
/datum/category_item/underwear/undershirt/bowlingp
|
||||
name = "Bowling Shirt, Pink"
|
||||
icon_state = "bowlingp"
|
||||
|
||||
/datum/category_item/underwear/undershirt/bowlingr
|
||||
name = "Bowling Shirt, Red"
|
||||
icon_state = "bowlingr"
|
||||
|
||||
/datum/category_item/underwear/undershirt/bowlingw
|
||||
name = "Bowling Shirt, White"
|
||||
icon_state = "bowlingw"
|
||||
|
||||
/datum/category_item/underwear/undershirt/longjon
|
||||
name = "Long John Shirt"
|
||||
icon_state = "ljont"
|
||||
|
||||
@@ -123,11 +123,11 @@
|
||||
path = /obj/item/ammo_magazine/super_heavy
|
||||
desc = "A spare magazine, for the super heavy K2557 pistol."
|
||||
|
||||
/datum/uplink_item/item/ammo/shotgun_slug
|
||||
name = "Shotgun Slug"
|
||||
telecrystal_cost = 1
|
||||
path = /obj/item/ammo_casing/shotgun
|
||||
desc = "A shotgun slug."
|
||||
/datum/uplink_item/item/ammo/shotgun_slugs
|
||||
name = "Box of Slug Shells"
|
||||
telecrystal_cost = 2
|
||||
path = /obj/item/storage/box/shells/slugs
|
||||
desc = "Contains eight shotgun slug shells."
|
||||
|
||||
/datum/uplink_item/item/ammo/tungsten_ammo_box
|
||||
name = "Tungsten Ammo Box"
|
||||
@@ -137,13 +137,13 @@
|
||||
|
||||
/datum/uplink_item/item/ammo/slug_magazine
|
||||
name = "Slug Magazine"
|
||||
telecrystal_cost = 8
|
||||
telecrystal_cost = 2
|
||||
path = /obj/item/ammo_magazine/assault_shotgun
|
||||
desc = "A magazine for an assault shotgun, loaded with slug shells."
|
||||
|
||||
/datum/uplink_item/item/ammo/buckshot_magazine
|
||||
name = "Buckshot Magazine"
|
||||
telecrystal_cost = 4
|
||||
telecrystal_cost = 1
|
||||
path = /obj/item/ammo_magazine/assault_shotgun/shells
|
||||
desc = "A magazine for an assault shotgun, loaded with buckshot shells."
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
record.sex = I.sex
|
||||
record.employer = I.employer_faction
|
||||
var/datum/faction/id_faction = SSjobs.name_factions[I.employer_faction]
|
||||
var/faction_abbreviation = id_faction.title_suffix
|
||||
var/faction_abbreviation = id_faction?.title_suffix
|
||||
var/assignment = "[I.assignment][ faction_abbreviation ? " ([faction_abbreviation])" : ""]"
|
||||
record.rank = assignment
|
||||
record.real_rank = assignment
|
||||
|
||||
@@ -104,13 +104,6 @@
|
||||
path = /obj/item/rig_module/storage
|
||||
desc = "A small hardsuit mounted storage unit, capable of holding a few items."
|
||||
|
||||
/datum/uplink_item/item/hardsuit_modules/vitalscanner
|
||||
name = "Vitals Tracker Module"
|
||||
telecrystal_cost = 1
|
||||
bluecrystal_cost = 1
|
||||
path = /obj/item/rig_module/device/healthscanner/vitalscanner
|
||||
desc = "A module that allows a hardsuit to scan the users vitals, and give readouts of them."
|
||||
|
||||
/datum/uplink_item/item/hardsuit_modules/basicinjector
|
||||
name = "Emergency Chemical Injector"
|
||||
telecrystal_cost = 2
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
wires = list(
|
||||
WIRE_POWER,
|
||||
WIRE_IDSCAN, WIRE_AI,
|
||||
WIRE_PANIC, WIRE_ALARM
|
||||
WIRE_PANIC, WIRE_ALARM,
|
||||
WIRE_RCON
|
||||
)
|
||||
add_duds(3)
|
||||
..()
|
||||
@@ -24,6 +25,7 @@
|
||||
. += A.locked ? "The air alarm is locked." : "The air alarm is unlocked."
|
||||
. += (A.shorted || (A.stat & (NOPOWER|BROKEN))) ? "The Air Alarm is offline." : "The Air Alarm is working properly!"
|
||||
. += A.aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on."
|
||||
. += A.rcon_setting ? "The remote control link is enabled." : "The remote control link is disabled."
|
||||
|
||||
/datum/wires/alarm/on_cut(wire, mend, source)
|
||||
var/obj/structure/machinery/alarm/A = holder
|
||||
@@ -51,6 +53,12 @@
|
||||
A.post_alert(2)
|
||||
A.update_icon()
|
||||
|
||||
if(WIRE_RCON)
|
||||
if(!mend)
|
||||
A.rcon_setting = FALSE
|
||||
else
|
||||
A.rcon_setting = TRUE
|
||||
|
||||
/datum/wires/alarm/on_pulse(wire)
|
||||
var/obj/structure/machinery/alarm/A = holder
|
||||
switch(wire)
|
||||
@@ -67,7 +75,6 @@
|
||||
A.shorted = 0
|
||||
A.update_icon()
|
||||
|
||||
|
||||
if (WIRE_AI)
|
||||
if (A.aidisabled == 0)
|
||||
A.aidisabled = 1
|
||||
@@ -83,7 +90,7 @@
|
||||
A.mode = 1 // AALARM_MODE_SCRUB
|
||||
A.apply_mode()
|
||||
|
||||
if(WIRE_ALARM)
|
||||
if(WIRE_ALARM, WIRE_RCON)
|
||||
if (A.alarm_area.atmosalert(0, A))
|
||||
A.post_alert(0)
|
||||
A.update_icon()
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
if(WIRE_TRANSMIT)
|
||||
R.set_broadcasting(!R.get_broadcasting() && !is_cut(WIRE_SIGNAL))
|
||||
SSnanoui.update_uis(holder)
|
||||
SStgui.update_uis(holder)
|
||||
|
||||
/datum/wires/radio/on_cut(wire, mend, source)
|
||||
var/obj/item/radio/R = holder
|
||||
@@ -45,4 +45,4 @@
|
||||
|
||||
if(WIRE_TRANSMIT)
|
||||
R.set_broadcasting(mend && !is_cut(WIRE_SIGNAL))
|
||||
SSnanoui.update_uis(holder)
|
||||
SStgui.update_uis(holder)
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
target_mob.standard_weapon_hit_effects(src, user, damageamount, armorpercent, target_zone)
|
||||
|
||||
user.visible_message("<span class='[class]'>[endmessage3rd][punct]</span>", "<span class='[class]'>[endmessage1st][punct]</span>")
|
||||
user.do_attack_animation(target_mob)
|
||||
user.do_attack_animation(target_mob, used_item = src)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
|
||||
if(soundname)
|
||||
|
||||
+22
-6
@@ -138,19 +138,31 @@
|
||||
/// This atom's cache of overlays that can only be removed explicitly, like C4. Do not manipulate directly- See SSoverlays.
|
||||
var/list/atom_protected_overlay_cache
|
||||
|
||||
/// The mob currently interacting with the atom during a `do_after` timer. Used to validate `DO_TARGET_UNIQUE_ACT` flag checks.
|
||||
var/mob/do_unique_target_user
|
||||
|
||||
/*
|
||||
* Duplicate vars and logic created for untranslated images for the sake of getting an untranslated langchat to display for listeners who do not understand
|
||||
* the language being spoken. Someone could certainly think of cleaner ways to do this, but for want of a better solution right now, it has been implemented
|
||||
* in this rote manner to make it easier to strip out in future if it needs replaced.
|
||||
*/
|
||||
|
||||
var/image/langchat_image
|
||||
var/image/langchat_image_untranslated
|
||||
var/list/mob/langchat_listeners
|
||||
var/list/mob/langchat_listeners_untranslated
|
||||
|
||||
/atom/Destroy(force)
|
||||
if(opacity)
|
||||
updateVisibility(src)
|
||||
|
||||
if(reagents)
|
||||
QDEL_NULL(reagents)
|
||||
QDEL_NULL(reagents)
|
||||
|
||||
// Checking length(overlays) before cutting has significant speed benefits
|
||||
if(length(overlays))
|
||||
overlays.Cut()
|
||||
|
||||
if(light)
|
||||
QDEL_NULL(light)
|
||||
QDEL_NULL(light)
|
||||
|
||||
if(smoothing_flags & SMOOTH_QUEUED)
|
||||
SSicon_smooth.remove_from_queues(src)
|
||||
@@ -167,8 +179,12 @@
|
||||
|
||||
// The component is attached to us normaly and will be deleted elsewhere
|
||||
orbiters = null
|
||||
|
||||
. = ..()
|
||||
do_unique_target_user = null
|
||||
QDEL_NULL(langchat_image)
|
||||
QDEL_NULL(langchat_image_untranslated)
|
||||
langchat_listeners?.Cut()
|
||||
langchat_listeners_untranslated?.Cut()
|
||||
return ..()
|
||||
|
||||
/atom/proc/handle_ricochet(obj/projectile/ricocheting_projectile)
|
||||
var/turf/p_turf = get_turf(ricocheting_projectile)
|
||||
|
||||
@@ -87,6 +87,15 @@
|
||||
if(src.desc)
|
||||
. += src.desc
|
||||
|
||||
var/list/tags_list = examine_tags(user)
|
||||
if(length(tags_list))
|
||||
var/tag_string = list()
|
||||
for (var/atom_tag in tags_list)
|
||||
tag_string += (isnull(tags_list[atom_tag]) ? atom_tag : SPAN_TOOLTIP(tags_list[atom_tag], atom_tag))
|
||||
// some regex to ensure that we don't add another "and" if the final element's main text (not tooltip) has one
|
||||
tag_string = english_list(tag_string, and_text = (findtext(tag_string[length(tag_string)], regex(@">.*?and .*?<"))) ? " " : " and ")
|
||||
. += "It is a [tag_string] [examine_descriptor(user)]."
|
||||
|
||||
// Returns a SPAN_* based on health, if configured.
|
||||
var/list/condition_hints = src.condition_hints()
|
||||
if(length(condition_hints))
|
||||
@@ -145,6 +154,35 @@
|
||||
if(H.glasses)
|
||||
H.glasses.glasses_examine_atom(src, H)
|
||||
|
||||
/// What this atom should be called in examine tags
|
||||
/atom/proc/examine_descriptor(mob/user)
|
||||
return "object"
|
||||
|
||||
/**
|
||||
* A list of "tags" displayed after atom's description in examine.
|
||||
* This should return an assoc list of tags -> tooltips for them. If item is null, then no tooltip is assigned.
|
||||
*
|
||||
* * TGUI tooltips (not the main text) in chat cannot use HTML stuff at all, so
|
||||
* trying something like `<b><big>ffff</big></b>` will not work for tooltips.
|
||||
*
|
||||
* For example:
|
||||
* ```byond
|
||||
* . = list()
|
||||
* .["small"] = "It is a small item."
|
||||
* .["fireproof"] = "It is made of fire-retardant materials."
|
||||
* .["and conductive"] = "It's made of conductive materials and whatnot. Blah blah blah." // having "and " in the end tag's main text/key works too!
|
||||
* ```
|
||||
* will result in
|
||||
*
|
||||
* It is a *small*, *fireproof* *and conductive* item.
|
||||
*
|
||||
* where "item" is pulled from [/atom/proc/examine_descriptor]
|
||||
*/
|
||||
/atom/proc/examine_tags(mob/user)
|
||||
. = list()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE_TAGS, user, .)
|
||||
|
||||
/**
|
||||
* Used to check if "examine_fluff" from the HTML link in examine() is true, i.e. if it was clicked.
|
||||
*/
|
||||
|
||||
@@ -543,6 +543,18 @@
|
||||
if(src.z == H.z && get_dist(src, H) <= range)
|
||||
H.intent_listen(src, message)
|
||||
|
||||
/proc/get_intent_listeners(var/atom/source, var/range = 7, var/list/hearers = list())
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
var/list/listeners = list()
|
||||
if(air_sound(source))
|
||||
if(!length(hearers))
|
||||
hearers = get_hearers_in_view(range, source)
|
||||
for(var/mob/living/carbon/human/H as anything in GLOB.intent_listener)
|
||||
if((H in hearers))
|
||||
if(source.z == H.z && get_dist(source, H) <= range)
|
||||
listeners += H
|
||||
return listeners
|
||||
|
||||
/atom/movable/proc/dropInto(var/atom/destination)
|
||||
while(istype(destination))
|
||||
var/atom/drop_destination = destination.onDropInto(src)
|
||||
|
||||
+203
-4
@@ -87,6 +87,11 @@
|
||||
/// Whether this atom should have its dir automatically changed when it moves. Setting this to FALSE allows for things such as directional windows to retain dir on moving without snowflake code all of the place.
|
||||
var/set_dir_on_move = TRUE
|
||||
|
||||
var/tmp/turf/airflow_dest
|
||||
var/tmp/airflow_speed = 0
|
||||
var/tmp/airflow_time = 0
|
||||
var/tmp/last_airflow = 0
|
||||
|
||||
/atom/movable/Initialize(mapload, ...)
|
||||
. = ..()
|
||||
update_emissive_blocker()
|
||||
@@ -114,14 +119,11 @@
|
||||
|
||||
QDEL_LAZYLIST(contained_mobs)
|
||||
|
||||
. = ..()
|
||||
|
||||
for(var/movable_content in contents)
|
||||
qdel(movable_content)
|
||||
|
||||
//Pretend this is moveToNullspace()
|
||||
moveToNullspace()
|
||||
loc = null
|
||||
|
||||
//This absolutely must be after moveToNullspace()
|
||||
//We rely on Entered and Exited to manage this list, and the copy of this list that is on any /atom/movable "Containers"
|
||||
@@ -150,6 +152,9 @@
|
||||
|
||||
QDEL_NULL(light)
|
||||
QDEL_NULL(static_light)
|
||||
airflow_dest = null
|
||||
loc = null
|
||||
return ..()
|
||||
|
||||
/atom/movable/proc/moveToNullspace()
|
||||
. = TRUE
|
||||
@@ -577,11 +582,19 @@
|
||||
/* END Spatial grid stuffs */
|
||||
|
||||
for(var/datum/dynamic_light_source/light as anything in hybrid_light_sources)
|
||||
if(!light) // datum was deleted but list entry not yet pruned
|
||||
LAZYREMOVE(hybrid_light_sources, light)
|
||||
continue
|
||||
if(!light.source_atom)
|
||||
continue
|
||||
light.source_atom.update_light()
|
||||
if(!isturf(loc))
|
||||
light.find_containing_atom()
|
||||
for(var/datum/static_light_source/L as anything in static_light_sources) // Cycle through the light sources on this atom and tell them to update.
|
||||
L.source_atom.static_update_light()
|
||||
if(!L) // datum was deleted but list entry not yet pruned
|
||||
LAZYREMOVE(static_light_sources, L)
|
||||
continue
|
||||
L.source_atom?.static_update_light()
|
||||
|
||||
/atom/movable/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
@@ -817,6 +830,192 @@
|
||||
// This is instant on byond's end, but to our clients this looks like a quick drop
|
||||
animate(src, alpha = old_alpha, pixel_x = old_x, pixel_y = old_y, transform = old_transform, time = 3, easing = CUBIC_EASING)
|
||||
|
||||
/atom/movable/proc/do_item_attack_animation(atom/attacked_atom, visual_effect_icon, obj/item/used_item, animation_type)
|
||||
if (!visual_effect_icon)
|
||||
if (used_item)
|
||||
used_item.animate_attack(src, attacked_atom, animation_type)
|
||||
return
|
||||
|
||||
var/image/attack_image = image(icon = 'icons/effects/effects.dmi', icon_state = visual_effect_icon)
|
||||
attack_image.plane = attacked_atom.plane + 1
|
||||
// Scale the icon.
|
||||
attack_image.transform *= 0.4
|
||||
// The icon should not rotate.
|
||||
attack_image.appearance_flags = APPEARANCE_UI
|
||||
var/atom/movable/flick_visual/attack = attacked_atom.flick_overlay_view(attack_image, 1 SECONDS)
|
||||
var/matrix/copy_transform = new(transform)
|
||||
animate(attack, alpha = 175, transform = copy_transform.Scale(0.75), time = 0.3 SECONDS)
|
||||
animate(time = 0.1 SECONDS)
|
||||
animate(alpha = 0, time = 0.3 SECONDS, easing = CIRCULAR_EASING|EASE_OUT)
|
||||
|
||||
/obj/item/proc/animate_attack(atom/movable/attacker, atom/attacked_atom, animation_type)
|
||||
var/list/image_override = list()
|
||||
var/list/animation_override = list()
|
||||
var/used_icon_angle = icon_angle
|
||||
var/list/angle_override = list()
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_ANIMATION, attacker, attacked_atom, animation_type, image_override, animation_override, angle_override)
|
||||
var/image/attack_image = null
|
||||
if (!length(image_override))
|
||||
attack_image = isnull(attack_icon) ? image(icon = src) : image(icon = attack_icon, icon_state = attack_icon_state)
|
||||
else
|
||||
attack_image = image_override[1]
|
||||
|
||||
if (length(animation_override))
|
||||
animation_type = animation_override[1]
|
||||
else if (!animation_type)
|
||||
var/damage_flags = damage_flags()
|
||||
if(damage_flags & DAMAGE_FLAG_SHARP|DAMAGE_FLAG_EDGE)
|
||||
animation_type = pick(ATTACK_ANIMATION_SLASH, ATTACK_ANIMATION_PIERCE)
|
||||
else if(damage_flags & DAMAGE_FLAG_SHARP)
|
||||
animation_type = ATTACK_ANIMATION_SLASH
|
||||
else if (damage_flags & DAMAGE_FLAG_EDGE)
|
||||
animation_type = ATTACK_ANIMATION_PIERCE
|
||||
else
|
||||
animation_type = ATTACK_ANIMATION_BLUNT
|
||||
|
||||
if (length(angle_override))
|
||||
used_icon_angle = angle_override[1]
|
||||
|
||||
attack_image.plane = attacked_atom.plane + 1
|
||||
attack_image.pixel_w = attacker.get_standard_pixel_x() + attacker.pixel_w - attacked_atom.get_standard_pixel_x() - attacked_atom.pixel_w
|
||||
attack_image.pixel_z = attacker.get_standard_pixel_y() + attacker.pixel_z - attacked_atom.get_standard_pixel_y() - attacked_atom.pixel_z
|
||||
// Scale the icon.
|
||||
attack_image.transform *= 0.5
|
||||
// The icon should not rotate.
|
||||
attack_image.appearance_flags = APPEARANCE_UI
|
||||
|
||||
var/atom/movable/flick_visual/attack = attacked_atom.flick_overlay_view(attack_image, 1 SECONDS)
|
||||
var/matrix/copy_transform = new(attacker.transform)
|
||||
var/x_sign = 0
|
||||
var/y_sign = 0
|
||||
var/direction = get_dir(attacker, attacked_atom)
|
||||
if (direction & NORTH)
|
||||
y_sign = -1
|
||||
else if (direction & SOUTH)
|
||||
y_sign = 1
|
||||
|
||||
if (direction & EAST)
|
||||
x_sign = -1
|
||||
else if (direction & WEST)
|
||||
x_sign = 1
|
||||
|
||||
// Attacking self, or something on the same turf as us
|
||||
if (!direction)
|
||||
y_sign = 1
|
||||
// Not a fan of this, but its the "cleanest" way to animate this
|
||||
x_sign = 0.25 * (prob(50) ? 1 : -1)
|
||||
// For piercing attacks
|
||||
direction = SOUTH
|
||||
|
||||
// And animate the attack!
|
||||
switch (animation_type)
|
||||
if (ATTACK_ANIMATION_BLUNT)
|
||||
attack.pixel_x = 14 * x_sign
|
||||
attack.pixel_y = 12 * y_sign
|
||||
animate(attack, alpha = 175, transform = copy_transform.Scale(0.75), pixel_x = 4 * x_sign, pixel_y = 3 * y_sign, time = 0.2 SECONDS)
|
||||
animate(time = 0.1 SECONDS)
|
||||
animate(alpha = 0, time = 0.1 SECONDS, easing = CIRCULAR_EASING|EASE_OUT)
|
||||
|
||||
if (ATTACK_ANIMATION_PIERCE)
|
||||
var/attack_angle = dir2angle(direction) + rand(-7, 7)
|
||||
// Deducting 90 because we're assuming that icon_angle of 0 means an east-facing sprite
|
||||
var/anim_angle = attack_angle - 90 - used_icon_angle
|
||||
var/angle_mult = 1
|
||||
if (x_sign && y_sign)
|
||||
angle_mult = 1.4
|
||||
attack.pixel_x = 22 * x_sign * angle_mult
|
||||
attack.pixel_y = 18 * y_sign * angle_mult
|
||||
attack.transform = attack.transform.Turn(anim_angle)
|
||||
copy_transform = copy_transform.Turn(anim_angle)
|
||||
animate(
|
||||
attack,
|
||||
pixel_x = (22 * x_sign - 12 * sin(attack_angle)) * angle_mult,
|
||||
pixel_y = (18 * y_sign - 8 * cos(attack_angle)) * angle_mult,
|
||||
time = 0.1 SECONDS,
|
||||
easing = CUBIC_EASING|EASE_IN,
|
||||
)
|
||||
animate(
|
||||
attack,
|
||||
alpha = 175,
|
||||
transform = copy_transform.Scale(0.75),
|
||||
pixel_x = (22 * x_sign + 26 * sin(attack_angle)) * angle_mult,
|
||||
pixel_y = (18 * y_sign + 22 * cos(attack_angle)) * angle_mult,
|
||||
time = 0.3 SECONDS,
|
||||
easing = CUBIC_EASING|EASE_OUT,
|
||||
)
|
||||
animate(
|
||||
alpha = 0,
|
||||
pixel_x = -3 * -(x_sign + sin(attack_angle)),
|
||||
pixel_y = -2 * -(y_sign + cos(attack_angle)),
|
||||
time = 0.1 SECONDS,
|
||||
easing = CIRCULAR_EASING|EASE_OUT
|
||||
)
|
||||
|
||||
if (ATTACK_ANIMATION_SLASH)
|
||||
attack.pixel_x = 18 * x_sign
|
||||
attack.pixel_y = 14 * y_sign
|
||||
var/x_rot_sign = 0
|
||||
var/y_rot_sign = 0
|
||||
var/attack_dir = (prob(50) ? 1 : -1)
|
||||
var/anim_angle = dir2angle(direction) - 90 - used_icon_angle
|
||||
|
||||
if (x_sign)
|
||||
y_rot_sign = attack_dir
|
||||
if (y_sign)
|
||||
x_rot_sign = attack_dir
|
||||
|
||||
// Animations are flipped, so flip us too!
|
||||
if (x_sign > 0 || y_sign < 0)
|
||||
attack_dir *= -1
|
||||
|
||||
// We're swinging diagonally, use separate logic
|
||||
var/anim_dir = attack_dir
|
||||
if (x_sign && y_sign)
|
||||
if (attack_dir < 0)
|
||||
x_rot_sign = -x_sign * 1.4
|
||||
y_rot_sign = 0
|
||||
else
|
||||
x_rot_sign = 0
|
||||
y_rot_sign = -y_sign * 1.4
|
||||
|
||||
// Flip us if we've been flipped *unless* we're flipped due to both axis
|
||||
if ((x_sign < 0 && y_sign > 0) || (x_sign > 0 && y_sign < 0))
|
||||
anim_dir *= -1
|
||||
|
||||
attack.pixel_x += 10 * x_rot_sign
|
||||
attack.pixel_y += 8 * y_rot_sign
|
||||
attack.transform = attack.transform.Turn(anim_angle - 45 * anim_dir)
|
||||
copy_transform = copy_transform.Scale(0.75)
|
||||
animate(attack, alpha = 175, time = 0.3 SECONDS, flags = ANIMATION_PARALLEL)
|
||||
animate(time = 0.1 SECONDS)
|
||||
animate(alpha = 0, time = 0.1 SECONDS, easing = CIRCULAR_EASING|EASE_OUT)
|
||||
|
||||
animate(attack, transform = copy_transform.Turn(anim_angle + 45 * anim_dir), time = 0.3 SECONDS, flags = ANIMATION_PARALLEL)
|
||||
|
||||
var/x_return = 10 * -x_rot_sign
|
||||
var/y_return = 8 * -y_rot_sign
|
||||
|
||||
if (!x_rot_sign)
|
||||
x_return = 18 * x_sign
|
||||
if (!y_rot_sign)
|
||||
y_return = 14 * y_sign
|
||||
|
||||
var/angle_mult = 1
|
||||
if (x_sign && y_sign)
|
||||
angle_mult = 1.4
|
||||
if (attack_dir > 0)
|
||||
x_return = 8 * x_sign
|
||||
y_return = 14 * y_sign
|
||||
else
|
||||
x_return = 18 * x_sign
|
||||
y_return = 6 * y_sign
|
||||
|
||||
animate(attack, pixel_x = 4 * x_sign * angle_mult, time = 0.2 SECONDS, easing = CIRCULAR_EASING | EASE_IN, flags = ANIMATION_PARALLEL)
|
||||
animate(pixel_x = x_return, time = 0.2 SECONDS, easing = CIRCULAR_EASING | EASE_OUT)
|
||||
|
||||
animate(attack, pixel_y = 3 * y_sign * angle_mult, time = 0.2 SECONDS, easing = CIRCULAR_EASING | EASE_IN, flags = ANIMATION_PARALLEL)
|
||||
animate(pixel_y = y_return, time = 0.2 SECONDS, easing = CIRCULAR_EASING | EASE_OUT)
|
||||
|
||||
/atom/movable/proc/get_floating_chat_x_offset()
|
||||
return 0
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/mob
|
||||
//thou shall always be able to see the Geometer of Blood
|
||||
var/image/narsimage = null
|
||||
var/image/narglow = null
|
||||
|
||||
/mob/proc/cultify()
|
||||
return
|
||||
|
||||
|
||||
@@ -54,11 +54,6 @@
|
||||
spawn (0)
|
||||
AM.singularity_pull(src, src.current_size)
|
||||
|
||||
|
||||
/mob
|
||||
//thou shall always be able to see the rift
|
||||
var/image/riftimage = null
|
||||
|
||||
/mob/proc/see_rift(var/obj/singularity/narsie/large/exit/R)
|
||||
var/turf/T_mob = get_turf(src)
|
||||
if((R.z == T_mob.z) && (get_dist(R,T_mob) <= (R.consume_range+10)) && !(R in view(T_mob)))
|
||||
|
||||
@@ -8,13 +8,6 @@
|
||||
#define TECHNOMANCER_INSTABILITY_PRECISION 0.1 // Instability is rounded to this.
|
||||
#define TECHNOMANCER_INSTABILITY_MIN_GLOW 10 // When above this number, the entity starts glowing, affecting others.
|
||||
|
||||
|
||||
/mob/living
|
||||
atom_flags = CRITICAL_ATOM
|
||||
var/instability = 0
|
||||
var/last_instability = 0 // Used to calculate instability delta.
|
||||
var/last_instability_event = null // most recent world.time that something bad happened due to instability.
|
||||
|
||||
// Proc: adjust_instability()
|
||||
// Parameters: 0
|
||||
// Description: Does nothing, because inheritance.
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
|
||||
/obj/structure/foamedmetal/attack_hand(var/mob/user)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
user.do_attack_animation(src, FIST_ATTACK_ANIMATION)
|
||||
user.do_attack_animation(src)
|
||||
if ((user.mutations & HULK) || (prob(75 - metal * 25)))
|
||||
user.visible_message(SPAN_WARNING("[user] smashes through the foamed metal."), SPAN_NOTICE("You smash through the metal foam wall."))
|
||||
qdel(src)
|
||||
@@ -238,7 +238,7 @@
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
user.do_attack_animation(src, attacking_item)
|
||||
user.do_attack_animation(src, used_item = attacking_item)
|
||||
if(prob(attacking_item.force * 20 - metal * 25))
|
||||
user.visible_message(SPAN_WARNING("[user] smashes through the foamed metal."), SPAN_NOTICE("You smash through the foamed metal with \the [attacking_item]."))
|
||||
qdel(src)
|
||||
|
||||
@@ -14,10 +14,6 @@ would spawn and follow the beaker, even if it is carried or thrown.
|
||||
pass_flags = PASSTABLE | PASSGRILLE
|
||||
blocks_emissive = EMISSIVE_BLOCK_GENERIC
|
||||
|
||||
/obj/effect/Destroy()
|
||||
QDEL_NULL(reagents)
|
||||
return ..()
|
||||
|
||||
/datum/effect/effect/system
|
||||
var/number = 3
|
||||
var/cardinals = 0
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
/proc/gibs(atom/location, var/list/viruses, var/datum/dna/MobDNA, gibber_type = /obj/effect/gibspawner/generic, var/fleshcolor, var/bloodcolor)
|
||||
new gibber_type(location,viruses,MobDNA,fleshcolor,bloodcolor)
|
||||
/proc/gibs(atom/location, var/datum/dna/MobDNA, gibber_type = /obj/effect/gibspawner/generic, var/fleshcolor, var/bloodcolor)
|
||||
new gibber_type(location,MobDNA,fleshcolor,bloodcolor)
|
||||
|
||||
/obj/effect/gibspawner
|
||||
icon = 'icons/effects/map_effects.dmi'
|
||||
icon_state = "gibspawner"
|
||||
var/sparks = 0 //whether sparks spread on Gib()
|
||||
var/virusProb = 20 //the chance for viruses to spread on the gibs
|
||||
var/list/gibtypes = list()
|
||||
var/list/gibamounts = list()
|
||||
var/list/gibdirections = list() //of lists
|
||||
var/fleshcolor //Used for gibbed humans.
|
||||
var/bloodcolor //Used for gibbed humans.
|
||||
|
||||
/obj/effect/gibspawner/Initialize(mapload, list/viruses, datum/dna/MobDNA, fleshcolor, bloodcolor)
|
||||
/obj/effect/gibspawner/Initialize(mapload, datum/dna/MobDNA, fleshcolor, bloodcolor)
|
||||
. = ..()
|
||||
|
||||
if(fleshcolor) src.fleshcolor = fleshcolor
|
||||
if(bloodcolor) src.bloodcolor = bloodcolor
|
||||
Gib(loc,viruses,MobDNA)
|
||||
Gib(loc,MobDNA)
|
||||
|
||||
/obj/effect/gibspawner/proc/Gib(atom/location, var/list/viruses = list(), var/datum/dna/MobDNA = null)
|
||||
/obj/effect/gibspawner/proc/Gib(atom/location, var/datum/dna/MobDNA = null)
|
||||
if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len)
|
||||
to_world(SPAN_WARNING("Gib list length mismatch!"))
|
||||
return
|
||||
|
||||
+39
-21
@@ -136,6 +136,8 @@
|
||||
var/zoomdevicename
|
||||
/// Boolean, `TRUE` if item is actively being used to zoom. For scoped guns and binoculars.
|
||||
var/zoom = FALSE
|
||||
/// The message used when stopping looking through a pair of binoculars/scope
|
||||
var/zoom_out_message
|
||||
|
||||
/// Boolean, if item_state, lefthand, righthand, and worn sprite are all in one dmi
|
||||
var/contained_sprite = FALSE
|
||||
@@ -205,6 +207,13 @@
|
||||
/// Used to override hardcoded clothing dmis in human clothing pr
|
||||
var/icon_override
|
||||
|
||||
/// Angle of the icon, used for piercing and slashing attack animations, clockwise from *east-facing* sprites
|
||||
var/icon_angle = 0
|
||||
///icon file for an alternate attack icon
|
||||
var/attack_icon
|
||||
///icon state for an alternate attack icon
|
||||
var/attack_icon_state
|
||||
|
||||
var/charge_failure_message = " cannot be recharged."
|
||||
var/held_maptext
|
||||
|
||||
@@ -259,8 +268,16 @@
|
||||
var/mob/m = loc
|
||||
m.drop_from_inventory(src, null)
|
||||
|
||||
if(!QDELETED(action))
|
||||
if(islist(action))
|
||||
var/list/action_list = action
|
||||
for(var/i in 1 to action_list.len)
|
||||
var/datum/action/A = action_list[i]
|
||||
if(!QDELETED(A))
|
||||
QDEL_NULL(A)
|
||||
action_list.Cut()
|
||||
else if(!QDELETED(action))
|
||||
QDEL_NULL(action) // /mob/living/proc/handle_actions() creates it, for ungodly reasons
|
||||
|
||||
action = null
|
||||
|
||||
if(!QDELETED(hidden_uplink))
|
||||
@@ -327,23 +344,22 @@
|
||||
|
||||
I.forceMove(T)
|
||||
|
||||
/obj/item/get_examine_text(mob/user, distance, is_adjacent, infix, suffix, get_extended = FALSE)
|
||||
var/size
|
||||
switch(src.w_class)
|
||||
if (WEIGHT_CLASS_HUGE to INFINITY)
|
||||
size = "huge"
|
||||
if (WEIGHT_CLASS_BULKY to WEIGHT_CLASS_HUGE)
|
||||
size = "bulky"
|
||||
if (WEIGHT_CLASS_NORMAL to WEIGHT_CLASS_BULKY)
|
||||
size = "normal-sized"
|
||||
if (WEIGHT_CLASS_SMALL to WEIGHT_CLASS_NORMAL)
|
||||
size = "small"
|
||||
if (0 to WEIGHT_CLASS_SMALL)
|
||||
size = "tiny"
|
||||
//Changed this switch to ranges instead of tiered values, to cope with granularity and also
|
||||
//things outside its range ~Nanako
|
||||
/obj/item/examine_descriptor(mob/user)
|
||||
return "item"
|
||||
|
||||
. = ..(user, distance, is_adjacent, "It is a [size] item.", get_extended = get_extended)
|
||||
/obj/item/examine_tags(mob/user)
|
||||
var/list/parent_tags = ..()
|
||||
parent_tags.Insert(1, weight_class_to_text(w_class)) // To make size display first, otherwise it looks goofy
|
||||
. = parent_tags
|
||||
.[weight_class_to_text(w_class)] = weight_class_to_tooltip(w_class)
|
||||
|
||||
if (siemens_coefficient == 0)
|
||||
.["insulated"] = "It is made from a robust electrical insulator and will block any electricity passing through it!"
|
||||
else if (siemens_coefficient <= 0.5)
|
||||
.["partially insulated"] = "It is made from a poor insulator that will dampen (but not fully block) electric shocks passing through it."
|
||||
|
||||
/obj/item/get_examine_text(mob/user, distance, is_adjacent, infix, suffix, get_extended = FALSE)
|
||||
. = ..(user, distance, is_adjacent, get_extended = get_extended)
|
||||
var/datum/component/armor/armor_component = GetComponent(/datum/component/armor)
|
||||
if(armor_component && !armor_component.hidden)
|
||||
. += FONT_SMALL(SPAN_NOTICE("\[?\] This item has armor values. <a href='byond://?src=[REF(src)];examine_armor=1'>\[Show Armor Values\]</a>"))
|
||||
@@ -1005,9 +1021,11 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
|
||||
M.client.pixel_x = 0
|
||||
M.client.pixel_y = 0
|
||||
|
||||
if(!cannotzoom)
|
||||
if(show_zoom_message)
|
||||
if(!cannotzoom && show_zoom_message)
|
||||
if(!zoom_out_message)
|
||||
M.visible_message("[zoomdevicename ? "<b>[M]</b> looks up from \the [src.name]" : "<b>[M]</b> lowers \the [src.name]"].")
|
||||
else
|
||||
M.visible_message("[zoomdevicename ? "<b>[M]</b>[zoom_out_message] \the [src.name]." : "<b>[M]</b>[zoom_out_message]"]")
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
@@ -1328,10 +1346,10 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
|
||||
. = ..()
|
||||
if(in_inventory || in_storage)
|
||||
var/mob/user = usr
|
||||
if(!(user.client.prefs.toggles_secondary & HIDE_ITEM_TOOLTIPS))
|
||||
tip_timer = addtimer(CALLBACK(src, PROC_REF(openTip), location, control, params, user), 8, TIMER_STOPPABLE)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!(user.client.prefs.toggles_secondary & HIDE_ITEM_TOOLTIPS))
|
||||
tip_timer = addtimer(CALLBACK(src, PROC_REF(openTip), location, control, params, user), 8, TIMER_STOPPABLE)
|
||||
if(!(user.client.prefs.toggles_secondary & SEE_ITEM_OUTLINES))
|
||||
return
|
||||
var/mob/living/L = user
|
||||
|
||||
@@ -4,7 +4,7 @@ pixel_y = 20;
|
||||
|
||||
#define PRESET_SOUTH \
|
||||
dir = SOUTH; \
|
||||
pixel_y = -6;
|
||||
pixel_y = -2;
|
||||
|
||||
#define PRESET_WEST \
|
||||
dir = WEST; \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/item/suit_cooling_unit
|
||||
name = "portable suit cooling unit"
|
||||
desc = "A portable heat sink and liquid cooled radiator that can be hooked up to a space suit's existing temperature controls to provide industrial levels of cooling."
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
icon = 'icons/obj/item/suitcooler.dmi'
|
||||
icon_state = "suitcooler0"
|
||||
item_state = "coolingpack"
|
||||
@@ -17,14 +17,25 @@
|
||||
|
||||
origin_tech = list(TECH_MAGNET = 2, TECH_MATERIAL = 2)
|
||||
|
||||
var/celltype = /obj/item/cell/high
|
||||
// Type of cell the IPC cooling unit starts with.
|
||||
var/celltype = /obj/item/cell/apc
|
||||
|
||||
matter = list(MATERIAL_ALUMINIUM = 25000, MATERIAL_GLASS = 3500)
|
||||
var/on = 0 //is it turned on?
|
||||
var/cover_open = 0 //is the cover open?
|
||||
|
||||
// Is it turned on?
|
||||
var/on = 0
|
||||
// Is the cover open?
|
||||
var/cover_open = 0
|
||||
|
||||
var/obj/item/cell/cell
|
||||
var/max_cooling = 24 //in degrees kelvin per second - probably don't need to mess with heat capacity here
|
||||
var/charge_consumption = 8.3 //charge per second at max_cooling
|
||||
|
||||
// In degrees kelvin per second - probably don't need to mess with heat capacity here
|
||||
var/max_cooling = 24
|
||||
|
||||
// Base charge consumption per second. Modified by how much cooling work the cooler is doing.
|
||||
var/charge_consumption = 15.4
|
||||
|
||||
// Target to cool an IPC to.
|
||||
var/thermostat = T20C
|
||||
|
||||
//TODO: make it heat up the surroundings when not in space
|
||||
@@ -241,3 +252,6 @@
|
||||
|
||||
/obj/item/suit_cooling_unit/no_cell
|
||||
celltype = null
|
||||
|
||||
/obj/item/suit_cooling_unit/hyper_cell // Mostly for special spawns, events, etc., so they don't have to worry about cell charge.
|
||||
celltype = /obj/item/cell/hyper
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
else if(crystal_type == CRYSTAL_TYPE_BLUECRYSTAL)
|
||||
I.hidden_uplink.bluecrystals += amount
|
||||
I.hidden_uplink.update_tgui_data()
|
||||
SSnanoui.update_uis(I.hidden_uplink)
|
||||
SStgui.update_uis(I.hidden_uplink)
|
||||
use(amount)
|
||||
to_chat(user, SPAN_NOTICE("You slot \the [src] into \the [I] and charge its internal uplink."))
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
build_path = /obj/structure/machinery/shield_gen/external
|
||||
origin_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3)
|
||||
req_components = list(
|
||||
"/obj/item/stock_parts/manipulator/pico" = 2,
|
||||
"/obj/item/stock_parts/manipulator" = 2,
|
||||
"/obj/item/stock_parts/micro_laser" = 2,
|
||||
"/obj/item/stock_parts/capacitor" = 2,
|
||||
"/obj/item/stock_parts/subspace/transmitter" = 1,
|
||||
"/obj/item/stock_parts/subspace/crystal" = 1,
|
||||
"/obj/item/stock_parts/subspace/amplifier" = 1,
|
||||
@@ -17,7 +19,9 @@
|
||||
build_path = /obj/structure/machinery/shield_gen
|
||||
origin_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3)
|
||||
req_components = list(
|
||||
"/obj/item/stock_parts/manipulator/pico" = 2,
|
||||
"/obj/item/stock_parts/manipulator" = 2,
|
||||
"/obj/item/stock_parts/micro_laser" = 2,
|
||||
"/obj/item/stock_parts/capacitor" = 2,
|
||||
"/obj/item/stock_parts/subspace/transmitter" = 1,
|
||||
"/obj/item/stock_parts/subspace/crystal" = 1,
|
||||
"/obj/item/stock_parts/subspace/amplifier" = 1,
|
||||
@@ -30,7 +34,8 @@
|
||||
build_path = /obj/structure/machinery/shield_capacitor
|
||||
origin_tech = list(TECH_MAGNET = 3, TECH_POWER = 4)
|
||||
req_components = list(
|
||||
"/obj/item/stock_parts/manipulator/pico" = 2,
|
||||
"/obj/item/stock_parts/capacitor" = 4,
|
||||
"/obj/item/stock_parts/micro_laser" = 1,
|
||||
"/obj/item/stock_parts/subspace/filter" = 1,
|
||||
"/obj/item/stock_parts/subspace/treatment" = 1,
|
||||
"/obj/item/stock_parts/subspace/analyzer" = 1,
|
||||
|
||||
@@ -36,13 +36,21 @@
|
||||
if(M.flash_act(ignore_inherent = TRUE))
|
||||
M.Weaken(10)
|
||||
|
||||
// 1 - 9x/70 gives us 100% at zero, 87% at 1 turf, all the way to 10% at 7
|
||||
var/bang_intensity = 1 - (9 * get_dist(T, M) / 70)
|
||||
M.noise_act(intensity = EAR_PROTECTION_MODERATE, damage_pwr = 10 * bang_intensity, deafen_pwr = 15 * (1 - bang_intensity))
|
||||
var/distance_to_grenade = get_dist(T, M)
|
||||
|
||||
if(M.get_hearing_sensitivity()) // we only stun if they've got sensitive ears
|
||||
// 1 - 9x/70 gives us 100% at zero, 87% at 1 turf, all the way to 10% at 7
|
||||
var/bang_intensity = 1 - (9 * distance_to_grenade / 70)
|
||||
|
||||
var/ear_damage = 10 * bang_intensity
|
||||
var/deafen_damage = 15 * (1 - bang_intensity)
|
||||
|
||||
|
||||
// we only stun if they've got sensitive ears and got it active as well as if it is close enough.
|
||||
if(M.get_hearing_sensitivity() && astype(M, /mob/living/carbon/human)?.is_listening() && distance_to_grenade < 5)
|
||||
// checking for protection is handled by noise_act
|
||||
M.noise_act(intensity = EAR_PROTECTION_MAJOR, stun_pwr = 2)
|
||||
M.noise_act(intensity = EAR_PROTECTION_MAJOR, stun_pwr = 2, damage_pwr = ear_damage, deafen_pwr = deafen_damage)
|
||||
else
|
||||
M.noise_act(intensity = EAR_PROTECTION_MODERATE, damage_pwr = ear_damage, deafen_pwr = deafen_damage)
|
||||
|
||||
M.disable_cloaking_device()
|
||||
M.update_icon()
|
||||
|
||||
@@ -1,8 +1,29 @@
|
||||
/proc/fragem(var/source,var/fragx,var/fragy,var/light_dam,var/flash_dam,var/p_dam,var/p_range,var/can_cover=TRUE,var/shard_range = 50)
|
||||
/**
|
||||
* Fragem works by shooting a projectile containing fragments at every tile in a circle around it.
|
||||
*
|
||||
* Source is the tile the projectiles spawn on.
|
||||
*
|
||||
* fragx and fragy are the upper and lower bounds of the random number of fragments produced.
|
||||
*
|
||||
* light_dam and flash_dam are the parameters for the explosion produced by the grenade. light_dam is the radius of minor explosive damage, flash_dam is the radius of the flash effect.
|
||||
*
|
||||
* p_dam is the damage of each individual fragments.
|
||||
*
|
||||
* p_range is the distance each projectile travels before losing a fragment. When a projectile loses all of its fragments, it is deleted.
|
||||
*
|
||||
* can_cover determines if a mob can lie on the source turf to absorb most of the fragments.
|
||||
*
|
||||
* shard_range is the maximum range of the projectiles produced by the fragem. This is separate from p_range to allow for projectiles that lose fragments over distance but have a hard maximum range. Default 50
|
||||
*
|
||||
* spread_range is the radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern. Default 7
|
||||
*
|
||||
* maim_rate is the bonus for projectiles to decapitate or gib limbs. Negative values reduce this chance, positive values increase it. There is a minimum maim multiplier of 0.1, see handle_limb_gibbing for details.
|
||||
*/
|
||||
/proc/fragem(var/source,var/fragx,var/fragy,var/light_dam,var/flash_dam,var/p_dam,var/p_range,var/can_cover=TRUE,var/shard_range = 50,var/spread_range = 7,var/maim_rate)
|
||||
var/turf/O = get_turf(source)
|
||||
var/fragger = rand(fragx,fragy)
|
||||
explosion(O, -1, -1, light_dam, flash_dam)
|
||||
var/list/target_turfs = getcircle(O, 7)
|
||||
var/list/target_turfs = getcircle(O, spread_range)
|
||||
var/fragments_per_projectile = round(fragger/target_turfs.len)
|
||||
|
||||
for(var/turf/T in target_turfs)
|
||||
@@ -12,9 +33,10 @@
|
||||
P.damage = p_dam
|
||||
P.pellets = fragments_per_projectile
|
||||
P.range_step = p_range
|
||||
if (maim_rate)
|
||||
P.maim_rate = maim_rate
|
||||
P.range = shard_range
|
||||
P.name = "shrapnel"
|
||||
|
||||
P.preparePixelProjectile(T, get_turf(source))
|
||||
P.firer = source
|
||||
P.fired_from = source
|
||||
|
||||
@@ -106,6 +106,11 @@
|
||||
/obj/item/material/shard/shrapnel/Initialize(newloc, material_key)
|
||||
. = ..(loc, MATERIAL_STEEL)
|
||||
|
||||
/obj/item/material/shard/shrapnel/large/Initialize(newloc, material_key) //Shrapnel large enough to be removed by hand. Used by ship weapons.
|
||||
. = ..(loc, MATERIAL_STEEL)
|
||||
icon_state = "large"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/material/shard/shrapnel/flechette/Initialize(newloc, material_key)
|
||||
. = ..(loc, MATERIAL_TITANIUM)
|
||||
|
||||
|
||||
@@ -200,11 +200,12 @@
|
||||
/obj/item/material/twohanded/fireaxe // DEM AXES MAN, marker -Agouri
|
||||
icon_state = "fireaxe0"
|
||||
base_icon = "fireaxe"
|
||||
icon_angle = -180
|
||||
name = "fire axe"
|
||||
desc = "Truly, the weapon of a madman. Who would think to fight fire with an axe?"
|
||||
unwielded_force_divisor = 0.25
|
||||
force_divisor = 0.7 // 10/42 with hardness 60 (steel) and 0.25 unwielded divisor
|
||||
sharp = 1
|
||||
sharp = FALSE
|
||||
edge = TRUE
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
slot_flags = SLOT_BACK
|
||||
@@ -243,6 +244,7 @@
|
||||
/obj/item/material/twohanded/spear
|
||||
icon_state = "spearglass0"
|
||||
base_icon = "spearglass"
|
||||
icon_angle = -45
|
||||
name = "spear"
|
||||
desc = "A haphazardly-constructed yet still deadly weapon of ancient design."
|
||||
force = 15
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
use_sound = 'sound/items/storage/toolbox.ogg'
|
||||
drop_sound = 'sound/items/drop/toolbox.ogg'
|
||||
pickup_sound = 'sound/items/pickup/toolbox.ogg'
|
||||
rustle_sound = 'sound/items/rustle/toolbox.ogg'
|
||||
|
||||
/obj/item/storage/briefcase/nt
|
||||
name = "\improper NT briefcase"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
use_sound = 'sound/items/storage/pillbottle.ogg'
|
||||
drop_sound = 'sound/items/drop/pillbottle.ogg'
|
||||
pickup_sound = 'sound/items/pickup/pillbottle.ogg'
|
||||
rustle_sound = 'sound/items/pickup/pillbottle.ogg'
|
||||
max_storage_space = DEFAULT_BOX_STORAGE
|
||||
|
||||
/obj/item/storage/pill_bottle/attack_self(mob/living/user)
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
/obj/effect/energy_net/attack_hand(var/mob/user)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
user.do_attack_animation(src, FIST_ATTACK_ANIMATION)
|
||||
user.do_attack_animation(src)
|
||||
if(user == affecting)
|
||||
to_chat(user, SPAN_WARNING("You can't claw at \the [src] while trapped inside it! You need to use a weapon."))
|
||||
return
|
||||
@@ -110,7 +110,7 @@
|
||||
|
||||
/obj/effect/energy_net/attackby(obj/item/attacking_item, mob/user)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
user.do_attack_animation(src, attacking_item)
|
||||
user.do_attack_animation(src, used_item = attacking_item)
|
||||
var/attack_force = attacking_item.force
|
||||
if(user == affecting)
|
||||
attack_force /= 2
|
||||
|
||||
@@ -108,6 +108,15 @@
|
||||
var/persistant_objects_expiration_time_days = PERSISTENT_DEFAULT_EXPIRATION_DAYS
|
||||
/* END PERSISTENCE VARS */
|
||||
|
||||
/// for easy reference of talking atoms
|
||||
var/datum/talking_atom/talking_atom
|
||||
|
||||
/// Whether this object has been contaminated by atmos gasses like chlorine or phoron.
|
||||
var/contaminated = FALSE
|
||||
|
||||
/// Allow overriding rad resistance.
|
||||
var/rad_resistance_modifier = 1
|
||||
|
||||
/obj/Initialize(mapload, ...)
|
||||
. = ..()
|
||||
if(maxhealth)
|
||||
|
||||
@@ -6,16 +6,20 @@
|
||||
pass_flags_self = PASSSTRUCTURE
|
||||
should_use_health = TRUE
|
||||
|
||||
var/material_alteration = MATERIAL_ALTERATION_ALL // Overrides for material shit. Set them manually if you don't want colors etc. See wood chairs/office chairs.
|
||||
/// Overrides for material shit. Set them manually if you don't want colors etc. See wood chairs/office chairs.
|
||||
var/material_alteration = MATERIAL_ALTERATION_ALL
|
||||
var/climbable
|
||||
var/parts
|
||||
var/list/climbers
|
||||
var/list/footstep_sound //footstep sounds when stepped on
|
||||
/// Footstep sounds when stepped on
|
||||
var/list/footstep_sound
|
||||
|
||||
var/material/material
|
||||
var/build_amt = 2 // used by some structures to determine into how many pieces they should disassemble into or be made with
|
||||
/// Used by some structures to determine into how many pieces they should disassemble into or be made with
|
||||
var/build_amt = 2
|
||||
|
||||
var/slowdown = 0 //amount that pulling mobs have their movement delayed by
|
||||
/// Amount that pulling mobs have their movement delayed by
|
||||
var/slowdown = 0
|
||||
|
||||
/obj/structure/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -40,6 +44,14 @@
|
||||
material = null
|
||||
return ..()
|
||||
|
||||
/obj/structure/examine_descriptor(mob/user)
|
||||
return "structure"
|
||||
|
||||
/obj/structure/examine_tags(atom/source, mob/user, list/examine_list)
|
||||
. = ..()
|
||||
if(climbable)
|
||||
.["climbable"] = "It can be climbed on, either by dragging your mob onto it or middle-clicking it."
|
||||
|
||||
/obj/structure/attackby(obj/item/attacking_item, mob/user, params)
|
||||
. = ..()
|
||||
if(user?.a_intent == I_HURT && maxhealth)
|
||||
@@ -95,9 +107,13 @@
|
||||
else
|
||||
dismantle_material = get_material()
|
||||
if(should_use_health && health <= 0)
|
||||
build_amt /= rand(2, 4) //if the structure is destroyed by damage, it will yield less materials
|
||||
for(var/i = 1 to build_amt)
|
||||
dismantle_material.place_sheet(loc)
|
||||
build_amt /= rand(2, 4) //if the structure is destroyed by damage, it will yield less materials.
|
||||
build_amt = max(1, min(build_amt, 5)) //Bound between 5 and 1, as shards don't stack into sheets.
|
||||
for(var/i = 1 to build_amt)
|
||||
dismantle_material.place_shard(loc)
|
||||
else
|
||||
for(var/i = 1 to build_amt)
|
||||
dismantle_material.place_sheet(loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
|
||||
@@ -250,12 +250,17 @@ Class Procs:
|
||||
for(var/i = 1 to 2)
|
||||
if(prob(50))
|
||||
metal_to_spawn++
|
||||
else
|
||||
new /obj/item/material/shard(current_turf, DEFAULT_WALL_MATERIAL)
|
||||
if(metal_to_spawn)
|
||||
new /obj/item/stack/material/steel(get_turf(src), metal_to_spawn)
|
||||
if(!should_use_health)
|
||||
return FALSE
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/machinery/examine_descriptor(mob/user)
|
||||
return "machine"
|
||||
|
||||
// /obj/structure/machinery/proc/process_all()
|
||||
// /* Uncomment this if/when you need component processing
|
||||
// if(processing_flags & MACHINERY_PROCESS_COMPONENTS)
|
||||
@@ -641,5 +646,5 @@ Class Procs:
|
||||
/obj/structure/machinery/ui_status(mob/user, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(. < UI_INTERACTIVE)
|
||||
if(user.machine)
|
||||
if(user?.machine)
|
||||
user.unset_machine()
|
||||
|
||||
@@ -1498,6 +1498,10 @@
|
||||
new /obj/item/coin/phoron(src)
|
||||
new /obj/item/coin/phoron(src)
|
||||
new /obj/item/coin/phoron(src)
|
||||
new /obj/item/modkit/multi_species(src)
|
||||
new /obj/item/modkit/multi_species(src)
|
||||
new /obj/item/modkit/multi_species(src)
|
||||
new /obj/item/modkit/multi_species(src)
|
||||
|
||||
/obj/structure/closet/crate/secure/gear_loadout/outereyes/single/fill()
|
||||
new /obj/item/clothing/head/helmet/space/void/outereyes(src)
|
||||
@@ -1514,6 +1518,7 @@
|
||||
new /obj/item/ammo_magazine/c46m/extended(src)
|
||||
new /obj/item/melee/energy/sword/knife(src)
|
||||
new /obj/item/coin/phoron(src)
|
||||
new /obj/item/modkit/multi_species(src)
|
||||
|
||||
/obj/structure/closet/crate/secure/gear_loadout/zavodskoi/fill()
|
||||
new /obj/item/rig/combat/zavod_heavy(src)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
maxhealth = OBJECT_HEALTH_MEDIUM
|
||||
color = COLOR_GRAY20
|
||||
build_amt = 4
|
||||
pass_flags_self = PASSRAILING
|
||||
layer = WINDOW_FRAME_LAYER
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
@@ -59,6 +60,11 @@
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/structure/window_frame/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
/obj/structure/window_frame/attackby(obj/item/attacking_item, mob/user)
|
||||
if((attacking_item.tool_behaviour == TOOL_SCREWDRIVER) && (istype(loc, /turf/simulated) || anchored))
|
||||
if(has_glass_installed)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user