+2
-3
@@ -22,7 +22,6 @@ tgstation.int
|
||||
tgstation.rsc
|
||||
tgstation.lk
|
||||
tgstation.dyn.rsc
|
||||
libmariadb.dll
|
||||
rust_g.dll
|
||||
BSQL.dll
|
||||
*.dll
|
||||
Dockerfile
|
||||
tools/bootstrap/.cache
|
||||
|
||||
+7
-1
@@ -4,7 +4,7 @@ indent_size = 4
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
#end_of_line = lf
|
||||
# end_of_line = lf
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
@@ -12,3 +12,9 @@ indent_size = 2
|
||||
|
||||
[*.py]
|
||||
indent_style = space
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Dockerfile]
|
||||
indent_style = space
|
||||
|
||||
+5
-6
@@ -1,8 +1,7 @@
|
||||
* text=auto
|
||||
|
||||
## Enforce text mode and LF line breaks
|
||||
## porter note: not yet LFing dm.
|
||||
# *.bat text eol=lf
|
||||
*.bat text eol=lf
|
||||
*.css text eol=lf
|
||||
# *.dm text eol=lf
|
||||
# *.dme text eol=lf
|
||||
@@ -12,15 +11,15 @@
|
||||
*.js text eol=lf
|
||||
*.json text eol=lf
|
||||
*.jsx text eol=lf
|
||||
# *.md text eol=lf
|
||||
*.md text eol=lf
|
||||
*.py text eol=lf
|
||||
*.scss text eol=lf
|
||||
# *.sh text eol=lf
|
||||
# *.sql text eol=lf
|
||||
*.sh text eol=lf
|
||||
*.sql text eol=lf
|
||||
*.svg text eol=lf
|
||||
*.ts text eol=lf
|
||||
*.tsx text eol=lf
|
||||
# *.txt text eol=lf
|
||||
*.txt text eol=lf
|
||||
*.yaml text eol=lf
|
||||
*.yml text eol=lf
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
run_linters:
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
name: Run Linters
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup cache
|
||||
@@ -21,18 +21,20 @@ jobs:
|
||||
- name: Install Tools
|
||||
run: |
|
||||
pip3 install setuptools
|
||||
bash tools/ci/install_build_tools.sh
|
||||
bash tools/ci/install_node.sh
|
||||
bash tools/ci/install_spaceman_dmm.sh dreamchecker
|
||||
pip3 install -r tools/mapmerge2/requirements.txt
|
||||
tools/bootstrap/python -c ''
|
||||
- name: Run Linters
|
||||
run: |
|
||||
bash tools/ci/check_filedirs.sh tgstation.dme
|
||||
bash tools/ci/check_changelogs.sh
|
||||
find . -name "*.php" -print0 | xargs -0 -n1 php -l
|
||||
find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py
|
||||
bash tools/ci/build_tgui.sh
|
||||
tgui/bin/tgui --lint
|
||||
tgui/bin/tgui --test
|
||||
bash tools/ci/check_grep.sh
|
||||
python3 tools/mapmerge2/dmi.py --test
|
||||
tools/bootstrap/python -m dmi.test
|
||||
tools/bootstrap/python -m mapmerge2.dmm_test
|
||||
~/dreamchecker > ${GITHUB_WORKSPACE}/output-annotations.txt 2>&1
|
||||
- name: Annotate Lints
|
||||
uses: yogstation13/DreamAnnotate@v1
|
||||
@@ -43,7 +45,7 @@ jobs:
|
||||
compile_all_maps:
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
name: Compile Maps
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup cache
|
||||
@@ -56,11 +58,13 @@ jobs:
|
||||
bash tools/ci/install_byond.sh
|
||||
source $HOME/BYOND/byond/bin/byondsetup
|
||||
python3 tools/ci/template_dm_generator.py
|
||||
tgui/bin/tgui --build
|
||||
bash tools/ci/dm.sh -DCIBUILDING -DCITESTING -DALL_MAPS tgstation.dme
|
||||
|
||||
run_all_tests:
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
name: Integration Tests
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:latest
|
||||
@@ -87,14 +91,16 @@ jobs:
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt update || true
|
||||
sudo apt install libssl1.1:i386
|
||||
sudo apt install -o APT::Immediate-Configure=false libssl1.1:i386
|
||||
bash tools/ci/install_rust_g.sh
|
||||
# - name: Compile and run tests
|
||||
# run: |
|
||||
# bash tools/ci/install_byond.sh
|
||||
# source $HOME/BYOND/byond/bin/byondsetup
|
||||
# bash tools/ci/dm.sh -DCIBUILDING tgstation.dme
|
||||
# bash tools/ci/run_server.sh
|
||||
- name: Compile and run tests
|
||||
run: |
|
||||
bash tools/ci/install_byond.sh
|
||||
source $HOME/BYOND/byond/bin/byondsetup
|
||||
tgui/bin/tgui --build
|
||||
bash tools/ci/dm.sh -DCIBUILDING tgstation.dme
|
||||
# bash tools/ci/run_server.sh
|
||||
|
||||
test_windows:
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
name: Windows Build
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
jobs:
|
||||
compile:
|
||||
name: "Compile changelogs"
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: "Check for CHANGELOG_ENABLER secret and pass true to output if it exists to be checked by later steps"
|
||||
id: value_holder
|
||||
|
||||
@@ -7,7 +7,8 @@ on:
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
jobs:
|
||||
generate_documentation:
|
||||
if: "!contains(github.event.head_commit.message, '[ci skip]')"
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup cache
|
||||
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
|
||||
jobs:
|
||||
link_rounds:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: Cidatel-Station-13/round_linker@master #notice: fork the round linkies from tg!!
|
||||
with:
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
update-dmapi:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-20.04
|
||||
name: Update the TGS DMAPI
|
||||
steps:
|
||||
- name: Clone
|
||||
|
||||
@@ -231,3 +231,6 @@ tools/LinuxOneShot/Database
|
||||
tools/LinuxOneShot/TGS_Config
|
||||
tools/LinuxOneShot/TGS_Instances
|
||||
tools/LinuxOneShot/TGS_Logs
|
||||
|
||||
# Common build tooling
|
||||
!/tools/build
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
static_files:
|
||||
- name: config
|
||||
populate: true
|
||||
- name: data
|
||||
linux_scripts:
|
||||
PreCompile.sh: tools/tgs4_scripts/PreCompile.sh
|
||||
windows_scripts:
|
||||
PreCompile.bat: tools/tgs4_scripts/PreCompile.bat
|
||||
Vendored
+2
-1
@@ -5,6 +5,7 @@
|
||||
"EditorConfig.EditorConfig",
|
||||
"arcanis.vscode-zipfs",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"kevinkyang.auto-comment-blocks"
|
||||
"stylemistake.auto-comment-blocks",
|
||||
"Donkie.vscode-tgstation-test-adapter"
|
||||
]
|
||||
}
|
||||
|
||||
Vendored
+5
-2
@@ -1,8 +1,10 @@
|
||||
{
|
||||
"eslint.nodePath": "tgui/.yarn/sdks",
|
||||
"eslint.nodePath": "./tgui/.yarn/sdks",
|
||||
"eslint.workingDirectories": [
|
||||
"./tgui"
|
||||
],
|
||||
"typescript.tsdk": "./tgui/.yarn/sdks/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"search.exclude": {
|
||||
"tgui/.yarn": true,
|
||||
"tgui/.pnp.*": true
|
||||
@@ -14,5 +16,6 @@
|
||||
}
|
||||
],
|
||||
"files.eol": "\n",
|
||||
"gitlens.advanced.blame.customArguments": ["-w"]
|
||||
"gitlens.advanced.blame.customArguments": ["-w"],
|
||||
"tgstationTestExplorer.project.resultsType": "json"
|
||||
}
|
||||
|
||||
+65
-42
@@ -1,62 +1,85 @@
|
||||
FROM tgstation/byond:513.1533 as base
|
||||
# base = ubuntu + full apt update
|
||||
FROM ubuntu:xenial AS base
|
||||
|
||||
FROM base as rust_g
|
||||
|
||||
RUN apt-get update \
|
||||
RUN dpkg --add-architecture i386 \
|
||||
&& apt-get update \
|
||||
&& apt-get upgrade -y \
|
||||
&& apt-get dist-upgrade -y \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
git \
|
||||
ca-certificates
|
||||
ca-certificates
|
||||
|
||||
# byond = base + byond installed globally
|
||||
FROM base AS byond
|
||||
WORKDIR /byond
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
unzip \
|
||||
make \
|
||||
libstdc++6:i386
|
||||
|
||||
COPY dependencies.sh .
|
||||
|
||||
RUN . ./dependencies.sh \
|
||||
&& curl "http://www.byond.com/download/build/${BYOND_MAJOR}/${BYOND_MAJOR}.${BYOND_MINOR}_byond_linux.zip" -o byond.zip \
|
||||
&& unzip byond.zip \
|
||||
&& cd byond \
|
||||
&& sed -i 's|install:|&\n\tmkdir -p $(MAN_DIR)/man6|' Makefile \
|
||||
&& make install \
|
||||
&& chmod 644 /usr/local/byond/man/man6/* \
|
||||
&& apt-get purge -y --auto-remove curl unzip make \
|
||||
&& cd .. \
|
||||
&& rm -rf byond byond.zip
|
||||
|
||||
# build = byond + tgstation compiled and deployed to /deploy
|
||||
FROM byond AS build
|
||||
WORKDIR /tgstation
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
curl
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN env TG_BOOTSTRAP_NODE_LINUX=1 tools/build/build \
|
||||
&& tools/deploy.sh /deploy
|
||||
|
||||
# rust = base + rustc and i686 target
|
||||
FROM base AS rust
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
curl && \
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal \
|
||||
&& ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
|
||||
|
||||
# rust_g = base + rust_g compiled to /rust_g
|
||||
FROM rust AS rust_g
|
||||
WORKDIR /rust_g
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
libssl-dev \
|
||||
pkg-config \
|
||||
curl \
|
||||
gcc-multilib \
|
||||
&& curl https://sh.rustup.rs -sSf | sh -s -- -y --default-host i686-unknown-linux-gnu \
|
||||
pkg-config:i386 \
|
||||
libssl-dev:i386 \
|
||||
gcc-multilib \
|
||||
git \
|
||||
&& git init \
|
||||
&& git remote add origin https://github.com/tgstation/rust-g
|
||||
|
||||
COPY dependencies.sh .
|
||||
|
||||
RUN /bin/bash -c "source dependencies.sh \
|
||||
&& git fetch --depth 1 origin \$RUST_G_VERSION" \
|
||||
RUN . ./dependencies.sh \
|
||||
&& git fetch --depth 1 origin "${RUST_G_VERSION}" \
|
||||
&& git checkout FETCH_HEAD \
|
||||
&& ~/.cargo/bin/cargo build --release
|
||||
|
||||
FROM base as dm_base
|
||||
&& env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo build --release --target i686-unknown-linux-gnu
|
||||
|
||||
# final = byond + runtime deps + rust_g + build
|
||||
FROM byond
|
||||
WORKDIR /tgstation
|
||||
|
||||
FROM dm_base as build
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
libssl1.0.0:i386 \
|
||||
zlib1g:i386
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN DreamMaker -max_errors 0 tgstation.dme \
|
||||
&& tools/deploy.sh /deploy \
|
||||
&& rm /deploy/*.dll
|
||||
|
||||
FROM dm_base
|
||||
|
||||
EXPOSE 1337
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends software-properties-common \
|
||||
&& add-apt-repository ppa:ubuntu-toolchain-r/test \
|
||||
&& apt-get update \
|
||||
&& apt-get upgrade -y \
|
||||
&& apt-get dist-upgrade -y \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
libmariadb2 \
|
||||
mariadb-client \
|
||||
libssl1.0.0 \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& mkdir -p /root/.byond/bin
|
||||
|
||||
COPY --from=rust_g /rust_g/target/release/librust_g.so /root/.byond/bin/rust_g
|
||||
COPY --from=build /deploy ./
|
||||
COPY --from=rust_g /rust_g/target/i686-unknown-linux-gnu/release/librust_g.so ./librust_g.so
|
||||
|
||||
VOLUME [ "/tgstation/config", "/tgstation/data" ]
|
||||
|
||||
ENTRYPOINT [ "DreamDaemon", "tgstation.dmb", "-port", "1337", "-trusted", "-close", "-verbose" ]
|
||||
EXPOSE 1337
|
||||
|
||||
@@ -1651,7 +1651,7 @@
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/ruin/space/has_grav/ancientstation/rnd)
|
||||
"eD" = (
|
||||
/obj/machinery/mecha_part_fabricator/offstation,
|
||||
/obj/machinery/mecha_part_fabricator,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/ruin/space/has_grav/ancientstation/rnd)
|
||||
@@ -2010,12 +2010,12 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/ruin/space/has_grav/ancientstation/deltacorridor)
|
||||
"fu" = (
|
||||
/obj/machinery/rnd/production/protolathe/offstation,
|
||||
/obj/machinery/rnd/production/protolathe,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/ruin/space/has_grav/ancientstation/rnd)
|
||||
"fv" = (
|
||||
/obj/machinery/rnd/production/circuit_imprinter/offstation,
|
||||
/obj/machinery/rnd/production/circuit_imprinter,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/item/reagent_containers/dropper,
|
||||
/turf/open/floor/plasteel/white,
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
// Keep the identifiers here below 32 characters, you can put the full display name in the actual achievement datum
|
||||
|
||||
#define ACHIEVEMENT_DEFAULT "default"
|
||||
#define ACHIEVEMENT_SCORE "score"
|
||||
|
||||
//Misc Medal hub IDs
|
||||
#define MEDAL_METEOR "Your Life Before Your Eyes"
|
||||
#define MEDAL_PULSE "Jackpot"
|
||||
#define MEDAL_TIMEWASTE "Overextended The Joke"
|
||||
#define MEDAL_RODSUPLEX "Feat of Strength"
|
||||
#define MEDAL_CLOWNCARKING "Round and Full"
|
||||
#define MEDAL_THANKSALOT "The Best Driver"
|
||||
#define MEDAL_HELBITALJANKEN "Hel-bent on Winning"
|
||||
#define MEDAL_MATERIALCRAFT "Getting an Upgrade"
|
||||
#define MEDAL_DISKPLEASE "Disk, Please!"
|
||||
#define MEDAL_GAMER "I'm Not Important"
|
||||
#define MEDAL_VENDORSQUISH "Teenage Anarchist"
|
||||
#define MEDAL_SWIRLIE "Bowl-d"
|
||||
#define MEDAL_SELFOUCH "Hands???"
|
||||
#define MEDAL_SANDMAN "Mister Sandman"
|
||||
#define MEDAL_CLEANBOSS "Cleanboss"
|
||||
#define MEDAL_RULE8 "Rule 8"
|
||||
#define MEDAL_LONGSHIFT "longshift"
|
||||
#define MEDAL_SNAIL "KKKiiilll mmmeee"
|
||||
#define MEDAL_LOOKOUTSIR "Look Out, Sir!"
|
||||
#define MEDAL_GOTTEM "GOTTEM"
|
||||
#define MEDAL_ASCENSION "Ascension"
|
||||
#define MEDAL_FRENCHING "FrenchingTheBubble"
|
||||
#define MEDAL_ASH_ASCENSION "Ash"
|
||||
#define MEDAL_FLESH_ASCENSION "Flesh"
|
||||
#define MEDAL_RUST_ASCENSION "Rust"
|
||||
#define MEDAL_VOID_ASCENSION "Void"
|
||||
#define MEDAL_TOOLBOX_SOUL "Toolsoul"
|
||||
#define MEDAL_CHEM_TUT "Beginner Chemist"
|
||||
|
||||
//Skill medal hub IDs
|
||||
#define MEDAL_LEGENDARY_MINER "Legendary Miner"
|
||||
|
||||
//Mafia medal hub IDs (wins)
|
||||
#define MAFIA_MEDAL_ASSISTANT "Assistant"
|
||||
#define MAFIA_MEDAL_DETECTIVE "Detective"
|
||||
#define MAFIA_MEDAL_PSYCHOLOGIST "Psychologist"
|
||||
#define MAFIA_MEDAL_CHAPLAIN "Chaplain"
|
||||
#define MAFIA_MEDAL_MD "Medical Doctor"
|
||||
#define MAFIA_MEDAL_OFFICER "Security Officer"
|
||||
#define MAFIA_MEDAL_LAWYER "Lawyer"
|
||||
#define MAFIA_MEDAL_HOP "Head of Personnel"
|
||||
#define MAFIA_MEDAL_HOS "Head of Security"
|
||||
#define MAFIA_MEDAL_WARDEN "Warden"
|
||||
#define MAFIA_MEDAL_CHANGELING "CHANGELING"
|
||||
#define MAFIA_MEDAL_THOUGHTFEEDER "Thoughtfeeder"
|
||||
#define MAFIA_MEDAL_TRAITOR "Traitor"
|
||||
#define MAFIA_MEDAL_NIGHTMARE "Nightmare"
|
||||
#define MAFIA_MEDAL_FUGITIVE "Fugitive"
|
||||
#define MAFIA_MEDAL_OBSESSED "Obsessed"
|
||||
#define MAFIA_MEDAL_CLOWN "Clown"
|
||||
|
||||
//Mafia medal hub IDs (misc stuff)
|
||||
#define MAFIA_MEDAL_HATED "Universally Hated"
|
||||
#define MAFIA_MEDAL_CHARISMATIC "Charismatic"
|
||||
#define MAFIA_MEDAL_VIP "VIP"
|
||||
|
||||
//Boss medals
|
||||
|
||||
// Medal hub IDs for boss medals (Pre-fixes)
|
||||
#define BOSS_MEDAL_ANY "Boss Killer"
|
||||
#define BOSS_MEDAL_MINER "Blood-drunk Miner Killer"
|
||||
#define BOSS_MEDAL_FROSTMINER "Demonic-frost Miner Killer"
|
||||
#define BOSS_MEDAL_BUBBLEGUM "Bubblegum Killer"
|
||||
#define BOSS_MEDAL_COLOSSUS "Colossus Killer"
|
||||
#define BOSS_MEDAL_DRAKE "Drake Killer"
|
||||
#define BOSS_MEDAL_HIEROPHANT "Hierophant Killer"
|
||||
#define BOSS_MEDAL_LEGION "Legion Killer"
|
||||
#define BOSS_MEDAL_TENDRIL "Tendril Exterminator"
|
||||
#define BOSS_MEDAL_SWARMERS "Swarmer Beacon Killer"
|
||||
#define BOSS_MEDAL_WENDIGO "Wendigo Killer"
|
||||
#define BOSS_MEDAL_KINGGOAT "King Goat Killer"
|
||||
|
||||
#define BOSS_MEDAL_MINER_CRUSHER "Blood-drunk Miner Crusher"
|
||||
#define BOSS_MEDAL_FROSTMINER_CRUSHER "Demonic-frost Miner Crusher"
|
||||
#define BOSS_MEDAL_BUBBLEGUM_CRUSHER "Bubblegum Crusher"
|
||||
#define BOSS_MEDAL_COLOSSUS_CRUSHER "Colossus Crusher"
|
||||
#define BOSS_MEDAL_DRAKE_CRUSHER "Drake Crusher"
|
||||
#define BOSS_MEDAL_HIEROPHANT_CRUSHER "Hierophant Crusher"
|
||||
#define BOSS_MEDAL_LEGION_CRUSHER "Legion Crusher"
|
||||
#define BOSS_MEDAL_SWARMERS_CRUSHER "Swarmer Beacon Crusher"
|
||||
#define BOSS_MEDAL_WENDIGO_CRUSHER "Wendigo Crusher"
|
||||
#define BOSS_MEDAL_KINGGOAT_CRUSHER "King Goat Crusher"
|
||||
|
||||
// Medal hub IDs for boss-kill scores
|
||||
#define BOSS_SCORE "Bosses Killed"
|
||||
#define MINER_SCORE "BDMs Killed"
|
||||
#define FROST_MINER_SCORE "DFMs Killed"
|
||||
#define BUBBLEGUM_SCORE "Bubblegum Killed"
|
||||
#define COLOSSUS_SCORE "Colossus Killed"
|
||||
#define DRAKE_SCORE "Drakes Killed"
|
||||
#define HIEROPHANT_SCORE "Hierophants Killed"
|
||||
#define LEGION_SCORE "Legion Killed"
|
||||
#define SWARMER_BEACON_SCORE "Swarmer Beacs Killed"
|
||||
#define WENDIGO_SCORE "Wendigos Killed"
|
||||
#define KINGGOAT_SCORE "King Goat Killed"
|
||||
#define TENDRIL_CLEAR_SCORE "Tendrils Killed"
|
||||
|
||||
// DB ID for hardcore random mode
|
||||
#define HARDCORE_RANDOM_SCORE "Hardcore Random Score"
|
||||
|
||||
// DB ID for amount of consumed maintenance pills
|
||||
#define MAINTENANCE_PILL_SCORE "Maintenance Pill Score"
|
||||
+24
-14
@@ -30,26 +30,36 @@
|
||||
#define POD_SHAPE_NORML 1
|
||||
#define POD_SHAPE_OTHER 2
|
||||
|
||||
#define POD_TRANSIT "1"
|
||||
#define POD_FALLING "2"
|
||||
#define POD_OPENING "3"
|
||||
#define POD_LEAVING "4"
|
||||
|
||||
#define SUPPLYPOD_X_OFFSET -16
|
||||
|
||||
/// The baseline unit for cargo crates. Adjusting this will change the cost of all in-game shuttles, crate export values, bounty rewards, and all supply pack import values, as they use this as their unit of measurement.
|
||||
#define CARGO_CRATE_VALUE 200
|
||||
|
||||
GLOBAL_LIST_EMPTY(supplypod_loading_bays)
|
||||
|
||||
GLOBAL_LIST_INIT(podstyles, list(\
|
||||
list(POD_SHAPE_NORML, "pod", TRUE, "default", "yellow", RUBBLE_NORMAL, "supply pod", "A Nanotrasen supply drop pod."),\
|
||||
list(POD_SHAPE_NORML, "advpod", TRUE, "bluespace", "blue", RUBBLE_NORMAL, "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\
|
||||
list(POD_SHAPE_NORML, "advpod", TRUE, "centcom", "blue", RUBBLE_NORMAL, "\improper CentCom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to CentCom after delivery."),\
|
||||
list(POD_SHAPE_NORML, "darkpod", TRUE, "syndicate", "red", RUBBLE_NORMAL, "blood-red supply pod", "An intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\
|
||||
list(POD_SHAPE_NORML, "darkpod", TRUE, "deathsquad", "blue", RUBBLE_NORMAL, "\improper Deathsquad drop pod", "A Nanotrasen drop pod. This one has been marked the markings of Nanotrasen's elite strike team."),\
|
||||
list(POD_SHAPE_NORML, "pod", TRUE, "cultist", "red", RUBBLE_NORMAL, "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\
|
||||
list(POD_SHAPE_OTHER, "missile", FALSE, FALSE, FALSE, RUBBLE_THIN, "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
|
||||
list(POD_SHAPE_OTHER, "smissile", FALSE, FALSE, FALSE, RUBBLE_THIN, "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
|
||||
list(POD_SHAPE_OTHER, "box", TRUE, FALSE, FALSE, RUBBLE_WIDE, "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\
|
||||
list(POD_SHAPE_NORML, "clownpod", TRUE, "clown", "green", RUBBLE_NORMAL, "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
|
||||
list(POD_SHAPE_OTHER, "orange", TRUE, FALSE, FALSE, RUBBLE_NONE, "\improper Orange", "An angry orange."),\
|
||||
list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
|
||||
list(POD_SHAPE_OTHER, "gondola", FALSE, FALSE, FALSE, RUBBLE_NONE, "gondola", "The silent walker. This one seems to be part of a delivery agency."),\
|
||||
list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, FALSE, FALSE, "rl_click", "give_po")\
|
||||
list(POD_SHAPE_NORML, "pod", TRUE, "default", "yellow", RUBBLE_NORMAL, "supply pod", "A Nanotrasen supply drop pod."),\
|
||||
list(POD_SHAPE_NORML, "advpod", TRUE, "bluespace", "blue", RUBBLE_NORMAL, "bluespace supply pod" , "A Nanotrasen Bluespace supply pod. Teleports back to CentCom after delivery."),\
|
||||
list(POD_SHAPE_NORML, "advpod", TRUE, "centcom", "blue", RUBBLE_NORMAL, "\improper CentCom supply pod", "A Nanotrasen supply pod, this one has been marked with Central Command's designations. Teleports back to CentCom after delivery."),\
|
||||
list(POD_SHAPE_NORML, "darkpod", TRUE, "syndicate", "red", RUBBLE_NORMAL, "blood-red supply pod", "An intimidating supply pod, covered in the blood-red markings of the Syndicate. It's probably best to stand back from this."),\
|
||||
list(POD_SHAPE_NORML, "darkpod", TRUE, "deathsquad", "blue", RUBBLE_NORMAL, "\improper Deathsquad drop pod", "A Nanotrasen drop pod. This one has been marked the markings of Nanotrasen's elite strike team."),\
|
||||
list(POD_SHAPE_NORML, "pod", TRUE, "cultist", "red", RUBBLE_NORMAL, "bloody supply pod", "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes."),\
|
||||
list(POD_SHAPE_OTHER, "missile", FALSE, FALSE, FALSE, RUBBLE_THIN, "cruise missile", "A big ass missile that didn't seem to fully detonate. It was likely launched from some far-off deep space missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
|
||||
list(POD_SHAPE_OTHER, "smissile", FALSE, FALSE, FALSE, RUBBLE_THIN, "\improper Syndicate cruise missile", "A big ass, blood-red missile that didn't seem to fully detonate. It was likely launched from some deep space Syndicate missile silo. There appears to be an auxillery payload hatch on the side, though manually opening it is likely impossible."),\
|
||||
list(POD_SHAPE_OTHER, "box", TRUE, FALSE, FALSE, RUBBLE_WIDE, "\improper Aussec supply crate", "An incredibly sturdy supply crate, designed to withstand orbital re-entry. Has 'Aussec Armory - 2532' engraved on the side."),\
|
||||
list(POD_SHAPE_NORML, "clownpod", TRUE, "clown", "green", RUBBLE_NORMAL, "\improper HONK pod", "A brightly-colored supply pod. It likely originated from the Clown Federation."),\
|
||||
list(POD_SHAPE_OTHER, "orange", TRUE, FALSE, FALSE, RUBBLE_NONE, "\improper Orange", "An angry orange."),\
|
||||
list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\
|
||||
list(POD_SHAPE_OTHER, "gondola", FALSE, FALSE, FALSE, RUBBLE_NONE, "gondola", "The silent walker. This one seems to be part of a delivery agency."),\
|
||||
list(POD_SHAPE_OTHER, FALSE, FALSE, FALSE, FALSE, RUBBLE_NONE, FALSE, FALSE, "rl_click", "give_po")\
|
||||
))
|
||||
|
||||
//cit
|
||||
#define PACK_GOODY_NONE 0
|
||||
#define PACK_GOODY_PUBLIC 1 //can be bought by both privates and cargo
|
||||
#define PACK_GOODY_PRIVATE 2 //can be bought only by privates
|
||||
|
||||
@@ -52,3 +52,9 @@
|
||||
#define COLOR_ASSEMBLY_BLUE "#38559E"
|
||||
#define COLOR_ASSEMBLY_PURPLE "#6F6192"
|
||||
#define COLOR_ASSEMBLY_PINK "#ff4adc"
|
||||
|
||||
#define COLOR_WHITE "#FFFFFF"
|
||||
#define COLOR_VERY_LIGHT_GRAY "#EEEEEE"
|
||||
#define COLOR_SILVER "#C0C0C0"
|
||||
#define COLOR_GRAY "#808080"
|
||||
#define COLOR_HALF_TRANSPARENT_BLACK "#0000007A"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define COMPONENT_GLOB_BLOCK_CINEMATIC 1
|
||||
|
||||
// signals from globally accessible objects
|
||||
/// from SSsun when the sun changes position : (azimuth)
|
||||
/// from SSsun when the sun changes position : (primary_sun, suns)
|
||||
#define COMSIG_SUN_MOVED "sun_moved"
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#define MAX_GRANT_SCI 5000
|
||||
#define MAX_GRANT_SECMEDSRV 3000
|
||||
|
||||
//What should vending machines charge when you buy something in-department.
|
||||
#define VENDING_DISCOUNT 0 // price * discount so 0 = 0
|
||||
|
||||
#define ACCOUNT_CIV "CIV"
|
||||
#define ACCOUNT_CIV_NAME "Civil Budget"
|
||||
#define ACCOUNT_ENG "ENG"
|
||||
|
||||
@@ -67,17 +67,19 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
#define isslimeperson(A) (is_species(A, /datum/species/jelly/slime))
|
||||
#define isluminescent(A) (is_species(A, /datum/species/jelly/luminescent))
|
||||
#define iszombie(A) (is_species(A, /datum/species/zombie))
|
||||
#define isskeleton(A) (is_species(A, /datum/species/skeleton))
|
||||
#define ismoth(A) (is_species(A, /datum/species/moth))
|
||||
#define ishumanbasic(A) (is_species(A, /datum/species/human))
|
||||
#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid))
|
||||
#define isdwarf(A) (is_species(A, /datum/species/dwarf))
|
||||
#define isethereal(A) (is_species(A, /datum/species/ethereal))
|
||||
#define isvampire(A) (is_species(A,/datum/species/vampire))
|
||||
#define isdullahan(A) (is_species(A, /datum/species/dullahan))
|
||||
|
||||
#define isangel(A) (is_species(A, /datum/species/angel))
|
||||
#define isvampire(A) (is_species(A, /datum/species/vampire))
|
||||
#define ismush(A) (is_species(A, /datum/species/mush))
|
||||
#define isshadow(A) (is_species(A, /datum/species/shadow))
|
||||
#define isskeleton(A) (is_species(A, /datum/species/skeleton))
|
||||
#define isrobotic(A) (is_species(A, /datum/species/ipc) || is_species(A, /datum/species/synthliz))
|
||||
#define isethereal(A) (is_species(A, /datum/species/ethereal))
|
||||
#define isdwarf(A) (is_species(A, /datum/species/dwarf))
|
||||
|
||||
// Citadel specific species
|
||||
#define isipcperson(A) (is_species(A, /datum/species/ipc))
|
||||
@@ -143,6 +145,10 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
|
||||
#define ishostile(A) (istype(A, /mob/living/simple_animal/hostile))
|
||||
|
||||
// #define israt(A) (istype(A, /mob/living/simple_animal/hostile/rat))
|
||||
|
||||
// #define isregalrat(A) (istype(A, /mob/living/simple_animal/hostile/regalrat))
|
||||
|
||||
#define isswarmer(A) (istype(A, /mob/living/simple_animal/hostile/swarmer))
|
||||
|
||||
#define isguardian(A) (istype(A, /mob/living/simple_animal/hostile/guardian))
|
||||
@@ -155,6 +161,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
|
||||
#define isclown(A) (istype(A, /mob/living/simple_animal/hostile/retaliate/clown))
|
||||
|
||||
|
||||
//Misc mobs
|
||||
#define isobserver(A) (istype(A, /mob/dead/observer))
|
||||
|
||||
@@ -184,6 +191,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
|
||||
#define isitem(A) (istype(A, /obj/item))
|
||||
|
||||
#define isstack(A) (istype(A, /obj/item/stack))
|
||||
|
||||
#define isgrenade(A) (istype(A, /obj/item/grenade))
|
||||
|
||||
#define islandmine(A) (istype(A, /obj/effect/mine))
|
||||
@@ -206,6 +215,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
|
||||
#define isclothing(A) (istype(A, /obj/item/clothing))
|
||||
|
||||
#define iscash(A) (istype(A, /obj/item/coin) || istype(A, /obj/item/stack/spacecash) || istype(A, /obj/item/holochip))
|
||||
|
||||
#define isbodypart(A) (istype(A, /obj/item/bodypart))
|
||||
|
||||
#define isprojectile(A) (istype(A, /obj/item/projectile))
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// Medal names
|
||||
#define BOSS_KILL_MEDAL "Killer"
|
||||
#define ALL_KILL_MEDAL "Exterminator" //Killing all of x type
|
||||
#define BOSS_KILL_MEDAL_CRUSHER "Crusher"
|
||||
|
||||
//Defines for boss medals
|
||||
#define BOSS_MEDAL_MINER "Blood-drunk Miner"
|
||||
#define BOSS_MEDAL_BUBBLEGUM "Bubblegum"
|
||||
#define BOSS_MEDAL_COLOSSUS "Colossus"
|
||||
#define BOSS_MEDAL_DRAKE "Drake"
|
||||
#define BOSS_MEDAL_HIEROPHANT "Hierophant"
|
||||
#define BOSS_MEDAL_LEGION "Legion"
|
||||
#define BOSS_MEDAL_TENDRIL "Tendril"
|
||||
#define BOSS_MEDAL_SWARMERS "Swarmer Beacon"
|
||||
|
||||
// Score names
|
||||
#define HIEROPHANT_SCORE "Hierophants Killed"
|
||||
#define BOSS_SCORE "Bosses Killed"
|
||||
#define BUBBLEGUM_SCORE "Bubblegum Killed"
|
||||
#define COLOSSUS_SCORE "Colossus Killed"
|
||||
#define DRAKE_SCORE "Drakes Killed"
|
||||
#define LEGION_SCORE "Legion Killed"
|
||||
#define SWARMER_BEACON_SCORE "Swarmer Beacons Killed"
|
||||
#define TENDRIL_CLEAR_SCORE "Tendrils Killed"
|
||||
|
||||
//Misc medals
|
||||
#define MEDAL_METEOR "Your Life Before Your Eyes"
|
||||
#define MEDAL_PULSE "Jackpot"
|
||||
#define MEDAL_TIMEWASTE "Overextended The Joke"
|
||||
@@ -435,8 +435,13 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
//text files
|
||||
#define BRAIN_DAMAGE_FILE "traumas.json"
|
||||
#define ION_FILE "ion_laws.json"
|
||||
#define REDPILL_FILE "redpill.json"
|
||||
#define PIRATE_NAMES_FILE "pirates.json"
|
||||
#define REDPILL_FILE "redpill.json"
|
||||
#define ARCADE_FILE "arcade.json"
|
||||
// #define BOOMER_FILE "boomer.json"
|
||||
// #define LOCATIONS_FILE "locations.json"
|
||||
// #define WANTED_FILE "wanted_message.json"
|
||||
// #define VISTA_FILE "steve.json"
|
||||
#define FLESH_SCAR_FILE "wounds/flesh_scar_desc.json"
|
||||
#define BONE_SCAR_FILE "wounds/bone_scar_desc.json"
|
||||
#define SCAR_LOC_FILE "wounds/scar_loc.json"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#define DEFAULT_SCAN_RANGE 7 //default view range for finding targets.
|
||||
|
||||
//Mode defines
|
||||
//Mode defines. If you add a new one make sure you update mode_name in /mob/living/simple_animal/bot
|
||||
#define BOT_IDLE 0 // idle
|
||||
#define BOT_HUNT 1 // found target, hunting
|
||||
#define BOT_PREP_ARREST 2 // at target, preparing to arrest
|
||||
@@ -27,7 +27,8 @@
|
||||
#define BOT_NAV 15 // computing navigation
|
||||
#define BOT_WAIT_FOR_NAV 16 // waiting for nav computation
|
||||
#define BOT_NO_ROUTE 17 // no destination beacon found (or no route)
|
||||
#define BOT_TIPPED 18 // someone tipped a medibot over ;_;
|
||||
#define BOT_SHOWERSTANCE 18 // cleaning unhygienic humans
|
||||
#define BOT_TIPPED 19 // someone tipped a medibot over ;_;
|
||||
|
||||
//Bot types
|
||||
#define SEC_BOT (1<<0) // Secutritrons (Beepsky) and ED-209s
|
||||
@@ -37,6 +38,7 @@
|
||||
#define MED_BOT (1<<4) // Medibots
|
||||
#define HONK_BOT (1<<5) // Honkbots & ED-Honks
|
||||
#define FIRE_BOT (1<<6) // Firebots
|
||||
#define HYGIENE_BOT (1<<7) // Hygienebots
|
||||
|
||||
//AI notification defines
|
||||
#define NEW_BORG 1
|
||||
@@ -69,8 +71,15 @@
|
||||
//Checks to determine borg availability depending on the server's config. These are defines in the interest of reducing copypasta
|
||||
#define BORG_SEC_AVAILABLE (!CONFIG_GET(flag/disable_secborg) && GLOB.security_level >= CONFIG_GET(number/minimum_secborg_alert))
|
||||
|
||||
//silicon_privileges flags
|
||||
//silicon_priviledges flags
|
||||
#define PRIVILEGES_SILICON (1<<0)
|
||||
#define PRIVILEGES_PAI (1<<1)
|
||||
#define PRIVILEGES_BOT (1<<2)
|
||||
#define PRIVILEGES_DRONE (1<<3)
|
||||
|
||||
#define BORG_LAMP_CD_RESET -1 //special value to reset cyborg's lamp_cooldown
|
||||
|
||||
/// Defines for whether or not module slots are broken.
|
||||
#define BORG_MODULE_ALL_DISABLED (1<<0)
|
||||
#define BORG_MODULE_TWO_DISABLED (1<<1)
|
||||
#define BORG_MODULE_THREE_DISABLED (1<<2)
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
#define INIT_ORDER_SOUNDS 83
|
||||
#define INIT_ORDER_INSTRUMENTS 82
|
||||
#define INIT_ORDER_VIS 80
|
||||
// #define INIT_ORDER_ACHIEVEMENTS 77
|
||||
#define INIT_ORDER_ACHIEVEMENTS 77
|
||||
#define INIT_ORDER_RESEARCH 75
|
||||
#define INIT_ORDER_EVENTS 70
|
||||
#define INIT_ORDER_JOBS 65
|
||||
|
||||
@@ -90,6 +90,9 @@
|
||||
#define VV_HK_TRIGGER_EMP "empulse"
|
||||
#define VV_HK_TRIGGER_EXPLOSION "explode"
|
||||
#define VV_HK_AUTO_RENAME "auto_rename"
|
||||
// #define VV_HK_RADIATE "radiate"
|
||||
#define VV_HK_EDIT_FILTERS "edit_filters"
|
||||
// #define VV_HK_ADD_AI "add_ai"
|
||||
|
||||
// /obj
|
||||
#define VV_HK_OSAY "osay"
|
||||
|
||||
@@ -614,7 +614,7 @@
|
||||
used_key_list[input_key] = 1
|
||||
return input_key
|
||||
|
||||
#if DM_VERSION > 513
|
||||
#if DM_VERSION > 514
|
||||
#error Remie said that lummox was adding a way to get a lists
|
||||
#error contents via list.values, if that is true remove this
|
||||
#error otherwise, update the version and bug lummox
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
#define ICON_NOT_SET "Not Set"
|
||||
|
||||
//This is stored as a nested list instead of datums or whatever because it json encodes nicely for usage in tgui
|
||||
GLOBAL_LIST_INIT(master_filter_info, list(
|
||||
"alpha" = list(
|
||||
"defaults" = list(
|
||||
"x" = 0,
|
||||
"y" = 0,
|
||||
"icon" = ICON_NOT_SET,
|
||||
"render_source" = "",
|
||||
"flags" = 0
|
||||
),
|
||||
"flags" = list(
|
||||
"MASK_INVERSE" = MASK_INVERSE,
|
||||
"MASK_SWAP" = MASK_SWAP
|
||||
)
|
||||
),
|
||||
"angular_blur" = list(
|
||||
"defaults" = list(
|
||||
"x" = 0,
|
||||
"y" = 0,
|
||||
"size" = 1
|
||||
)
|
||||
),
|
||||
/* Not supported because making a proper matrix editor on the frontend would be a huge dick pain.
|
||||
Uncomment if you ever implement it
|
||||
"color" = list(
|
||||
"defaults" = list(
|
||||
"color" = matrix(),
|
||||
"space" = FILTER_COLOR_RGB
|
||||
)
|
||||
),
|
||||
*/
|
||||
"displace" = list(
|
||||
"defaults" = list(
|
||||
"x" = 0,
|
||||
"y" = 0,
|
||||
"size" = null,
|
||||
"icon" = ICON_NOT_SET,
|
||||
"render_source" = ""
|
||||
)
|
||||
),
|
||||
"drop_shadow" = list(
|
||||
"defaults" = list(
|
||||
"x" = 1,
|
||||
"y" = -1,
|
||||
"size" = 1,
|
||||
"offset" = 0,
|
||||
"color" = COLOR_HALF_TRANSPARENT_BLACK
|
||||
)
|
||||
),
|
||||
"blur" = list(
|
||||
"defaults" = list(
|
||||
"size" = 1
|
||||
)
|
||||
),
|
||||
"layer" = list(
|
||||
"defaults" = list(
|
||||
"x" = 0,
|
||||
"y" = 0,
|
||||
"icon" = ICON_NOT_SET,
|
||||
"render_source" = "",
|
||||
"flags" = FILTER_OVERLAY,
|
||||
"color" = "",
|
||||
"transform" = null,
|
||||
"blend_mode" = BLEND_DEFAULT
|
||||
)
|
||||
),
|
||||
"motion_blur" = list(
|
||||
"defaults" = list(
|
||||
"x" = 0,
|
||||
"y" = 0
|
||||
)
|
||||
),
|
||||
"outline" = list(
|
||||
"defaults" = list(
|
||||
"size" = 0,
|
||||
"color" = COLOR_BLACK,
|
||||
"flags" = NONE
|
||||
),
|
||||
"flags" = list(
|
||||
"OUTLINE_SHARP" = OUTLINE_SHARP,
|
||||
"OUTLINE_SQUARE" = OUTLINE_SQUARE
|
||||
)
|
||||
),
|
||||
"radial_blur" = list(
|
||||
"defaults" = list(
|
||||
"x" = 0,
|
||||
"y" = 0,
|
||||
"size" = 0.01
|
||||
)
|
||||
),
|
||||
"rays" = list(
|
||||
"defaults" = list(
|
||||
"x" = 0,
|
||||
"y" = 0,
|
||||
"size" = 16,
|
||||
"color" = COLOR_WHITE,
|
||||
"offset" = 0,
|
||||
"density" = 10,
|
||||
"threshold" = 0.5,
|
||||
"factor" = 0,
|
||||
"flags" = FILTER_OVERLAY | FILTER_UNDERLAY
|
||||
),
|
||||
"flags" = list(
|
||||
"FILTER_OVERLAY" = FILTER_OVERLAY,
|
||||
"FILTER_UNDERLAY" = FILTER_UNDERLAY
|
||||
)
|
||||
),
|
||||
"ripple" = list(
|
||||
"defaults" = list(
|
||||
"x" = 0,
|
||||
"y" = 0,
|
||||
"size" = 1,
|
||||
"repeat" = 2,
|
||||
"radius" = 0,
|
||||
"falloff" = 1,
|
||||
"flags" = NONE
|
||||
),
|
||||
"flags" = list(
|
||||
"WAVE_BOUNDED" = WAVE_BOUNDED
|
||||
)
|
||||
),
|
||||
"wave" = list(
|
||||
"defaults" = list(
|
||||
"x" = 0,
|
||||
"y" = 0,
|
||||
"size" = 1,
|
||||
"offset" = 0,
|
||||
"flags" = NONE
|
||||
),
|
||||
"flags" = list(
|
||||
"WAVE_SIDEWAYS" = WAVE_SIDEWAYS,
|
||||
"WAVE_BOUNDED" = WAVE_BOUNDED
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
#undef ICON_NOT_SET
|
||||
|
||||
//Helpers to generate lists for filter helpers
|
||||
//This is the only practical way of writing these that actually produces sane lists
|
||||
/proc/alpha_mask_filter(x, y, icon/icon, render_source, flags)
|
||||
. = list("type" = "alpha")
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
if(!isnull(icon))
|
||||
.["icon"] = icon
|
||||
if(!isnull(render_source))
|
||||
.["render_source"] = render_source
|
||||
if(!isnull(flags))
|
||||
.["flags"] = flags
|
||||
|
||||
/proc/angular_blur_filter(x, y, size)
|
||||
. = list("type" = "angular_blur")
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
if(!isnull(size))
|
||||
.["size"] = size
|
||||
|
||||
/proc/color_matrix_filter(matrix/in_matrix, space)
|
||||
. = list("type" = "color")
|
||||
.["color"] = in_matrix
|
||||
if(!isnull(space))
|
||||
.["space"] = space
|
||||
|
||||
/proc/displacement_map_filter(icon, render_source, x, y, size = 32)
|
||||
. = list("type" = "displace")
|
||||
if(!isnull(icon))
|
||||
.["icon"] = icon
|
||||
if(!isnull(render_source))
|
||||
.["render_source"] = render_source
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
if(!isnull(size))
|
||||
.["size"] = size
|
||||
|
||||
/proc/drop_shadow_filter(x, y, size, offset, color)
|
||||
. = list("type" = "drop_shadow")
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
if(!isnull(size))
|
||||
.["size"] = size
|
||||
if(!isnull(offset))
|
||||
.["offset"] = offset
|
||||
if(!isnull(color))
|
||||
.["color"] = color
|
||||
|
||||
/proc/gauss_blur_filter(size)
|
||||
. = list("type" = "blur")
|
||||
if(!isnull(size))
|
||||
.["size"] = size
|
||||
|
||||
/proc/layering_filter(icon, render_source, x, y, flags, color, transform, blend_mode)
|
||||
. = list("type" = "layer")
|
||||
if(!isnull(icon))
|
||||
.["icon"] = icon
|
||||
if(!isnull(render_source))
|
||||
.["render_source"] = render_source
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
if(!isnull(color))
|
||||
.["color"] = color
|
||||
if(!isnull(flags))
|
||||
.["flags"] = flags
|
||||
if(!isnull(transform))
|
||||
.["transform"] = transform
|
||||
if(!isnull(blend_mode))
|
||||
.["blend_mode"] = blend_mode
|
||||
|
||||
/proc/motion_blur_filter(x, y)
|
||||
. = list("type" = "motion_blur")
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
|
||||
/proc/outline_filter(size, color, flags)
|
||||
. = list("type" = "outline")
|
||||
if(!isnull(size))
|
||||
.["size"] = size
|
||||
if(!isnull(color))
|
||||
.["color"] = color
|
||||
if(!isnull(flags))
|
||||
.["flags"] = flags
|
||||
|
||||
/proc/radial_blur_filter(size, x, y)
|
||||
. = list("type" = "radial_blur")
|
||||
if(!isnull(size))
|
||||
.["size"] = size
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
|
||||
/proc/rays_filter(size, color, offset, density, threshold, factor, x, y, flags)
|
||||
. = list("type" = "rays")
|
||||
if(!isnull(size))
|
||||
.["size"] = size
|
||||
if(!isnull(color))
|
||||
.["color"] = color
|
||||
if(!isnull(offset))
|
||||
.["offset"] = offset
|
||||
if(!isnull(density))
|
||||
.["density"] = density
|
||||
if(!isnull(threshold))
|
||||
.["threshold"] = threshold
|
||||
if(!isnull(factor))
|
||||
.["factor"] = factor
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
if(!isnull(flags))
|
||||
.["flags"] = flags
|
||||
|
||||
/proc/ripple_filter(radius, size, falloff, repeat, x, y, flags)
|
||||
. = list("type" = "ripple")
|
||||
if(!isnull(radius))
|
||||
.["radius"] = radius
|
||||
if(!isnull(size))
|
||||
.["size"] = size
|
||||
if(!isnull(falloff))
|
||||
.["falloff"] = falloff
|
||||
if(!isnull(repeat))
|
||||
.["repeat"] = repeat
|
||||
if(!isnull(flags))
|
||||
.["flags"] = flags
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
|
||||
/proc/wave_filter(x, y, size, offset, flags)
|
||||
. = list("type" = "wave")
|
||||
if(!isnull(size))
|
||||
.["size"] = size
|
||||
if(!isnull(x))
|
||||
.["x"] = x
|
||||
if(!isnull(y))
|
||||
.["y"] = y
|
||||
if(!isnull(offset))
|
||||
.["offset"] = offset
|
||||
if(!isnull(flags))
|
||||
.["flags"] = flags
|
||||
|
||||
/proc/apply_wibbly_filters(atom/in_atom, length)
|
||||
for(var/i in 1 to 7)
|
||||
//This is a very baffling and strange way of doing this but I am just preserving old functionality
|
||||
var/X
|
||||
var/Y
|
||||
var/rsq
|
||||
do
|
||||
X = 60*rand() - 30
|
||||
Y = 60*rand() - 30
|
||||
rsq = X*X + Y*Y
|
||||
while(rsq<100 || rsq>900) // Yeah let's just loop infinitely due to bad luck what's the worst that could happen?
|
||||
var/random_roll = rand()
|
||||
in_atom.add_filter("wibbly-[i]", 5, wave_filter(x = X, y = Y, size = rand() * 2.5 + 0.5, offset = random_roll))
|
||||
var/filter = in_atom.get_filter("wibbly-[i]")
|
||||
animate(filter, offset = random_roll, time = 0, loop = -1, flags = ANIMATION_PARALLEL)
|
||||
animate(offset = random_roll - 1, time = rand() * 20 + 10)
|
||||
|
||||
/proc/remove_wibbly_filters(atom/in_atom)
|
||||
var/filter
|
||||
for(var/i in 1 to 7)
|
||||
filter = in_atom.get_filter("wibbly-[i]")
|
||||
animate(filter)
|
||||
in_atom.remove_filter("wibbly-[i]")
|
||||
+223
-80
@@ -1,81 +1,102 @@
|
||||
#define POPCOUNT_SURVIVORS "survivors" //Not dead at roundend
|
||||
#define POPCOUNT_ESCAPEES "escapees" //Not dead and on centcom/shuttles marked as escaped
|
||||
#define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only.
|
||||
#define POPCOUNT_SURVIVORS "survivors" //Not dead at roundend
|
||||
#define POPCOUNT_ESCAPEES "escapees" //Not dead and on centcom/shuttles marked as escaped
|
||||
#define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only.
|
||||
#define PERSONAL_LAST_ROUND "personal last round"
|
||||
#define SERVER_LAST_ROUND "server last round"
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/gather_roundend_feedback()
|
||||
var/datum/station_state/end_state = new /datum/station_state()
|
||||
end_state.count()
|
||||
station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
|
||||
gather_antag_data()
|
||||
record_nuke_disk_location()
|
||||
var/json_file = file("[GLOB.log_directory]/round_end_data.json")
|
||||
// All but npcs sublists and ghost category contain only mobs with minds
|
||||
var/list/file_data = list("escapees" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "abandoned" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "ghosts" = list(), "additional data" = list())
|
||||
var/num_survivors = 0
|
||||
var/num_escapees = 0
|
||||
var/num_shuttle_escapees = 0
|
||||
var/num_survivors = 0 //Count of non-brain non-camera mobs with mind that are alive
|
||||
var/num_escapees = 0 //Above and on centcom z
|
||||
var/num_shuttle_escapees = 0 //Above and on escape shuttle
|
||||
var/list/area/shuttle_areas
|
||||
if(SSshuttle && SSshuttle.emergency)
|
||||
if(SSshuttle?.emergency)
|
||||
shuttle_areas = SSshuttle.emergency.shuttle_areas
|
||||
for(var/mob/m in GLOB.mob_list)
|
||||
var/escaped
|
||||
var/category
|
||||
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
var/list/mob_data = list()
|
||||
if(isnewplayer(m))
|
||||
if(isnewplayer(M))
|
||||
continue
|
||||
if (m.client && m.client.prefs && m.client.prefs.auto_ooc)
|
||||
if (!(m.client.prefs.chat_toggles & CHAT_OOC))
|
||||
m.client.prefs.chat_toggles ^= CHAT_OOC
|
||||
if(m.mind)
|
||||
if(m.stat != DEAD && !isbrain(m) && !iscameramob(m))
|
||||
// enable their ooc?
|
||||
if (M.client?.prefs?.auto_ooc)
|
||||
if (!(M.client.prefs.chat_toggles & CHAT_OOC))
|
||||
M.client.prefs.chat_toggles ^= CHAT_OOC
|
||||
|
||||
var/escape_status = "abandoned" //default to abandoned
|
||||
var/category = "npcs" //Default to simple count only bracket
|
||||
var/count_only = TRUE //Count by name only or full info
|
||||
|
||||
mob_data["name"] = M.name
|
||||
if(M.mind)
|
||||
count_only = FALSE
|
||||
mob_data["ckey"] = M.mind.key
|
||||
if(M.stat != DEAD && !isbrain(M) && !iscameramob(M))
|
||||
num_survivors++
|
||||
mob_data += list("name" = m.name, "ckey" = ckey(m.mind.key))
|
||||
if(isobserver(m))
|
||||
escaped = "ghosts"
|
||||
else if(isliving(m))
|
||||
var/mob/living/L = m
|
||||
mob_data += list("location" = get_area(L), "health" = L.health)
|
||||
if(EMERGENCY_ESCAPED_OR_ENDGAMED && (M.onCentCom() || M.onSyndieBase()))
|
||||
num_escapees++
|
||||
escape_status = "escapees"
|
||||
if(shuttle_areas[get_area(M)])
|
||||
num_shuttle_escapees++
|
||||
if(isliving(M))
|
||||
var/mob/living/L = M
|
||||
mob_data["location"] = get_area(L)
|
||||
mob_data["health"] = L.health
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
category = "humans"
|
||||
mob_data += list("job" = H.mind.assigned_role, "species" = H.dna.species.name)
|
||||
if(H.mind)
|
||||
mob_data["job"] = H.mind.assigned_role
|
||||
else
|
||||
mob_data["job"] = "Unknown"
|
||||
mob_data["species"] = H.dna.species.name
|
||||
else if(issilicon(L))
|
||||
category = "silicons"
|
||||
if(isAI(L))
|
||||
mob_data += list("module" = "AI")
|
||||
if(isAI(L))
|
||||
mob_data += list("module" = "pAI")
|
||||
if(iscyborg(L))
|
||||
mob_data["module"] = "AI"
|
||||
else if(ispAI(L))
|
||||
mob_data["module"] = "pAI"
|
||||
else if(iscyborg(L))
|
||||
var/mob/living/silicon/robot/R = L
|
||||
mob_data += list("module" = R.module)
|
||||
else
|
||||
category = "others"
|
||||
mob_data += list("typepath" = m.type)
|
||||
if(!escaped)
|
||||
if(EMERGENCY_ESCAPED_OR_ENDGAMED && (m.onCentCom() || m.onSyndieBase()))
|
||||
escaped = "escapees"
|
||||
num_escapees++
|
||||
if(shuttle_areas[get_area(m)])
|
||||
num_shuttle_escapees++
|
||||
else
|
||||
escaped = "abandoned"
|
||||
if(!m.mind && (!ishuman(m) || !issilicon(m)))
|
||||
var/list/npc_nest = file_data["[escaped]"]["npcs"]
|
||||
if(npc_nest.Find(initial(m.name)))
|
||||
file_data["[escaped]"]["npcs"]["[initial(m.name)]"] += 1
|
||||
else
|
||||
file_data["[escaped]"]["npcs"]["[initial(m.name)]"] = 1
|
||||
else
|
||||
if(isobserver(m))
|
||||
var/pos = length(file_data["[escaped]"]) + 1
|
||||
file_data["[escaped]"]["[pos]"] = mob_data
|
||||
else
|
||||
if(!category)
|
||||
mob_data["module"] = R.module.name
|
||||
else
|
||||
category = "others"
|
||||
mob_data += list("name" = m.name, "typepath" = m.type)
|
||||
var/pos = length(file_data["[escaped]"]["[category]"]) + 1
|
||||
file_data["[escaped]"]["[category]"]["[pos]"] = mob_data
|
||||
mob_data["typepath"] = M.type
|
||||
//Ghosts don't care about minds, but we want to retain ckey data etc
|
||||
if(isobserver(M))
|
||||
count_only = FALSE
|
||||
escape_status = "ghosts"
|
||||
if(!M.mind)
|
||||
mob_data["ckey"] = M.key
|
||||
category = null //ghosts are one list deep
|
||||
//All other mindless stuff just gets counts by name
|
||||
if(count_only)
|
||||
var/list/npc_nest = file_data["[escape_status]"]["npcs"]
|
||||
var/name_to_use = initial(M.name)
|
||||
if(ishuman(M))
|
||||
name_to_use = "Unknown Human" //Monkeymen and other mindless corpses
|
||||
if(npc_nest.Find(name_to_use))
|
||||
file_data["[escape_status]"]["npcs"][name_to_use] += 1
|
||||
else
|
||||
file_data["[escape_status]"]["npcs"][name_to_use] = 1
|
||||
else
|
||||
//Mobs with minds and ghosts get detailed data
|
||||
if(category)
|
||||
var/pos = length(file_data["[escape_status]"]["[category]"]) + 1
|
||||
file_data["[escape_status]"]["[category]"]["[pos]"] = mob_data
|
||||
else
|
||||
var/pos = length(file_data["[escape_status]"]) + 1
|
||||
file_data["[escape_status]"]["[pos]"] = mob_data
|
||||
|
||||
var/datum/station_state/end_state = new /datum/station_state()
|
||||
end_state.count()
|
||||
station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
|
||||
file_data["additional data"]["station integrity"] = station_integrity
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", num_survivors, list("survivors", "total"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", num_escapees, list("escapees", "total"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", GLOB.joined_player_list.len, list("players", "total"))
|
||||
@@ -169,10 +190,34 @@
|
||||
file_data["wanted"] = list("author" = "[GLOB.news_network.wanted_issue.scannedUser]", "criminal" = "[GLOB.news_network.wanted_issue.criminal]", "description" = "[GLOB.news_network.wanted_issue.body]", "photo file" = "[GLOB.news_network.wanted_issue.photo_file]")
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
///Handles random hardcore point rewarding if it applies.
|
||||
/datum/controller/subsystem/ticker/proc/HandleRandomHardcoreScore(client/player_client)
|
||||
if(!ishuman(player_client.mob))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/human_mob = player_client.mob
|
||||
if(!human_mob.hardcore_survival_score) ///no score no glory
|
||||
return FALSE
|
||||
|
||||
if(human_mob.mind && (human_mob.mind.special_role || length(human_mob.mind.antag_datums) > 0))
|
||||
var/didthegamerwin = TRUE
|
||||
for(var/a in human_mob.mind.antag_datums)
|
||||
var/datum/antagonist/antag_datum = a
|
||||
for(var/i in antag_datum.objectives)
|
||||
var/datum/objective/objective_datum = i
|
||||
if(!objective_datum.check_completion())
|
||||
didthegamerwin = FALSE
|
||||
if(!didthegamerwin)
|
||||
return FALSE
|
||||
player_client.give_award(/datum/award/score/hardcore_random, human_mob, round(human_mob.hardcore_survival_score))
|
||||
else if(human_mob.onCentCom())
|
||||
player_client.give_award(/datum/award/score/hardcore_random, human_mob, round(human_mob.hardcore_survival_score))
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/declare_completion()
|
||||
set waitfor = FALSE
|
||||
|
||||
to_chat(world, "<BR><BR><BR><span class='big bold'>The round has ended.</span>")
|
||||
log_game("The round has ended.")
|
||||
if(LAZYLEN(GLOB.round_end_notifiees))
|
||||
world.TgsTargetedChatBroadcast("[GLOB.round_end_notifiees.Join(", ")] the round has ended.", FALSE)
|
||||
|
||||
@@ -186,6 +231,19 @@
|
||||
C.RollCredits()
|
||||
C.playtitlemusic(40)
|
||||
CONFIG_SET(flag/suicide_allowed,TRUE) // EORG suicides allowed
|
||||
|
||||
var/speed_round = FALSE
|
||||
if(world.time - SSticker.round_start_time <= 300 SECONDS)
|
||||
speed_round = TRUE
|
||||
|
||||
for(var/client/C in GLOB.clients)
|
||||
if(!C.credits)
|
||||
C.RollCredits()
|
||||
C.playtitlemusic(40)
|
||||
if(speed_round)
|
||||
C.give_award(/datum/award/achievement/misc/speed_round, C.mob)
|
||||
HandleRandomHardcoreScore(C)
|
||||
|
||||
var/popcount = gather_roundend_feedback()
|
||||
display_report(popcount)
|
||||
|
||||
@@ -215,6 +273,11 @@
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
// handle_hearts()
|
||||
set_observer_default_invisibility(0, "<span class='warning'>The round is over! You are now visible to the living.</span>")
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
//These need update to actually reflect the real antagonists
|
||||
//Print a list of antagonists to the server log
|
||||
var/list/total_antagonists = list()
|
||||
@@ -233,18 +296,13 @@
|
||||
for(var/antag_name in total_antagonists)
|
||||
var/list/L = total_antagonists[antag_name]
|
||||
log_game("[antag_name]s :[L.Join(", ")].")
|
||||
set_observer_default_invisibility(0, "<span class='warning'>The round is over! You are now visible to the living.</span>")
|
||||
|
||||
CHECK_TICK
|
||||
SSdbcore.SetRoundEnd()
|
||||
//Collects persistence features
|
||||
if(mode.station_was_nuked)
|
||||
SSpersistence.station_was_destroyed = TRUE
|
||||
if(!mode.allow_persistence_save)
|
||||
SSpersistence.station_persistence_save_disabled = TRUE
|
||||
else
|
||||
if(mode.allow_persistence_save)
|
||||
SSpersistence.SaveTCGCards()
|
||||
SSpersistence.CollectData()
|
||||
SSpersistence.CollectData()
|
||||
|
||||
//stop collecting feedback during grifftime
|
||||
SSblackbox.Seal()
|
||||
@@ -279,11 +337,15 @@
|
||||
//Antagonists
|
||||
parts += antag_report()
|
||||
|
||||
parts += hardcore_random_report()
|
||||
|
||||
CHECK_TICK
|
||||
//Medals
|
||||
parts += medal_report()
|
||||
//Station Goals
|
||||
parts += goal_report()
|
||||
//Economy & Money
|
||||
parts += market_report()
|
||||
|
||||
listclearnulls(parts)
|
||||
|
||||
@@ -326,9 +388,9 @@
|
||||
parts += "[FOURSPACES]<i>Nobody died this shift!</i>"
|
||||
if(istype(SSticker.mode, /datum/game_mode/dynamic))
|
||||
var/datum/game_mode/dynamic/mode = SSticker.mode
|
||||
mode.update_playercounts()
|
||||
parts += "[FOURSPACES]Final threat level: [mode.threat_level]"
|
||||
parts += "[FOURSPACES]Final threat: [mode.threat]"
|
||||
mode.update_playercounts() // ?
|
||||
parts += "[FOURSPACES]Threat level: [mode.threat_level]"
|
||||
parts += "[FOURSPACES]Threat left: [mode.threat]"
|
||||
parts += "[FOURSPACES]Average threat: [mode.threat_average]"
|
||||
parts += "[FOURSPACES]Executed rules:"
|
||||
for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
|
||||
@@ -345,20 +407,47 @@
|
||||
/client/proc/roundend_report_file()
|
||||
return "data/roundend_reports/[ckey].html"
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C, previous = FALSE)
|
||||
/**
|
||||
* Log the round-end report as an HTML file
|
||||
*
|
||||
* Composits the roundend report, and saves it in two locations.
|
||||
* The report is first saved along with the round's logs
|
||||
* Then, the report is copied to a fixed directory specifically for
|
||||
* housing the server's last roundend report. In this location,
|
||||
* the file will be overwritten at the end of each shift.
|
||||
*/
|
||||
/datum/controller/subsystem/ticker/proc/log_roundend_report()
|
||||
var/roundend_file = file("[GLOB.log_directory]/round_end_data.html")
|
||||
var/list/parts = list()
|
||||
parts += "<div class='panel stationborder'>"
|
||||
parts += GLOB.survivor_report
|
||||
parts += "</div>"
|
||||
parts += GLOB.common_report
|
||||
var/content = parts.Join()
|
||||
//Log the rendered HTML in the round log directory
|
||||
fdel(roundend_file)
|
||||
WRITE_FILE(roundend_file, content)
|
||||
//Place a copy in the root folder, to be overwritten each round.
|
||||
roundend_file = file("data/server_last_roundend_report.html")
|
||||
fdel(roundend_file)
|
||||
WRITE_FILE(roundend_file, content)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C, report_type = null)
|
||||
var/datum/browser/roundend_report = new(C, "roundend")
|
||||
roundend_report.width = 800
|
||||
roundend_report.height = 600
|
||||
var/content
|
||||
var/filename = C.roundend_report_file()
|
||||
if(!previous)
|
||||
if(report_type == PERSONAL_LAST_ROUND) //Look at this player's last round
|
||||
content = file2text(filename)
|
||||
else if (report_type == SERVER_LAST_ROUND) //Look at the last round that this server has seen
|
||||
content = file2text("data/server_last_roundend_report.html")
|
||||
else //report_type is null, so make a new report based on the current round and show that to the player
|
||||
var/list/report_parts = list(personal_report(C), GLOB.common_report)
|
||||
content = report_parts.Join()
|
||||
remove_verb(C, /client/proc/show_previous_roundend_report)
|
||||
fdel(filename)
|
||||
text2file(content, filename)
|
||||
else
|
||||
content = file2text(filename)
|
||||
|
||||
roundend_report.set_content(content)
|
||||
roundend_report.stylesheets = list()
|
||||
roundend_report.add_stylesheet("roundend", 'html/browser/roundend.css')
|
||||
@@ -395,8 +484,9 @@
|
||||
/datum/controller/subsystem/ticker/proc/display_report(popcount)
|
||||
GLOB.common_report = build_roundend_report()
|
||||
GLOB.survivor_report = survivor_report(popcount)
|
||||
log_roundend_report()
|
||||
for(var/client/C in GLOB.clients)
|
||||
show_roundend_report(C, FALSE)
|
||||
show_roundend_report(C)
|
||||
give_show_report_button(C)
|
||||
CHECK_TICK
|
||||
|
||||
@@ -414,12 +504,11 @@
|
||||
|
||||
if (aiPlayer.connected_robots.len)
|
||||
var/borg_num = aiPlayer.connected_robots.len
|
||||
var/robolist = "<br><b>[aiPlayer.real_name]</b>'s minions were: "
|
||||
parts += "<br><b>[aiPlayer.real_name]</b>'s minions were:"
|
||||
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
|
||||
borg_num--
|
||||
if(robo.mind)
|
||||
robolist += "<b>[robo.name]</b>[robo.mind.hide_ckey ? "" : " (Played by: <b>[robo.mind.key]</b>)"] [robo.stat == DEAD ? " <span class='redtext'>(Deactivated)</span>" : ""][borg_num ?", ":""]<br>"
|
||||
parts += "[robolist]"
|
||||
parts += "<b>[robo.name]</b>[robo.mind.hide_ckey ? "" : " (Played by: <b>[robo.mind.key]</b>)"] [robo.stat == DEAD ? " <span class='redtext'>(Deactivated)</span>" : ""][borg_num ?", ":""]"
|
||||
if(!borg_spacer)
|
||||
borg_spacer = TRUE
|
||||
|
||||
@@ -446,6 +535,34 @@
|
||||
parts += G.get_result()
|
||||
return "<div class='panel stationborder'><ul>[parts.Join()]</ul></div>"
|
||||
|
||||
///Generate a report for how much money is on station, as well as the richest crewmember on the station.
|
||||
/datum/controller/subsystem/ticker/proc/market_report()
|
||||
var/list/parts = list()
|
||||
parts += "<span class='header'>Station Economic Summary:</span>"
|
||||
///This is the richest account on station at roundend.
|
||||
var/datum/bank_account/mr_moneybags
|
||||
///This is the station's total wealth at the end of the round.
|
||||
var/station_vault = 0
|
||||
///How many players joined the round.
|
||||
var/total_players = GLOB.joined_player_list.len
|
||||
var/list/typecache_bank = typecacheof(list(/datum/bank_account/department, /datum/bank_account/remote))
|
||||
for(var/i in SSeconomy.generated_accounts)
|
||||
var/datum/bank_account/current_acc = SSeconomy.generated_accounts[i]
|
||||
if(typecache_bank[current_acc.type])
|
||||
continue
|
||||
station_vault += current_acc.account_balance
|
||||
if(!mr_moneybags || mr_moneybags.account_balance < current_acc.account_balance)
|
||||
mr_moneybags = current_acc
|
||||
parts += "<div class='panel stationborder'>There were [station_vault] credits collected by crew this shift.<br>"
|
||||
if(total_players > 0)
|
||||
parts += "An average of [station_vault/total_players] credits were collected.<br>"
|
||||
// log_econ("Roundend credit total: [station_vault] credits. Average Credits: [station_vault/total_players]")
|
||||
if(mr_moneybags)
|
||||
parts += "The most affluent crew member at shift end was <b>[mr_moneybags.account_holder] with [mr_moneybags.account_balance]</b> cr!</div>"
|
||||
else
|
||||
parts += "Somehow, nobody made any money this shift! This'll result in some budget cuts...</div>"
|
||||
return parts
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/medal_report()
|
||||
if(GLOB.commendations.len)
|
||||
var/list/parts = list()
|
||||
@@ -455,16 +572,40 @@
|
||||
return "<div class='panel stationborder'>[parts.Join("<br>")]</div>"
|
||||
return ""
|
||||
|
||||
///Generate a report for all players who made it out alive with a hardcore random character and prints their final score
|
||||
/datum/controller/subsystem/ticker/proc/hardcore_random_report()
|
||||
. = list()
|
||||
var/list/hardcores = list()
|
||||
for(var/i in GLOB.player_list)
|
||||
if(!ishuman(i))
|
||||
continue
|
||||
var/mob/living/carbon/human/human_player = i
|
||||
if(!human_player.hardcore_survival_score || !human_player.onCentCom() || human_player.stat == DEAD) ///gotta escape nerd
|
||||
continue
|
||||
if(!human_player.mind)
|
||||
continue
|
||||
hardcores += human_player
|
||||
if(!length(hardcores))
|
||||
return
|
||||
. += "<div class='panel stationborder'><span class='header'>The following people made it out as a random hardcore character:</span>"
|
||||
. += "<ul class='playerlist'>"
|
||||
for(var/mob/living/carbon/human/human_player in hardcores)
|
||||
. += "<li>[printplayer(human_player.mind)] with a hardcore random score of [round(human_player.hardcore_survival_score)]</li>"
|
||||
. += "</ul></div>"
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/antag_report()
|
||||
var/list/result = list()
|
||||
var/list/all_teams = list()
|
||||
var/list/all_antagonists = list()
|
||||
|
||||
// for(var/datum/team/A in GLOB.antagonist_teams)
|
||||
// all_teams |= A
|
||||
|
||||
for(var/datum/antagonist/A in GLOB.antagonists)
|
||||
if(!A.owner)
|
||||
continue
|
||||
all_teams |= A.get_team()
|
||||
all_antagonists += A
|
||||
all_antagonists |= A
|
||||
|
||||
for(var/datum/team/T in all_teams)
|
||||
result += T.roundend_report()
|
||||
@@ -517,9 +658,9 @@
|
||||
|
||||
/datum/action/report/Trigger()
|
||||
if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED)
|
||||
SSticker.show_roundend_report(owner.client, FALSE)
|
||||
SSticker.show_roundend_report(owner.client)
|
||||
|
||||
/datum/action/report/IsAvailable(silent = FALSE)
|
||||
/datum/action/report/IsAvailable()
|
||||
return 1
|
||||
|
||||
/datum/action/report/Topic(href,href_list)
|
||||
@@ -534,7 +675,9 @@
|
||||
var/jobtext = ""
|
||||
if(ply.assigned_role)
|
||||
jobtext = " the <b>[ply.assigned_role]</b>"
|
||||
var/text = "<b>[ply.hide_ckey ? "<b>[ply.name]</b>[jobtext] " : "[ply.key]</b> was <b>[ply.name]</b>[jobtext] and "]"
|
||||
var/text = (ply.hide_ckey ? \
|
||||
"<b>[ply.key]</b> was <b>[ply.name]</b>[jobtext] and" \
|
||||
: "<b>[ply.name]</b>[jobtext]")
|
||||
if(ply.current)
|
||||
if(ply.current.stat == DEAD)
|
||||
text += " <span class='redtext'>died</span>"
|
||||
|
||||
@@ -666,7 +666,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
if(fexists(log))
|
||||
oldjson = json_decode(file2text(log))
|
||||
oldentries = oldjson["data"]
|
||||
if(!isemptylist(oldentries))
|
||||
if(length(oldentries))
|
||||
for(var/string in accepted)
|
||||
for(var/old in oldentries)
|
||||
if(string == old)
|
||||
@@ -676,7 +676,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
var/list/finalized = list()
|
||||
finalized = accepted.Copy() + oldentries.Copy() //we keep old and unreferenced phrases near the bottom for culling
|
||||
listclearnulls(finalized)
|
||||
if(!isemptylist(finalized) && length(finalized) > storemax)
|
||||
if(length(finalized) > storemax)
|
||||
finalized.Cut(storemax + 1)
|
||||
fdel(log)
|
||||
|
||||
|
||||
+28
-16
@@ -1247,28 +1247,40 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
|
||||
#define FOR_DVIEW_END GLOB.dview_mob.loc = null
|
||||
|
||||
//can a window be here, or is there a window blocking it?
|
||||
/proc/valid_window_location(turf/T, dir_to_check)
|
||||
if(!T)
|
||||
/**
|
||||
* Checks whether the target turf is in a valid state to accept a directional window
|
||||
* or other directional pseudo-dense object such as railings.
|
||||
*
|
||||
* Returns FALSE if the target turf cannot accept a directional window or railing.
|
||||
* Returns TRUE otherwise.
|
||||
*
|
||||
* Arguments:
|
||||
* * dest_turf - The destination turf to check for existing windows and railings
|
||||
* * test_dir - The prospective dir of some atom you'd like to put on this turf.
|
||||
* * is_fulltile - Whether the thing you're attempting to move to this turf takes up the entire tile or whether it supports multiple movable atoms on its tile.
|
||||
*/
|
||||
/proc/valid_window_location(turf/dest_turf, test_dir, is_fulltile = FALSE)
|
||||
if(!dest_turf)
|
||||
return FALSE
|
||||
for(var/obj/O in T)
|
||||
if(istype(O, /obj/machinery/door/window) && (O.dir == dir_to_check || dir_to_check == FULLTILE_WINDOW_DIR))
|
||||
return FALSE
|
||||
if(istype(O, /obj/structure/windoor_assembly))
|
||||
var/obj/structure/windoor_assembly/W = O
|
||||
if(W.ini_dir == dir_to_check || dir_to_check == FULLTILE_WINDOW_DIR)
|
||||
for(var/obj/turf_content in dest_turf)
|
||||
if(istype(turf_content, /obj/machinery/door/window))
|
||||
if((turf_content.dir == test_dir) || is_fulltile)
|
||||
return FALSE
|
||||
if(istype(O, /obj/structure/window))
|
||||
var/obj/structure/window/W = O
|
||||
if(W.ini_dir == dir_to_check || W.ini_dir == FULLTILE_WINDOW_DIR || dir_to_check == FULLTILE_WINDOW_DIR)
|
||||
if(istype(turf_content, /obj/structure/windoor_assembly))
|
||||
var/obj/structure/windoor_assembly/windoor_assembly = turf_content
|
||||
if(windoor_assembly.dir == test_dir || is_fulltile)
|
||||
return FALSE
|
||||
if(istype(O, /obj/structure/railing))
|
||||
var/obj/structure/railing/rail = O
|
||||
if(rail.ini_dir == dir_to_check || rail.ini_dir == FULLTILE_WINDOW_DIR || dir_to_check == FULLTILE_WINDOW_DIR)
|
||||
if(istype(turf_content, /obj/structure/window))
|
||||
var/obj/structure/window/window_structure = turf_content
|
||||
if(window_structure.dir == test_dir || window_structure.fulltile || is_fulltile)
|
||||
return FALSE
|
||||
if(istype(turf_content, /obj/structure/railing))
|
||||
var/obj/structure/railing/rail = turf_content
|
||||
if(rail.dir == test_dir || is_fulltile)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/proc/pass()
|
||||
/proc/pass(...)
|
||||
return
|
||||
|
||||
/proc/get_mob_or_brainmob(occupant)
|
||||
|
||||
Executable → Regular
@@ -126,6 +126,7 @@ GLOBAL_LIST_INIT(ai_core_display_screens, list(
|
||||
"Not Malf",
|
||||
"Patriot",
|
||||
"Pirate",
|
||||
"Portrait",
|
||||
"President",
|
||||
"Rainbow",
|
||||
"Clown",
|
||||
@@ -158,6 +159,10 @@ GLOBAL_LIST_INIT(ai_core_display_screens, list(
|
||||
else
|
||||
if(input == "Random")
|
||||
input = pick(GLOB.ai_core_display_screens - "Random")
|
||||
if(input == "Portrait")
|
||||
var/datum/portrait_picker/tgui = new(usr)//create the datum
|
||||
tgui.ui_interact(usr)//datum has a tgui component, here we open the window
|
||||
return "ai-portrait" //just take this until they decide
|
||||
return "ai-[lowertext(input)]"
|
||||
|
||||
GLOBAL_LIST_INIT(security_depts_prefs, list(SEC_DEPT_RANDOM, SEC_DEPT_NONE, SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT_SCIENCE, SEC_DEPT_SUPPLY))
|
||||
|
||||
@@ -17,21 +17,6 @@
|
||||
Therefore, the top right corner (except during admin shenanigans) is at "15,15"
|
||||
*/
|
||||
|
||||
//Lower left, persistent menu
|
||||
#define ui_inventory "WEST:6,SOUTH:5"
|
||||
|
||||
//Middle left indicators
|
||||
#define ui_lingchemdisplay "WEST,CENTER-1:15"
|
||||
#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
|
||||
|
||||
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
|
||||
|
||||
//Lower center, persistent menu
|
||||
#define ui_sstore1 "CENTER-5:10,SOUTH:5"
|
||||
#define ui_id "CENTER-4:12,SOUTH:5"
|
||||
#define ui_belt "CENTER-3:14,SOUTH:5"
|
||||
#define ui_back "CENTER-2:14,SOUTH:5"
|
||||
|
||||
/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5)
|
||||
var/x_off = -(!(i % 2))
|
||||
var/y_off = round((i-1) / 2)
|
||||
@@ -46,35 +31,23 @@
|
||||
var/y_off = round((M.held_items.len-1) / 2)
|
||||
return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5"
|
||||
|
||||
//Lower left, persistent menu
|
||||
#define ui_inventory "WEST:6,SOUTH:5"
|
||||
|
||||
//Middle left indicators
|
||||
#define ui_lingchemdisplay "WEST,CENTER-1:15"
|
||||
#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
|
||||
|
||||
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
|
||||
|
||||
//Lower center, persistent menu
|
||||
#define ui_sstore1 "CENTER-5:10,SOUTH:5"
|
||||
#define ui_id "CENTER-4:12,SOUTH:5"
|
||||
#define ui_belt "CENTER-3:14,SOUTH:5"
|
||||
#define ui_back "CENTER-2:14,SOUTH:5"
|
||||
#define ui_storage1 "CENTER+1:18,SOUTH:5"
|
||||
#define ui_storage2 "CENTER+2:20,SOUTH:5"
|
||||
|
||||
#define ui_borg_sensor "CENTER-3:15, SOUTH:5" //borgs
|
||||
#define ui_borg_lamp "CENTER-4:15, SOUTH:5" //borgs
|
||||
#define ui_borg_thrusters "CENTER-5:15, SOUTH:5" //borgs
|
||||
#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs
|
||||
#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs
|
||||
#define ui_inv3 "CENTER :16,SOUTH:5" //borgs
|
||||
#define ui_borg_module "CENTER+1:16,SOUTH:5" //borgs
|
||||
#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs
|
||||
#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs
|
||||
#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs
|
||||
#define ui_borg_language_menu "EAST-1:27,SOUTH+2:8" //borgs
|
||||
|
||||
#define ui_monkey_head "CENTER-5:13,SOUTH:5" //monkey
|
||||
#define ui_monkey_mask "CENTER-4:14,SOUTH:5" //monkey
|
||||
#define ui_monkey_neck "CENTER-3:15,SOUTH:5" //monkey
|
||||
#define ui_monkey_back "CENTER-2:16,SOUTH:5" //monkey
|
||||
|
||||
//#define ui_alien_storage_l "CENTER-2:14,SOUTH:5"//alien
|
||||
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"//alien
|
||||
#define ui_alien_language_menu "EAST-3:26,SOUTH:5" //alien
|
||||
|
||||
#define ui_drone_drop "CENTER+1:18,SOUTH:5" //maintenance drones
|
||||
#define ui_drone_pull "CENTER+2:2,SOUTH:5" //maintenance drones
|
||||
#define ui_drone_storage "CENTER-2:14,SOUTH:5" //maintenance drones
|
||||
#define ui_drone_head "CENTER-3:14,SOUTH:5" //maintenance drones
|
||||
|
||||
//Lower right, persistent menu
|
||||
#define ui_drop_throw "EAST-1:28,SOUTH+1:7"
|
||||
#define ui_pull_resist "EAST-2:26,SOUTH+1:7"
|
||||
@@ -88,11 +61,6 @@
|
||||
#define ui_language_menu "EAST-5:4,SOUTH:21"//CIT CHANGE - ditto
|
||||
#define ui_voremode "EAST-5:20,SOUTH:5"
|
||||
|
||||
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
|
||||
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
|
||||
#define ui_borg_intents "EAST-2:26,SOUTH:5"
|
||||
|
||||
|
||||
//Upper-middle right (alerts)
|
||||
#define ui_alert1 "EAST-1:28,CENTER+5:27"
|
||||
#define ui_alert2 "EAST-1:28,CENTER+4:25"
|
||||
@@ -100,31 +68,70 @@
|
||||
#define ui_alert4 "EAST-1:28,CENTER+2:21"
|
||||
#define ui_alert5 "EAST-1:28,CENTER+1:19"
|
||||
|
||||
|
||||
//Middle right (status indicators)
|
||||
#define ui_healthdoll "EAST-1:28,CENTER-2:13"
|
||||
#define ui_health "EAST-1:28,CENTER-1:15"
|
||||
#define ui_internal "EAST-1:28,CENTER+1:19"//CIT CHANGE - moves internal icon up a little bit to accommodate for the stamina meter
|
||||
#define ui_mood "EAST-1:28,CENTER-3:10"
|
||||
// #define ui_spacesuit "EAST-1:28,CENTER-4:10"
|
||||
|
||||
//living
|
||||
//Pop-up inventory
|
||||
#define ui_shoes "WEST+1:8,SOUTH:5"
|
||||
#define ui_iclothing "WEST:6,SOUTH+1:7"
|
||||
#define ui_oclothing "WEST+1:8,SOUTH+1:7"
|
||||
#define ui_gloves "WEST+2:10,SOUTH+1:7"
|
||||
#define ui_glasses "WEST:6,SOUTH+3:11"
|
||||
#define ui_mask "WEST+1:8,SOUTH+2:9"
|
||||
#define ui_ears "WEST+2:10,SOUTH+2:9"
|
||||
#define ui_neck "WEST:6,SOUTH+2:9"
|
||||
#define ui_head "WEST+1:8,SOUTH+3:11"
|
||||
|
||||
//Generic living
|
||||
#define ui_living_pull "EAST-1:28,CENTER-2:15"
|
||||
#define ui_living_health "EAST-1:28,CENTER:15"
|
||||
|
||||
//borgs
|
||||
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
|
||||
//Monkeys
|
||||
#define ui_monkey_head "CENTER-5:13,SOUTH:5"
|
||||
#define ui_monkey_mask "CENTER-4:14,SOUTH:5"
|
||||
#define ui_monkey_neck "CENTER-3:15,SOUTH:5"
|
||||
#define ui_monkey_back "CENTER-2:16,SOUTH:5"
|
||||
|
||||
//aliens
|
||||
#define ui_alien_health "EAST,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator.
|
||||
//Drones
|
||||
#define ui_drone_drop "CENTER+1:18,SOUTH:5"
|
||||
#define ui_drone_pull "CENTER+2:2,SOUTH:5"
|
||||
#define ui_drone_storage "CENTER-2:14,SOUTH:5"
|
||||
#define ui_drone_head "CENTER-3:14,SOUTH:5"
|
||||
|
||||
//Cyborgs
|
||||
#define ui_borg_health "EAST-1:28,CENTER-1:15"
|
||||
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
|
||||
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
|
||||
#define ui_borg_intents "EAST-2:26,SOUTH:5"
|
||||
#define ui_borg_lamp "CENTER-3:16, SOUTH:5"
|
||||
#define ui_borg_tablet "CENTER-4:16, SOUTH:5"
|
||||
#define ui_inv1 "CENTER-2:16,SOUTH:5"
|
||||
#define ui_inv2 "CENTER-1 :16,SOUTH:5"
|
||||
#define ui_inv3 "CENTER :16,SOUTH:5"
|
||||
#define ui_borg_module "CENTER+1:16,SOUTH:5"
|
||||
#define ui_borg_store "CENTER+2:16,SOUTH:5"
|
||||
#define ui_borg_camera "CENTER+3:21,SOUTH:5"
|
||||
#define ui_borg_alerts "CENTER+4:21,SOUTH:5"
|
||||
#define ui_borg_language_menu "CENTER+4:21,SOUTH+1:5"
|
||||
#define ui_borg_sensor "CENTER-6:16, SOUTH:5" //LEGACY
|
||||
#define ui_borg_thrusters "CENTER-5:16, SOUTH:5" //LEGACY
|
||||
|
||||
//Aliens
|
||||
#define ui_alien_health "EAST,CENTER-1:15"
|
||||
#define ui_alienplasmadisplay "EAST,CENTER-2:15"
|
||||
#define ui_alien_queen_finder "EAST,CENTER-3:15"
|
||||
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"
|
||||
#define ui_alien_language_menu "EAST-3:26,SOUTH:5"
|
||||
|
||||
//constructs
|
||||
//Constructs
|
||||
#define ui_construct_pull "EAST,CENTER-2:15"
|
||||
#define ui_construct_health "EAST,CENTER:15" //same as borgs and humans
|
||||
#define ui_construct_health "EAST,CENTER:15"
|
||||
|
||||
// AI
|
||||
|
||||
#define ui_ai_core "SOUTH:6,WEST"
|
||||
#define ui_ai_camera_list "SOUTH:6,WEST+1"
|
||||
#define ui_ai_track_with_camera "SOUTH:6,WEST+2"
|
||||
@@ -143,26 +150,32 @@
|
||||
#define ui_ai_multicam "SOUTH+1:6,WEST+13"
|
||||
#define ui_ai_add_multicam "SOUTH+1:6,WEST+14"
|
||||
|
||||
//Pop-up inventory
|
||||
#define ui_shoes "WEST+1:8,SOUTH:5"
|
||||
|
||||
#define ui_iclothing "WEST:6,SOUTH+1:7"
|
||||
#define ui_oclothing "WEST+1:8,SOUTH+1:7"
|
||||
#define ui_gloves "WEST+2:10,SOUTH+1:7"
|
||||
|
||||
#define ui_glasses "WEST:6,SOUTH+3:11"
|
||||
#define ui_mask "WEST+1:8,SOUTH+2:9"
|
||||
#define ui_ears "WEST+2:10,SOUTH+2:9"
|
||||
#define ui_neck "WEST:6,SOUTH+2:9"
|
||||
#define ui_head "WEST+1:8,SOUTH+3:11"
|
||||
// pAI
|
||||
// #define ui_pai_software "SOUTH:6,WEST"
|
||||
// #define ui_pai_shell "SOUTH:6,WEST+1"
|
||||
// #define ui_pai_chassis "SOUTH:6,WEST+2"
|
||||
// #define ui_pai_rest "SOUTH:6,WEST+3"
|
||||
// #define ui_pai_light "SOUTH:6,WEST+4"
|
||||
// #define ui_pai_newscaster "SOUTH:6,WEST+5"
|
||||
// #define ui_pai_host_monitor "SOUTH:6,WEST+6"
|
||||
// #define ui_pai_crew_manifest "SOUTH:6,WEST+7"
|
||||
// #define ui_pai_state_laws "SOUTH:6,WEST+8"
|
||||
// #define ui_pai_pda_send "SOUTH:6,WEST+9"
|
||||
// #define ui_pai_pda_log "SOUTH:6,WEST+10"
|
||||
// #define ui_pai_take_picture "SOUTH:6,WEST+12"
|
||||
// #define ui_pai_view_images "SOUTH:6,WEST+13"
|
||||
|
||||
//Ghosts
|
||||
#define ui_ghost_jumptomob "SOUTH:6,CENTER-3:24"
|
||||
#define ui_ghost_orbit "SOUTH:6,CENTER-2:24"
|
||||
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER-1:24"
|
||||
#define ui_ghost_teleport "SOUTH:6,CENTER:24"
|
||||
#define ui_ghost_pai "SOUTH: 6, CENTER+1:24"
|
||||
#define ui_ghost_mafia "SOUTH: 6, CENTER+2:24"
|
||||
#define ui_ghost_spawners "SOUTH: 6, CENTER+1:24" // LEGACY. SAME LOC AS PAI
|
||||
|
||||
#define ui_ghost_jumptomob "SOUTH:6,CENTER-2:24"
|
||||
#define ui_ghost_orbit "SOUTH:6,CENTER-1:24"
|
||||
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24"
|
||||
#define ui_ghost_teleport "SOUTH:6,CENTER+1:24"
|
||||
#define ui_ghost_spawners "SOUTH: 6, CENTER+2:24"
|
||||
// #define ui_wanted_lvl "NORTH,11"
|
||||
|
||||
|
||||
//UI position overrides for 1:1 screen layout. (default is 7:5)
|
||||
|
||||
@@ -38,9 +38,6 @@
|
||||
/obj/screen/plane_master/proc/shadow(_size, _offset = 0, _x = 0, _y = 0, _color = "#04080FAA")
|
||||
filters += filter(type = "drop_shadow", x = _x, y = _y, color = _color, size = _size, offset = _offset)
|
||||
|
||||
/obj/screen/plane_master/proc/clear_filters()
|
||||
filters = list()
|
||||
|
||||
///Contains just the floor
|
||||
/obj/screen/plane_master/floor
|
||||
name = "floor plane master"
|
||||
|
||||
+112
-75
@@ -68,57 +68,17 @@
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.uneq_active()
|
||||
|
||||
/obj/screen/robot/lamp
|
||||
name = "headlamp"
|
||||
icon_state = "lamp0"
|
||||
|
||||
/obj/screen/robot/lamp/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.control_headlamp()
|
||||
|
||||
/obj/screen/robot/thrusters
|
||||
name = "ion thrusters"
|
||||
icon_state = "ionpulse0"
|
||||
|
||||
/obj/screen/robot/thrusters/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_ionpulse()
|
||||
|
||||
/obj/screen/robot/sensors
|
||||
name = "Sensor Augmentation"
|
||||
icon_state = "cyborg_sensor"
|
||||
|
||||
/obj/screen/robot/sensors/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/S = usr
|
||||
S.toggle_sensors()
|
||||
|
||||
/obj/screen/robot/language_menu
|
||||
name = "silicon language selection"
|
||||
icon_state = "talk_wheel"
|
||||
|
||||
/obj/screen/robot/language_menu/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/S = usr
|
||||
S.open_language_menu(usr)
|
||||
|
||||
/datum/hud/robot
|
||||
ui_style = 'icons/mob/screen_cyborg.dmi'
|
||||
|
||||
/datum/hud/robot/New(mob/owner)
|
||||
..()
|
||||
var/mob/living/silicon/robot/mymobR = mymob
|
||||
// i, Robit
|
||||
var/mob/living/silicon/robot/robit = mymob
|
||||
var/obj/screen/using
|
||||
|
||||
using = new/obj/screen/robot/language_menu
|
||||
using = new/obj/screen/language_menu
|
||||
using.screen_loc = ui_borg_language_menu
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
|
||||
//Radio
|
||||
@@ -128,56 +88,72 @@
|
||||
static_inventory += using
|
||||
|
||||
//Module select
|
||||
using = new /obj/screen/robot/module1()
|
||||
using.screen_loc = ui_inv1
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
mymobR.inv1 = using
|
||||
if(!robit.inv1)
|
||||
robit.inv1 = new /obj/screen/robot/module1()
|
||||
|
||||
using = new /obj/screen/robot/module2()
|
||||
using.screen_loc = ui_inv2
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
mymobR.inv2 = using
|
||||
robit.inv1.screen_loc = ui_inv1
|
||||
robit.inv1.hud = src
|
||||
static_inventory += robit.inv1
|
||||
|
||||
using = new /obj/screen/robot/module3()
|
||||
using.screen_loc = ui_inv3
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
mymobR.inv3 = using
|
||||
if(!robit.inv2)
|
||||
robit.inv2 = new /obj/screen/robot/module2()
|
||||
|
||||
robit.inv2.screen_loc = ui_inv2
|
||||
robit.inv2.hud = src
|
||||
static_inventory += robit.inv2
|
||||
|
||||
if(!robit.inv3)
|
||||
robit.inv3 = new /obj/screen/robot/module3()
|
||||
|
||||
robit.inv3.screen_loc = ui_inv3
|
||||
robit.inv3.hud = src
|
||||
static_inventory += robit.inv3
|
||||
|
||||
//End of module select
|
||||
|
||||
using = new /obj/screen/robot/lamp()
|
||||
using.screen_loc = ui_borg_lamp
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
robit.lampButton = using
|
||||
var/obj/screen/robot/lamp/lampscreen = using
|
||||
lampscreen.robot = robit
|
||||
|
||||
//Photography stuff
|
||||
using = new /obj/screen/ai/image_take()
|
||||
using.screen_loc = ui_borg_camera
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
|
||||
using = new /obj/screen/ai/image_view()
|
||||
using.screen_loc = ui_borg_album
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
|
||||
//Sec/Med HUDs
|
||||
using = new /obj/screen/robot/sensors()
|
||||
using.screen_loc = ui_borg_sensor
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
|
||||
//Headlamp control
|
||||
using = new /obj/screen/robot/lamp()
|
||||
using.screen_loc = ui_borg_lamp
|
||||
//Borg Integrated Tablet
|
||||
using = new /obj/screen/robot/modPC()
|
||||
using.screen_loc = ui_borg_tablet
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
robit.interfaceButton = using
|
||||
if(robit.modularInterface)
|
||||
using.vis_contents += robit.modularInterface
|
||||
var/obj/screen/robot/modPC/tabletbutton = using
|
||||
tabletbutton.robot = robit
|
||||
|
||||
//Alerts
|
||||
using = new /obj/screen/robot/alerts()
|
||||
using.screen_loc = ui_borg_alerts
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
mymobR.lamp_button = using
|
||||
|
||||
//Thrusters
|
||||
using = new /obj/screen/robot/thrusters()
|
||||
using.screen_loc = ui_borg_thrusters
|
||||
using.hud = src
|
||||
static_inventory += using
|
||||
mymobR.thruster_button = using
|
||||
robit.thruster_button = using
|
||||
|
||||
//Intent
|
||||
action_intent = new /obj/screen/act_intent/robot()
|
||||
@@ -191,20 +167,21 @@
|
||||
infodisplay += healths
|
||||
|
||||
//Installed Module
|
||||
mymobR.hands = new /obj/screen/robot/module()
|
||||
mymobR.hands.screen_loc = ui_borg_module
|
||||
static_inventory += mymobR.hands
|
||||
robit.hands = new /obj/screen/robot/module()
|
||||
robit.hands.screen_loc = ui_borg_module
|
||||
robit.hands.hud = src
|
||||
static_inventory += robit.hands
|
||||
|
||||
//Store
|
||||
module_store_icon = new /obj/screen/robot/store()
|
||||
module_store_icon.hud = src
|
||||
module_store_icon.screen_loc = ui_borg_store
|
||||
module_store_icon.hud = src
|
||||
|
||||
pull_icon = new /obj/screen/pull()
|
||||
pull_icon.icon = 'icons/mob/screen_cyborg.dmi'
|
||||
pull_icon.screen_loc = ui_borg_pull
|
||||
pull_icon.hud = src
|
||||
pull_icon.update_icon()
|
||||
pull_icon.screen_loc = ui_borg_pull
|
||||
hotkeybuttons += pull_icon
|
||||
|
||||
|
||||
@@ -242,13 +219,13 @@
|
||||
screenmob.client.screen += module_store_icon //"store" icon
|
||||
|
||||
if(!R.module.modules)
|
||||
to_chat(usr, "<span class='danger'>Selected module has no modules to select</span>")
|
||||
to_chat(usr, "<span class='warning'>Selected module has no modules to select!</span>")
|
||||
return
|
||||
|
||||
if(!R.robot_modules_background)
|
||||
return
|
||||
|
||||
var/display_rows = CEILING(length(R.module.get_inactive_modules()) / 8, 1)
|
||||
var/display_rows = max(CEILING(length(R.module.get_inactive_modules()) / 8, 1),1)
|
||||
R.robot_modules_background.screen_loc = "CENTER-4:16,SOUTH+1:7 to CENTER+3:16,SOUTH+[display_rows]:7"
|
||||
screenmob.client.screen += R.robot_modules_background
|
||||
|
||||
@@ -305,3 +282,63 @@
|
||||
else
|
||||
for(var/obj/item/I in R.held_items)
|
||||
screenmob.client.screen -= I
|
||||
|
||||
/obj/screen/robot/lamp
|
||||
name = "headlamp"
|
||||
icon_state = "lamp_off"
|
||||
var/mob/living/silicon/robot/robot
|
||||
|
||||
/obj/screen/robot/lamp/Click()
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
robot?.toggle_headlamp()
|
||||
update_icon()
|
||||
|
||||
/obj/screen/robot/lamp/update_icon()
|
||||
if(robot?.lamp_enabled)
|
||||
icon_state = "lamp_on"
|
||||
else
|
||||
icon_state = "lamp_off"
|
||||
|
||||
/obj/screen/robot/alerts
|
||||
name = "Alert Panel"
|
||||
icon = 'icons/mob/screen_ai.dmi'
|
||||
icon_state = "alerts"
|
||||
|
||||
/obj/screen/robot/alerts/Click()
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/living/silicon/robot/borgo = usr
|
||||
borgo.robot_alerts()
|
||||
|
||||
/obj/screen/robot/thrusters
|
||||
name = "ion thrusters"
|
||||
icon_state = "ionpulse0"
|
||||
|
||||
/obj/screen/robot/thrusters/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
R.toggle_ionpulse()
|
||||
|
||||
/obj/screen/robot/sensors
|
||||
name = "Sensor Augmentation"
|
||||
icon_state = "cyborg_sensor"
|
||||
|
||||
/obj/screen/robot/sensors/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/S = usr
|
||||
S.toggle_sensors()
|
||||
/obj/screen/robot/modPC
|
||||
name = "Modular Interface"
|
||||
icon_state = "template"
|
||||
var/mob/living/silicon/robot/robot
|
||||
|
||||
/obj/screen/robot/modPC/Click()
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
robot.modularInterface?.interact(robot)
|
||||
|
||||
@@ -97,6 +97,9 @@
|
||||
M.lastattacker = user.real_name
|
||||
M.lastattackerckey = user.ckey
|
||||
|
||||
if(force && M == user && user.client)
|
||||
user.client.give_award(/datum/award/achievement/misc/selfouch, user)
|
||||
|
||||
user.do_attack_animation(M)
|
||||
M.attacked_by(src, user, attackchain_flags, damage_multiplier)
|
||||
|
||||
|
||||
@@ -415,7 +415,7 @@ Example config:
|
||||
while(recent_round)
|
||||
adjustment += repeated_mode_adjust[recent_round]
|
||||
recent_round = SSpersistence.saved_modes.Find(name,recent_round+1,0)
|
||||
probability *= ((100-adjustment)/100)
|
||||
probability *= max(0,((100-adjustment)/100))
|
||||
runnable_storytellers[S] = probability
|
||||
return runnable_storytellers
|
||||
|
||||
@@ -448,7 +448,7 @@ Example config:
|
||||
while(recent_round)
|
||||
adjustment += repeated_mode_adjust[recent_round]
|
||||
recent_round = SSpersistence.saved_modes.Find(M.config_tag,recent_round+1,0)
|
||||
final_weight *= ((100-adjustment)/100)
|
||||
final_weight *= max(0,((100-adjustment)/100))
|
||||
runnable_modes[M] = final_weight
|
||||
return runnable_modes
|
||||
|
||||
|
||||
@@ -22,11 +22,10 @@
|
||||
|
||||
/datum/config_entry/string/cross_comms_name
|
||||
|
||||
/datum/config_entry/string/medal_hub_address
|
||||
|
||||
/datum/config_entry/string/medal_hub_password
|
||||
protection = CONFIG_ENTRY_HIDDEN
|
||||
/datum/config_entry/string/cross_comms_network
|
||||
protection = CONFIG_ENTRY_LOCKED
|
||||
|
||||
/// cit config
|
||||
/datum/config_entry/keyed_list/cross_server_bunker_override
|
||||
key_mode = KEY_MODE_TEXT
|
||||
value_mode = VALUE_MODE_TEXT
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
SUBSYSTEM_DEF(achievements)
|
||||
name = "Achievements"
|
||||
flags = SS_NO_FIRE
|
||||
init_order = INIT_ORDER_ACHIEVEMENTS
|
||||
var/achievements_enabled = FALSE
|
||||
|
||||
///List of achievements
|
||||
var/list/datum/award/achievement/achievements = list()
|
||||
///List of scores
|
||||
var/list/datum/award/score/scores = list()
|
||||
///List of all awards
|
||||
var/list/datum/award/awards = list()
|
||||
|
||||
/datum/controller/subsystem/achievements/Initialize(timeofday)
|
||||
if(!SSdbcore.Connect())
|
||||
return ..()
|
||||
achievements_enabled = TRUE
|
||||
|
||||
for(var/T in subtypesof(/datum/award/achievement))
|
||||
var/instance = new T
|
||||
achievements[T] = instance
|
||||
awards[T] = instance
|
||||
|
||||
for(var/T in subtypesof(/datum/award/score))
|
||||
var/instance = new T
|
||||
scores[T] = instance
|
||||
awards[T] = instance
|
||||
|
||||
update_metadata()
|
||||
|
||||
for(var/i in GLOB.clients)
|
||||
var/client/C = i
|
||||
if(!C.player_details.achievements.initialized)
|
||||
C.player_details.achievements.InitializeData()
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/achievements/Shutdown()
|
||||
save_achievements_to_db()
|
||||
|
||||
/datum/controller/subsystem/achievements/proc/save_achievements_to_db()
|
||||
var/list/cheevos_to_save = list()
|
||||
for(var/ckey in GLOB.player_details)
|
||||
var/datum/player_details/PD = GLOB.player_details[ckey]
|
||||
if(!PD || !PD.achievements)
|
||||
continue
|
||||
cheevos_to_save += PD.achievements.get_changed_data()
|
||||
if(!length(cheevos_to_save))
|
||||
return
|
||||
SSdbcore.MassInsert(format_table_name("achievements"),cheevos_to_save,duplicate_key = TRUE)
|
||||
|
||||
//Update the metadata if any are behind
|
||||
/datum/controller/subsystem/achievements/proc/update_metadata()
|
||||
var/list/current_metadata = list()
|
||||
//select metadata here
|
||||
var/datum/db_query/Q = SSdbcore.NewQuery("SELECT achievement_key,achievement_version FROM [format_table_name("achievement_metadata")]")
|
||||
if(!Q.Execute(async = TRUE))
|
||||
qdel(Q)
|
||||
return
|
||||
else
|
||||
while(Q.NextRow())
|
||||
current_metadata[Q.item[1]] = text2num(Q.item[2])
|
||||
qdel(Q)
|
||||
|
||||
var/list/to_update = list()
|
||||
for(var/T in awards)
|
||||
var/datum/award/A = awards[T]
|
||||
if(!A.database_id)
|
||||
continue
|
||||
if(!current_metadata[A.database_id] || current_metadata[A.database_id] < A.achievement_version)
|
||||
to_update += list(A.get_metadata_row())
|
||||
|
||||
if(to_update.len)
|
||||
SSdbcore.MassInsert(format_table_name("achievement_metadata"),to_update,duplicate_key = TRUE)
|
||||
@@ -1,6 +1,8 @@
|
||||
/*! How material datums work
|
||||
Materials are now instanced datums, with an associative list of them being kept in SSmaterials. We only instance the materials once and then re-use these instances for everything.
|
||||
|
||||
These materials call on_applied() on whatever item they are applied to, common effects are adding components, changing color and changing description. This allows us to differentiate items based on the material they are made out of.area
|
||||
|
||||
*/
|
||||
|
||||
SUBSYSTEM_DEF(materials)
|
||||
@@ -14,12 +16,16 @@ SUBSYSTEM_DEF(materials)
|
||||
var/list/materialtypes_by_category
|
||||
///A cache of all material combinations that have been used
|
||||
var/list/list/material_combos
|
||||
///List of stackcrafting recipes for materials using rigid materials
|
||||
///List of stackcrafting recipes for materials using base recipes
|
||||
var/list/base_stack_recipes = list(
|
||||
new /datum/stack_recipe("Chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE),
|
||||
new /datum/stack_recipe("Toilet", /obj/structure/toilet/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE),
|
||||
new /datum/stack_recipe("Sink Frame", /obj/structure/sink/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE),
|
||||
new /datum/stack_recipe("Floor tile", /obj/item/stack/tile/material, 1, 4, 20, applies_mats = TRUE),
|
||||
)
|
||||
///List of stackcrafting recipes for materials using rigid recipes
|
||||
var/list/rigid_stack_recipes = list(
|
||||
new /datum/stack_recipe("chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE),
|
||||
new /datum/stack_recipe("toilet", /obj/structure/toilet/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE),
|
||||
new /datum/stack_recipe("sink", /obj/structure/sink/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE),
|
||||
new /datum/stack_recipe("Floor tile", /obj/item/stack/tile/material, 1, 4, 20, applies_mats = TRUE)
|
||||
// new /datum/stack_recipe("Carving block", /obj/structure/carving_block, 5, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE),
|
||||
)
|
||||
|
||||
///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info)
|
||||
@@ -29,7 +35,11 @@ SUBSYSTEM_DEF(materials)
|
||||
materialtypes_by_category = list()
|
||||
material_combos = list()
|
||||
for(var/type in subtypesof(/datum/material))
|
||||
var/datum/material/ref = new type
|
||||
var/datum/material/ref = type
|
||||
// if(!(initial(ref.init_flags) & MATERIAL_INIT_MAPLOAD))
|
||||
// continue // Do not initialize
|
||||
|
||||
ref = new ref
|
||||
materials[type] = ref
|
||||
for(var/c in ref.categories)
|
||||
materials_by_category[c] += list(ref)
|
||||
@@ -40,7 +50,6 @@ SUBSYSTEM_DEF(materials)
|
||||
InitializeMaterials()
|
||||
return materials[fakemat] || fakemat
|
||||
|
||||
|
||||
///Returns a list to be used as an object's custom_materials. Lists will be cached and re-used based on the parameters.
|
||||
/datum/controller/subsystem/materials/proc/FindOrCreateMaterialCombo(list/materials_declaration, multiplier)
|
||||
if(!material_combos)
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
SUBSYSTEM_DEF(medals)
|
||||
name = "Medals"
|
||||
flags = SS_NO_FIRE
|
||||
var/hub_enabled = FALSE
|
||||
|
||||
/datum/controller/subsystem/medals/Initialize(timeofday)
|
||||
if(CONFIG_GET(string/medal_hub_address) && CONFIG_GET(string/medal_hub_password))
|
||||
hub_enabled = TRUE
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/medals/proc/UnlockMedal(medal, client/player)
|
||||
set waitfor = FALSE
|
||||
if(!medal || !hub_enabled)
|
||||
return
|
||||
if(isnull(world.SetMedal(medal, player, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))))
|
||||
hub_enabled = FALSE
|
||||
log_game("MEDAL ERROR: Could not contact hub to award medal:[medal] player:[player.key]")
|
||||
message_admins("Error! Failed to contact hub to award [medal] medal to [player.key]!")
|
||||
return
|
||||
to_chat(player, "<span class='greenannounce'><B>Achievement unlocked: [medal]!</B></span>")
|
||||
|
||||
|
||||
/datum/controller/subsystem/medals/proc/SetScore(score, client/player, increment, force)
|
||||
set waitfor = FALSE
|
||||
if(!score || !hub_enabled)
|
||||
return
|
||||
|
||||
var/list/oldscore = GetScore(score, player, TRUE)
|
||||
if(increment)
|
||||
if(!oldscore[score])
|
||||
oldscore[score] = 1
|
||||
else
|
||||
oldscore[score] = (text2num(oldscore[score]) + 1)
|
||||
else
|
||||
oldscore[score] = force
|
||||
|
||||
var/newscoreparam = list2params(oldscore)
|
||||
|
||||
if(isnull(world.SetScores(player.ckey, newscoreparam, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))))
|
||||
hub_enabled = FALSE
|
||||
log_game("SCORE ERROR: Could not contact hub to set score. Score:[score] player:[player.key]")
|
||||
message_admins("Error! Failed to contact hub to set [score] score for [player.key]!")
|
||||
|
||||
/datum/controller/subsystem/medals/proc/GetScore(score, client/player, returnlist)
|
||||
if(!score || !hub_enabled)
|
||||
return
|
||||
|
||||
var/scoreget = world.GetScores(player.ckey, score, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))
|
||||
if(isnull(scoreget))
|
||||
hub_enabled = FALSE
|
||||
log_game("SCORE ERROR: Could not contact hub to get score. Score:[score] player:[player.key]")
|
||||
message_admins("Error! Failed to contact hub to get score: [score] for [player.key]!")
|
||||
return
|
||||
. = params2list(scoreget)
|
||||
if(!returnlist)
|
||||
return .[score]
|
||||
|
||||
/datum/controller/subsystem/medals/proc/CheckMedal(medal, client/player)
|
||||
if(!medal || !hub_enabled)
|
||||
return
|
||||
|
||||
if(isnull(world.GetMedal(medal, player, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))))
|
||||
hub_enabled = FALSE
|
||||
log_game("MEDAL ERROR: Could not contact hub to get medal:[medal] player: [player.key]")
|
||||
message_admins("Error! Failed to contact hub to get [medal] medal for [player.key]!")
|
||||
return
|
||||
to_chat(player, "[medal] is unlocked")
|
||||
|
||||
/datum/controller/subsystem/medals/proc/LockMedal(medal, client/player)
|
||||
if(!player || !medal || !hub_enabled)
|
||||
return
|
||||
var/result = world.ClearMedal(medal, player, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))
|
||||
switch(result)
|
||||
if(null)
|
||||
hub_enabled = FALSE
|
||||
log_game("MEDAL ERROR: Could not contact hub to clear medal:[medal] player:[player.key]")
|
||||
message_admins("Error! Failed to contact hub to clear [medal] medal for [player.key]!")
|
||||
if(TRUE)
|
||||
message_admins("Medal: [medal] removed for [player.key]")
|
||||
if(FALSE)
|
||||
message_admins("Medal: [medal] was not found for [player.key]. Unable to clear.")
|
||||
|
||||
|
||||
/datum/controller/subsystem/medals/proc/ClearScore(client/player)
|
||||
if(isnull(world.SetScores(player.ckey, "", CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))))
|
||||
log_game("MEDAL ERROR: Could not contact hub to clear scores for [player.key]!")
|
||||
message_admins("Error! Failed to contact hub to clear scores for [player.key]!")
|
||||
@@ -70,3 +70,8 @@ PROCESSING_SUBSYSTEM_DEF(weather)
|
||||
A = W
|
||||
break
|
||||
return A
|
||||
|
||||
/datum/controller/subsystem/processing/weather/proc/get_weather_by_type(datum/weather/weather_datum_type)
|
||||
for(var/V in processing)
|
||||
if(istype(V,weather_datum_type))
|
||||
return V
|
||||
|
||||
@@ -12,6 +12,10 @@ SUBSYSTEM_DEF(shuttle)
|
||||
var/list/beacons = list()
|
||||
var/list/transit = list()
|
||||
|
||||
//Now it only for ID generation
|
||||
var/list/assoc_mobile = list()
|
||||
var/list/assoc_stationary = list()
|
||||
|
||||
var/list/transit_requesters = list()
|
||||
var/list/transit_request_failures = list()
|
||||
|
||||
@@ -26,6 +30,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
var/emergencyCallAmount = 0 //how many times the escape shuttle was called
|
||||
var/emergencyNoEscape
|
||||
var/emergencyNoRecall = FALSE
|
||||
var/adminEmergencyNoRecall = FALSE
|
||||
var/list/hostileEnvironments = list() //Things blocking escape shuttle from leaving
|
||||
var/list/tradeBlockade = list() //Things blocking cargo from leaving.
|
||||
var/supplyBlocked = FALSE
|
||||
@@ -65,6 +70,8 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
var/datum/turf_reservation/preview_reservation
|
||||
|
||||
var/shuttle_loading
|
||||
|
||||
/datum/controller/subsystem/shuttle/Initialize(timeofday)
|
||||
ordernum = rand(1, 9000)
|
||||
|
||||
@@ -134,7 +141,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
break
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/CheckAutoEvac()
|
||||
if(emergencyNoEscape || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted())
|
||||
if(emergencyNoEscape || adminEmergencyNoRecall || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted())
|
||||
return
|
||||
|
||||
var/threshold = CONFIG_GET(number/emergency_shuttle_autocall_threshold)
|
||||
@@ -179,31 +186,26 @@ SUBSYSTEM_DEF(shuttle)
|
||||
return S
|
||||
WARNING("couldn't find dock with id: [id]")
|
||||
|
||||
/// Check if we can call the evac shuttle.
|
||||
/// Returns TRUE if we can. Otherwise, returns a string detailing the problem.
|
||||
/datum/controller/subsystem/shuttle/proc/canEvac(mob/user)
|
||||
var/srd = CONFIG_GET(number/shuttle_refuel_delay)
|
||||
if(world.time - SSticker.round_start_time < srd)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.</span>")
|
||||
return FALSE
|
||||
return "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before attempting to call."
|
||||
|
||||
switch(emergency.mode)
|
||||
if(SHUTTLE_RECALL)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle may not be called while returning to CentCom.</span>")
|
||||
return FALSE
|
||||
return "The emergency shuttle may not be called while returning to CentCom."
|
||||
if(SHUTTLE_CALL)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is already on its way.</span>")
|
||||
return FALSE
|
||||
return "The emergency shuttle is already on its way."
|
||||
if(SHUTTLE_DOCKED)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is already here.</span>")
|
||||
return FALSE
|
||||
return "The emergency shuttle is already here."
|
||||
if(SHUTTLE_IGNITING)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is firing its engines to leave.</span>")
|
||||
return FALSE
|
||||
return "The emergency shuttle is firing its engines to leave."
|
||||
if(SHUTTLE_ESCAPE)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle is moving away to a safe distance.</span>")
|
||||
return FALSE
|
||||
return "The emergency shuttle is moving away to a safe distance."
|
||||
if(SHUTTLE_STRANDED)
|
||||
to_chat(user, "<span class='alert'>The emergency shuttle has been disabled by CentCom.</span>")
|
||||
return FALSE
|
||||
return "The emergency shuttle has been disabled by CentCom."
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -221,7 +223,9 @@ SUBSYSTEM_DEF(shuttle)
|
||||
Good luck.")
|
||||
emergency = backup_shuttle
|
||||
|
||||
if(!canEvac(user))
|
||||
var/can_evac_or_fail_reason = SSshuttle.canEvac(user)
|
||||
if(can_evac_or_fail_reason != TRUE)
|
||||
to_chat(user, "<span class='alert'>[can_evac_or_fail_reason]</span>")
|
||||
return
|
||||
|
||||
call_reason = trim(html_encode(call_reason))
|
||||
@@ -250,10 +254,11 @@ SUBSYSTEM_DEF(shuttle)
|
||||
var/area/A = get_area(user)
|
||||
|
||||
log_shuttle("[key_name(user)] has called the emergency shuttle.")
|
||||
deadchat_broadcast(" has called the shuttle at <span class='name'>[A.name]</span>.", "<span class='name'>[user.real_name]</span>", user)
|
||||
deadchat_broadcast(" has called the shuttle at <span class='name'>[A.name]</span>.", "<span class='name'>[user.real_name]</span>", user) //, message_type=DEADCHAT_ANNOUNCEMENT)
|
||||
if(call_reason)
|
||||
SSblackbox.record_feedback("text", "shuttle_reason", 1, "[call_reason]")
|
||||
log_shuttle("Shuttle call reason: [call_reason]")
|
||||
SSticker.emergency_reason = call_reason
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has called the shuttle. (<A HREF='?_src_=holder;[HrefToken()];trigger_centcom_recall=1'>TRIGGER CENTCOM RECALL</A>)")
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/centcom_recall(old_timer, admiral_message)
|
||||
@@ -288,7 +293,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
emergency.cancel(get_area(user))
|
||||
log_shuttle("[key_name(user)] has recalled the shuttle.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] has recalled the shuttle.")
|
||||
deadchat_broadcast(" has recalled the shuttle from <span class='name'>[get_area_name(user, TRUE)]</span>.", "<span class='name'>[user.real_name]</span>", user)
|
||||
deadchat_broadcast(" has recalled the shuttle from <span class='name'>[get_area_name(user, TRUE)]</span>.", "<span class='name'>[user.real_name]</span>", user) //, message_type=DEADCHAT_ANNOUNCEMENT)
|
||||
return 1
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/canRecall()
|
||||
@@ -314,7 +319,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if (!SSticker.IsRoundInProgress())
|
||||
return
|
||||
|
||||
var/callShuttle = 1
|
||||
var/callShuttle = TRUE
|
||||
|
||||
for(var/thing in GLOB.shuttle_caller_list)
|
||||
if(isAI(thing))
|
||||
@@ -330,7 +335,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
var/turf/T = get_turf(thing)
|
||||
if(T && is_station_level(T.z))
|
||||
callShuttle = 0
|
||||
callShuttle = FALSE
|
||||
break
|
||||
|
||||
if(callShuttle)
|
||||
@@ -406,7 +411,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
else
|
||||
if(M.initiate_docking(getDock(destination)) != DOCKING_SUCCESS)
|
||||
return 2
|
||||
return 0 //dock successful
|
||||
return 0 //dock successful
|
||||
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/moveShuttle(shuttleId, dockId, timed)
|
||||
@@ -664,7 +669,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
emergencyNoRecall = TRUE
|
||||
endvote_passed = TRUE
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/action_load(datum/map_template/shuttle/loading_template, obj/docking_port/stationary/destination_port)
|
||||
/datum/controller/subsystem/shuttle/proc/action_load(datum/map_template/shuttle/loading_template, obj/docking_port/stationary/destination_port, replace = FALSE)
|
||||
// Check for an existing preview
|
||||
if(preview_shuttle && (loading_template != preview_template))
|
||||
preview_shuttle.jumpToNullSpace()
|
||||
@@ -673,8 +678,8 @@ SUBSYSTEM_DEF(shuttle)
|
||||
QDEL_NULL(preview_reservation)
|
||||
|
||||
if(!preview_shuttle)
|
||||
if(load_template(loading_template))
|
||||
preview_shuttle.linkup(loading_template, destination_port)
|
||||
load_template(loading_template)
|
||||
// preview_shuttle.linkup(loading_template, destination_port)
|
||||
preview_template = loading_template
|
||||
|
||||
// get the existing shuttle information, if any
|
||||
@@ -684,7 +689,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
if(istype(destination_port))
|
||||
D = destination_port
|
||||
else if(existing_shuttle)
|
||||
else if(existing_shuttle && replace)
|
||||
timer = existing_shuttle.timer
|
||||
mode = existing_shuttle.mode
|
||||
D = existing_shuttle.get_docked()
|
||||
@@ -703,11 +708,12 @@ SUBSYSTEM_DEF(shuttle)
|
||||
WARNING("Template shuttle [preview_shuttle] cannot dock at [D] ([result]).")
|
||||
return
|
||||
|
||||
if(existing_shuttle)
|
||||
if(existing_shuttle && replace)
|
||||
existing_shuttle.jumpToNullSpace()
|
||||
|
||||
var/list/force_memory = preview_shuttle.movement_force
|
||||
preview_shuttle.movement_force = list("KNOCKDOWN" = 0, "THROW" = 0)
|
||||
preview_shuttle.mode = SHUTTLE_PREARRIVAL//No idle shuttle moving. Transit dock get removed if shuttle moves too long.
|
||||
preview_shuttle.initiate_docking(D)
|
||||
preview_shuttle.movement_force = force_memory
|
||||
|
||||
@@ -718,7 +724,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
preview_shuttle.timer = timer
|
||||
preview_shuttle.mode = mode
|
||||
|
||||
preview_shuttle.register()
|
||||
preview_shuttle.register(replace)
|
||||
|
||||
// TODO indicate to the user that success happened, rather than just
|
||||
// blanking the modification tab
|
||||
@@ -848,7 +854,8 @@ SUBSYSTEM_DEF(shuttle)
|
||||
return data
|
||||
|
||||
/datum/controller/subsystem/shuttle/ui_act(action, params)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/mob/user = usr
|
||||
@@ -891,22 +898,10 @@ SUBSYSTEM_DEF(shuttle)
|
||||
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[M.name]")
|
||||
break
|
||||
|
||||
if("preview")
|
||||
if(S)
|
||||
. = TRUE
|
||||
unload_preview()
|
||||
load_template(S)
|
||||
if(preview_shuttle)
|
||||
preview_template = S
|
||||
user.forceMove(get_turf(preview_shuttle))
|
||||
if("load")
|
||||
if(existing_shuttle == backup_shuttle)
|
||||
// TODO make the load button disabled
|
||||
WARNING("The shuttle that the selected shuttle will replace \
|
||||
is the backup shuttle. Backup shuttle is required to be \
|
||||
intact for round sanity.")
|
||||
else if(S)
|
||||
if(S && !shuttle_loading)
|
||||
. = TRUE
|
||||
shuttle_loading = TRUE
|
||||
// If successful, returns the mobile docking port
|
||||
var/obj/docking_port/mobile/mdp = action_load(S)
|
||||
if(mdp)
|
||||
@@ -914,3 +909,38 @@ SUBSYSTEM_DEF(shuttle)
|
||||
message_admins("[key_name_admin(usr)] loaded [mdp] with the shuttle manipulator.")
|
||||
log_admin("[key_name(usr)] loaded [mdp] with the shuttle manipulator.</span>")
|
||||
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[mdp.name]")
|
||||
shuttle_loading = FALSE
|
||||
|
||||
if("preview")
|
||||
//if(preview_shuttle && (loading_template != preview_template))
|
||||
if(S && !shuttle_loading)
|
||||
. = TRUE
|
||||
shuttle_loading = TRUE
|
||||
unload_preview()
|
||||
load_template(S)
|
||||
if(preview_shuttle)
|
||||
preview_template = S
|
||||
user.forceMove(get_turf(preview_shuttle))
|
||||
shuttle_loading = FALSE
|
||||
|
||||
if("replace")
|
||||
if(existing_shuttle == backup_shuttle)
|
||||
// TODO make the load button disabled
|
||||
WARNING("The shuttle that the selected shuttle will replace \
|
||||
is the backup shuttle. Backup shuttle is required to be \
|
||||
intact for round sanity.")
|
||||
else if(S && !shuttle_loading)
|
||||
. = TRUE
|
||||
shuttle_loading = TRUE
|
||||
// If successful, returns the mobile docking port
|
||||
var/obj/docking_port/mobile/mdp = action_load(S, replace = TRUE)
|
||||
if(mdp)
|
||||
user.forceMove(get_turf(mdp))
|
||||
message_admins("[key_name_admin(usr)] load/replaced [mdp] with the shuttle manipulator.")
|
||||
log_admin("[key_name(usr)] load/replaced [mdp] with the shuttle manipulator.</span>")
|
||||
SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[mdp.name]")
|
||||
shuttle_loading = FALSE
|
||||
if(emergency == mdp) //you just changed the emergency shuttle, there are events in game + captains that can change your snowflake choice.
|
||||
var/set_purchase = alert(usr, "Do you want to also disable shuttle purchases/random events that would change the shuttle?", "Butthurt Admin Prevention", "Yes, disable purchases/events", "No, I want to possibly get owned")
|
||||
if(set_purchase == "Yes, disable purchases/events")
|
||||
SSshuttle.shuttle_purchased = SHUTTLEPURCHASE_FORCED
|
||||
|
||||
@@ -1,32 +1,63 @@
|
||||
#define OCCLUSION_DISTANCE 20
|
||||
|
||||
/datum/sun
|
||||
var/azimuth = 0 // clockwise, top-down rotation from 0 (north) to 359
|
||||
var/power_mod = 1 // how much power this sun is outputting relative to standard
|
||||
|
||||
|
||||
/datum/sun/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
if(var_name == NAMEOF(src, azimuth))
|
||||
SSsun.complete_movement()
|
||||
|
||||
/atom/proc/check_obscured(datum/sun/sun, distance = OCCLUSION_DISTANCE)
|
||||
var/target_x = round(sin(sun.azimuth), 0.01)
|
||||
var/target_y = round(cos(sun.azimuth), 0.01)
|
||||
var/x_hit = x
|
||||
var/y_hit = y
|
||||
var/turf/hit
|
||||
|
||||
for(var/run in 1 to distance)
|
||||
x_hit += target_x
|
||||
y_hit += target_y
|
||||
hit = locate(round(x_hit, 1), round(y_hit, 1), z)
|
||||
if(hit.opacity)
|
||||
return TRUE
|
||||
if(hit.x == 1 || hit.x == world.maxx || hit.y == 1 || hit.y == world.maxy) //edge of the map
|
||||
break
|
||||
return FALSE
|
||||
|
||||
SUBSYSTEM_DEF(sun)
|
||||
name = "Sun"
|
||||
wait = 1 MINUTES
|
||||
flags = SS_NO_TICK_CHECK
|
||||
|
||||
var/azimuth = 0 ///clockwise, top-down rotation from 0 (north) to 359
|
||||
var/list/datum/sun/suns = list()
|
||||
var/datum/sun/primary_sun
|
||||
var/azimuth_mod = 1 ///multiplier against base_rotation
|
||||
var/base_rotation = 6 ///base rotation in degrees per fire
|
||||
|
||||
/datum/controller/subsystem/sun/Initialize(start_timeofday)
|
||||
azimuth = rand(0, 359)
|
||||
primary_sun = new
|
||||
suns += primary_sun
|
||||
primary_sun.azimuth = rand(0, 359)
|
||||
azimuth_mod = round(rand(50, 200)/100, 0.01) // 50% - 200% of standard rotation
|
||||
if(prob(50))
|
||||
azimuth_mod *= -1
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/sun/fire(resumed = FALSE)
|
||||
azimuth += azimuth_mod * base_rotation
|
||||
azimuth = round(azimuth, 0.01)
|
||||
if(azimuth >= 360)
|
||||
azimuth -= 360
|
||||
if(azimuth < 0)
|
||||
azimuth += 360
|
||||
for(var/S in suns)
|
||||
var/datum/sun/sun = S
|
||||
sun.azimuth += azimuth_mod * base_rotation
|
||||
sun.azimuth = round(sun.azimuth, 0.01)
|
||||
if(sun.azimuth >= 360)
|
||||
sun.azimuth -= 360
|
||||
if(sun.azimuth < 0)
|
||||
sun.azimuth += 360
|
||||
complete_movement()
|
||||
|
||||
/datum/controller/subsystem/sun/proc/complete_movement()
|
||||
SEND_SIGNAL(src, COMSIG_SUN_MOVED, azimuth)
|
||||
SEND_SIGNAL(src, COMSIG_SUN_MOVED, primary_sun, suns)
|
||||
|
||||
/datum/controller/subsystem/sun/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
if(var_name == NAMEOF(src, azimuth))
|
||||
complete_movement()
|
||||
#undef OCCLUSION_DISTANCE
|
||||
|
||||
@@ -69,6 +69,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
var/modevoted = FALSE //Have we sent a vote for the gamemode?
|
||||
|
||||
var/station_integrity = 100 // stored at roundend for use in some antag goals
|
||||
var/emergency_reason
|
||||
|
||||
/datum/controller/subsystem/ticker/Initialize(timeofday)
|
||||
load_mode()
|
||||
@@ -563,7 +564,10 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(STATION_DESTROYED_NUKE)
|
||||
news_message = "We would like to reassure all employees that the reports of a Syndicate backed nuclear attack on [station_name()] are, in fact, a hoax. Have a secure day!"
|
||||
if(STATION_EVACUATED)
|
||||
news_message = "The crew of [station_name()] has been evacuated amid unconfirmed reports of enemy activity."
|
||||
if(emergency_reason)
|
||||
news_message = "[station_name()] has been evacuated after transmitting the following distress beacon:\n\n[emergency_reason]"
|
||||
else
|
||||
news_message = "The crew of [station_name()] has been evacuated amid unconfirmed reports of enemy activity."
|
||||
if(BLOB_WIN)
|
||||
news_message = "[station_name()] was overcome by an unknown biological outbreak, killing all crew on board. Don't let it happen to you! Remember, a clean work station is a safe work station."
|
||||
if(BLOB_NUKE)
|
||||
@@ -589,7 +593,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(WIZARD_KILLED)
|
||||
news_message = "Tensions have flared with the Space Wizard Federation following the death of one of their members aboard [station_name()]."
|
||||
if(STATION_NUKED)
|
||||
news_message = "[station_name()] activated its self destruct device for unknown reasons. Attempts to clone the Captain so he can be arrested and executed are underway."
|
||||
news_message = "[station_name()] activated its self-destruct device for unknown reasons. Attempts to clone the Captain so he can be arrested and executed are underway."
|
||||
if(CLOCK_SUMMON)
|
||||
news_message = "The garbled messages about hailing a mouse and strange energy readings from [station_name()] have been discovered to be an ill-advised, if thorough, prank by a clown."
|
||||
if(CLOCK_SILICONS)
|
||||
@@ -604,7 +608,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(SSblackbox.first_death)
|
||||
var/list/ded = SSblackbox.first_death
|
||||
if(ded.len)
|
||||
news_message += " NT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[ded["last_words"] ? " Their last words were: \"[ded["last_words"]]\"" : ""]"
|
||||
var/last_words = ded["last_words"] ? " Their last words were: \"[ded["last_words"]]\"" : ""
|
||||
news_message += " NT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]"
|
||||
else
|
||||
news_message += " NT Sanctioned Psykers proudly confirm reports that nobody died this shift!"
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
///Datum that handles
|
||||
/datum/achievement_data
|
||||
///Ckey of this achievement data's owner
|
||||
var/owner_ckey
|
||||
///Up to date list of all achievements and their info.
|
||||
var/data = list()
|
||||
///Original status of achievement.
|
||||
var/original_cached_data = list()
|
||||
///Have we done our set-up yet?
|
||||
var/initialized = FALSE
|
||||
|
||||
/datum/achievement_data/New(ckey)
|
||||
owner_ckey = ckey
|
||||
if(SSachievements.initialized && !initialized)
|
||||
InitializeData()
|
||||
|
||||
/datum/achievement_data/proc/InitializeData()
|
||||
initialized = TRUE
|
||||
load_all_achievements() //So we know which achievements we have unlocked so far.
|
||||
|
||||
///Gets list of changed rows in MassInsert format
|
||||
/datum/achievement_data/proc/get_changed_data()
|
||||
. = list()
|
||||
for(var/T in data)
|
||||
var/datum/award/A = SSachievements.awards[T]
|
||||
if(data[T] != original_cached_data[T])//If our data from before is not the same as now, save it to db.
|
||||
var/deets = A.get_changed_rows(owner_ckey,data[T])
|
||||
if(deets)
|
||||
. += list(deets)
|
||||
|
||||
/datum/achievement_data/proc/load_all_achievements()
|
||||
set waitfor = FALSE
|
||||
|
||||
var/list/kv = list()
|
||||
var/datum/db_query/Query = SSdbcore.NewQuery(
|
||||
"SELECT achievement_key,value FROM [format_table_name("achievements")] WHERE ckey = :ckey",
|
||||
list("ckey" = owner_ckey)
|
||||
)
|
||||
if(!Query.Execute())
|
||||
qdel(Query)
|
||||
return
|
||||
while(Query.NextRow())
|
||||
var/key = Query.item[1]
|
||||
var/value = text2num(Query.item[2])
|
||||
kv[key] = value
|
||||
qdel(Query)
|
||||
|
||||
for(var/T in subtypesof(/datum/award))
|
||||
var/datum/award/A = SSachievements.awards[T]
|
||||
if(!A || !A.name) //Skip abstract achievements types
|
||||
continue
|
||||
if(!data[T])
|
||||
data[T] = A.parse_value(kv[A.database_id])
|
||||
original_cached_data[T] = data[T]
|
||||
|
||||
///Updates local cache with db data for the given achievement type if it wasn't loaded yet.
|
||||
/datum/achievement_data/proc/get_data(achievement_type)
|
||||
var/datum/award/A = SSachievements.awards[achievement_type]
|
||||
if(!A.name)
|
||||
return FALSE
|
||||
if(!data[achievement_type])
|
||||
data[achievement_type] = A.load(owner_ckey)
|
||||
original_cached_data[achievement_type] = data[achievement_type]
|
||||
|
||||
///Unlocks an achievement of a specific type. achievement type is a typepath to the award, user is the mob getting the award, and value is an optional value to be used for defining a score to add to the leaderboard
|
||||
/datum/achievement_data/proc/unlock(achievement_type, mob/user, value = 1)
|
||||
set waitfor = FALSE
|
||||
|
||||
if(!SSachievements.achievements_enabled)
|
||||
return
|
||||
var/datum/award/A = SSachievements.awards[achievement_type]
|
||||
get_data(achievement_type) //Get the current status first if necessary
|
||||
if(istype(A, /datum/award/achievement))
|
||||
if(data[achievement_type]) //You already unlocked it so don't bother running the unlock proc
|
||||
return
|
||||
data[achievement_type] = TRUE
|
||||
A.on_unlock(user) //Only on default achievement, as scores keep going up.
|
||||
else if(istype(A, /datum/award/score))
|
||||
data[achievement_type] += value
|
||||
|
||||
///Getter for the status/score of an achievement
|
||||
/datum/achievement_data/proc/get_achievement_status(achievement_type)
|
||||
return data[achievement_type]
|
||||
|
||||
///Resets an achievement to default values.
|
||||
/datum/achievement_data/proc/reset(achievement_type)
|
||||
if(!SSachievements.achievements_enabled)
|
||||
return
|
||||
var/datum/award/A = SSachievements.awards[achievement_type]
|
||||
get_data(achievement_type)
|
||||
if(istype(A, /datum/award/achievement))
|
||||
data[achievement_type] = FALSE
|
||||
else if(istype(A, /datum/award/score))
|
||||
data[achievement_type] = 0
|
||||
|
||||
/datum/achievement_data/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/spritesheet/simple/achievements),
|
||||
)
|
||||
|
||||
/datum/achievement_data/ui_state(mob/user)
|
||||
return GLOB.always_state
|
||||
|
||||
/datum/achievement_data/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Achievements")
|
||||
ui.open()
|
||||
|
||||
/datum/achievement_data/ui_data(mob/user)
|
||||
var/ret_data = list() // screw standards (qustinnus you must rename src.data ok)
|
||||
ret_data["categories"] = list("Bosses", "Misc", "Mafia", "Scores")
|
||||
ret_data["achievements"] = list()
|
||||
ret_data["user_key"] = user.ckey
|
||||
|
||||
var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/achievements)
|
||||
//This should be split into static data later
|
||||
for(var/achievement_type in SSachievements.awards)
|
||||
if(!SSachievements.awards[achievement_type].name) //No name? we a subtype.
|
||||
continue
|
||||
if(isnull(data[achievement_type])) //We're still loading
|
||||
continue
|
||||
var/list/this = list(
|
||||
"name" = SSachievements.awards[achievement_type].name,
|
||||
"desc" = SSachievements.awards[achievement_type].desc,
|
||||
"category" = SSachievements.awards[achievement_type].category,
|
||||
"icon_class" = assets.icon_class_name(SSachievements.awards[achievement_type].icon),
|
||||
"value" = data[achievement_type],
|
||||
"score" = ispath(achievement_type,/datum/award/score)
|
||||
)
|
||||
ret_data["achievements"] += list(this)
|
||||
|
||||
return ret_data
|
||||
|
||||
/datum/achievement_data/ui_static_data(mob/user)
|
||||
. = ..()
|
||||
.["highscore"] = list()
|
||||
for(var/score in SSachievements.scores)
|
||||
var/datum/award/score/S = SSachievements.scores[score]
|
||||
if(!S.name || !S.track_high_scores || !S.high_scores.len)
|
||||
continue
|
||||
.["highscore"] += list(list("name" = S.name,"scores" = S.high_scores))
|
||||
|
||||
/client/verb/checkachievements()
|
||||
set category = "OOC"
|
||||
set name = "Check achievements"
|
||||
set desc = "See all of your achievements!"
|
||||
|
||||
player_details.achievements.ui_interact(usr)
|
||||
@@ -0,0 +1,117 @@
|
||||
/datum/award
|
||||
///Name of the achievement, If null it won't show up in the achievement browser. (Handy for inheritance trees)
|
||||
var/name
|
||||
var/desc = "You did it."
|
||||
///Found in UI_Icons/Achievements
|
||||
var/icon = "default"
|
||||
var/category = "Normal"
|
||||
|
||||
///What ID do we use in db, limited to 32 characters
|
||||
var/database_id
|
||||
//Bump this up if you're changing outdated table identifier and/or achievement type
|
||||
var/achievement_version = 2
|
||||
|
||||
//Value returned on db connection failure, in case we want to differ 0 and nonexistent later on
|
||||
var/default_value = FALSE
|
||||
|
||||
///This proc loads the achievement data from the hub.
|
||||
/datum/award/proc/load(key)
|
||||
if(!SSdbcore.Connect())
|
||||
return default_value
|
||||
if(!key || !database_id || !name)
|
||||
return default_value
|
||||
var/raw_value = get_raw_value(key)
|
||||
return parse_value(raw_value)
|
||||
|
||||
///This saves the changed data to the hub.
|
||||
/datum/award/proc/get_changed_rows(key, value)
|
||||
if(!database_id || !key || !name)
|
||||
return
|
||||
return list(
|
||||
"ckey" = key,
|
||||
"achievement_key" = database_id,
|
||||
"value" = value,
|
||||
)
|
||||
|
||||
/datum/award/proc/get_metadata_row()
|
||||
return list(
|
||||
"achievement_key" = database_id,
|
||||
"achievement_version" = achievement_version,
|
||||
"achievement_type" = "award",
|
||||
"achievement_name" = name,
|
||||
"achievement_description" = desc,
|
||||
)
|
||||
|
||||
///Get raw numerical achievement value from the database
|
||||
/datum/award/proc/get_raw_value(key)
|
||||
var/datum/db_query/Q = SSdbcore.NewQuery(
|
||||
"SELECT value FROM [format_table_name("achievements")] WHERE ckey = :ckey AND achievement_key = :achievement_key",
|
||||
list("ckey" = key, "achievement_key" = database_id)
|
||||
)
|
||||
if(!Q.Execute(async = TRUE))
|
||||
qdel(Q)
|
||||
return 0
|
||||
var/result = 0
|
||||
if(Q.NextRow())
|
||||
result = text2num(Q.item[1])
|
||||
qdel(Q)
|
||||
return result
|
||||
|
||||
//Should return sanitized value for achievement cache
|
||||
/datum/award/proc/parse_value(raw_value)
|
||||
return default_value
|
||||
|
||||
///Can be overriden for achievement specific events
|
||||
/datum/award/proc/on_unlock(mob/user)
|
||||
return
|
||||
|
||||
///Achievements are one-off awards for usually doing cool things.
|
||||
/datum/award/achievement
|
||||
desc = "Achievement for epic people"
|
||||
|
||||
/datum/award/achievement/get_metadata_row()
|
||||
. = ..()
|
||||
.["achievement_type"] = "achievement"
|
||||
|
||||
/datum/award/achievement/parse_value(raw_value)
|
||||
return raw_value > 0
|
||||
|
||||
/datum/award/achievement/on_unlock(mob/user)
|
||||
. = ..()
|
||||
to_chat(user, "<span class='greenannounce'><B>Achievement unlocked: [name]!</B></span>")
|
||||
|
||||
///Scores are for leaderboarded things, such as killcount of a specific boss
|
||||
/datum/award/score
|
||||
desc = "you did it sooo many times."
|
||||
category = "Scores"
|
||||
default_value = 0
|
||||
|
||||
var/track_high_scores = TRUE
|
||||
var/list/high_scores = list()
|
||||
|
||||
/datum/award/score/New()
|
||||
. = ..()
|
||||
if(track_high_scores)
|
||||
LoadHighScores()
|
||||
|
||||
/datum/award/score/get_metadata_row()
|
||||
. = ..()
|
||||
.["achievement_type"] = "score"
|
||||
|
||||
/datum/award/score/proc/LoadHighScores()
|
||||
var/datum/db_query/Q = SSdbcore.NewQuery(
|
||||
"SELECT ckey,value FROM [format_table_name("achievements")] WHERE achievement_key = :achievement_key ORDER BY value DESC LIMIT 50",
|
||||
list("achievement_key" = database_id)
|
||||
)
|
||||
if(!Q.Execute(async = TRUE))
|
||||
qdel(Q)
|
||||
return
|
||||
else
|
||||
while(Q.NextRow())
|
||||
var/key = Q.item[1]
|
||||
var/score = text2num(Q.item[2])
|
||||
high_scores[key] = score
|
||||
qdel(Q)
|
||||
|
||||
/datum/award/score/parse_value(raw_value)
|
||||
return isnum(raw_value) ? raw_value : 0
|
||||
@@ -0,0 +1,130 @@
|
||||
/datum/award/achievement/boss
|
||||
category = "Bosses"
|
||||
icon = "baseboss"
|
||||
|
||||
/datum/award/achievement/boss/tendril_exterminator
|
||||
name = "Tendril Exterminator"
|
||||
desc = "Watch your step"
|
||||
database_id = BOSS_MEDAL_TENDRIL
|
||||
icon = "tendril"
|
||||
|
||||
/datum/award/achievement/boss/boss_killer
|
||||
name = "Boss Killer"
|
||||
desc = "You've come a long ways from asking how to switch hands."
|
||||
database_id = "Boss Killer"
|
||||
// icon = "firstboss"
|
||||
|
||||
/datum/award/achievement/boss/blood_miner_kill
|
||||
name = "Blood-Drunk Miner Killer"
|
||||
desc = "I guess he couldn't handle his drink that well."
|
||||
database_id = BOSS_MEDAL_MINER
|
||||
icon = "miner"
|
||||
|
||||
/datum/award/achievement/boss/demonic_miner_kill
|
||||
name = "Demonic-Frost Miner Killer"
|
||||
desc = "Definitely harder than the Blood-Drunk Miner."
|
||||
database_id = BOSS_MEDAL_FROSTMINER
|
||||
|
||||
/datum/award/achievement/boss/bubblegum_kill
|
||||
name = "Bubblegum Killer"
|
||||
desc = "I guess he wasn't made of candy after all"
|
||||
database_id = BOSS_MEDAL_BUBBLEGUM
|
||||
icon = "bbgum"
|
||||
|
||||
/datum/award/achievement/boss/colossus_kill
|
||||
name = "Colossus Killer"
|
||||
desc = "The bigger they are... the better the loot"
|
||||
database_id = BOSS_MEDAL_COLOSSUS
|
||||
icon = "colossus"
|
||||
|
||||
/datum/award/achievement/boss/drake_kill
|
||||
name = "Drake Killer"
|
||||
desc = "Now I can wear Rune Platebodies!"
|
||||
database_id = BOSS_MEDAL_DRAKE
|
||||
icon = "drake"
|
||||
|
||||
/datum/award/achievement/boss/hierophant_kill
|
||||
name = "Hierophant Killer"
|
||||
desc = "Hierophant, but not triumphant."
|
||||
database_id = BOSS_MEDAL_HIEROPHANT
|
||||
icon = "hierophant"
|
||||
|
||||
/datum/award/achievement/boss/legion_kill
|
||||
name = "Legion Killer"
|
||||
desc = "We were many..now we are none."
|
||||
database_id = BOSS_MEDAL_LEGION
|
||||
icon = "legion"
|
||||
|
||||
/datum/award/achievement/boss/swarmer_beacon_kill
|
||||
name = "Swarm Beacon Killer"
|
||||
desc = "GET THEM OFF OF ME!"
|
||||
database_id = BOSS_MEDAL_SWARMERS
|
||||
icon = "swarmer"
|
||||
|
||||
/datum/award/achievement/boss/wendigo_kill
|
||||
name = "Wendigo Killer"
|
||||
desc = "You've now ruined years of mythical storytelling."
|
||||
database_id = BOSS_MEDAL_WENDIGO
|
||||
|
||||
/datum/award/achievement/boss/blood_miner_crusher
|
||||
name = "Blood-Drunk Miner Crusher"
|
||||
desc = "I guess he couldn't handle his drink that well."
|
||||
database_id = BOSS_MEDAL_MINER_CRUSHER
|
||||
icon = "miner"
|
||||
|
||||
/datum/award/achievement/boss/demonic_miner_crusher
|
||||
name = "Demonic-Frost Miner Crusher"
|
||||
desc = "Definitely harder than the Blood-Drunk Miner."
|
||||
database_id = BOSS_MEDAL_FROSTMINER_CRUSHER
|
||||
|
||||
/datum/award/achievement/boss/bubblegum_crusher
|
||||
name = "Bubblegum Crusher"
|
||||
desc = "I guess he wasn't made of candy after all"
|
||||
database_id = BOSS_MEDAL_BUBBLEGUM_CRUSHER
|
||||
icon = "bbgum"
|
||||
|
||||
/datum/award/achievement/boss/colossus_crusher
|
||||
name = "Colossus Crusher"
|
||||
desc = "The bigger they are... the better the loot"
|
||||
database_id = BOSS_MEDAL_COLOSSUS_CRUSHER
|
||||
icon = "colossus"
|
||||
|
||||
/datum/award/achievement/boss/drake_crusher
|
||||
name = "Drake Crusher"
|
||||
desc = "Now I can wear Rune Platebodies!"
|
||||
database_id = BOSS_MEDAL_DRAKE_CRUSHER
|
||||
icon = "drake"
|
||||
|
||||
/datum/award/achievement/boss/hierophant_crusher
|
||||
name = "Hierophant Crusher"
|
||||
desc = "Hierophant, but not triumphant."
|
||||
database_id = BOSS_MEDAL_HIEROPHANT_CRUSHER
|
||||
icon = "hierophant"
|
||||
|
||||
/datum/award/achievement/boss/legion_crusher
|
||||
name = "Legion Crusher"
|
||||
desc = "We were many... now we are none."
|
||||
database_id = BOSS_MEDAL_LEGION_CRUSHER
|
||||
|
||||
/datum/award/achievement/boss/swarmer_beacon_crusher
|
||||
name = "Swarm Beacon Crusher"
|
||||
desc = "GET THEM OFF OF ME!"
|
||||
database_id = BOSS_MEDAL_SWARMERS_CRUSHER
|
||||
|
||||
/datum/award/achievement/boss/wendigo_crusher
|
||||
name = "Wendigo Crusher"
|
||||
desc = "You've now ruined years of mythical storytelling."
|
||||
database_id = BOSS_MEDAL_WENDIGO_CRUSHER
|
||||
|
||||
//should be removed soon
|
||||
// /datum/award/achievement/boss/king_goat_kill
|
||||
// name = "King Goat Killer"
|
||||
// desc = "The king is dead, long live the king!"
|
||||
// database_id = BOSS_MEDAL_KINGGOAT
|
||||
// icon = "goatboss"
|
||||
|
||||
// /datum/award/achievement/boss/king_goat_crusher
|
||||
// name = "King Goat Crusher"
|
||||
// desc = "The king is dead, long live the king!"
|
||||
// database_id = BOSS_MEDAL_KINGGOAT_CRUSHER
|
||||
// icon = "goatboss"
|
||||
@@ -0,0 +1,54 @@
|
||||
/datum/award/score/tendril_score
|
||||
name = "Tendril Score"
|
||||
desc = "Watch your step"
|
||||
database_id = TENDRIL_CLEAR_SCORE
|
||||
|
||||
/datum/award/score/boss_score
|
||||
name = "Bosses Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = BOSS_SCORE
|
||||
|
||||
/datum/award/score/blood_miner_score
|
||||
name = "Blood-Drunk Miners Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = MINER_SCORE
|
||||
|
||||
/datum/award/score/demonic_miner_score
|
||||
name = "Demonic-Frost Miners Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = FROST_MINER_SCORE
|
||||
|
||||
/datum/award/score/bubblegum_score
|
||||
name = "Bubblegums Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = BUBBLEGUM_SCORE
|
||||
|
||||
/datum/award/score/colussus_score
|
||||
name = "Colossus Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = COLOSSUS_SCORE
|
||||
|
||||
/datum/award/score/drake_score
|
||||
name = "Drakes Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = DRAKE_SCORE
|
||||
|
||||
/datum/award/score/hierophant_score
|
||||
name = "Hierophants Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = HIEROPHANT_SCORE
|
||||
|
||||
/datum/award/score/legion_score
|
||||
name = "Legions Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = LEGION_SCORE
|
||||
|
||||
/datum/award/score/swarmer_beacon_score
|
||||
name = "Swarmer Beacons Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = SWARMER_BEACON_SCORE
|
||||
|
||||
/datum/award/score/wendigo_score
|
||||
name = "Wendigos Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = WENDIGO_SCORE
|
||||
@@ -0,0 +1,115 @@
|
||||
/datum/award/achievement/mafia
|
||||
category = "Mafia"
|
||||
icon = "basemafia"
|
||||
|
||||
///ALL THE ACHIEVEMENTS FOR WINNING A ROUND AS A ROLE///
|
||||
|
||||
/datum/award/achievement/mafia/assistant
|
||||
name = "Assistant Victory"
|
||||
desc = "If you got killed instead of someone more important, you just flexed the true strength of your \"\"\"\"role\"\"\"\"."
|
||||
database_id = MAFIA_MEDAL_ASSISTANT
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/detective
|
||||
name = "Detective Victory"
|
||||
desc = "If you did this with a Medical Doctor in the game, i'm not really that impressed."
|
||||
database_id = MAFIA_MEDAL_DETECTIVE
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/psychologist
|
||||
name = "Psychologist Victory"
|
||||
desc = "You learned how to not reveal someone random night one! Or... maybe you're just a lucky bastard."
|
||||
database_id = MAFIA_MEDAL_PSYCHOLOGIST
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/chaplain
|
||||
name = "Chaplain Victory"
|
||||
desc = "Useless... until the one night the thoughtfeeder confidently claims themselves as detective. Mafia's true bullshit detector."
|
||||
database_id = MAFIA_MEDAL_CHAPLAIN
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/md
|
||||
name = "Medical Doctor Victory"
|
||||
desc = "Congratulations on learning how to not talk!"
|
||||
database_id = MAFIA_MEDAL_MD
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/officer
|
||||
name = "Security Officer Victory"
|
||||
desc = "Don't worry, you can win this if you're dead! You... did use your ability to become dead, right?"
|
||||
database_id = MAFIA_MEDAL_OFFICER
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/lawyer
|
||||
name = "Lawyer Victory"
|
||||
desc = "Oh don't mind me, i'm just the worst rol- Oops, I just instantly ended the game."
|
||||
database_id = MAFIA_MEDAL_LAWYER
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/hop
|
||||
name = "Head of Personnel Victory"
|
||||
desc = "King of Assistants, waster of a single mafia's night, thrower of games."
|
||||
database_id = MAFIA_MEDAL_HOP
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/warden
|
||||
name = "Warden Victory"
|
||||
desc = "Make changelings think you're detective, go on lockdown, actual detective investigates you and dies. Cha cha real smooth!"
|
||||
database_id = MAFIA_MEDAL_WARDEN
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/hos
|
||||
name = "Head of Security Victory"
|
||||
desc = "Certified not shitcurity."
|
||||
database_id = MAFIA_MEDAL_HOS
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/changeling
|
||||
name = "Changeling Victory"
|
||||
desc = "I think the changelings are metacomming."
|
||||
database_id = MAFIA_MEDAL_CHANGELING
|
||||
icon = "mafia"
|
||||
|
||||
/datum/award/achievement/mafia/thoughtfeeder
|
||||
name = "Thoughtfeeder Victory"
|
||||
desc = "Clown's best friend. And Obsessed. And fugitive? Whose side are you on?!"
|
||||
database_id = MAFIA_MEDAL_THOUGHTFEEDER
|
||||
icon = "mafia"
|
||||
|
||||
/datum/award/achievement/mafia/traitor
|
||||
name = "Traitor Victory"
|
||||
desc = "Guys, we still have two more changelings to ki-!! TRAITOR VICTORY !!"
|
||||
database_id = MAFIA_MEDAL_TRAITOR
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/nightmare
|
||||
name = "Nightmare Victory"
|
||||
desc = "DID YOUR LIGHT FLICKER?!"
|
||||
database_id = MAFIA_MEDAL_NIGHTMARE
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/fugitive
|
||||
name = "Fugitive Victory"
|
||||
desc = "I'm just the description on an achievement, but if you end up having to choose between town and changelings, go changelings."
|
||||
database_id = MAFIA_MEDAL_FUGITIVE
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/obsessed
|
||||
name = "Obsessed Victory"
|
||||
desc = "You got your target lynched, so instead of being spiteful and annoying, you're just smug and annoying."
|
||||
database_id = MAFIA_MEDAL_OBSESSED
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/clown
|
||||
name = "Clown Victory"
|
||||
desc = "Did you know this works on traitors, despite their immunity? If you hit the jackpot and manage to kill one, they'll salt into the next dimension. Clown tips!"
|
||||
database_id = MAFIA_MEDAL_CLOWN
|
||||
icon = "neutral"
|
||||
|
||||
///ALL THE ACHIEVEMENTS FOR MISC MAFIA ODDITIES///
|
||||
|
||||
/datum/award/achievement/mafia/universally_hated
|
||||
name = "Universally Hated"
|
||||
desc = "Managed to get more than 12 votes when put up on trial, jesus christ."
|
||||
database_id = MAFIA_MEDAL_HATED
|
||||
icon = "hated"
|
||||
@@ -0,0 +1,161 @@
|
||||
/datum/award/achievement/misc
|
||||
category = "Misc"
|
||||
icon = "basemisc"
|
||||
|
||||
/datum/award/achievement/misc/meteor_examine
|
||||
name = "Your Life Before Your Eyes"
|
||||
desc = "Take a close look at hurtling space debris"
|
||||
database_id = MEDAL_METEOR
|
||||
icon = "meteors"
|
||||
|
||||
/datum/award/achievement/misc/pulse
|
||||
name = "Jackpot"
|
||||
desc = "Win a pulse rifle from an arcade machine"
|
||||
database_id = MEDAL_PULSE
|
||||
icon = "jackpot"
|
||||
|
||||
/datum/award/achievement/misc/time_waste
|
||||
name = "Time waster"
|
||||
desc = "Speak no evil, hear no evil, see just errors"
|
||||
database_id = MEDAL_TIMEWASTE
|
||||
icon = "timewaste"
|
||||
|
||||
/datum/award/achievement/misc/feat_of_strength
|
||||
name = "Feat of Strength"
|
||||
desc = "If the rod is immovable, is it passing you or are you passing it?"
|
||||
database_id = MEDAL_RODSUPLEX
|
||||
icon = "featofstrength"
|
||||
|
||||
/datum/award/achievement/misc/round_and_full
|
||||
name = "Round and Full"
|
||||
desc = "Well at least you aren't down the river, I hear they eat people there."
|
||||
database_id = MEDAL_CLOWNCARKING
|
||||
icon = "clownking"
|
||||
|
||||
/datum/award/achievement/misc/the_best_driver
|
||||
name = "The Best Driver"
|
||||
desc = "100 honks later"
|
||||
database_id = MEDAL_THANKSALOT
|
||||
icon = "clownthanks"
|
||||
|
||||
/datum/award/achievement/misc/helbitaljanken
|
||||
name = "Helbitaljanken"
|
||||
desc = "You janked hard"
|
||||
database_id = MEDAL_HELBITALJANKEN
|
||||
icon = "helbital"
|
||||
|
||||
/datum/award/achievement/misc/getting_an_upgrade
|
||||
name = "Getting an upgrade"
|
||||
desc = "Make your first unique material item!"
|
||||
database_id = MEDAL_MATERIALCRAFT
|
||||
|
||||
/datum/award/achievement/misc/rocket_holdup
|
||||
name = "Disk, Please!"
|
||||
desc = "Is the man currently pointing a loaded rocket launcher at your head point blank really dumb enough to pull the trigger? Do you really want to find out?"
|
||||
database_id = MEDAL_DISKPLEASE
|
||||
|
||||
/datum/award/achievement/misc/gamer
|
||||
name = "My Watchlist Status is Not Important"
|
||||
desc = "You may be under the impression that violent video games are a harmless pastime, but the security and medical personnel swarming your location with batons and knockout gas look like they disagree."
|
||||
database_id = MEDAL_GAMER
|
||||
|
||||
/datum/award/achievement/misc/vendor_squish
|
||||
name = "I Was a Teenage Anarchist"
|
||||
desc = "You were doing a great job sticking it to the system until that vending machine decided to fight back."
|
||||
database_id = MEDAL_VENDORSQUISH
|
||||
|
||||
/datum/award/achievement/misc/swirlie
|
||||
name = "A Bowl-d New World"
|
||||
desc = "There's a lot of grisly ways to kick it on the Spinward Periphery, but drowning to death in a toilet probably wasn't what you had in mind. Probably."
|
||||
database_id = MEDAL_SWIRLIE
|
||||
|
||||
/datum/award/achievement/misc/selfouch
|
||||
name = "How Do I Switch Hands???"
|
||||
desc = "If you saw someone casually club themselves upside the head with a toolbox anywhere in the galaxy but here, you'd probably be pretty concerned for them."
|
||||
database_id = MEDAL_SELFOUCH
|
||||
|
||||
/datum/award/achievement/misc/sandman
|
||||
name = "Mister Sandman"
|
||||
desc = "Mechanically speaking, there's no real benefit to being unconscious during surgery. Weird how insistent this doctor is about using the N2O anyway though, huh?"
|
||||
database_id = MEDAL_SANDMAN
|
||||
|
||||
/datum/award/achievement/misc/cleanboss
|
||||
name = "One Lean, Mean, Cleaning Machine"
|
||||
desc = "How does it feel to know that your workplace values a mop bucket on wheels more than you?" // i can do better than this give me time
|
||||
database_id = MEDAL_CLEANBOSS
|
||||
|
||||
/datum/award/achievement/misc/rule8
|
||||
name = "Rule 8"
|
||||
desc = "Call an admin this is ILLEGAL!!"
|
||||
database_id = MEDAL_RULE8
|
||||
icon = "rule8"
|
||||
|
||||
/datum/award/achievement/misc/speed_round
|
||||
name = "Long shift"
|
||||
desc = "Well, that didn't take long."
|
||||
database_id = MEDAL_LONGSHIFT
|
||||
icon = "longshift"
|
||||
|
||||
/datum/award/achievement/misc/snail
|
||||
name = "KKKiiilll mmmeee"
|
||||
desc = "You were a little too ambitious, but hey, I guess you're still alive?"
|
||||
database_id = MEDAL_SNAIL
|
||||
icon = "snail"
|
||||
|
||||
/datum/award/achievement/misc/lookoutsir
|
||||
name = "Look Out, Sir!"
|
||||
desc = "Either awarded for making the ultimate sacrifice for your comrades, or a really dumb attempt at grenade jumping."
|
||||
database_id = MEDAL_LOOKOUTSIR
|
||||
|
||||
/datum/award/achievement/misc/gottem
|
||||
name = "HA, GOTTEM"
|
||||
desc = "Made you look!"
|
||||
database_id = MEDAL_GOTTEM
|
||||
|
||||
/datum/award/achievement/misc/ascension
|
||||
name = "Ascension"
|
||||
desc = "Caedite eos. Novit enim Dominus qui sunt eius."
|
||||
database_id = MEDAL_ASCENSION
|
||||
icon = "ascension"
|
||||
|
||||
/datum/award/achievement/misc/frenching
|
||||
name = "Frenching"
|
||||
desc = "Just a taste, for science!"
|
||||
database_id = MEDAL_FRENCHING
|
||||
icon = "frenching"
|
||||
|
||||
/datum/award/achievement/misc/ash_ascension
|
||||
name = "Nightwatcher's Eyes"
|
||||
desc = "You've risen above the flames, became one with the ashes. You've been reborn as one with the Nightwatcher."
|
||||
database_id = MEDAL_ASH_ASCENSION
|
||||
icon = "ashascend"
|
||||
|
||||
/datum/award/achievement/misc/flesh_ascension
|
||||
name = "Vortex of Arms"
|
||||
desc = "You've became something more, something greater. A piece of the emperor resides within you, and you within him."
|
||||
database_id = MEDAL_FLESH_ASCENSION
|
||||
icon = "fleshascend"
|
||||
|
||||
/datum/award/achievement/misc/rust_ascension
|
||||
name = "Hills of Rust"
|
||||
desc = "You've summoned a piece of the Hill of rust, and so the Hills welcome you."
|
||||
database_id = MEDAL_RUST_ASCENSION
|
||||
icon = "rustascend"
|
||||
|
||||
/datum/award/achievement/misc/void_ascension
|
||||
name = "All that perish"
|
||||
desc = "Place of a different being, different time. Everything ends there... but maybe it is just the beginning?"
|
||||
database_id = MEDAL_VOID_ASCENSION
|
||||
icon = "voidascend"
|
||||
|
||||
/datum/award/achievement/misc/toolbox_soul
|
||||
name = "SOUL'd Out"
|
||||
desc = "My eternal soul was destroyed to make a toolbox look funny and all I got was this achievement..."
|
||||
database_id = MEDAL_TOOLBOX_SOUL
|
||||
icon = "toolbox_soul"
|
||||
|
||||
/datum/award/achievement/misc/chemistry_tut
|
||||
name = "Perfect chemistry blossom"
|
||||
desc = "Passed the chemistry tutorial with perfect purity!"
|
||||
database_id = MEDAL_CHEM_TUT
|
||||
icon = "chem_tut"
|
||||
@@ -0,0 +1,11 @@
|
||||
///How many times did we survive being a cripple?
|
||||
/datum/award/score/hardcore_random
|
||||
name = "Hardcore random points"
|
||||
desc = "Well, I might be a blind, deaf, crippled guy, but hey, at least I'm alive."
|
||||
database_id = HARDCORE_RANDOM_SCORE
|
||||
|
||||
///How many maintenance pills did you eat?
|
||||
/datum/award/score/maintenance_pill
|
||||
name = "Maintenance Pills Consumed"
|
||||
desc = "Wait why?"
|
||||
database_id = MAINTENANCE_PILL_SCORE
|
||||
@@ -0,0 +1,10 @@
|
||||
/datum/award/achievement/skill
|
||||
category = "Skills"
|
||||
icon = "baseskill"
|
||||
|
||||
/datum/award/achievement/skill/legendary_miner
|
||||
name = "Legendary miner"
|
||||
desc = "No mere rock can stop me!"
|
||||
database_id = MEDAL_LEGENDARY_MINER
|
||||
icon = "mining"
|
||||
|
||||
+88
-88
@@ -1,53 +1,53 @@
|
||||
/**
|
||||
*# Callback Datums
|
||||
*A datum that holds a proc to be called on another object, used to track proccalls to other objects
|
||||
*
|
||||
* ## USAGE
|
||||
*
|
||||
* ```
|
||||
* var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn)
|
||||
* var/timerid = addtimer(C, time, timertype)
|
||||
* you can also use the compiler define shorthand
|
||||
* var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype)
|
||||
* ```
|
||||
*
|
||||
* Note: proc strings can only be given for datum proc calls, global procs must be proc paths
|
||||
*
|
||||
* Also proc strings are strongly advised against because they don't compile error if the proc stops existing
|
||||
*
|
||||
* In some cases you can provide a shortform of the procname, see the proc typepath shortcuts documentation below
|
||||
*
|
||||
* ## INVOKING THE CALLBACK
|
||||
*`var/result = C.Invoke(args, to, add)` additional args are added after the ones given when the callback was created
|
||||
*
|
||||
* `var/result = C.InvokeAsync(args, to, add)` Asyncronous - returns . on the first sleep then continues on in the background
|
||||
* after the sleep/block ends, otherwise operates normally.
|
||||
*
|
||||
* ## PROC TYPEPATH SHORTCUTS
|
||||
* (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
|
||||
*
|
||||
* ### global proc while in another global proc:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(GLOBAL_PROC, .some_proc_here)`
|
||||
*
|
||||
* ### proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(src, .some_proc_here)`
|
||||
*
|
||||
* ### when the above doesn't apply:
|
||||
*.proc/procname
|
||||
*
|
||||
* `CALLBACK(src, .proc/some_proc_here)`
|
||||
*
|
||||
*
|
||||
* proc defined on a parent of a some type
|
||||
*
|
||||
* `/some/type/.proc/some_proc_here`
|
||||
*
|
||||
* Otherwise you must always provide the full typepath of the proc (/type/of/thing/proc/procname)
|
||||
*/
|
||||
*# Callback Datums
|
||||
*A datum that holds a proc to be called on another object, used to track proccalls to other objects
|
||||
*
|
||||
* ## USAGE
|
||||
*
|
||||
* ```
|
||||
* var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn)
|
||||
* var/timerid = addtimer(C, time, timertype)
|
||||
* you can also use the compiler define shorthand
|
||||
* var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype)
|
||||
* ```
|
||||
*
|
||||
* Note: proc strings can only be given for datum proc calls, global procs must be proc paths
|
||||
*
|
||||
* Also proc strings are strongly advised against because they don't compile error if the proc stops existing
|
||||
*
|
||||
* In some cases you can provide a shortform of the procname, see the proc typepath shortcuts documentation below
|
||||
*
|
||||
* ## INVOKING THE CALLBACK
|
||||
*`var/result = C.Invoke(args, to, add)` additional args are added after the ones given when the callback was created
|
||||
*
|
||||
* `var/result = C.InvokeAsync(args, to, add)` Asyncronous - returns . on the first sleep then continues on in the background
|
||||
* after the sleep/block ends, otherwise operates normally.
|
||||
*
|
||||
* ## PROC TYPEPATH SHORTCUTS
|
||||
* (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
|
||||
*
|
||||
* ### global proc while in another global proc:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(GLOBAL_PROC, .some_proc_here)`
|
||||
*
|
||||
* ### proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(src, .some_proc_here)`
|
||||
*
|
||||
* ### when the above doesn't apply:
|
||||
*.proc/procname
|
||||
*
|
||||
* `CALLBACK(src, .proc/some_proc_here)`
|
||||
*
|
||||
*
|
||||
* proc defined on a parent of a some type
|
||||
*
|
||||
* `/some/type/.proc/some_proc_here`
|
||||
*
|
||||
* Otherwise you must always provide the full typepath of the proc (/type/of/thing/proc/procname)
|
||||
*/
|
||||
/datum/callback
|
||||
|
||||
///The object we will be calling the proc on
|
||||
@@ -60,13 +60,13 @@
|
||||
var/datum/weakref/user
|
||||
|
||||
/**
|
||||
* Create a new callback datum
|
||||
*
|
||||
* Arguments
|
||||
* * thingtocall the object to call the proc on
|
||||
* * proctocall the proc to call on the target object
|
||||
* * ... an optional list of extra arguments to pass to the proc
|
||||
*/
|
||||
* Create a new callback datum
|
||||
*
|
||||
* Arguments
|
||||
* * thingtocall the object to call the proc on
|
||||
* * proctocall the proc to call on the target object
|
||||
* * ... an optional list of extra arguments to pass to the proc
|
||||
*/
|
||||
/datum/callback/New(thingtocall, proctocall, ...)
|
||||
if (thingtocall)
|
||||
object = thingtocall
|
||||
@@ -76,13 +76,13 @@
|
||||
if(usr)
|
||||
user = WEAKREF(usr)
|
||||
/**
|
||||
* Immediately Invoke proctocall on thingtocall, with waitfor set to false
|
||||
*
|
||||
* Arguments:
|
||||
* * thingtocall Object to call on
|
||||
* * proctocall Proc to call on that object
|
||||
* * ... optional list of arguments to pass as arguments to the proc being called
|
||||
*/
|
||||
* Immediately Invoke proctocall on thingtocall, with waitfor set to false
|
||||
*
|
||||
* Arguments:
|
||||
* * thingtocall Object to call on
|
||||
* * proctocall Proc to call on that object
|
||||
* * ... optional list of arguments to pass as arguments to the proc being called
|
||||
*/
|
||||
/world/proc/ImmediateInvokeAsync(thingtocall, proctocall, ...)
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -97,13 +97,13 @@
|
||||
call(thingtocall, proctocall)(arglist(calling_arguments))
|
||||
|
||||
/**
|
||||
* Invoke this callback
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
|
||||
*/
|
||||
* Invoke this callback
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via [WrapAdminProcCall][/proc/WrapAdminProcCall]
|
||||
*/
|
||||
/datum/callback/proc/Invoke(...)
|
||||
if(!usr)
|
||||
var/datum/weakref/W = user
|
||||
@@ -130,13 +130,13 @@
|
||||
return call(object, delegate)(arglist(calling_arguments))
|
||||
|
||||
/**
|
||||
* Invoke this callback async (waitfor=false)
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
|
||||
*/
|
||||
* Invoke this callback async (waitfor=false)
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
|
||||
*/
|
||||
/datum/callback/proc/InvokeAsync(...)
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
|
||||
/**
|
||||
Helper datum for the select callbacks proc
|
||||
*/
|
||||
*/
|
||||
/datum/callback_select
|
||||
var/list/finished
|
||||
var/pendingcount
|
||||
@@ -192,16 +192,16 @@
|
||||
finished[index] = rtn
|
||||
|
||||
/**
|
||||
* Runs a list of callbacks asyncronously, returning only when all have finished
|
||||
*
|
||||
* Callbacks can be repeated, to call it multiple times
|
||||
*
|
||||
* Arguments:
|
||||
* * list/callbacks the list of callbacks to be called
|
||||
* * list/callback_args the list of lists of arguments to pass into each callback
|
||||
* * savereturns Optionally save and return the list of returned values from each of the callbacks
|
||||
* * resolution The number of byond ticks between each time you check if all callbacks are complete
|
||||
*/
|
||||
* Runs a list of callbacks asyncronously, returning only when all have finished
|
||||
*
|
||||
* Callbacks can be repeated, to call it multiple times
|
||||
*
|
||||
* Arguments:
|
||||
* * list/callbacks the list of callbacks to be called
|
||||
* * list/callback_args the list of lists of arguments to pass into each callback
|
||||
* * savereturns Optionally save and return the list of returned values from each of the callbacks
|
||||
* * resolution The number of byond ticks between each time you check if all callbacks are complete
|
||||
*/
|
||||
/proc/callback_select(list/callbacks, list/callback_args, savereturns = TRUE, resolution = 1)
|
||||
if (!callbacks)
|
||||
return
|
||||
|
||||
@@ -10,25 +10,37 @@
|
||||
*/
|
||||
|
||||
/datum/component/material_container
|
||||
/// The total amount of materials this material container contains
|
||||
var/total_amount = 0
|
||||
/// The maximum amount of materials this material container can contain
|
||||
var/max_amount
|
||||
var/sheet_type
|
||||
/// Map of material ref -> amount
|
||||
var/list/materials //Map of key = material ref | Value = amount
|
||||
/// The list of materials that this material container can accept
|
||||
var/list/allowed_materials
|
||||
var/show_on_examine
|
||||
var/disable_attackby
|
||||
var/list/allowed_typecache
|
||||
/// The last main material that was inserted into this container
|
||||
var/last_inserted_id
|
||||
/// Whether or not this material container allows specific amounts from sheets to be inserted
|
||||
var/precise_insertion = FALSE
|
||||
/// A callback invoked before materials are inserted into this container
|
||||
var/datum/callback/precondition
|
||||
/// A callback invoked after materials are inserted into this container
|
||||
var/datum/callback/after_insert
|
||||
|
||||
/// Sets up the proper signals and fills the list of materials with the appropriate references.
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert, _disable_attackby)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
materials = list()
|
||||
max_amount = max(0, max_amt)
|
||||
show_on_examine = _show_on_examine
|
||||
disable_attackby = _disable_attackby
|
||||
|
||||
allowed_materials = mat_list || list()
|
||||
if(allowed_types)
|
||||
if(ispath(allowed_types) && allowed_types == /obj/item/stack)
|
||||
allowed_typecache = GLOB.typecache_stack
|
||||
@@ -38,14 +50,32 @@
|
||||
precondition = _precondition
|
||||
after_insert = _after_insert
|
||||
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/OnExamine)
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/on_attackby)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
|
||||
|
||||
for(var/mat in mat_list) //Make the assoc list ref | amount
|
||||
var/datum/material/M = SSmaterials.GetMaterialRef(mat)
|
||||
materials[M] = 0
|
||||
for(var/mat in mat_list) //Make the assoc list material reference -> amount
|
||||
var/mat_ref = SSmaterials.GetMaterialRef(mat)
|
||||
if(isnull(mat_ref))
|
||||
continue
|
||||
var/mat_amt = mat_list[mat]
|
||||
if(isnull(mat_amt))
|
||||
mat_amt = 0
|
||||
materials[mat_ref] += mat_amt
|
||||
|
||||
/datum/component/material_container/Destroy(force, silent)
|
||||
materials = null
|
||||
allowed_typecache = null
|
||||
// if(insertion_check)
|
||||
// QDEL_NULL(insertion_check)
|
||||
if(precondition)
|
||||
QDEL_NULL(precondition)
|
||||
if(after_insert)
|
||||
QDEL_NULL(after_insert)
|
||||
return ..()
|
||||
|
||||
/datum/component/material_container/proc/on_examine(datum/source, mob/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
|
||||
if(show_on_examine)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = I
|
||||
@@ -54,7 +84,9 @@
|
||||
examine_list += "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>"
|
||||
|
||||
/// Proc that allows players to fill the parent with mats
|
||||
/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user)
|
||||
/datum/component/material_container/proc/on_attackby(datum/source, obj/item/I, mob/living/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/list/tc = allowed_typecache
|
||||
if(disable_attackby)
|
||||
return
|
||||
@@ -63,48 +95,104 @@
|
||||
if(I.item_flags & ABSTRACT)
|
||||
return
|
||||
if((I.flags_1 & HOLOGRAM_1) || (I.item_flags & NO_MAT_REDEMPTION) || (tc && !is_type_in_typecache(I, tc)))
|
||||
// if(!(mat_container_flags & MATCONTAINER_SILENT))
|
||||
to_chat(user, "<span class='warning'>[parent] won't accept [I]!</span>")
|
||||
return
|
||||
. = COMPONENT_NO_AFTERATTACK
|
||||
var/datum/callback/pc = precondition
|
||||
if(pc && !pc.Invoke(user))
|
||||
return
|
||||
var/material_amount = get_item_material_amount(I)
|
||||
var/material_amount = get_item_material_amount(I) //, mat_container_flags)
|
||||
if(!material_amount)
|
||||
to_chat(user, "<span class='warning'>[I] does not contain sufficient materials to be accepted by [parent].</span>")
|
||||
return
|
||||
if((!precise_insertion || !GLOB.typecache_stack[I.type]) && !has_space(material_amount))
|
||||
to_chat(user, "<span class='warning'>[parent] has not enough space. Please remove materials from [parent] in order to insert more.</span>")
|
||||
to_chat(user, "<span class='warning'>[parent] is full. Please remove materials from [parent] in order to insert more.</span>")
|
||||
return
|
||||
user_insert(I, user)
|
||||
user_insert(I, user) //, mat_container_flags)
|
||||
|
||||
/// Proc used for when player inserts materials
|
||||
/datum/component/material_container/proc/user_insert(obj/item/I, mob/living/user)
|
||||
/datum/component/material_container/proc/user_insert(obj/item/I, mob/living/user, datum/component/remote_materials/remote = null)
|
||||
set waitfor = FALSE
|
||||
var/requested_amount
|
||||
var/active_held = user.get_active_held_item() // differs from I when using TK
|
||||
if(istype(I, /obj/item/stack) && precise_insertion)
|
||||
var/atom/current_parent = parent
|
||||
var/inserted = 0
|
||||
|
||||
//handle stacks specially
|
||||
if(istype(I, /obj/item/stack))
|
||||
var/atom/current_parent = remote ? remote.parent : parent //is the user using a remote materials component?
|
||||
var/obj/item/stack/S = I
|
||||
requested_amount = input(user, "How much do you want to insert?", "Inserting [S.singular_name]s") as num|null
|
||||
|
||||
//try to get ammount to use
|
||||
var/requested_amount
|
||||
if(precise_insertion)
|
||||
requested_amount = input(user, "How much do you want to insert?", "Inserting [S.singular_name]s") as num|null
|
||||
else
|
||||
requested_amount= S.amount
|
||||
|
||||
if(isnull(requested_amount) || (requested_amount <= 0))
|
||||
return
|
||||
if(QDELETED(I) || QDELETED(user) || QDELETED(src) || parent != current_parent || user.physical_can_use_topic(current_parent) < UI_INTERACTIVE || user.get_active_held_item() != active_held)
|
||||
if(QDELETED(I) || QDELETED(user) || QDELETED(src) || user.get_active_held_item() != active_held)
|
||||
return
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
to_chat(user, "<span class='warning'>[I] is stuck to you and cannot be placed into [parent].</span>")
|
||||
return
|
||||
var/inserted = insert_item(I, stack_amt = requested_amount)
|
||||
//are we still in range after the user input?
|
||||
if((remote ? remote.parent : parent) != current_parent || user.physical_can_use_topic(current_parent) < UI_INTERACTIVE)
|
||||
return
|
||||
inserted = insert_stack(S, requested_amount)
|
||||
else
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
to_chat(user, "<span class='warning'>[I] is stuck to you and cannot be placed into [parent].</span>")
|
||||
return
|
||||
inserted = insert_item(I)
|
||||
qdel(I)
|
||||
|
||||
if(inserted)
|
||||
to_chat(user, "<span class='notice'>You insert a material total of [inserted] into [parent].</span>")
|
||||
qdel(I)
|
||||
if(after_insert)
|
||||
after_insert.Invoke(I, last_inserted_id, inserted)
|
||||
else if(I == active_held)
|
||||
user.put_in_active_hand(I)
|
||||
if(remote && remote.after_insert)
|
||||
remote.after_insert.Invoke(I, last_inserted_id, inserted)
|
||||
|
||||
//Inserts a number of sheets from a stack, returns the amount of sheets used.
|
||||
/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt, multiplier = 1)
|
||||
if(isnull(amt))
|
||||
amt = S.amount
|
||||
|
||||
if(amt <= 0)
|
||||
return FALSE
|
||||
|
||||
if(amt > S.amount)
|
||||
amt = S.amount
|
||||
|
||||
var/material_amt = get_item_material_amount(S)
|
||||
if(!material_amt)
|
||||
return FALSE
|
||||
|
||||
//get max number of sheets we have room to add
|
||||
var/mat_per_sheet = material_amt/S.amount
|
||||
amt = min(amt, round((max_amount - total_amount) / (mat_per_sheet)))
|
||||
if(!amt)
|
||||
return FALSE
|
||||
|
||||
//add the mats and keep track of how much was added
|
||||
var/starting_total = total_amount
|
||||
for(var/MAT in materials)
|
||||
materials[MAT] += S.mats_per_unit[MAT] * amt * multiplier
|
||||
total_amount += S.mats_per_unit[MAT] * amt * multiplier
|
||||
var/total_added = total_amount - starting_total
|
||||
|
||||
//update last_inserted_id with mat making up majority of the stack
|
||||
var/primary_mat
|
||||
var/max_mat_value = 0
|
||||
for(var/MAT in materials)
|
||||
if(S.mats_per_unit[MAT] > max_mat_value)
|
||||
max_mat_value = S.mats_per_unit[MAT]
|
||||
primary_mat = MAT
|
||||
last_inserted_id = primary_mat
|
||||
|
||||
S.use(amt)
|
||||
return total_added
|
||||
|
||||
/// Proc specifically for inserting items, returns the amount of materials entered.
|
||||
/datum/component/material_container/proc/insert_item(obj/item/I, var/multiplier = 1, stack_amt)
|
||||
/datum/component/material_container/proc/insert_item(obj/item/I, var/multiplier = 1)
|
||||
if(QDELETED(I))
|
||||
return FALSE
|
||||
|
||||
@@ -117,16 +205,46 @@
|
||||
last_inserted_id = insert_item_materials(I, multiplier)
|
||||
return material_amount
|
||||
|
||||
/**
|
||||
* Inserts the relevant materials from an item into this material container.
|
||||
*
|
||||
* Arguments:
|
||||
* - [source][/obj/item]: The source of the materials we are inserting.
|
||||
* - multiplier: The multiplier for the materials being inserted.
|
||||
* - breakdown_flags: The breakdown bitflags that will be used to retrieve the materials from the source
|
||||
*/
|
||||
/datum/component/material_container/proc/insert_item_materials(obj/item/I, multiplier = 1)
|
||||
var/primary_mat
|
||||
var/max_mat_value = 0
|
||||
for(var/MAT in materials)
|
||||
materials[MAT] += I.custom_materials[MAT] * multiplier
|
||||
total_amount += I.custom_materials[MAT] * multiplier
|
||||
if(I.custom_materials[MAT] > max_mat_value)
|
||||
var/list/item_materials = I.custom_materials
|
||||
for(var/MAT in item_materials)
|
||||
if(!can_hold_material(MAT))
|
||||
continue
|
||||
materials[MAT] += item_materials[MAT] * multiplier
|
||||
total_amount += item_materials[MAT] * multiplier
|
||||
if(item_materials[MAT] > max_mat_value)
|
||||
max_mat_value = item_materials[MAT]
|
||||
primary_mat = MAT
|
||||
|
||||
return primary_mat
|
||||
|
||||
/**
|
||||
* The default check for whether we can add materials to this material container.
|
||||
*
|
||||
* Arguments:
|
||||
* - [mat][/atom/material]: The material we are checking for insertability.
|
||||
*/
|
||||
/datum/component/material_container/proc/can_hold_material(datum/material/mat)
|
||||
if(mat in allowed_typecache)
|
||||
return TRUE
|
||||
if(istype(mat) && ((mat.id in allowed_typecache) || (mat.type in allowed_materials)))
|
||||
allowed_materials += mat // This could get messy with passing lists by ref... but if you're doing that the list expansion is probably being taken care of elsewhere anyway...
|
||||
return TRUE
|
||||
// if(insertion_check?.Invoke(mat))
|
||||
// allowed_materials += mat
|
||||
// return TRUE
|
||||
return FALSE
|
||||
|
||||
/// For inserting an amount of material
|
||||
/datum/component/material_container/proc/insert_amount_mat(amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
@@ -135,6 +253,7 @@
|
||||
var/total_amount_saved = total_amount
|
||||
if(mat)
|
||||
materials[mat] += amt
|
||||
total_amount += amt
|
||||
else
|
||||
for(var/i in materials)
|
||||
materials[i] += amt
|
||||
|
||||
@@ -275,6 +275,11 @@
|
||||
else
|
||||
target.visible_message("<span class='danger'>[target] is hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!</span>", null, null, COMBAT_MESSAGE_RANGE, target)
|
||||
to_chat(target, "<span class='userdanger'>You're hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!</span>")
|
||||
|
||||
for(var/M in purple_hearts)
|
||||
var/mob/living/martyr = M
|
||||
if(martyr.stat == DEAD && martyr.client)
|
||||
martyr.client.give_award(/datum/award/achievement/misc/lookoutsir, martyr)
|
||||
UnregisterSignal(parent, COMSIG_PARENT_PREQDELETED)
|
||||
if(queued_delete)
|
||||
qdel(parent)
|
||||
|
||||
@@ -15,13 +15,15 @@ handles linking back and forth.
|
||||
var/category
|
||||
var/allow_standalone
|
||||
var/local_size = INFINITY
|
||||
var/datum/callback/after_insert
|
||||
|
||||
/datum/component/remote_materials/Initialize(category, mapload, allow_standalone = TRUE, force_connect = FALSE)
|
||||
/datum/component/remote_materials/Initialize(category, mapload, allow_standalone = TRUE, force_connect = FALSE, _after_insert)
|
||||
if (!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.category = category
|
||||
src.allow_standalone = allow_standalone
|
||||
after_insert = _after_insert
|
||||
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
|
||||
|
||||
@@ -67,7 +69,7 @@ handles linking back and forth.
|
||||
/datum/material/plastic,
|
||||
)
|
||||
|
||||
mat_container = parent.AddComponent(/datum/component/material_container, allowed_mats, local_size, allowed_types=/obj/item/stack)
|
||||
mat_container = parent.AddComponent(/datum/component/material_container, allowed_mats, local_size, allowed_types=/obj/item/stack, _after_insert = after_insert)
|
||||
|
||||
/datum/component/remote_materials/proc/set_local_size(size)
|
||||
local_size = size
|
||||
@@ -103,7 +105,7 @@ handles linking back and forth.
|
||||
return COMPONENT_NO_AFTERATTACK
|
||||
|
||||
else if(silo && istype(I, /obj/item/stack))
|
||||
if(silo.remote_attackby(parent, user, I))
|
||||
if(silo.remote_attackby(parent, user, I, src))
|
||||
return COMPONENT_NO_AFTERATTACK
|
||||
|
||||
/datum/component/remote_materials/proc/on_hold()
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
_S.add(can_insert)
|
||||
S.use(can_insert, TRUE)
|
||||
return TRUE
|
||||
return ..(S.change_stack(null, can_insert), override)
|
||||
I = S.split_stack(null, can_insert)
|
||||
return ..()
|
||||
|
||||
/datum/component/storage/concrete/stack/remove_from_storage(obj/item/I, atom/new_location)
|
||||
var/atom/real_location = real_location()
|
||||
|
||||
@@ -99,18 +99,18 @@
|
||||
falloff_exponent = 5
|
||||
volume = 50
|
||||
*/
|
||||
// /datum/looping_sound/computer
|
||||
// start_sound = 'sound/machines/computer/computer_start.ogg'
|
||||
// start_length = 7.2 SECONDS
|
||||
// start_volume = 10
|
||||
// mid_sounds = list('sound/machines/computer/computer_mid1.ogg'=1, 'sound/machines/computer/computer_mid2.ogg'=1)
|
||||
// mid_length = 1.8 SECONDS
|
||||
// end_sound = 'sound/machines/computer/computer_end.ogg'
|
||||
// end_volume = 10
|
||||
// volume = 2
|
||||
// falloff_exponent = 5 //Ultra quiet very fast
|
||||
// extra_range = -12
|
||||
// falloff_distance = 1 //Instant falloff after initial tile
|
||||
/datum/looping_sound/computer
|
||||
start_sound = 'sound/machines/computer/computer_start.ogg'
|
||||
start_length = 7.2 SECONDS
|
||||
start_volume = 10
|
||||
mid_sounds = list('sound/machines/computer/computer_mid1.ogg'=1, 'sound/machines/computer/computer_mid2.ogg'=1)
|
||||
mid_length = 1.8 SECONDS
|
||||
end_sound = 'sound/machines/computer/computer_end.ogg'
|
||||
end_volume = 10
|
||||
volume = 2
|
||||
falloff_exponent = 5 //Ultra quiet very fast
|
||||
extra_range = -12
|
||||
falloff_distance = 1 //Instant falloff after initial tile
|
||||
|
||||
// /datum/looping_sound/gravgen
|
||||
// mid_sounds = list('sound/machines/gravgen/gravgen_mid1.ogg'=1,'sound/machines/gravgen/gravgen_mid2.ogg'=1,'sound/machines/gravgen/gravgen_mid3.ogg'=1,'sound/machines/gravgen/gravgen_mid4.ogg'=1,)
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
D.visible_message("<span class='warning'>[A] locks [D] into a restraining position!</span>", \
|
||||
"<span class='userdanger'>[A] locks you into a restraining position!</span>")
|
||||
D.apply_damage(damage, STAMINA)
|
||||
D.Stun(100)
|
||||
D.Stun(10)
|
||||
restraining = TRUE
|
||||
addtimer(VARSET_CALLBACK(src, restraining, FALSE), 50, TIMER_UNIQUE)
|
||||
return TRUE
|
||||
@@ -175,7 +175,7 @@
|
||||
return TRUE
|
||||
if(CHECK_MOBILITY(D, MOBILITY_MOVE) || !restraining)
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
|
||||
if(damage >= stunthreshold)
|
||||
if(damage >= stunthreshold)
|
||||
I = D.get_active_held_item()
|
||||
D.visible_message("<span class='warning'>[A] strikes [D]'s jaw with their hand!</span>", \
|
||||
"<span class='userdanger'>[A] strikes your jaw, disorienting you!</span>")
|
||||
@@ -196,7 +196,8 @@
|
||||
log_combat(A, D, "knocked out (Chokehold)(CQC)")
|
||||
D.visible_message("<span class='danger'>[A] puts [D] into a chokehold!</span>", \
|
||||
"<span class='userdanger'>[A] puts you into a chokehold!</span>")
|
||||
D.SetSleeping(400)
|
||||
if(D.silent <= 10)
|
||||
D.silent = clamp(D.silent + 10, 0, 10)
|
||||
restraining = FALSE
|
||||
if(A.grab_state < GRAB_NECK)
|
||||
A.setGrabState(GRAB_NECK)
|
||||
@@ -213,7 +214,7 @@
|
||||
|
||||
to_chat(usr, "<span class='notice'>Slam</span>: Grab Harm. Slam opponent into the ground, knocking them down.")
|
||||
to_chat(usr, "<span class='notice'>CQC Kick</span>: Harm Harm. Knocks opponent away. Knocks out stunned or knocked down opponents.")
|
||||
to_chat(usr, "<span class='notice'>Restrain</span>: Grab Grab. Locks opponents into a restraining position, disarm to knock them out with a chokehold.")
|
||||
to_chat(usr, "<span class='notice'>Restrain</span>: Grab Grab. Locks opponents into a restraining position, disarm to mute them with a chokehold.")
|
||||
to_chat(usr, "<span class='notice'>Pressure</span>: Disarm Grab. Decent stamina damage.")
|
||||
to_chat(usr, "<span class='notice'>Consecutive CQC</span>: Disarm Disarm Harm. Mainly offensive move, huge damage and decent stamina damage.")
|
||||
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
/*! Material datum
|
||||
|
||||
Simple datum which is instanced once per type and is used for every object of said material. It has a variety of variables that define behavior. Subtyping from this makes it easier to create your own materials.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/datum/material
|
||||
/// What the material is referred to as IC.
|
||||
var/name = "material"
|
||||
/// A short description of the material. Not used anywhere, yet...
|
||||
var/desc = "its..stuff."
|
||||
/// What the material is indexed by in the SSmaterials.materials list. Defaults to the type of the material.
|
||||
var/id
|
||||
|
||||
///Base color of the material, is used for greyscale. Item isn't changed in color if this is null.
|
||||
var/color
|
||||
///Base alpha of the material, is used for greyscale icons.
|
||||
var/alpha
|
||||
///Bitflags that influence how SSmaterials handles this material.
|
||||
// var/init_flags = MATERIAL_INIT_MAPLOAD
|
||||
///Materials "Traits". its a map of key = category | Value = Bool. Used to define what it can be used for
|
||||
var/list/categories = list()
|
||||
///The type of sheet this material creates. This should be replaced as soon as possible by greyscale sheets
|
||||
@@ -22,7 +31,7 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
var/value_per_unit = 0
|
||||
///Armor modifiers, multiplies an items normal armor vars by these amounts.
|
||||
var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1)
|
||||
///How beautiful is this material per unit?
|
||||
///How beautiful is this material per unit.
|
||||
var/beauty_modifier = 0
|
||||
///Can be used to override the sound items make, lets add some SLOSHing.
|
||||
var/item_sound_override
|
||||
@@ -30,14 +39,31 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
var/turf_sound_override
|
||||
///what texture icon state to overlay
|
||||
var/texture_layer_icon_state
|
||||
///a cached filter for the texture icon
|
||||
///a cached icon for the texture filter
|
||||
var/cached_texture_filter
|
||||
///What type of shard the material will shatter to
|
||||
var/obj/item/shard_type
|
||||
|
||||
|
||||
/** Handles initializing the material.
|
||||
*
|
||||
* Arugments:
|
||||
* - _id: The ID the material should use. Overrides the existing ID.
|
||||
*/
|
||||
/datum/material/proc/Initialize(_id, ...)
|
||||
if(_id)
|
||||
id = _id
|
||||
else if(isnull(id))
|
||||
id = type
|
||||
|
||||
if(texture_layer_icon_state)
|
||||
cached_texture_filter = icon('icons/materials/composite.dmi', texture_layer_icon_state)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/material/New()
|
||||
. = ..()
|
||||
if(texture_layer_icon_state)
|
||||
var/texture_icon = icon('icons/materials/composite.dmi', texture_layer_icon_state)
|
||||
cached_texture_filter = filter(type="layer", icon=texture_icon, blend_mode = BLEND_INSET_OVERLAY)
|
||||
Initialize()
|
||||
|
||||
///This proc is called when the material is added to an object.
|
||||
/datum/material/proc/on_applied(atom/source, amount, material_flags)
|
||||
@@ -48,18 +74,20 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
source.alpha = alpha
|
||||
if(texture_layer_icon_state)
|
||||
ADD_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
|
||||
source.filters += cached_texture_filter
|
||||
source.add_filter("material_texture_[name]",1,layering_filter(icon=cached_texture_filter,blend_mode=BLEND_INSET_OVERLAY))
|
||||
|
||||
if(alpha < 255)
|
||||
source.opacity = FALSE
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = "[name] [source.name]"
|
||||
|
||||
if(beauty_modifier)
|
||||
addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, beauty_modifier * amount)), 0)
|
||||
// if(beauty_modifier) returnign in hardsync2 if i ever port ebeauty cmp
|
||||
// addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, beauty_modifier * amount)), 0)
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_applied_obj(source, amount, material_flags)
|
||||
|
||||
else if(isturf(source, /turf)) //turfs
|
||||
if(istype(source, /turf)) //turfs
|
||||
on_applied_turf(source, amount, material_flags)
|
||||
|
||||
source.mat_update_desc(src)
|
||||
@@ -67,8 +95,9 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
///This proc is called when a material updates an object's description
|
||||
/atom/proc/mat_update_desc(/datum/material/mat)
|
||||
return
|
||||
|
||||
///This proc is called when the material is added to an object specifically.
|
||||
/datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags)
|
||||
/datum/material/proc/on_applied_obj(obj/o, amount, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
@@ -92,43 +121,73 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
I.hitsound = item_sound_override
|
||||
I.usesound = item_sound_override
|
||||
I.throwhitsound = item_sound_override
|
||||
// I.mob_throw_hit_sound = item_sound_override
|
||||
// I.equip_sound = item_sound_override
|
||||
// I.pickup_sound = item_sound_override
|
||||
// I.drop_sound = item_sound_override
|
||||
|
||||
/datum/material/proc/on_applied_turf(var/turf/T, amount, material_flags)
|
||||
/datum/material/proc/on_applied_turf(turf/T, amount, material_flags)
|
||||
if(isopenturf(T))
|
||||
if(!turf_sound_override)
|
||||
return
|
||||
var/turf/open/O = T
|
||||
O.footstep = turf_sound_override
|
||||
O.barefootstep = turf_sound_override
|
||||
O.clawfootstep = turf_sound_override
|
||||
O.heavyfootstep = turf_sound_override
|
||||
if(turf_sound_override)
|
||||
var/turf/open/O = T
|
||||
O.footstep = turf_sound_override
|
||||
O.barefootstep = turf_sound_override
|
||||
O.clawfootstep = turf_sound_override
|
||||
O.heavyfootstep = turf_sound_override
|
||||
// if(alpha < 255)
|
||||
// T.AddElement(/datum/element/turf_z_transparency, TRUE)
|
||||
return
|
||||
|
||||
///This proc is called when the material is removed from an object.
|
||||
/datum/material/proc/on_removed(atom/source, material_flags)
|
||||
/datum/material/proc/on_removed(atom/source, amount, material_flags)
|
||||
if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example
|
||||
if(color)
|
||||
source.remove_atom_colour(FIXED_COLOUR_PRIORITY, color)
|
||||
source.alpha = initial(source.alpha)
|
||||
if(texture_layer_icon_state)
|
||||
source.filters -= cached_texture_filter
|
||||
source.remove_filter("material_texture_[name]")
|
||||
REMOVE_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
|
||||
source.alpha = initial(source.alpha)
|
||||
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = initial(source.name)
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_removed_obj(source, material_flags)
|
||||
// if(beauty_modifier) //component/beauty/InheritComponent() will handle the removal.
|
||||
// addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, -beauty_modifier * amount)), 0)
|
||||
|
||||
else if(istype(source, /turf)) //turfs
|
||||
on_removed_turf(source, material_flags)
|
||||
if(istype(source, /obj)) //objs
|
||||
on_removed_obj(source, amount, material_flags)
|
||||
|
||||
if(istype(source, /turf)) //turfs
|
||||
on_removed_turf(source, amount, material_flags)
|
||||
|
||||
///This proc is called when the material is removed from an object specifically.
|
||||
/datum/material/proc/on_removed_obj(obj/o, material_flags)
|
||||
/datum/material/proc/on_removed_obj(obj/o, amount, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
|
||||
/datum/material/proc/on_removed_turf(turf/T, material_flags)
|
||||
return
|
||||
/datum/material/proc/on_removed_turf(turf/T, amount, material_flags)
|
||||
// if(alpha)
|
||||
// RemoveElement(/datum/element/turf_z_transparency, FALSE)
|
||||
|
||||
/**
|
||||
* This proc is called when the mat is found in an item that's consumed by accident. see /obj/item/proc/on_accidental_consumption.
|
||||
* Arguments
|
||||
* * M - person consuming the mat
|
||||
* * S - (optional) item the mat is contained in (NOT the item with the mat itself)
|
||||
*/
|
||||
/datum/material/proc/on_accidental_mat_consumption(mob/living/carbon/M, obj/item/S)
|
||||
return FALSE
|
||||
|
||||
/** Returns the composition of this material.
|
||||
*
|
||||
* Mostly used for alloys when breaking down materials.
|
||||
*
|
||||
* Arguments:
|
||||
* - amount: The amount of the material to break down.
|
||||
* - breakdown_flags: Some flags dictating how exactly this material is being broken down.
|
||||
*/
|
||||
/datum/material/proc/return_composition(amount=1, breakdown_flags=NONE)
|
||||
return list((src) = amount) // Yes we need the parenthesis, without them BYOND stringifies src into "src" and things break.
|
||||
|
||||
+158
-69
@@ -8,12 +8,16 @@
|
||||
var/description
|
||||
var/prerequisites
|
||||
var/admin_notes
|
||||
|
||||
/// How much does this shuttle cost the cargo budget to purchase? Put in terms of CARGO_CRATE_VALUE to properly scale the cost with the current balance of cargo's income.
|
||||
var/credit_cost = INFINITY
|
||||
/// Can the be legitimately purchased by the station? Used by hardcoded or pre-mapped shuttles like the lavaland or cargo shuttle.
|
||||
var/can_be_bought = TRUE
|
||||
/// If set, overrides default movement_force on shuttle
|
||||
var/list/movement_force
|
||||
|
||||
var/port_x_offset
|
||||
var/port_y_offset
|
||||
var/extra_desc = ""
|
||||
|
||||
/datum/map_template/shuttle/proc/prerequisites_met()
|
||||
return TRUE
|
||||
@@ -23,7 +27,7 @@
|
||||
mappath = "[prefix][shuttle_id].dmm"
|
||||
. = ..()
|
||||
|
||||
/datum/map_template/shuttle/preload_size(path = mappath, force_cache = FALSE)
|
||||
/datum/map_template/shuttle/preload_size(path, force_cache)
|
||||
. = ..(path, TRUE) // Done this way because we still want to know if someone actualy wanted to cache the map
|
||||
if(!cached_map)
|
||||
return
|
||||
@@ -64,6 +68,9 @@
|
||||
continue
|
||||
if(length(place.baseturfs) < 2) // Some snowflake shuttle shit
|
||||
continue
|
||||
// var/list/sanity = place.baseturfs.Copy() // we do not have new baseturfs yet
|
||||
// sanity.Insert(3, /turf/baseturf_skipover/shuttle)
|
||||
// place.baseturfs = baseturfs_string_list(sanity, place)
|
||||
place.baseturfs.Insert(3, /turf/baseturf_skipover/shuttle)
|
||||
|
||||
for(var/obj/docking_port/mobile/port in place)
|
||||
@@ -93,6 +100,7 @@
|
||||
port.dwidth = port_y_offset - 1
|
||||
port.dheight = width - port_x_offset
|
||||
|
||||
// these three for loops are cit specific.
|
||||
for(var/obj/structure/closet/closet in place)
|
||||
if(closet.anchorable)
|
||||
closet.anchored = TRUE
|
||||
@@ -104,11 +112,10 @@
|
||||
rack.AddComponent(/datum/component/magnetic_catch)
|
||||
|
||||
//Whatever special stuff you want
|
||||
/datum/map_template/shuttle/proc/post_load(obj/docking_port/mobile/M)
|
||||
return
|
||||
|
||||
/datum/map_template/shuttle/proc/on_bought()
|
||||
return
|
||||
/datum/map_template/shuttle/post_load(obj/docking_port/mobile/M)
|
||||
if(movement_force)
|
||||
M.movement_force = movement_force.Copy()
|
||||
M.linkup()
|
||||
|
||||
/datum/map_template/shuttle/emergency
|
||||
port_id = "emergency"
|
||||
@@ -117,6 +124,7 @@
|
||||
/datum/map_template/shuttle/cargo
|
||||
port_id = "cargo"
|
||||
name = "Base Shuttle Template (Cargo)"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/ferry
|
||||
port_id = "ferry"
|
||||
@@ -137,10 +145,6 @@
|
||||
port_id = "mining_common"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/cargo
|
||||
port_id = "cargo"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/arrival
|
||||
port_id = "arrival"
|
||||
can_be_bought = FALSE
|
||||
@@ -189,21 +193,23 @@
|
||||
name = "Backup Shuttle"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/emergency/airless
|
||||
suffix = "airless"
|
||||
/datum/map_template/shuttle/emergency/construction
|
||||
suffix = "construction"
|
||||
name = "Build your own shuttle kit"
|
||||
description = "Save money by building your own shuttle! The chassis will dock upon purchase, but launch will have to be authorized as usual via shuttle call. Interior and lighting not included."
|
||||
description = "For the enterprising shuttle engineer! The chassis will dock upon purchase, but launch will have to be authorized as usual via shuttle call. Comes stocked with construction materials. Unlocks the ability to buy shuttle engine crates from cargo."
|
||||
admin_notes = "No brig, no medical facilities, just an empty box."
|
||||
credit_cost = -7500
|
||||
|
||||
/datum/map_template/shuttle/emergency/airless/prerequisites_met()
|
||||
/datum/map_template/shuttle/emergency/construction/prerequisites_met()
|
||||
// first 10 minutes only
|
||||
return world.time - SSticker.round_start_time < 6000
|
||||
|
||||
/datum/map_template/shuttle/emergency/airless/on_bought()
|
||||
//enable buying engines from cargo
|
||||
var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine]
|
||||
P.special_enabled = TRUE
|
||||
// this is broken and does not work. Thanks TG
|
||||
// /datum/map_template/shuttle/emergency/airless/post_load()
|
||||
// . = ..()
|
||||
// //enable buying engines from cargo
|
||||
// var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine]
|
||||
// P.special_enabled = TRUE
|
||||
|
||||
|
||||
/datum/map_template/shuttle/emergency/asteroid
|
||||
@@ -220,6 +226,13 @@
|
||||
Has medical facilities."
|
||||
credit_cost = 5000
|
||||
|
||||
// /datum/map_template/shuttle/emergency/pod
|
||||
// suffix = "pod"
|
||||
// name = "Emergency Pods"
|
||||
// description = "We did not expect an evacuation this quickly. All we have available is two escape pods."
|
||||
// admin_notes = "For player punishment."
|
||||
// can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/emergency/russiafightpit
|
||||
suffix = "russiafightpit"
|
||||
name = "Mother Russia Bleeds"
|
||||
@@ -230,9 +243,10 @@
|
||||
/datum/map_template/shuttle/emergency/meteor
|
||||
suffix = "meteor"
|
||||
name = "Asteroid With Engines Strapped To It"
|
||||
description = "A hollowed out asteroid with engines strapped to it. Due to its size and difficulty in steering it, this shuttle may damage the docking area."
|
||||
description = "A hollowed out asteroid with engines strapped to it, the hollowing procedure makes it very difficult to hijack but is very expensive. Due to its size and difficulty in steering it, this shuttle may damage the docking area."
|
||||
admin_notes = "This shuttle will likely crush escape, killing anyone there."
|
||||
credit_cost = -5000
|
||||
movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
|
||||
|
||||
/datum/map_template/shuttle/emergency/luxury
|
||||
suffix = "luxury"
|
||||
@@ -247,18 +261,30 @@
|
||||
description = "The glorious results of centuries of plasma research done by Nanotrasen employees. This is the reason why you are here. Get on and dance like you're on fire, burn baby burn!"
|
||||
admin_notes = "Flaming hot. The main area has a dance machine as well as plasma floor tiles that will be ignited by players every single time."
|
||||
credit_cost = 10000
|
||||
// can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/emergency/arena
|
||||
suffix = "arena"
|
||||
name = "The Arena"
|
||||
description = "The crew must pass through an otherworldy arena to board this shuttle. Expect massive casualties. The source of the Bloody Signal must be tracked down and eliminated to unlock this shuttle."
|
||||
admin_notes = "RIP AND TEAR."
|
||||
credit_cost = 10000
|
||||
// /datum/map_template/shuttle/emergency/arena
|
||||
// suffix = "arena"
|
||||
// name = "The Arena"
|
||||
// description = "The crew must pass through an otherworldy arena to board this shuttle. Expect massive casualties. The source of the Bloody Signal must be tracked down and eliminated to unlock this shuttle."
|
||||
// admin_notes = "RIP AND TEAR."
|
||||
// credit_cost = 10000
|
||||
// /// Whether the arena z-level has been created
|
||||
// var/arena_loaded = FALSE
|
||||
|
||||
/datum/map_template/shuttle/emergency/arena/prerequisites_met()
|
||||
if("bubblegum" in SSshuttle.shuttle_purchase_requirements_met)
|
||||
return TRUE
|
||||
return FALSE
|
||||
// /datum/map_template/shuttle/emergency/arena/prerequisites_met()
|
||||
// return SSshuttle.shuttle_purchase_requirements_met["bubblegum"]
|
||||
|
||||
// /datum/map_template/shuttle/emergency/arena/post_load(obj/docking_port/mobile/M)
|
||||
// . = ..()
|
||||
// if(!arena_loaded)
|
||||
// arena_loaded = TRUE
|
||||
// var/datum/map_template/arena/arena_template = new()
|
||||
// arena_template.load_new_z()
|
||||
|
||||
// /datum/map_template/arena
|
||||
// name = "The Arena"
|
||||
// mappath = "_maps/templates/the_arena.dmm"
|
||||
|
||||
/datum/map_template/shuttle/emergency/birdboat
|
||||
suffix = "birdboat"
|
||||
@@ -272,6 +298,13 @@
|
||||
credit_cost = 2000
|
||||
description = "The gold standard in emergency exfiltration, this tried and true design is equipped with everything the crew needs for a safe flight home."
|
||||
|
||||
// /datum/map_template/shuttle/emergency/donut
|
||||
// suffix = "donut"
|
||||
// name = "Donutstation Emergency Shuttle"
|
||||
// description = "The perfect spearhead for any crude joke involving the station's shape, this shuttle supports a separate containment cell for prisoners and a compact medical wing."
|
||||
// admin_notes = "Has airlocks on both sides of the shuttle and will probably intersect near the front on some stations that build past departures."
|
||||
// credit_cost = 2500
|
||||
|
||||
/datum/map_template/shuttle/emergency/clown
|
||||
suffix = "clown"
|
||||
name = "Snappop(tm)!"
|
||||
@@ -316,7 +349,9 @@
|
||||
credit_cost = -1000
|
||||
description = "Due to a lack of functional emergency shuttles, we bought this second hand from a scrapyard and pressed it into service. Please do not lean too heavily on the exterior windows, they are fragile."
|
||||
admin_notes = "An abomination with no functional medbay, sections missing, and some very fragile windows. Surprisingly airtight."
|
||||
movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
|
||||
|
||||
// CIT SPECIFIC
|
||||
/datum/map_template/shuttle/emergency/syndicate
|
||||
suffix = "syndicate"
|
||||
name = "Syndicate GM Battlecruiser"
|
||||
@@ -325,9 +360,7 @@
|
||||
admin_notes = "An emag exclusive, stocked with syndicate equipment and turrets that will target any simplemob."
|
||||
|
||||
/datum/map_template/shuttle/emergency/syndicate/prerequisites_met()
|
||||
if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
|
||||
return TRUE
|
||||
return FALSE
|
||||
return SSshuttle.shuttle_purchase_requirements_met["emagged"]
|
||||
|
||||
/datum/map_template/shuttle/emergency/narnar
|
||||
suffix = "narnar"
|
||||
@@ -335,6 +368,10 @@
|
||||
description = "Looks like this shuttle may have wandered into the darkness between the stars on route to the station. Let's not think too hard about where all the bodies came from."
|
||||
admin_notes = "Contains real cult ruins, mob eyeballs, and inactive constructs. Cult mobs will automatically be sentienced by fun balloon. \
|
||||
Cloning pods in 'medbay' area are showcases and nonfunctional."
|
||||
credit_cost = 6667 ///The joke is the number so no defines
|
||||
|
||||
/datum/map_template/shuttle/emergency/narnar/prerequisites_met()
|
||||
return SSshuttle.shuttle_purchase_requirements_met["narsie"]
|
||||
|
||||
/datum/map_template/shuttle/emergency/pubby
|
||||
suffix = "pubby"
|
||||
@@ -354,7 +391,7 @@
|
||||
/datum/map_template/shuttle/emergency/supermatter
|
||||
suffix = "supermatter"
|
||||
name = "Hyperfractal Gigashuttle"
|
||||
description = "(Emag only) \"I dunno, this seems kinda needlessly complicated.\"\n\
|
||||
description = "\"I dunno, this seems kinda needlessly complicated.\"\n\
|
||||
\"This shuttle has very a very high safety record, according to CentCom Officer Cadet Yins.\"\n\
|
||||
\"Are you sure?\"\n\
|
||||
\"Yes, it has a safety record of N-A-N, which is apparently larger than 100%.\""
|
||||
@@ -363,19 +400,19 @@
|
||||
It does, however, still dust anything on contact, emits high levels of radiation, and induce hallucinations in anyone looking at it without protective goggles. \
|
||||
Emitters spawn powered on, expect admin notices, they are harmless."
|
||||
credit_cost = 15000
|
||||
movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
|
||||
|
||||
/datum/map_template/shuttle/emergency/supermatter/prerequisites_met()
|
||||
if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
return SSshuttle.shuttle_purchase_requirements_met["emagged"]
|
||||
/datum/map_template/shuttle/emergency/imfedupwiththisworld
|
||||
suffix = "imfedupwiththisworld"
|
||||
name = "Oh, Hi Daniel"
|
||||
description = "How was space work today? Oh, pretty good. We got a new space station and the company will make a lot of money. What space station? I cannot tell you; it's space confidential. \
|
||||
Aw, come space on. Why not? No, I can't. Anyway, how is your space roleplay life?"
|
||||
admin_notes = "Tiny, with a single airlock and wooden walls. What could go wrong?"
|
||||
// can_be_bought = FALSE
|
||||
credit_cost = -5000
|
||||
movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
|
||||
|
||||
/datum/map_template/shuttle/emergency/goon
|
||||
suffix = "goon"
|
||||
@@ -383,6 +420,14 @@
|
||||
description = "The Nanotrasen Emergency Shuttle Port(NES Port for short) is a shuttle used at other less known Nanotrasen facilities and has a more open inside for larger crowds, but fewer onboard shuttle facilities."
|
||||
credit_cost = 500
|
||||
|
||||
// /datum/map_template/shuttle/emergency/rollerdome
|
||||
// suffix = "rollerdome"
|
||||
// name = "Uncle Pete's Rollerdome"
|
||||
// description = "Developed by a member of Nanotrasen's R&D crew that claims to have travelled from the year 2028.
|
||||
// He says this shuttle is based off an old entertainment complex from the 1990s, though our database has no records on anything pertaining to that decade."
|
||||
// admin_notes = "ONLY NINETIES KIDS REMEMBER. Uses the fun balloon and drone from the Emergency Bar."
|
||||
// credit_cost = 500 * 5
|
||||
|
||||
/datum/map_template/shuttle/emergency/wabbajack
|
||||
suffix = "wabbajack"
|
||||
name = "NT Lepton Violet"
|
||||
@@ -398,6 +443,7 @@
|
||||
description = "On the smaller size with a modern design, this shuttle is for the crew who like the cosier things, while still being able to stretch their legs."
|
||||
credit_cost = 1000
|
||||
|
||||
// CIT SPECIFIC
|
||||
/datum/map_template/shuttle/emergency/gorilla
|
||||
suffix = "gorilla"
|
||||
name = "Gorilla Cargo Freighter"
|
||||
@@ -405,11 +451,17 @@
|
||||
credit_cost = 2000
|
||||
|
||||
/datum/map_template/shuttle/emergency/gorilla/prerequisites_met()
|
||||
if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
|
||||
return TRUE
|
||||
return FALSE
|
||||
return SSshuttle.shuttle_purchase_requirements_met["emagged"]
|
||||
|
||||
/datum/map_template/shuttle/emergency/cruise
|
||||
|
||||
// /datum/map_template/shuttle/emergency/cruise
|
||||
// suffix = "cruise"
|
||||
// name = "The NTSS Independence"
|
||||
// description = "Ordinarily reserved for special functions and events, the Cruise Shuttle Independence can bring a summery cheer to your next station evacuation for a 'modest' fee!"
|
||||
// admin_notes = "This motherfucker is BIG. You might need to force dock it."
|
||||
// credit_cost = 8000
|
||||
|
||||
/datum/map_template/shuttle/emergency/monkey
|
||||
suffix = "nature"
|
||||
name = "Dynamic Environmental Interaction Shuttle"
|
||||
description = "A large shuttle with a center biodome that is flourishing with life. Frolick with the monkeys! (Extra monkeys are stored on the bridge.)"
|
||||
@@ -441,7 +493,7 @@
|
||||
/datum/map_template/shuttle/ferry/fancy
|
||||
suffix = "fancy"
|
||||
name = "fancy transport ferry"
|
||||
description = "At some point, someone upgraded the ferry to have fancier flooring... and less seats."
|
||||
description = "At some point, someone upgraded the ferry to have fancier flooring... and fewer seats."
|
||||
|
||||
/datum/map_template/shuttle/ferry/kilo
|
||||
suffix = "kilo"
|
||||
@@ -464,6 +516,14 @@
|
||||
suffix = "cere"
|
||||
name = "NT Construction Vessel"
|
||||
|
||||
// /datum/map_template/shuttle/whiteship/kilo
|
||||
// suffix = "kilo"
|
||||
// name = "NT Mining Shuttle"
|
||||
|
||||
// /datum/map_template/shuttle/whiteship/donut
|
||||
// suffix = "donut"
|
||||
// name = "NT Long-Distance Bluespace Jumper"
|
||||
|
||||
/datum/map_template/shuttle/whiteship/delta
|
||||
suffix = "delta"
|
||||
name = "NT Frigate"
|
||||
@@ -476,10 +536,6 @@
|
||||
suffix = "cog"
|
||||
name = "NT Prisoner Transport"
|
||||
|
||||
/datum/map_template/shuttle/cargo/box
|
||||
suffix = "box"
|
||||
name = "supply shuttle (Box)"
|
||||
|
||||
/datum/map_template/shuttle/cargo/kilo
|
||||
suffix = "kilo"
|
||||
name = "supply shuttle (Kilo)"
|
||||
@@ -488,6 +544,14 @@
|
||||
suffix = "birdboat"
|
||||
name = "supply shuttle (Birdboat)"
|
||||
|
||||
// /datum/map_template/shuttle/cargo/donut
|
||||
// suffix = "donut"
|
||||
// name = "supply shuttle (Donut)"
|
||||
|
||||
// /datum/map_template/shuttle/cargo/pubby
|
||||
// suffix = "pubby"
|
||||
// name = "supply shuttle (Pubby)"
|
||||
|
||||
/datum/map_template/shuttle/emergency/delta
|
||||
suffix = "delta"
|
||||
name = "Delta Station Emergency Shuttle"
|
||||
@@ -497,11 +561,24 @@
|
||||
|
||||
/datum/map_template/shuttle/emergency/raven
|
||||
suffix = "raven"
|
||||
name = "CentCom Raven Battlecruiser"
|
||||
description = "The CentCom Raven Battlecruiser is currently docked at the CentCom ship bay awaiting a mission, this Battlecruiser has been reassigned as an emergency escape shuttle for currently unknown reasons. The CentCom Raven Battlecruiser should comfortably fit a medium to large crew size crew and is complete with all required facitlities including a top of the range CentCom Medical Bay."
|
||||
admin_notes = "Comes with turrets that will target any simplemob."
|
||||
name = "CentCom Raven Cruiser"
|
||||
description = "The CentCom Raven Cruiser is a former high-risk salvage vessel, now repurposed into an emergency escape shuttle. \
|
||||
Once first to the scene to pick through warzones for valuable remains, it now serves as an excellent escape option for stations under heavy fire from outside forces. \
|
||||
This escape shuttle boasts shields and numerous anti-personnel turrets guarding its perimeter to fend off meteors and enemy boarding attempts."
|
||||
admin_notes = "Comes with turrets that will target anything without the neutral faction (nuke ops, xenos etc, but not pets)."
|
||||
credit_cost = 12500
|
||||
|
||||
// /datum/map_template/shuttle/emergency/zeta
|
||||
// suffix = "zeta"
|
||||
// name = "Tr%nPo2r& Z3TA"
|
||||
// description = "A glitch appears on your monitor, flickering in and out of the options laid before you.
|
||||
// It seems strange and alien, you may need a special technology to access the signal.."
|
||||
// admin_notes = "Has alien surgery tools, and a void core that provides unlimited power."
|
||||
// credit_cost = CARGO_CRATE_VALUE * 16
|
||||
|
||||
// /datum/map_template/shuttle/emergency/zeta/prerequisites_met()
|
||||
// return SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_ALIENTECH]
|
||||
|
||||
/datum/map_template/shuttle/emergency/cog
|
||||
suffix = "cog"
|
||||
name = "NES Classic"
|
||||
@@ -524,18 +601,22 @@
|
||||
suffix = "box"
|
||||
name = "labour shuttle (Box)"
|
||||
|
||||
/datum/map_template/shuttle/labour/kilo
|
||||
suffix = "kilo"
|
||||
name = "labour shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/labour/cog
|
||||
suffix = "cog"
|
||||
name = "labour shuttle (Cog)"
|
||||
|
||||
// /datum/map_template/shuttle/arrival/donut
|
||||
// suffix = "donut"
|
||||
// name = "arrival shuttle (Donut)"
|
||||
|
||||
/datum/map_template/shuttle/infiltrator/basic
|
||||
suffix = "basic"
|
||||
name = "basic syndicate infiltrator"
|
||||
|
||||
// /datum/map_template/shuttle/infiltrator/advanced
|
||||
// suffix = "advanced"
|
||||
// name = "advanced syndicate infiltrator"
|
||||
|
||||
/datum/map_template/shuttle/cargo/delta
|
||||
suffix = "delta"
|
||||
name = "cargo ferry (Delta)"
|
||||
@@ -548,17 +629,25 @@
|
||||
suffix = "kilo"
|
||||
name = "mining shuttle (Kilo)"
|
||||
|
||||
// /datum/map_template/shuttle/mining/large
|
||||
// suffix = "large"
|
||||
// name = "mining shuttle (Large)"
|
||||
|
||||
/datum/map_template/shuttle/labour/delta
|
||||
suffix = "delta"
|
||||
name = "labour shuttle (Delta)"
|
||||
|
||||
/datum/map_template/shuttle/labour/kilo
|
||||
suffix = "kilo"
|
||||
name = "labour shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/mining_common/meta
|
||||
suffix = "meta"
|
||||
name = "lavaland shuttle (Meta)"
|
||||
|
||||
/datum/map_template/shuttle/labour/kilo
|
||||
suffix = "kilo"
|
||||
name = "labour shuttle (Kilo)"
|
||||
// /datum/map_template/shuttle/mining_common/kilo
|
||||
// suffix = "kilo"
|
||||
// name = "lavaland shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/arrival/delta
|
||||
suffix = "delta"
|
||||
@@ -608,6 +697,18 @@
|
||||
suffix = "default"
|
||||
name = "pirate ship (Default)"
|
||||
|
||||
/datum/map_template/shuttle/hunter/space_cop
|
||||
suffix = "space_cop"
|
||||
name = "Police Spacevan"
|
||||
|
||||
/datum/map_template/shuttle/hunter/russian
|
||||
suffix = "russian"
|
||||
name = "Russian Cargo Ship"
|
||||
|
||||
/datum/map_template/shuttle/hunter/bounty
|
||||
suffix = "bounty"
|
||||
name = "Bounty Hunter Ship"
|
||||
|
||||
/datum/map_template/shuttle/ruin/caravan_victim
|
||||
suffix = "caravan_victim"
|
||||
name = "Small Freighter"
|
||||
@@ -631,15 +732,3 @@
|
||||
/datum/map_template/shuttle/snowdin/excavation
|
||||
suffix = "excavation"
|
||||
name = "Snowdin Excavation Elevator"
|
||||
|
||||
/datum/map_template/shuttle/hunter/space_cop
|
||||
suffix = "space_cop"
|
||||
name = "Police Spacevan"
|
||||
|
||||
/datum/map_template/shuttle/hunter/russian
|
||||
suffix = "russian"
|
||||
name = "Russian Cargo Ship"
|
||||
|
||||
/datum/map_template/shuttle/hunter/bounty
|
||||
suffix = "bounty"
|
||||
name = "Bounty Hunter Ship"
|
||||
|
||||
@@ -83,8 +83,6 @@
|
||||
/datum/viewData/proc/apply()
|
||||
chief.change_view(getView())
|
||||
safeApplyFormat()
|
||||
if(chief.prefs.auto_fit_viewport)
|
||||
chief.fit_viewport()
|
||||
|
||||
/datum/viewData/proc/supress()
|
||||
is_suppressed = TRUE
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
target_trait = ZTRAIT_STATION
|
||||
|
||||
immunity_type = "rad"
|
||||
|
||||
|
||||
var/radiation_intensity = 100
|
||||
|
||||
/datum/weather/rad_storm/telegraph()
|
||||
|
||||
@@ -106,8 +106,8 @@
|
||||
|
||||
/datum/world_topic/comms_console/Run(list/input, addr)
|
||||
minor_announce(input["message"], "Incoming message from [input["message_sender"]]")
|
||||
for(var/obj/machinery/computer/communications/CM in GLOB.machines)
|
||||
CM.overrideCooldown()
|
||||
for(var/obj/machinery/computer/communications/console in GLOB.machines)
|
||||
console.override_cooldown()
|
||||
|
||||
/datum/world_topic/news_report
|
||||
keyword = "News_Report"
|
||||
|
||||
+51
-8
@@ -885,6 +885,9 @@
|
||||
VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent")
|
||||
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse")
|
||||
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion")
|
||||
// VV_DROPDOWN_OPTION(VV_HK_RADIATE, "Radiate")
|
||||
VV_DROPDOWN_OPTION(VV_HK_EDIT_FILTERS, "Edit Filters")
|
||||
// VV_DROPDOWN_OPTION(VV_HK_ADD_AI, "Add AI controller")
|
||||
|
||||
/atom/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
@@ -928,6 +931,9 @@
|
||||
var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text
|
||||
if(newname)
|
||||
vv_auto_rename(newname)
|
||||
if(href_list[VV_HK_EDIT_FILTERS] && check_rights(R_VAREDIT))
|
||||
var/client/C = usr.client
|
||||
C?.open_filter_editor(src)
|
||||
|
||||
/atom/vv_get_header()
|
||||
. = ..()
|
||||
@@ -1148,7 +1154,6 @@
|
||||
|
||||
victim.log_message(message, LOG_ATTACK, color="blue")
|
||||
|
||||
// Filter stuff
|
||||
/atom/proc/add_filter(name,priority,list/params)
|
||||
LAZYINITLIST(filter_data)
|
||||
var/list/p = params.Copy()
|
||||
@@ -1164,26 +1169,64 @@
|
||||
var/list/arguments = data.Copy()
|
||||
arguments -= "priority"
|
||||
filters += filter(arglist(arguments))
|
||||
UNSETEMPTY(filter_data)
|
||||
|
||||
/atom/proc/transition_filter(name, time, list/new_params, easing, loop)
|
||||
var/filter = get_filter(name)
|
||||
if(!filter)
|
||||
return
|
||||
|
||||
var/list/old_filter_data = filter_data[name]
|
||||
|
||||
var/list/params = old_filter_data.Copy()
|
||||
for(var/thing in new_params)
|
||||
params[thing] = new_params[thing]
|
||||
|
||||
animate(filter, new_params, time = time, easing = easing, loop = loop)
|
||||
for(var/param in params)
|
||||
filter_data[name][param] = params[param]
|
||||
|
||||
/atom/proc/change_filter_priority(name, new_priority)
|
||||
if(!filter_data || !filter_data[name])
|
||||
return
|
||||
|
||||
filter_data[name]["priority"] = new_priority
|
||||
update_filters()
|
||||
|
||||
/obj/item/update_filters()
|
||||
. = ..()
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.UpdateButtonIcon()
|
||||
|
||||
/atom/proc/get_filter(name)
|
||||
if(filter_data && filter_data[name])
|
||||
return filters[filter_data.Find(name)]
|
||||
|
||||
/atom/proc/remove_filter(name)
|
||||
if(filter_data && filter_data[name])
|
||||
filter_data -= name
|
||||
update_filters()
|
||||
return TRUE
|
||||
/atom/proc/remove_filter(name_or_names)
|
||||
if(!filter_data)
|
||||
return
|
||||
|
||||
var/list/names = islist(name_or_names) ? name_or_names : list(name_or_names)
|
||||
|
||||
for(var/name in names)
|
||||
if(filter_data[name])
|
||||
filter_data -= name
|
||||
update_filters()
|
||||
|
||||
/atom/proc/clear_filters()
|
||||
filter_data = null
|
||||
filters = null
|
||||
|
||||
/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1)
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
|
||||
|
||||
///Sets the custom materials for an item.
|
||||
/atom/proc/set_custom_materials(var/list/materials, multiplier = 1)
|
||||
/atom/proc/set_custom_materials(list/materials, multiplier = 1)
|
||||
if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways
|
||||
for(var/i in custom_materials)
|
||||
var/datum/material/custom_material = SSmaterials.GetMaterialRef(i)
|
||||
custom_material.on_removed(src, material_flags) //Remove the current materials
|
||||
custom_material.on_removed(src, custom_materials[i], material_flags) //Remove the current materials
|
||||
|
||||
if(!length(materials))
|
||||
custom_materials = null
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
// Init Sunlight (called from datum_bloodsucker.on_gain(), in case game mode isn't even Bloodsucker
|
||||
/datum/game_mode/proc/check_start_sunlight()
|
||||
// Already Sunlight (and not about to cancel)
|
||||
if(istype(bloodsucker_sunlight) && !bloodsucker_sunlight.cancel_me)
|
||||
if(istype(bloodsucker_sunlight))
|
||||
return
|
||||
bloodsucker_sunlight = new ()
|
||||
|
||||
@@ -97,7 +97,6 @@
|
||||
if(!istype(bloodsucker_sunlight))
|
||||
return
|
||||
if(bloodsuckers.len <= 0)
|
||||
bloodsucker_sunlight.cancel_me = TRUE
|
||||
qdel(bloodsucker_sunlight)
|
||||
bloodsucker_sunlight = null
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
for(var/i in 1 to 3)
|
||||
if(config_tag in saved_dynamic_rules[i])
|
||||
weight_mult -= (repeated_mode_adjust[i]/100)
|
||||
weight_mult = max(0,weight_mult)
|
||||
if(config_tag in costs)
|
||||
cost = costs[config_tag]
|
||||
if(config_tag in requirementses)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#define DEFAULT_METEOR_LIFETIME 1800
|
||||
#define MAP_EDGE_PAD 5
|
||||
|
||||
GLOBAL_VAR_INIT(meteor_wave_delay, 625) //minimum wait between waves in tenths of seconds
|
||||
//set to at least 100 unless you want evarr ruining every round
|
||||
|
||||
@@ -30,7 +32,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
var/turf/pickedgoal
|
||||
var/max_i = 10//number of tries to spawn meteor.
|
||||
while(!isspaceturf(pickedstart))
|
||||
var/startSide = dir || pick(GLOB.cardinals)
|
||||
var/startSide = (dir ? dir : pick(GLOB.cardinals))
|
||||
var/startZ = pick(SSmapping.levels_by_trait(ZTRAIT_STATION))
|
||||
pickedstart = spaceDebrisStartLoc(startSide, startZ)
|
||||
pickedgoal = spaceDebrisFinishLoc(startSide, startZ)
|
||||
@@ -46,17 +48,17 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
var/startx
|
||||
switch(startSide)
|
||||
if(NORTH)
|
||||
starty = world.maxy-(TRANSITIONEDGE+2)
|
||||
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
|
||||
starty = world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)
|
||||
startx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
|
||||
if(EAST)
|
||||
starty = rand((TRANSITIONEDGE+2),world.maxy-(TRANSITIONEDGE+2))
|
||||
startx = world.maxx-(TRANSITIONEDGE+2)
|
||||
starty = rand((TRANSITIONEDGE + MAP_EDGE_PAD),world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
|
||||
startx = world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)
|
||||
if(SOUTH)
|
||||
starty = (TRANSITIONEDGE+2)
|
||||
startx = rand((TRANSITIONEDGE+2), world.maxx-(TRANSITIONEDGE+2))
|
||||
starty = (TRANSITIONEDGE + MAP_EDGE_PAD)
|
||||
startx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
|
||||
if(WEST)
|
||||
starty = rand((TRANSITIONEDGE+2), world.maxy-(TRANSITIONEDGE+2))
|
||||
startx = (TRANSITIONEDGE+2)
|
||||
starty = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
|
||||
startx = (TRANSITIONEDGE + MAP_EDGE_PAD)
|
||||
. = locate(startx, starty, Z)
|
||||
|
||||
/proc/spaceDebrisFinishLoc(startSide, Z)
|
||||
@@ -64,17 +66,17 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
var/endx
|
||||
switch(startSide)
|
||||
if(NORTH)
|
||||
endy = (TRANSITIONEDGE+1)
|
||||
endx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
|
||||
endy = (TRANSITIONEDGE + MAP_EDGE_PAD)
|
||||
endx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
|
||||
if(EAST)
|
||||
endy = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1))
|
||||
endx = (TRANSITIONEDGE+1)
|
||||
endy = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
|
||||
endx = (TRANSITIONEDGE + MAP_EDGE_PAD)
|
||||
if(SOUTH)
|
||||
endy = world.maxy-(TRANSITIONEDGE+1)
|
||||
endx = rand((TRANSITIONEDGE+1), world.maxx-(TRANSITIONEDGE+1))
|
||||
endy = world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD)
|
||||
endx = rand((TRANSITIONEDGE + MAP_EDGE_PAD), world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD))
|
||||
if(WEST)
|
||||
endy = rand((TRANSITIONEDGE+1),world.maxy-(TRANSITIONEDGE+1))
|
||||
endx = world.maxx-(TRANSITIONEDGE+1)
|
||||
endy = rand((TRANSITIONEDGE + MAP_EDGE_PAD),world.maxy-(TRANSITIONEDGE + MAP_EDGE_PAD))
|
||||
endx = world.maxx-(TRANSITIONEDGE + MAP_EDGE_PAD)
|
||||
. = locate(endx, endy, Z)
|
||||
|
||||
///////////////////////
|
||||
@@ -82,7 +84,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
//////////////////////
|
||||
|
||||
/obj/effect/meteor
|
||||
name = "the concept of meteor"
|
||||
name = "\proper the concept of meteor"
|
||||
desc = "You should probably run instead of gawking at this."
|
||||
icon = 'icons/obj/meteor.dmi'
|
||||
icon_state = "small"
|
||||
@@ -92,7 +94,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
var/hitpwr = 2 //Level of ex_act to be called on hit.
|
||||
var/dest
|
||||
pass_flags = PASSTABLE
|
||||
var/heavy = 0
|
||||
var/heavy = FALSE
|
||||
var/meteorsound = 'sound/effects/meteorimpact.ogg'
|
||||
var/z_original
|
||||
var/threat = 0 // used for determining which meteors are most interesting
|
||||
@@ -108,12 +110,12 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
|
||||
. = ..() //process movement...
|
||||
|
||||
var/turf/T = get_turf(loc)
|
||||
if(.)//.. if did move, ram the turf we get in
|
||||
var/turf/T = get_turf(loc)
|
||||
ram_turf(T)
|
||||
|
||||
if(prob(10) && !isspaceturf(T) && !istype(T, /turf/closed/mineral) && !istype(T, /turf/open/floor/plating/asteroid))//randomly takes a 'hit' from ramming
|
||||
get_hit()
|
||||
if(prob(10) && !isspaceturf(T) && !istype(T, /turf/closed/mineral) && !istype(T, /turf/open/floor/plating/asteroid))//randomly takes a 'hit' from ramming, and ignore spare ruin aseroids
|
||||
get_hit()
|
||||
|
||||
/obj/effect/meteor/Destroy()
|
||||
if (timerid)
|
||||
@@ -135,24 +137,25 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
/obj/effect/meteor/Bump(atom/A)
|
||||
if(A)
|
||||
ram_turf(get_turf(A))
|
||||
playsound(src.loc, meteorsound, 40, 1)
|
||||
if(!istype(A, /turf/closed/mineral) && !istype(A, /turf/open/floor/plating/asteroid))
|
||||
playsound(src.loc, meteorsound, 40, TRUE)
|
||||
if(!istype(A, /turf/closed/mineral) && !istype(A, /turf/open/floor/plating/asteroid)) // ignore localstation ruins
|
||||
get_hit()
|
||||
|
||||
/obj/effect/meteor/proc/ram_turf(turf/T)
|
||||
//first bust whatever is in the turf
|
||||
for(var/atom/A in T)
|
||||
if(A != src)
|
||||
if(isliving(A))
|
||||
A.visible_message("<span class='warning'>[src] slams into [A].</span>", "<span class='userdanger'>[src] slams into you!.</span>")
|
||||
A.ex_act(hitpwr)
|
||||
for(var/thing in T)
|
||||
if(thing == src)
|
||||
continue
|
||||
if(isliving(thing))
|
||||
var/mob/living/living_thing = thing
|
||||
living_thing.visible_message("<span class='warning'>[src] slams into [living_thing].</span>", "<span class='userdanger'>[src] slams into you!.</span>")
|
||||
living_thing.ex_act(hitpwr)
|
||||
|
||||
//then, ram the turf if it still exists
|
||||
if(T)
|
||||
T.ex_act(hitpwr)
|
||||
|
||||
|
||||
|
||||
//process getting 'hit' by colliding with a dense object
|
||||
//or randomly when ramming turfs
|
||||
/obj/effect/meteor/proc/get_hit()
|
||||
@@ -162,13 +165,10 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
meteor_effect()
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/meteor/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/meteor/examine(mob/user)
|
||||
. = ..()
|
||||
if(!(flags_1 & ADMIN_SPAWNED_1) && isliving(user))
|
||||
SSmedals.UnlockMedal(MEDAL_METEOR, user.client)
|
||||
return ..()
|
||||
user.client.give_award(/datum/award/achievement/misc/meteor_examine, user)
|
||||
|
||||
/obj/effect/meteor/attackby(obj/item/I, mob/user, params)
|
||||
if(I.tool_behaviour == TOOL_MINING)
|
||||
@@ -232,7 +232,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
name = "big meteor"
|
||||
icon_state = "large"
|
||||
hits = 6
|
||||
heavy = 1
|
||||
heavy = TRUE
|
||||
dropamt = 4
|
||||
threat = 10
|
||||
|
||||
@@ -245,7 +245,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
name = "flaming meteor"
|
||||
icon_state = "flaming"
|
||||
hits = 5
|
||||
heavy = 1
|
||||
heavy = TRUE
|
||||
meteorsound = 'sound/effects/bamf.ogg'
|
||||
meteordrop = list(/obj/item/stack/ore/plasma)
|
||||
threat = 20
|
||||
@@ -258,7 +258,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
/obj/effect/meteor/irradiated
|
||||
name = "glowing meteor"
|
||||
icon_state = "glowing"
|
||||
heavy = 1
|
||||
heavy = TRUE
|
||||
meteordrop = list(/obj/item/stack/ore/uranium)
|
||||
threat = 15
|
||||
|
||||
@@ -275,7 +275,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
icon_state = "meateor"
|
||||
desc = "Just... don't think too hard about where this thing came from."
|
||||
hits = 2
|
||||
heavy = 1
|
||||
heavy = TRUE
|
||||
meteorsound = 'sound/effects/blobattack.ogg'
|
||||
meteordrop = list(/obj/item/reagent_containers/food/snacks/meat/slab/human, /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant, /obj/item/organ/heart, /obj/item/organ/lungs, /obj/item/organ/tongue, /obj/item/organ/appendix/)
|
||||
var/meteorgibs = /obj/effect/gibspawner/generic
|
||||
@@ -327,7 +327,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
desc = "Your life briefly passes before your eyes the moment you lay them on this monstrosity."
|
||||
hits = 30
|
||||
hitpwr = 1
|
||||
heavy = 1
|
||||
heavy = TRUE
|
||||
meteorsound = 'sound/effects/bamf.ogg'
|
||||
meteordrop = list(/obj/item/stack/ore/plasma)
|
||||
threat = 50
|
||||
@@ -358,7 +358,7 @@ GLOBAL_LIST_INIT(meteorsSPOOKY, list(/obj/effect/meteor/pumpkin))
|
||||
icon = 'icons/obj/meteor_spooky.dmi'
|
||||
icon_state = "pumpkin"
|
||||
hits = 10
|
||||
heavy = 1
|
||||
heavy = TRUE
|
||||
dropamt = 1
|
||||
meteordrop = list(/obj/item/clothing/head/hardhat/pumpkinhead, /obj/item/reagent_containers/food/snacks/grown/pumpkin)
|
||||
threat = 100
|
||||
@@ -368,3 +368,4 @@ GLOBAL_LIST_INIT(meteorsSPOOKY, list(/obj/effect/meteor/pumpkin))
|
||||
meteorsound = pick('sound/hallucinations/im_here1.ogg','sound/hallucinations/im_here2.ogg')
|
||||
//////////////////////////
|
||||
#undef DEFAULT_METEOR_LIFETIME
|
||||
#undef MAP_EDGE_PAD
|
||||
|
||||
@@ -8,7 +8,19 @@
|
||||
max_integrity = 200
|
||||
var/obj/item/bodypart/storedpart
|
||||
var/initial_icon_state
|
||||
var/static/list/style_list_icons = list("standard" = 'icons/mob/augmentation/augments.dmi', "engineer" = 'icons/mob/augmentation/augments_engineer.dmi', "security" = 'icons/mob/augmentation/augments_security.dmi', "mining" = 'icons/mob/augmentation/augments_mining.dmi')
|
||||
var/static/list/style_list_icons = list("standard" = 'icons/mob/augmentation/augments.dmi',
|
||||
"engineer" = 'icons/mob/augmentation/augments_engineer.dmi',
|
||||
"security" = 'icons/mob/augmentation/augments_security.dmi',
|
||||
"mining" = 'icons/mob/augmentation/augments_mining.dmi',
|
||||
"Talon" = 'icons/mob/augmentation/cosmetic_prosthetic/talon.dmi',
|
||||
"Nanotrasen" = 'icons/mob/augmentation/cosmetic_prosthetic/nanotrasen.dmi',
|
||||
"Hephaesthus" = 'icons/mob/augmentation/cosmetic_prosthetic/hephaestus.dmi',
|
||||
"Bishop" = 'icons/mob/augmentation/cosmetic_prosthetic/bishop.dmi',
|
||||
"Xion" = 'icons/mob/augmentation/cosmetic_prosthetic/xion.dmi',
|
||||
"Grayson" = 'icons/mob/augmentation/cosmetic_prosthetic/grayson.dmi',
|
||||
"Cybersolutions" = 'icons/mob/augmentation/cosmetic_prosthetic/cybersolutions.dmi',
|
||||
"Ward" = 'icons/mob/augmentation/cosmetic_prosthetic/ward.dmi'
|
||||
)
|
||||
|
||||
/obj/machinery/aug_manipulator/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#define AUTOLATHE_MAIN_MENU 1
|
||||
#define AUTOLATHE_CATEGORY_MENU 2
|
||||
#define AUTOLATHE_SEARCH_MENU 3
|
||||
#define AUTOLATHE_MAIN_MENU 1
|
||||
#define AUTOLATHE_CATEGORY_MENU 2
|
||||
#define AUTOLATHE_SEARCH_MENU 3
|
||||
|
||||
/obj/machinery/autolathe
|
||||
name = "autolathe"
|
||||
@@ -17,7 +17,7 @@
|
||||
var/list/L = list()
|
||||
var/list/LL = list()
|
||||
var/hacked = FALSE
|
||||
var/disabled = 0
|
||||
var/disabled = FALSE
|
||||
var/shocked = FALSE
|
||||
var/hack_wire
|
||||
var/disable_wire
|
||||
@@ -27,13 +27,13 @@
|
||||
var/prod_coeff = 1
|
||||
|
||||
var/datum/design/being_built
|
||||
var/datum/techweb/stored_research
|
||||
var/list/datum/design/matching_designs
|
||||
var/selected_category
|
||||
var/screen = 1
|
||||
var/base_price = 25
|
||||
var/hacked_price = 50
|
||||
|
||||
var/datum/techweb/specialized/autounlocking/stored_research = /datum/techweb/specialized/autounlocking/autolathe
|
||||
var/list/categories = list(
|
||||
"Tools",
|
||||
"Electronics",
|
||||
@@ -46,19 +46,13 @@
|
||||
"Dinnerware",
|
||||
"Imported"
|
||||
)
|
||||
var/list/allowed_materials
|
||||
|
||||
/// Base print speed
|
||||
var/base_print_speed = 10
|
||||
|
||||
/obj/machinery/autolathe/Initialize()
|
||||
var/list/mats = allowed_materials
|
||||
if(!mats)
|
||||
mats = SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID]
|
||||
AddComponent(/datum/component/material_container, mats, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
AddComponent(/datum/component/material_container, SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID], 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
. = ..()
|
||||
|
||||
wires = new /datum/wires/autolathe(src)
|
||||
stored_research = new stored_research
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
|
||||
matching_designs = list()
|
||||
|
||||
/obj/machinery/autolathe/Destroy()
|
||||
@@ -83,7 +77,7 @@
|
||||
if(AUTOLATHE_SEARCH_MENU)
|
||||
dat = search_win(user)
|
||||
|
||||
var/datum/browser/popup = new(user, name, name, 400, 500)
|
||||
var/datum/browser/popup = new(user, "autolathe", name, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
@@ -114,9 +108,9 @@
|
||||
return TRUE
|
||||
|
||||
if(istype(O, /obj/item/disk/design_disk))
|
||||
user.visible_message("[user] begins to load \the [O] in \the [src]...",
|
||||
"You begin to load a design from \the [O]...",
|
||||
"You hear the chatter of a floppy drive.")
|
||||
user.visible_message("<span class='notice'>[user] begins to load \the [O] in \the [src]...</span>",
|
||||
"<span class='notice'>You begin to load a design from \the [O]...</span>",
|
||||
"<span class='hear'>You hear the chatter of a floppy drive.</span>")
|
||||
busy = TRUE
|
||||
var/obj/item/disk/design_disk/D = O
|
||||
if(do_after(user, 14.4, target = src))
|
||||
@@ -128,14 +122,16 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
|
||||
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
|
||||
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
use_power(MINERAL_MATERIAL_AMOUNT / 10)
|
||||
else if(item_inserted.custom_materials?.len && item_inserted.custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
|
||||
else if(custom_materials && custom_materials.len && custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
|
||||
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
|
||||
else
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
|
||||
|
||||
use_power(min(1000, amount_inserted / 100))
|
||||
updateUsrDialog()
|
||||
|
||||
@@ -187,7 +183,7 @@
|
||||
if(materials.materials[i] > 0)
|
||||
list_to_show += i
|
||||
|
||||
used_material = input("Choose [used_material]", "Custom Material") as null|anything in list_to_show
|
||||
used_material = input("Choose [used_material]", "Custom Material") as null|anything in sortList(list_to_show, /proc/cmp_typepaths_asc)
|
||||
if(!used_material)
|
||||
return //Didn't pick any material, so you can't build shit either.
|
||||
custom_materials[used_material] += amount_needed
|
||||
@@ -198,8 +194,8 @@
|
||||
busy = TRUE
|
||||
use_power(power)
|
||||
icon_state = "autolathe_n"
|
||||
var/time = is_stack ? 10 : base_print_speed * coeff * multiplier
|
||||
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack), time)
|
||||
var/time = is_stack ? 32 : (32 * coeff * multiplier) ** 0.8
|
||||
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack, usr), time)
|
||||
else
|
||||
to_chat(usr, "<span class=\"alert\">Not enough materials for this operation.</span>")
|
||||
|
||||
@@ -218,10 +214,11 @@
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/autolathe/proc/make_item(power, var/list/materials_used, var/list/picked_materials, multiplier, coeff, is_stack)
|
||||
/obj/machinery/autolathe/proc/make_item(power, list/materials_used, list/picked_materials, multiplier, coeff, is_stack, mob/user)
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/atom/A = drop_location()
|
||||
use_power(power)
|
||||
|
||||
materials.use_materials(materials_used)
|
||||
|
||||
if(is_stack)
|
||||
@@ -235,6 +232,11 @@
|
||||
|
||||
if(length(picked_materials))
|
||||
new_item.set_custom_materials(picked_materials, 1 / multiplier) //Ensure we get the non multiplied amount
|
||||
for(var/x in picked_materials)
|
||||
var/datum/material/M = x
|
||||
if(!istype(M, /datum/material/glass) && !istype(M, /datum/material/iron))
|
||||
user.client.give_award(/datum/award/achievement/misc/getting_an_upgrade, user)
|
||||
|
||||
|
||||
icon_state = "autolathe"
|
||||
busy = FALSE
|
||||
@@ -246,12 +248,10 @@
|
||||
T += MB.rating*75000
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.max_amount = T
|
||||
var/manips = 0
|
||||
var/total_manip_rating = 0
|
||||
T=1.2
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
total_manip_rating += M.rating
|
||||
manips++
|
||||
prod_coeff = STANDARD_PART_LEVEL_LATHE_COEFFICIENT(total_manip_rating / (manips? manips : 1))
|
||||
T -= M.rating*0.2
|
||||
prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4
|
||||
|
||||
/obj/machinery/autolathe/examine(mob/user)
|
||||
. += ..()
|
||||
@@ -376,6 +376,7 @@
|
||||
|
||||
return materials.has_materials(required_materials)
|
||||
|
||||
|
||||
/obj/machinery/autolathe/proc/get_design_cost(datum/design/D)
|
||||
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
|
||||
var/dat
|
||||
@@ -416,9 +417,7 @@
|
||||
hacked = state
|
||||
for(var/id in SSresearch.techweb_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
||||
if(D.build_type & stored_research.design_autounlock_skip_types)
|
||||
continue
|
||||
if((D.build_type & stored_research.design_autounlock_buildtypes) && ("hacked" in D.category))
|
||||
if((D.build_type & AUTOLATHE) && ("hacked" in D.category))
|
||||
if(hacked)
|
||||
stored_research.add_design(D)
|
||||
else
|
||||
@@ -428,19 +427,24 @@
|
||||
. = ..()
|
||||
adjust_hacked(TRUE)
|
||||
|
||||
//Called when the object is constructed by an autolathe
|
||||
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
|
||||
/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A)
|
||||
return
|
||||
|
||||
/obj/machinery/autolathe/secure
|
||||
name = "secured autolathe"
|
||||
desc = "It produces items using metal and glass. This model was reprogrammed without some of the more hazardous designs."
|
||||
circuit = /obj/item/circuitboard/machine/autolathe/secure
|
||||
stored_research = /datum/techweb/specialized/autounlocking/autolathe/public
|
||||
base_print_speed = 20
|
||||
|
||||
/obj/machinery/autolathe/secure/Initialize()
|
||||
. = ..()
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/public
|
||||
|
||||
/obj/machinery/autolathe/toy
|
||||
name = "autoylathe"
|
||||
desc = "It produces toys using plastic, metal and glass."
|
||||
circuit = /obj/item/circuitboard/machine/autolathe/toy
|
||||
|
||||
stored_research = /datum/techweb/specialized/autounlocking/autolathe/toy
|
||||
categories = list(
|
||||
"Toys",
|
||||
"Figurines",
|
||||
@@ -453,12 +457,8 @@
|
||||
"Misc",
|
||||
"Imported"
|
||||
)
|
||||
allowed_materials = list(
|
||||
/datum/material/iron,
|
||||
/datum/material/glass,
|
||||
/datum/material/plastic
|
||||
)
|
||||
|
||||
/obj/machinery/autolathe/toy/hacked/Initialize()
|
||||
. = ..()
|
||||
adjust_hacked(TRUE)
|
||||
stored_research = new /datum/techweb/specialized/autounlocking/autolathe/toy
|
||||
|
||||
@@ -3,14 +3,7 @@
|
||||
#define ARCADE_WEIGHT_RARE 1
|
||||
#define ARCADE_RATIO_PLUSH 0.20 // average 1 out of 6 wins is a plush.
|
||||
|
||||
/obj/machinery/computer/arcade
|
||||
name = "random arcade"
|
||||
desc = "random arcade machine"
|
||||
icon_state = "arcade"
|
||||
icon_keyboard = null
|
||||
icon_screen = "invaders"
|
||||
clockwork = TRUE //it'd look weird
|
||||
var/list/prizes = list(
|
||||
GLOBAL_LIST_INIT(arcade_prize_pool, list(
|
||||
/obj/item/toy/balloon = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/beach_ball = ARCADE_WEIGHT_USELESS,
|
||||
/obj/item/toy/cattoy = ARCADE_WEIGHT_USELESS,
|
||||
@@ -70,9 +63,16 @@
|
||||
/obj/item/clothing/mask/fakemoustache/italian = ARCADE_WEIGHT_RARE,
|
||||
/obj/item/clothing/suit/hooded/wintercoat/ratvar/fake = ARCADE_WEIGHT_TRICK,
|
||||
/obj/item/clothing/suit/hooded/wintercoat/narsie/fake = ARCADE_WEIGHT_TRICK
|
||||
)
|
||||
))
|
||||
|
||||
/obj/machinery/computer/arcade
|
||||
name = "random arcade"
|
||||
desc = "random arcade machine"
|
||||
icon_state = "arcade"
|
||||
icon_keyboard = "no_keyboard"
|
||||
icon_screen = "invaders"
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
var/list/prize_override
|
||||
|
||||
/obj/machinery/computer/arcade/proc/Reset()
|
||||
return
|
||||
@@ -91,44 +91,54 @@
|
||||
var/obj/machinery/computer/arcade/A = new CB.build_path(loc, CB)
|
||||
A.setDir(dir)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
//The below object acts as a spawner with a wide array of possible picks, most being uninspired references to past/current player characters.
|
||||
//Nevertheless, this keeps its ratio constant with the sum of all the others prizes.
|
||||
prizes[/obj/item/toy/plush/random] = counterlist_sum(prizes) * ARCADE_RATIO_PLUSH
|
||||
|
||||
Reset()
|
||||
|
||||
/obj/machinery/computer/arcade/proc/prizevend(mob/user, list/rarity_classes)
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade)
|
||||
/obj/machinery/computer/arcade/proc/prizevend(mob/user, prizes = 1)
|
||||
// if(user.mind?.get_skill_level(/datum/skill/gaming) >= SKILL_LEVEL_LEGENDARY && HAS_TRAIT(user, TRAIT_GAMERGOD))
|
||||
// visible_message("<span class='notice'>[user] inputs an intense cheat code!</span>",
|
||||
// "<span class='notice'>You hear a flurry of buttons being pressed.</span>")
|
||||
// say("CODE ACTIVATED: EXTRA PRIZES.")
|
||||
// prizes *= 2
|
||||
for(var/i = 0, i < prizes, i++)
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade)
|
||||
if(prob(0.0001)) //1 in a million
|
||||
new /obj/item/gun/energy/pulse/prize(src)
|
||||
visible_message("<span class='notice'>[src] dispenses.. woah, a gun! Way past cool.</span>", "<span class='notice'>You hear a chime and a shot.</span>")
|
||||
user.client.give_award(/datum/award/achievement/misc/pulse, user)
|
||||
return
|
||||
|
||||
if(prob(1) && prob(1) && prob(1)) //Proper 1 in a million
|
||||
new /obj/item/gun/energy/pulse/prize(src)
|
||||
SSmedals.UnlockMedal(MEDAL_PULSE, usr.client)
|
||||
var/prizeselect
|
||||
if(prize_override)
|
||||
prizeselect = pickweight(prize_override)
|
||||
else
|
||||
prizeselect = pickweight(GLOB.arcade_prize_pool)
|
||||
var/atom/movable/the_prize = new prizeselect(get_turf(src))
|
||||
playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3)
|
||||
visible_message("<span class='notice'>[src] dispenses [the_prize]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
|
||||
|
||||
if(!contents.len)
|
||||
var/list/toy_raffle
|
||||
if(rarity_classes)
|
||||
for(var/A in prizes)
|
||||
if(prizes[A] in rarity_classes)
|
||||
LAZYSET(toy_raffle, A, prizes[A])
|
||||
if(!toy_raffle)
|
||||
toy_raffle = prizes
|
||||
var/prizeselect = pickweight(toy_raffle)
|
||||
new prizeselect(src)
|
||||
|
||||
var/atom/movable/prize = pick(contents)
|
||||
visible_message("<span class='notice'>[src] dispenses [prize]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
|
||||
|
||||
prize.forceMove(get_turf(src))
|
||||
|
||||
/obj/machinery/computer/arcade/emp_act(severity)
|
||||
. = ..()
|
||||
var/override = FALSE
|
||||
if(prize_override)
|
||||
override = TRUE
|
||||
|
||||
if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF)
|
||||
return
|
||||
|
||||
var/empprize = null
|
||||
var/num_of_prizes = rand(round(severity/50),round(severity/100))
|
||||
var/num_of_prizes = 0
|
||||
switch(severity)
|
||||
if(1)
|
||||
num_of_prizes = rand(1,4)
|
||||
if(2)
|
||||
num_of_prizes = rand(0,2)
|
||||
for(var/i = num_of_prizes; i > 0; i--)
|
||||
empprize = pickweight(prizes)
|
||||
if(override)
|
||||
empprize = pickweight(prize_override)
|
||||
else
|
||||
empprize = pickweight(GLOB.arcade_prize_pool)
|
||||
new empprize(loc)
|
||||
explosion(loc, -1, 0, 1+num_of_prizes, flame_range = 1+num_of_prizes)
|
||||
|
||||
|
||||
@@ -1,130 +1,399 @@
|
||||
// ** BATTLE ** //
|
||||
|
||||
|
||||
/obj/machinery/computer/arcade/battle
|
||||
name = "arcade machine"
|
||||
desc = "Does not support Pinball."
|
||||
icon_state = "arcade"
|
||||
circuit = /obj/item/circuitboard/computer/arcade/battle
|
||||
var/enemy_name = "Space Villain"
|
||||
var/temp = "Winners don't use space drugs" //Temporary message, for attack messages, etc
|
||||
var/player_hp = 30 //Player health/attack points
|
||||
var/player_mp = 10
|
||||
var/enemy_hp = 45 //Enemy health/attack points
|
||||
var/enemy_mp = 20
|
||||
var/gameover = FALSE
|
||||
var/blocked = FALSE //Player cannot attack/heal while set
|
||||
var/turtle = 0
|
||||
|
||||
var/turn_speed = 5 //Measured in deciseconds.
|
||||
var/enemy_name = "Space Villain"
|
||||
///Enemy health/attack points
|
||||
var/enemy_hp = 100
|
||||
var/enemy_mp = 40
|
||||
///Temporary message, for attack messages, etc
|
||||
var/temp = "<br><center><h3>Winners don't use space drugs<center><h3>"
|
||||
///the list of passive skill the enemy currently has. the actual passives are added in the enemy_setup() proc
|
||||
var/list/enemy_passive
|
||||
///if all the enemy's weakpoints have been triggered becomes TRUE
|
||||
var/finishing_move = FALSE
|
||||
///linked to passives, when it's equal or above the max_passive finishing move will become TRUE
|
||||
var/pissed_off = 0
|
||||
///the number of passives the enemy will start with
|
||||
var/max_passive = 3
|
||||
///weapon wielded by the enemy, the shotgun doesn't count.
|
||||
var/chosen_weapon
|
||||
|
||||
///Player health
|
||||
var/player_hp = 85
|
||||
///player magic points
|
||||
var/player_mp = 20
|
||||
///used to remember the last three move of the player before this turn.
|
||||
var/list/last_three_move
|
||||
///if the enemy or player died. restart the game when TRUE
|
||||
var/gameover = FALSE
|
||||
///the player cannot make any move while this is set to TRUE. should only TRUE during enemy turns.
|
||||
var/blocked = FALSE
|
||||
///used to clear the enemy_action proc timer when the game is restarted
|
||||
var/timer_id
|
||||
///weapon used by the enemy, pure fluff.for certain actions
|
||||
var/list/weapons
|
||||
///unique to the emag mode, acts as a time limit where the player dies when it reaches 0.
|
||||
var/bomb_cooldown = 19
|
||||
|
||||
///creates the enemy base stats for a new round along with the enemy passives
|
||||
/obj/machinery/computer/arcade/battle/proc/enemy_setup(player_skill)
|
||||
player_hp = 85
|
||||
player_mp = 20
|
||||
enemy_hp = 100
|
||||
enemy_mp = 40
|
||||
gameover = FALSE
|
||||
blocked = FALSE
|
||||
finishing_move = FALSE
|
||||
pissed_off = 0
|
||||
last_three_move = null
|
||||
|
||||
enemy_passive = list("short_temper" = TRUE, "poisonous" = TRUE, "smart" = TRUE, "shotgun" = TRUE, "magical" = TRUE, "chonker" = TRUE)
|
||||
for(var/i = LAZYLEN(enemy_passive); i > max_passive; i--) //we'll remove passives from the list until we have the number of passive we want
|
||||
var/picked_passive = pick(enemy_passive)
|
||||
LAZYREMOVE(enemy_passive, picked_passive)
|
||||
|
||||
if(LAZYACCESS(enemy_passive, "chonker"))
|
||||
enemy_hp += 20
|
||||
|
||||
if(LAZYACCESS(enemy_passive, "shotgun"))
|
||||
chosen_weapon = "shotgun"
|
||||
else if(weapons)
|
||||
chosen_weapon = pick(weapons)
|
||||
else
|
||||
chosen_weapon = "null gun" //if the weapons list is somehow empty, shouldn't happen but runtimes are sneaky bastards.
|
||||
|
||||
if(player_skill)
|
||||
player_hp += player_skill * 2
|
||||
|
||||
/obj/machinery/computer/arcade/battle/Reset()
|
||||
max_passive = 3
|
||||
var/name_action
|
||||
var/name_part1
|
||||
var/name_part2
|
||||
|
||||
name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ", "Ban ")
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
|
||||
name_action = pick_list(ARCADE_FILE, "rpg_action_halloween")
|
||||
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_halloween")
|
||||
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_halloween")
|
||||
weapons = strings(ARCADE_FILE, "rpg_weapon_halloween")
|
||||
else if(SSevents.holidays && SSevents.holidays[CHRISTMAS])
|
||||
name_action = pick_list(ARCADE_FILE, "rpg_action_xmas")
|
||||
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_xmas")
|
||||
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_xmas")
|
||||
weapons = strings(ARCADE_FILE, "rpg_weapon_xmas")
|
||||
else if(SSevents.holidays && SSevents.holidays[VALENTINES])
|
||||
name_action = pick_list(ARCADE_FILE, "rpg_action_valentines")
|
||||
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective_valentines")
|
||||
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy_valentines")
|
||||
weapons = strings(ARCADE_FILE, "rpg_weapon_valentines")
|
||||
else
|
||||
name_action = pick_list(ARCADE_FILE, "rpg_action")
|
||||
name_part1 = pick_list(ARCADE_FILE, "rpg_adjective")
|
||||
name_part2 = pick_list(ARCADE_FILE, "rpg_enemy")
|
||||
weapons = strings(ARCADE_FILE, "rpg_weapon")
|
||||
|
||||
name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ")
|
||||
name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn", "Bloopers")
|
||||
enemy_name = ("The " + name_part1 + " " + name_part2)
|
||||
name = (name_action + " " + enemy_name)
|
||||
|
||||
enemy_name = replacetext((name_part1 + name_part2), "the ", "")
|
||||
name = (name_action + name_part1 + name_part2)
|
||||
enemy_setup(0) //in the case it's reset we assume the player skill is 0 because the VOID isn't a gamer
|
||||
|
||||
/obj/machinery/computer/arcade/battle/ui_interact(mob/user)
|
||||
. = ..()
|
||||
screen_setup(user)
|
||||
|
||||
///sets up the main screen for the user
|
||||
/obj/machinery/computer/arcade/battle/proc/screen_setup(mob/user)
|
||||
var/dat = "<a href='byond://?src=[REF(src)];close=1'>Close</a>"
|
||||
dat += "<center><h4>[enemy_name]</h4></center>"
|
||||
|
||||
dat += "<br><center><h3>[temp]</h3></center>"
|
||||
dat += "[temp]"
|
||||
dat += "<br><center>Health: [player_hp] | Magic: [player_mp] | Enemy Health: [enemy_hp]</center>"
|
||||
|
||||
if (gameover)
|
||||
dat += "<center><b><a href='byond://?src=[REF(src)];newgame=1'>New Game</a>"
|
||||
else
|
||||
dat += "<center><b><a href='byond://?src=[REF(src)];attack=1'>Attack</a> | "
|
||||
dat += "<a href='byond://?src=[REF(src)];heal=1'>Heal</a> | "
|
||||
dat += "<a href='byond://?src=[REF(src)];charge=1'>Recharge Power</a>"
|
||||
dat += "<center><b><a href='byond://?src=[REF(src)];attack=1'>Light attack</a>"
|
||||
dat += "<center><b><a href='byond://?src=[REF(src)];defend=1'>Defend</a>"
|
||||
dat += "<center><b><a href='byond://?src=[REF(src)];counter_attack=1'>Counter attack</a>"
|
||||
dat += "<center><b><a href='byond://?src=[REF(src)];power_attack=1'>Power attack</a>"
|
||||
|
||||
dat += "</b></center>"
|
||||
var/datum/browser/popup = new(user, "arcade", "Space Villain 2000")
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
if(user.client) //mainly here to avoid a runtime when the player gets gibbed when losing the emag mode.
|
||||
var/datum/browser/popup = new(user, "arcade", "Space Villain 2000")
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/arcade/battle/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
var/gamerSkill = 0
|
||||
// if(usr?.mind)
|
||||
// gamerSkill = usr.mind.get_skill_level(/datum/skill/gaming)
|
||||
|
||||
if (!blocked && !gameover)
|
||||
var/attackamt = rand(5,7) + rand(0, gamerSkill)
|
||||
|
||||
if(finishing_move) //time to bonk that fucker,cuban pete will sometime survive a finishing move.
|
||||
attackamt *= 100
|
||||
|
||||
//light attack suck absolute ass but it doesn't cost any MP so it's pretty good to finish an enemy off
|
||||
if (href_list["attack"])
|
||||
blocked = TRUE
|
||||
var/attackamt = rand(2,6)
|
||||
temp = "You attack for [attackamt] damage!"
|
||||
playsound(loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
|
||||
updateUsrDialog()
|
||||
if(turtle > 0)
|
||||
turtle--
|
||||
|
||||
sleep(turn_speed)
|
||||
temp = "<br><center><h3>you do quick jab for [attackamt] of damage!</h3></center>"
|
||||
enemy_hp -= attackamt
|
||||
arcade_action(usr)
|
||||
arcade_action(usr,"attack",attackamt)
|
||||
|
||||
else if (href_list["heal"])
|
||||
blocked = TRUE
|
||||
var/pointamt = rand(1,3)
|
||||
var/healamt = rand(6,8)
|
||||
temp = "You use [pointamt] magic to heal for [healamt] damage!"
|
||||
playsound(loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
|
||||
updateUsrDialog()
|
||||
turtle++
|
||||
//defend lets you gain back MP and take less damage from non magical attack.
|
||||
else if(href_list["defend"])
|
||||
temp = "<br><center><h3>you take a defensive stance and gain back 10 mp!</h3></center>"
|
||||
player_mp += 10
|
||||
arcade_action(usr,"defend",attackamt)
|
||||
playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
|
||||
|
||||
sleep(turn_speed)
|
||||
player_mp -= pointamt
|
||||
player_hp += healamt
|
||||
blocked = TRUE
|
||||
updateUsrDialog()
|
||||
arcade_action(usr)
|
||||
//mainly used to counter short temper and their absurd damage, will deal twice the damage the player took of a non magical attack.
|
||||
else if(href_list["counter_attack"] && player_mp >= 10)
|
||||
temp = "<br><center><h3>you prepare yourself to counter the next attack!</h3></center>"
|
||||
player_mp -= 10
|
||||
arcade_action(usr,"counter_attack",attackamt)
|
||||
playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
|
||||
|
||||
else if (href_list["charge"])
|
||||
blocked = TRUE
|
||||
var/chargeamt = rand(4,7)
|
||||
temp = "You regain [chargeamt] points"
|
||||
playsound(loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
|
||||
player_mp += chargeamt
|
||||
if(turtle > 0)
|
||||
turtle--
|
||||
else if(href_list["counter_attack"] && player_mp < 10)
|
||||
temp = "<br><center><h3>you don't have the mp necessary to counter attack and defend yourself instead</h3></center>"
|
||||
player_mp += 10
|
||||
arcade_action(usr,"defend",attackamt)
|
||||
playsound(src, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3)
|
||||
|
||||
updateUsrDialog()
|
||||
sleep(turn_speed)
|
||||
arcade_action(usr)
|
||||
//power attack deals twice the amount of damage but is really expensive MP wise, mainly used with combos to get weakpoints.
|
||||
else if (href_list["power_attack"] && player_mp >= 20)
|
||||
temp = "<br><center><h3>You attack [enemy_name] with all your might for [attackamt * 2] damage!</h3></center>"
|
||||
enemy_hp -= attackamt * 2
|
||||
player_mp -= 20
|
||||
arcade_action(usr,"power_attack",attackamt)
|
||||
|
||||
else if(href_list["power_attack"] && player_mp < 20)
|
||||
temp = "<br><center><h3>You don't have the mp necessary for a power attack and settle for a light attack!</h3></center>"
|
||||
enemy_hp -= attackamt
|
||||
arcade_action(usr,"attack",attackamt)
|
||||
|
||||
if (href_list["close"])
|
||||
usr.unset_machine()
|
||||
usr << browse(null, "window=arcade")
|
||||
|
||||
else if (href_list["newgame"]) //Reset everything
|
||||
temp = "New Round"
|
||||
player_hp = initial(player_hp)
|
||||
player_mp = initial(player_mp)
|
||||
enemy_hp = initial(enemy_hp)
|
||||
enemy_mp = initial(enemy_mp)
|
||||
gameover = FALSE
|
||||
turtle = 0
|
||||
temp = "<br><center><h3>New Round<center><h3>"
|
||||
|
||||
if(obj_flags & EMAGGED)
|
||||
Reset()
|
||||
obj_flags &= ~EMAGGED
|
||||
|
||||
enemy_setup(gamerSkill)
|
||||
screen_setup(usr)
|
||||
|
||||
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user)
|
||||
if ((enemy_mp <= 0) || (enemy_hp <= 0))
|
||||
///happens after a player action and before the enemy turn. the enemy turn will be cancelled if there's a gameover.
|
||||
/obj/machinery/computer/arcade/battle/proc/arcade_action(mob/user,player_stance,attackamt)
|
||||
screen_setup(user)
|
||||
blocked = TRUE
|
||||
if(player_stance == "attack" || player_stance == "power_attack")
|
||||
if(attackamt > 40)
|
||||
playsound(src, 'sound/arcade/boom.ogg', 50, TRUE, extrarange = -3)
|
||||
else
|
||||
playsound(src, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
|
||||
|
||||
timer_id = addtimer(CALLBACK(src, .proc/enemy_action,player_stance,user),1 SECONDS,TIMER_STOPPABLE)
|
||||
gameover_check(user)
|
||||
|
||||
///the enemy turn, the enemy's action entirely depend on their current passive and a teensy tiny bit of randomness
|
||||
/obj/machinery/computer/arcade/battle/proc/enemy_action(player_stance,mob/user)
|
||||
var/list/list_temp = list()
|
||||
|
||||
switch(LAZYLEN(last_three_move)) //we keep the last three action of the player in a list here
|
||||
if(0 to 2)
|
||||
LAZYADD(last_three_move, player_stance)
|
||||
if(3)
|
||||
for(var/i in 1 to 2)
|
||||
last_three_move[i] = last_three_move[i + 1]
|
||||
last_three_move[3] = player_stance
|
||||
|
||||
if(4 to INFINITY)
|
||||
last_three_move = null //this shouldn't even happen but we empty the list if it somehow goes above 3
|
||||
|
||||
var/enemy_stance
|
||||
var/attack_amount = rand(8,10) //making the attack amount not vary too much so that it's easier to see if the enemy has a shotgun
|
||||
|
||||
if(player_stance == "defend")
|
||||
attack_amount -= 5
|
||||
|
||||
//if emagged, cuban pete will set up a bomb acting up as a timer. when it reaches 0 the player fucking dies
|
||||
if(obj_flags & EMAGGED)
|
||||
switch(bomb_cooldown--)
|
||||
if(18)
|
||||
list_temp += "<br><center><h3>[enemy_name] takes two valve tank and links them together, what's he planning?<center><h3>"
|
||||
if(15)
|
||||
list_temp += "<br><center><h3>[enemy_name] adds a remote control to the tan- ho god is that a bomb?<center><h3>"
|
||||
if(12)
|
||||
list_temp += "<br><center><h3>[enemy_name] throws the bomb next to you, you'r too scared to pick it up. <center><h3>"
|
||||
if(6)
|
||||
list_temp += "<br><center><h3>[enemy_name]'s hand brushes the remote linked to the bomb, your heart skipped a beat. <center><h3>"
|
||||
if(2)
|
||||
list_temp += "<br><center><h3>[enemy_name] is going to press the button! It's now or never! <center><h3>"
|
||||
if(0)
|
||||
player_hp -= attack_amount * 1000 //hey it's a maxcap we might as well go all in
|
||||
|
||||
//yeah I used the shotgun as a passive, you know why? because the shotgun gives +5 attack which is pretty good
|
||||
if(LAZYACCESS(enemy_passive, "shotgun"))
|
||||
if(weakpoint_check("shotgun","defend","defend","power_attack"))
|
||||
list_temp += "<br><center><h3>You manage to disarm [enemy_name] with a surprise power attack and shoot him with his shotgun until it runs out of ammo! <center><h3> "
|
||||
enemy_hp -= 10
|
||||
chosen_weapon = "empty shotgun"
|
||||
else
|
||||
attack_amount += 5
|
||||
|
||||
//heccing chonker passive, only gives more HP at the start of a new game but has one of the hardest weakpoint to trigger.
|
||||
if(LAZYACCESS(enemy_passive, "chonker"))
|
||||
if(weakpoint_check("chonker","power_attack","power_attack","power_attack"))
|
||||
list_temp += "<br><center><h3>After a lot of power attacks you manage to tip over [enemy_name] as they fall over their enormous weight<center><h3> "
|
||||
enemy_hp -= 30
|
||||
|
||||
//smart passive trait, mainly works in tandem with other traits, makes the enemy unable to be counter_attacked
|
||||
if(LAZYACCESS(enemy_passive, "smart"))
|
||||
if(weakpoint_check("smart","defend","defend","attack"))
|
||||
list_temp += "<br><center><h3>[enemy_name] is confused by your illogical strategy!<center><h3> "
|
||||
attack_amount -= 5
|
||||
|
||||
else if(attack_amount >= player_hp)
|
||||
player_hp -= attack_amount
|
||||
list_temp += "<br><center><h3>[enemy_name] figures out you are really close to death and finishes you off with their [chosen_weapon]!<center><h3>"
|
||||
enemy_stance = "attack"
|
||||
|
||||
else if(player_stance == "counter_attack")
|
||||
list_temp += "<br><center><h3>[enemy_name] is not taking your bait. <center><h3> "
|
||||
if(LAZYACCESS(enemy_passive, "short_temper"))
|
||||
list_temp += "However controlling their hatred of you still takes a toll on their mental and physical health!"
|
||||
enemy_hp -= 5
|
||||
enemy_mp -= 5
|
||||
enemy_stance = "defensive"
|
||||
|
||||
//short temper passive trait, gets easily baited into being counter attacked but will bypass your counter when low on HP
|
||||
if(LAZYACCESS(enemy_passive, "short_temper"))
|
||||
if(weakpoint_check("short_temper","counter_attack","counter_attack","counter_attack"))
|
||||
list_temp += "<br><center><h3>[enemy_name] is getting frustrated at all your counter attacks and throws a tantrum!<center><h3>"
|
||||
enemy_hp -= attack_amount
|
||||
|
||||
else if(player_stance == "counter_attack")
|
||||
if(!(LAZYACCESS(enemy_passive, "smart")) && enemy_hp > 30)
|
||||
list_temp += "<br><center><h3>[enemy_name] took the bait and allowed you to counter attack for [attack_amount * 2] damage!<center><h3>"
|
||||
player_hp -= attack_amount
|
||||
enemy_hp -= attack_amount * 2
|
||||
enemy_stance = "attack"
|
||||
|
||||
else if(enemy_hp <= 30) //will break through the counter when low enough on HP even when smart.
|
||||
list_temp += "<br><center><h3>[enemy_name] is getting tired of your tricks and breaks through your counter with their [chosen_weapon]!<center><h3>"
|
||||
player_hp -= attack_amount
|
||||
enemy_stance = "attack"
|
||||
|
||||
else if(!enemy_stance)
|
||||
var/added_temp
|
||||
|
||||
if(rand())
|
||||
added_temp = "you for [attack_amount + 5] damage!"
|
||||
player_hp -= attack_amount + 5
|
||||
enemy_stance = "attack"
|
||||
else
|
||||
added_temp = "the wall, breaking their skull in the process and losing [attack_amount] hp!" //[enemy_name] you have a literal dent in your skull
|
||||
enemy_hp -= attack_amount
|
||||
enemy_stance = "attack"
|
||||
|
||||
list_temp += "<br><center><h3>[enemy_name] grits their teeth and charge right into [added_temp]<center><h3>"
|
||||
|
||||
//in the case none of the previous passive triggered, Mainly here to set an enemy stance for passives that needs it like the magical passive.
|
||||
if(!enemy_stance)
|
||||
enemy_stance = pick("attack","defensive")
|
||||
if(enemy_stance == "attack")
|
||||
player_hp -= attack_amount
|
||||
list_temp += "<br><center><h3>[enemy_name] attacks you for [attack_amount] points of damage with their [chosen_weapon]<center><h3>"
|
||||
if(player_stance == "counter_attack")
|
||||
enemy_hp -= attack_amount * 2
|
||||
list_temp += "<br><center><h3>You counter [enemy_name]'s attack and deal [attack_amount * 2] points of damage!<center><h3>"
|
||||
|
||||
if(enemy_stance == "defensive" && enemy_mp < 15)
|
||||
list_temp += "<br><center><h3>[enemy_name] take some time to get some mp back!<center><h3> "
|
||||
enemy_mp += attack_amount
|
||||
|
||||
else if (enemy_stance == "defensive" && enemy_mp >= 15 && !(LAZYACCESS(enemy_passive, "magical")))
|
||||
list_temp += "<br><center><h3>[enemy_name] quickly heal themselves for 5 hp!<center><h3> "
|
||||
enemy_mp -= 15
|
||||
enemy_hp += 5
|
||||
|
||||
//magical passive trait, recharges MP nearly every turn it's not blasting you with magic.
|
||||
if(LAZYACCESS(enemy_passive, "magical"))
|
||||
if(player_mp >= 50)
|
||||
list_temp += "<br><center><h3>the huge amount of magical energy you have acumulated throws [enemy_name] off balance!<center><h3>"
|
||||
enemy_mp = 0
|
||||
LAZYREMOVE(enemy_passive, "magical")
|
||||
pissed_off++
|
||||
|
||||
else if(LAZYACCESS(enemy_passive, "smart") && player_stance == "counter_attack" && enemy_mp >= 20)
|
||||
list_temp += "<br><center><h3>[enemy_name] blasts you with magic from afar for 10 points of damage before you can counter!<center><h3>"
|
||||
player_hp -= 10
|
||||
enemy_mp -= 20
|
||||
|
||||
else if(enemy_hp >= 20 && enemy_mp >= 40 && enemy_stance == "defensive")
|
||||
list_temp += "<br><center><h3>[enemy_name] Blasts you with magic from afar!<center><h3>"
|
||||
enemy_mp -= 40
|
||||
player_hp -= 30
|
||||
enemy_stance = "attack"
|
||||
|
||||
else if(enemy_hp < 20 && enemy_mp >= 20 && enemy_stance == "defensive") //it's a pretty expensive spell so they can't spam it that much
|
||||
list_temp += "<br><center><h3>[enemy_name] heal themselves with magic and gain back 20 hp!<center><h3>"
|
||||
enemy_hp += 20
|
||||
enemy_mp -= 30
|
||||
else
|
||||
list_temp += "<br><center><h3>[enemy_name]'s magical nature lets them get some mp back!<center><h3>"
|
||||
enemy_mp += attack_amount
|
||||
|
||||
//poisonous passive trait, while it's less damage added than the shotgun it acts up even when the enemy doesn't attack at all.
|
||||
if(LAZYACCESS(enemy_passive, "poisonous"))
|
||||
if(weakpoint_check("poisonous","attack","attack","attack"))
|
||||
list_temp += "<br><center><h3>your flurry of attack throws back the poisonnous gas at [enemy_name] and makes them choke on it!<center><h3> "
|
||||
enemy_hp -= 5
|
||||
else
|
||||
list_temp += "<br><center><h3>the stinky breath of [enemy_name] hurts you for 3 hp!<center><h3> "
|
||||
player_hp -= 3
|
||||
|
||||
//if all passive's weakpoint have been triggered, set finishing_move to TRUE
|
||||
if(pissed_off >= max_passive && !finishing_move)
|
||||
list_temp += "<br><center><h3>You have weakened [enemy_name] enough for them to show their weak point, you will do 10 times as much damage with your next attack!<center><h3> "
|
||||
finishing_move = TRUE
|
||||
|
||||
playsound(src, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
|
||||
|
||||
temp = list_temp.Join()
|
||||
gameover_check(user)
|
||||
screen_setup(user)
|
||||
blocked = FALSE
|
||||
|
||||
|
||||
/obj/machinery/computer/arcade/battle/proc/gameover_check(mob/user)
|
||||
var/xp_gained = 0
|
||||
if(enemy_hp <= 0)
|
||||
if(!gameover)
|
||||
if(timer_id)
|
||||
deltimer(timer_id)
|
||||
timer_id = null
|
||||
if(player_hp <= 0)
|
||||
player_hp = 1 //let's just pretend the enemy didn't kill you so not both the player and enemy look dead.
|
||||
gameover = TRUE
|
||||
temp = "[enemy_name] has fallen! Rejoice!"
|
||||
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3)
|
||||
blocked = FALSE
|
||||
temp = "<br><center><h3>[enemy_name] has fallen! Rejoice!<center><h3>"
|
||||
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE)
|
||||
|
||||
if(obj_flags & EMAGGED)
|
||||
new /obj/effect/spawner/newbomb/timer/syndicate(loc)
|
||||
@@ -133,78 +402,76 @@
|
||||
log_game("[key_name(usr)] has outbombed Cuban Pete and been awarded a bomb.")
|
||||
Reset()
|
||||
obj_flags &= ~EMAGGED
|
||||
xp_gained += 100
|
||||
else
|
||||
prizevend(user)
|
||||
xp_gained += 50
|
||||
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("win", (obj_flags & EMAGGED ? "emagged":"normal")))
|
||||
|
||||
|
||||
else if ((obj_flags & EMAGGED) && (turtle >= 4))
|
||||
var/boomamt = rand(5,10)
|
||||
temp = "[enemy_name] throws a bomb, exploding you for [boomamt] damage!"
|
||||
playsound(loc, 'sound/arcade/boom.ogg', 50, TRUE, extrarange = -3)
|
||||
player_hp -= boomamt
|
||||
|
||||
else if ((enemy_mp <= 5) && (prob(70)))
|
||||
var/stealamt = rand(2,3)
|
||||
temp = "[enemy_name] steals [stealamt] of your power!"
|
||||
playsound(loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3)
|
||||
player_mp -= stealamt
|
||||
updateUsrDialog()
|
||||
|
||||
if (player_mp <= 0)
|
||||
gameover = TRUE
|
||||
sleep(turn_speed)
|
||||
temp = "You have been drained! GAME OVER"
|
||||
playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3)
|
||||
if(obj_flags & EMAGGED)
|
||||
usr.gib()
|
||||
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "mana", (obj_flags & EMAGGED ? "emagged":"normal")))
|
||||
|
||||
else if ((enemy_hp <= 10) && (enemy_mp > 4))
|
||||
temp = "[enemy_name] heals for 4 health!"
|
||||
playsound(loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3)
|
||||
enemy_hp += 4
|
||||
enemy_mp -= 4
|
||||
|
||||
else
|
||||
var/attackamt = rand(3,6)
|
||||
temp = "[enemy_name] attacks for [attackamt] damage!"
|
||||
playsound(loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3)
|
||||
player_hp -= attackamt
|
||||
|
||||
if ((player_mp <= 0) || (player_hp <= 0))
|
||||
else if(player_hp <= 0)
|
||||
if(timer_id)
|
||||
deltimer(timer_id)
|
||||
timer_id = null
|
||||
gameover = TRUE
|
||||
temp = "You have been crushed! GAME OVER"
|
||||
playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3)
|
||||
temp = "<br><center><h3>You have been crushed! GAME OVER<center><h3>"
|
||||
playsound(loc, 'sound/arcade/lose.ogg', 50, TRUE)
|
||||
xp_gained += 10//pity points
|
||||
if(obj_flags & EMAGGED)
|
||||
usr.gib()
|
||||
var/mob/living/living_user = user
|
||||
if (istype(living_user))
|
||||
living_user.gib()
|
||||
SSblackbox.record_feedback("nested tally", "arcade_results", 1, list("loss", "hp", (obj_flags & EMAGGED ? "emagged":"normal")))
|
||||
|
||||
blocked = FALSE
|
||||
return
|
||||
// if(gameover)
|
||||
// user?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1)//always gain at least 1 point of XP
|
||||
|
||||
|
||||
///used to check if the last three move of the player are the one we want in the right order and if the passive's weakpoint has been triggered yet
|
||||
/obj/machinery/computer/arcade/battle/proc/weakpoint_check(passive,first_move,second_move,third_move)
|
||||
if(LAZYLEN(last_three_move) < 3)
|
||||
return FALSE
|
||||
|
||||
if(last_three_move[1] == first_move && last_three_move[2] == second_move && last_three_move[3] == third_move && LAZYACCESS(enemy_passive, passive))
|
||||
LAZYREMOVE(enemy_passive, passive)
|
||||
pissed_off++
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/machinery/computer/arcade/battle/Destroy()
|
||||
enemy_passive = null
|
||||
weapons = null
|
||||
last_three_move = null
|
||||
return ..() //well boys we did it, lists are no more
|
||||
|
||||
/obj/machinery/computer/arcade/battle/examine_more(mob/user)
|
||||
to_chat(user, "<span class='notice'>Scribbled on the side of the Arcade Machine you notice some writing...\
|
||||
\nmagical -> >=50 power\
|
||||
\nsmart -> defend, defend, light attack\
|
||||
\nshotgun -> defend, defend, power attack\
|
||||
\nshort temper -> counter, counter, counter\
|
||||
\npoisonous -> light attack, light attack, light attack\
|
||||
\nchonker -> power attack, power attack, power attack</span>")
|
||||
return ..()
|
||||
var/list/msg = list("<span class='notice'><i>You notice some writing scribbled on the side of [src]...</i></span>")
|
||||
msg += "\t<span class='info'>smart -> defend, defend, light attack</span>"
|
||||
msg += "\t<span class='info'>shotgun -> defend, defend, power attack</span>"
|
||||
msg += "\t<span class='info'>short temper -> counter, counter, counter</span>"
|
||||
msg += "\t<span class='info'>poisonous -> light attack, light attack, light attack</span>"
|
||||
msg += "\t<span class='info'>chonker -> power attack, power attack, power attack</span>"
|
||||
return msg
|
||||
|
||||
/obj/machinery/computer/arcade/battle/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='warning'>A mesmerizing Rhumba beat starts playing from the arcade machine's speakers!</span>")
|
||||
temp = "If you die in the game, you die for real!"
|
||||
player_hp = 30
|
||||
player_mp = 10
|
||||
enemy_hp = 45
|
||||
enemy_mp = 20
|
||||
temp = "<br><center><h2>If you die in the game, you die for real!<center><h2>"
|
||||
max_passive = 6
|
||||
bomb_cooldown = 18
|
||||
var/gamerSkill = 0
|
||||
// if(usr?.mind)
|
||||
// gamerSkill = usr.mind.get_skill_level(/datum/skill/gaming)
|
||||
enemy_setup(gamerSkill)
|
||||
enemy_hp += 100 //extra HP just to make cuban pete even more bullshit
|
||||
player_hp += 30 //the player will also get a few extra HP in order to have a fucking chance
|
||||
|
||||
screen_setup(user)
|
||||
gameover = FALSE
|
||||
blocked = FALSE
|
||||
|
||||
obj_flags |= EMAGGED
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@
|
||||
visible_message("<span class='notice'>[src] dispenses [itemname]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
|
||||
DISABLE_BITFIELD(obj_flags, EMAGGED)
|
||||
else
|
||||
var/dope_prizes = (area >= 480) ? list(ARCADE_WEIGHT_RARE) : (area >= 256) ? list(ARCADE_WEIGHT_RARE, ARCADE_WEIGHT_TRICK) : null
|
||||
var/dope_prizes = (area >= 480) ? 6 : (area >= 256) ? 4 : 2
|
||||
prizevend(user, dope_prizes)
|
||||
|
||||
if(game_status == MINESWEEPER_GAME_WON)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
icon_state = "arcade"
|
||||
circuit = /obj/item/circuitboard/computer/arcade/amputation
|
||||
|
||||
/obj/machinery/computer/arcade/amputation/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
/obj/machinery/computer/arcade/amputation/on_attack_hand(mob/user)
|
||||
if(!iscarbon(user))
|
||||
return
|
||||
var/mob/living/carbon/c_user = user
|
||||
@@ -24,8 +24,13 @@
|
||||
var/obj/item/bodypart/chopchop = c_user.get_bodypart(which_hand)
|
||||
chopchop.dismember()
|
||||
qdel(chopchop)
|
||||
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3)
|
||||
for(var/i=1; i<=rand(3,5); i++)
|
||||
prizevend(user)
|
||||
// user.mind?.adjust_experience(/datum/skill/gaming, 100)
|
||||
playsound(loc, 'sound/arcade/win.ogg', 50, TRUE)
|
||||
prizevend(user, rand(3,5))
|
||||
else
|
||||
to_chat(c_user, "<span class='notice'>You (wisely) decide against putting your hand in the machine.</span>")
|
||||
|
||||
/obj/machinery/computer/arcade/amputation/festive //dispenses wrapped gifts instead of arcade prizes, also known as the ancap christmas tree
|
||||
name = "Mediborg's Festive Amputation Adventure"
|
||||
desc = "A picture of a blood-soaked medical cyborg wearing a Santa hat flashes on the screen. The mediborg has a speech bubble that says, \"Put your hand in the machine if you aren't a <b>coward!</b>\""
|
||||
prize_override = list(/obj/item/a_gift/anything = 1)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
// *** THE ORION TRAIL ** //
|
||||
|
||||
#define ORION_TRAIL_WINTURN 9
|
||||
@@ -15,6 +13,8 @@
|
||||
#define ORION_TRAIL_COLLISION "Collision"
|
||||
#define ORION_TRAIL_SPACEPORT "Spaceport"
|
||||
#define ORION_TRAIL_BLACKHOLE "BlackHole"
|
||||
#define ORION_TRAIL_OLDSHIP "Old Ship"
|
||||
#define ORION_TRAIL_SEARCH "Old Ship Search"
|
||||
|
||||
#define ORION_STATUS_START 1
|
||||
#define ORION_STATUS_NORMAL 2
|
||||
@@ -44,7 +44,8 @@
|
||||
ORION_TRAIL_LING = 3,
|
||||
ORION_TRAIL_MALFUNCTION = 2,
|
||||
ORION_TRAIL_COLLISION = 1,
|
||||
ORION_TRAIL_SPACEPORT = 2
|
||||
ORION_TRAIL_SPACEPORT = 2,
|
||||
ORION_TRAIL_OLDSHIP = 2
|
||||
)
|
||||
var/list/stops = list()
|
||||
var/list/stopblurbs = list()
|
||||
@@ -55,13 +56,27 @@
|
||||
var/gameStatus = ORION_STATUS_START
|
||||
var/canContinueEvent = 0
|
||||
|
||||
var/obj/item/radio/Radio
|
||||
var/list/gamers = list()
|
||||
var/killed_crew = 0
|
||||
|
||||
|
||||
/obj/machinery/computer/arcade/orion_trail/Initialize()
|
||||
. = ..()
|
||||
Radio = new /obj/item/radio(src)
|
||||
Radio.listening = 0
|
||||
|
||||
/obj/machinery/computer/arcade/orion_trail/Destroy()
|
||||
QDEL_NULL(Radio)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/arcade/orion_trail/kobayashi
|
||||
name = "Kobayashi Maru control computer"
|
||||
desc = "A test for cadets"
|
||||
icon = 'icons/obj/machines/particle_accelerator.dmi'
|
||||
icon_state = "control_boxp"
|
||||
events = list("Raiders" = 3, "Interstellar Flux" = 1, "Illness" = 3, "Breakdown" = 2, "Malfunction" = 2, "Collision" = 1, "Spaceport" = 2)
|
||||
prizes = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1)
|
||||
prize_override = list(/obj/item/paper/fluff/holodeck/trek_diploma = 1)
|
||||
settlers = list("Kirk","Worf","Gene")
|
||||
|
||||
/obj/machinery/computer/arcade/orion_trail/Reset()
|
||||
@@ -96,14 +111,52 @@
|
||||
event = null
|
||||
gameStatus = ORION_STATUS_NORMAL
|
||||
lings_aboard = 0
|
||||
killed_crew = 0
|
||||
|
||||
//spaceport junk
|
||||
spaceport_raided = 0
|
||||
spaceport_freebie = 0
|
||||
last_spaceport_action = ""
|
||||
|
||||
/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/user)
|
||||
/obj/machinery/computer/arcade/orion_trail/proc/report_player(mob/gamer)
|
||||
if(gamers[gamer] == -2)
|
||||
return // enough harassing them
|
||||
|
||||
if(gamers[gamer] == -1)
|
||||
say("WARNING: Continued antisocial behavior detected: Dispensing self-help literature.")
|
||||
new /obj/item/paper/pamphlet/violent_video_games(drop_location())
|
||||
gamers[gamer]--
|
||||
return
|
||||
|
||||
if(!(gamer in gamers))
|
||||
gamers[gamer] = 0
|
||||
|
||||
gamers[gamer]++ // How many times the player has 'prestiged' (massacred their crew)
|
||||
|
||||
if(gamers[gamer] > 2 && prob(20 * gamers[gamer]))
|
||||
|
||||
Radio.set_frequency(FREQ_SECURITY)
|
||||
Radio.talk_into(src, "SECURITY ALERT: Crewmember [gamer] recorded displaying antisocial tendencies in [get_area(src)]. Please watch for violent behavior.", FREQ_SECURITY)
|
||||
|
||||
Radio.set_frequency(FREQ_MEDICAL)
|
||||
Radio.talk_into(src, "PSYCH ALERT: Crewmember [gamer] recorded displaying antisocial tendencies in [get_area(src)]. Please schedule psych evaluation.", FREQ_MEDICAL)
|
||||
|
||||
gamers[gamer] = -1
|
||||
|
||||
gamer.client.give_award(/datum/award/achievement/misc/gamer, gamer) // PSYCH REPORT NOTE: patient kept rambling about how they did it for an "achievement", recommend continued holding for observation
|
||||
// gamer.mind?.adjust_experience(/datum/skill/gaming, 50) // cheevos make u better
|
||||
|
||||
if(!isnull(GLOB.data_core.general))
|
||||
for(var/datum/data/record/R in GLOB.data_core.general)
|
||||
if(R.fields["name"] == gamer.name)
|
||||
R.fields["m_stat"] = "*Unstable*"
|
||||
return
|
||||
|
||||
/obj/machinery/computer/arcade/orion_trail/ui_interact(mob/_user)
|
||||
. = ..()
|
||||
if (!isliving(_user))
|
||||
return
|
||||
var/mob/living/user = _user
|
||||
if(fuel <= 0 || food <=0 || settlers.len == 0)
|
||||
gameStatus = ORION_STATUS_GAMEOVER
|
||||
event = null
|
||||
@@ -136,6 +189,8 @@
|
||||
desc = "Learn how our ancestors got to Orion, and have fun in the process!"
|
||||
|
||||
dat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];menu=1'>May They Rest In Peace</a></P>"
|
||||
// user?.mind?.adjust_experience(/datum/skill/gaming, 10)//learning from your mistakes is the first rule of roguelikes
|
||||
|
||||
else if(event)
|
||||
dat = eventdat
|
||||
else if(gameStatus == ORION_STATUS_NORMAL)
|
||||
@@ -174,20 +229,32 @@
|
||||
return
|
||||
busy = TRUE
|
||||
|
||||
// var/gamerSkillLevel = 0
|
||||
var/gamerSkill = 0
|
||||
var/gamerSkillRands = 0
|
||||
|
||||
// if(usr?.mind)
|
||||
// gamerSkillLevel = usr.mind.get_skill_level(/datum/skill/gaming)
|
||||
// gamerSkill = usr.mind.get_skill_modifier(/datum/skill/gaming, SKILL_PROBS_MODIFIER)
|
||||
// gamerSkillRands = usr.mind.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER)
|
||||
|
||||
|
||||
var/xp_gained = 0
|
||||
if (href_list["continue"]) //Continue your travels
|
||||
if(gameStatus == ORION_STATUS_NORMAL && !event && turns != 7)
|
||||
if(turns >= ORION_TRAIL_WINTURN)
|
||||
win(usr)
|
||||
xp_gained += 34
|
||||
else
|
||||
food -= (alive+lings_aboard)*2
|
||||
fuel -= 5
|
||||
if(turns == 2 && prob(30))
|
||||
if(turns == 2 && prob(30-gamerSkill))
|
||||
event = ORION_TRAIL_COLLISION
|
||||
event()
|
||||
else if(prob(75))
|
||||
else if(prob(75-gamerSkill))
|
||||
event = pickweight(events)
|
||||
if(lings_aboard)
|
||||
if(event == ORION_TRAIL_LING || prob(55))
|
||||
if(event == ORION_TRAIL_LING || prob(55-gamerSkill))
|
||||
event = ORION_TRAIL_LING_ATTACK
|
||||
event()
|
||||
turns += 1
|
||||
@@ -195,15 +262,18 @@
|
||||
var/mob/living/carbon/M = usr //for some vars
|
||||
switch(event)
|
||||
if(ORION_TRAIL_RAIDERS)
|
||||
if(prob(50))
|
||||
if(prob(50-gamerSkill))
|
||||
to_chat(usr, "<span class='userdanger'>You hear battle shouts. The tramping of boots on cold metal. Screams of agony. The rush of venting air. Are you going insane?</span>")
|
||||
M.hallucination += 30
|
||||
else
|
||||
to_chat(usr, "<span class='userdanger'>Something strikes you from behind! It hurts like hell and feel like a blunt weapon, but nothing is there...</span>")
|
||||
M.take_bodypart_damage(30)
|
||||
playsound(loc, 'sound/weapons/genhit2.ogg', 100, 1)
|
||||
playsound(loc, 'sound/weapons/genhit2.ogg', 100, TRUE)
|
||||
if(ORION_TRAIL_ILLNESS)
|
||||
var/severity = rand(1,3) //pray to RNGesus. PRAY, PIGS
|
||||
var/maxSeverity = 3
|
||||
// if(gamerSkillLevel >= SKILL_LEVEL_EXPERT)
|
||||
// maxSeverity = 2 //part of gitting gud is rng mitigation
|
||||
var/severity = rand(1,maxSeverity) //pray to RNGesus. PRAY, PIGS
|
||||
if(severity == 1)
|
||||
to_chat(M, "<span class='userdanger'>You suddenly feel slightly nauseated.</span>" )
|
||||
if(severity == 2)
|
||||
@@ -215,16 +285,16 @@
|
||||
sleep(30)
|
||||
M.vomit(10, distance = 5)
|
||||
if(ORION_TRAIL_FLUX)
|
||||
if(prob(75))
|
||||
if(prob(75-gamerSkill))
|
||||
M.DefaultCombatKnockdown(60)
|
||||
say("A sudden gust of powerful wind slams [M] into the floor!")
|
||||
M.take_bodypart_damage(25)
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 100, TRUE)
|
||||
else
|
||||
to_chat(M, "<span class='userdanger'>A violent gale blows past you, and you barely manage to stay standing!</span>")
|
||||
if(ORION_TRAIL_COLLISION) //by far the most damaging event
|
||||
if(prob(90))
|
||||
playsound(loc, 'sound/effects/bang.ogg', 100, 1)
|
||||
if(prob(90-gamerSkill))
|
||||
playsound(loc, 'sound/effects/bang.ogg', 100, TRUE)
|
||||
var/turf/open/floor/F
|
||||
for(F in orange(1, src))
|
||||
F.ScrapeAway()
|
||||
@@ -232,15 +302,15 @@
|
||||
if(hull)
|
||||
sleep(10)
|
||||
say("A new floor suddenly appears around [src]. What the hell?")
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 100, 1)
|
||||
playsound(loc, 'sound/weapons/genhit.ogg', 100, TRUE)
|
||||
var/turf/open/space/T
|
||||
for(T in orange(1, src))
|
||||
T.PlaceOnTop(/turf/open/floor/plating)
|
||||
else
|
||||
say("Something slams into the floor around [src] - luckily, it didn't get through!")
|
||||
playsound(loc, 'sound/effects/bang.ogg', 50, 1)
|
||||
playsound(loc, 'sound/effects/bang.ogg', 50, TRUE)
|
||||
if(ORION_TRAIL_MALFUNCTION)
|
||||
playsound(loc, 'sound/effects/empulse.ogg', 50, 1)
|
||||
playsound(loc, 'sound/effects/empulse.ogg', 50, TRUE)
|
||||
visible_message("<span class='danger'>[src] malfunctions, randomizing in-game stats!</span>")
|
||||
var/oldfood = food
|
||||
var/oldfuel = fuel
|
||||
@@ -254,7 +324,7 @@
|
||||
audible_message("<span class='danger'>[src] lets out a somehow ominous chime.</span>")
|
||||
food = oldfood
|
||||
fuel = oldfuel
|
||||
playsound(loc, 'sound/machines/chime.ogg', 50, 1)
|
||||
playsound(loc, 'sound/machines/chime.ogg', 50, TRUE)
|
||||
|
||||
else if(href_list["newgame"]) //Reset everything
|
||||
if(gameStatus == ORION_STATUS_START)
|
||||
@@ -266,6 +336,10 @@
|
||||
food = 80
|
||||
fuel = 60
|
||||
settlers = list("Harry","Larry","Bob")
|
||||
else if(href_list["search"]) //search old ship
|
||||
if(event == ORION_TRAIL_OLDSHIP)
|
||||
event = ORION_TRAIL_SEARCH
|
||||
event()
|
||||
else if(href_list["slow"]) //slow down
|
||||
if(event == ORION_TRAIL_FLUX)
|
||||
food -= (alive+lings_aboard)*2
|
||||
@@ -302,11 +376,11 @@
|
||||
event = null
|
||||
else if(href_list["blackhole"]) //keep speed past a black hole
|
||||
if(turns == 7)
|
||||
if(prob(75))
|
||||
if(prob(75-gamerSkill))
|
||||
event = ORION_TRAIL_BLACKHOLE
|
||||
event()
|
||||
if(obj_flags & EMAGGED)
|
||||
playsound(loc, 'sound/effects/supermatter.ogg', 100, 1)
|
||||
playsound(loc, 'sound/effects/supermatter.ogg', 100, TRUE)
|
||||
say("A miniature black hole suddenly appears in front of [src], devouring [usr] alive!")
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
@@ -328,22 +402,29 @@
|
||||
else if(href_list["killcrew"]) //shoot a crewmember
|
||||
if(gameStatus == ORION_STATUS_NORMAL || event == ORION_TRAIL_LING)
|
||||
var/sheriff = remove_crewmember() //I shot the sheriff
|
||||
playsound(loc,'sound/weapons/gunshot.ogg', 100, 1)
|
||||
playsound(loc,'sound/weapons/gunshot.ogg', 100, TRUE)
|
||||
killed_crew++
|
||||
|
||||
var/mob/living/user = usr
|
||||
|
||||
if(settlers.len == 0 || alive == 0)
|
||||
say("The last crewmember [sheriff], shot themselves, GAME OVER!")
|
||||
if(obj_flags & EMAGGED)
|
||||
usr.death(0)
|
||||
obj_flags &= EMAGGED
|
||||
user.death(FALSE)
|
||||
gameStatus = ORION_STATUS_GAMEOVER
|
||||
event = null
|
||||
|
||||
if(killed_crew >= 4)
|
||||
xp_gained -= 15//no cheating by spamming game overs
|
||||
report_player(usr)
|
||||
else if(obj_flags & EMAGGED)
|
||||
if(usr.name == sheriff)
|
||||
say("The crew of the ship chose to kill [usr.name]!")
|
||||
usr.death(0)
|
||||
user.death(FALSE)
|
||||
|
||||
if(event == ORION_TRAIL_LING) //only ends the ORION_TRAIL_LING event, since you can do this action in multiple places
|
||||
event = null
|
||||
killed_crew-- // the kill was valid
|
||||
|
||||
//Spaceport specific interactions
|
||||
//they get a header because most of them don't reset event (because it's a shop, you leave when you want to)
|
||||
@@ -356,6 +437,7 @@
|
||||
fuel -= 10
|
||||
food -= 10
|
||||
event()
|
||||
killed_crew-- // I mean not really but you know
|
||||
|
||||
else if(href_list["sellcrew"]) //sell a crewmember
|
||||
if(gameStatus == ORION_STATUS_MARKET)
|
||||
@@ -377,15 +459,16 @@
|
||||
else if(href_list["raid_spaceport"])
|
||||
if(gameStatus == ORION_STATUS_MARKET)
|
||||
if(!spaceport_raided)
|
||||
var/success = min(15 * alive,100) //default crew (4) have a 60% chance
|
||||
var/success = min(15 * alive + gamerSkill,100) //default crew (4) have a 60% chance
|
||||
spaceport_raided = 1
|
||||
|
||||
var/FU = 0
|
||||
var/FO = 0
|
||||
if(prob(success))
|
||||
FU = rand(5,15)
|
||||
FO = rand(5,15)
|
||||
FU = rand(5 + gamerSkillRands,15 + gamerSkillRands)
|
||||
FO = rand(5 + gamerSkillRands,15 + gamerSkillRands)
|
||||
last_spaceport_action = "You successfully raided the spaceport! You gained [FU] Fuel and [FO] Food! (+[FU]FU,+[FO]FO)"
|
||||
xp_gained += 10
|
||||
else
|
||||
FU = rand(-5,-15)
|
||||
FO = rand(-5,-15)
|
||||
@@ -444,8 +527,7 @@
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
busy = FALSE
|
||||
return
|
||||
|
||||
// usr?.mind?.adjust_experience(/datum/skill/gaming, xp_gained+1)
|
||||
|
||||
/obj/machinery/computer/arcade/orion_trail/proc/event()
|
||||
eventdat = "<center><h1>[event]</h1></center>"
|
||||
@@ -474,6 +556,38 @@
|
||||
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];slow=1'>Slow Down</a> <a href='byond://?src=[REF(src)];keepspeed=1'>Continue</a></P>"
|
||||
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
|
||||
|
||||
if(ORION_TRAIL_OLDSHIP)
|
||||
eventdat += "<br>Your crew spots an old ship floating through space. It might have some supplies, but then again it looks rather unsafe."
|
||||
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];search=1'>Search it</a><a href='byond://?src=[REF(src)];eventclose=1'>Leave it</a></P><P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
|
||||
canContinueEvent = 1
|
||||
|
||||
if(ORION_TRAIL_SEARCH)
|
||||
switch(rand(100))
|
||||
if(0 to 15)
|
||||
var/rescued = add_crewmember()
|
||||
var/oldfood = rand(1,7)
|
||||
var/oldfuel = rand(4,10)
|
||||
food += oldfood
|
||||
fuel += oldfuel
|
||||
eventdat += "<br>As you look through it you find some supplies and a living person!"
|
||||
eventdat += "<br>[rescued] was rescued from the abandoned ship!"
|
||||
eventdat += "<br>You found [oldfood] <b>Food</b> and [oldfuel] <b>Fuel</b>."
|
||||
if(15 to 35)
|
||||
var/lfuel = rand(4,7)
|
||||
var/deadname = remove_crewmember()
|
||||
fuel -= lfuel
|
||||
eventdat += "<br>[deadname] was lost deep in the wreckage, and your own vessel lost [lfuel] <b>Fuel</b> maneuvering to the the abandoned ship."
|
||||
if(35 to 65)
|
||||
var/oldfood = rand(5,11)
|
||||
food += oldfood
|
||||
engine++
|
||||
eventdat += "<br>You found [oldfood] <b>Food</b> and some parts amongst the wreck."
|
||||
else
|
||||
eventdat += "<br>As you look through the wreck you cannot find much of use."
|
||||
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];eventclose=1'>Continue</a></P>"
|
||||
eventdat += "<P ALIGN=Right><a href='byond://?src=[REF(src)];close=1'>Close</a></P>"
|
||||
canContinueEvent = 1
|
||||
|
||||
if(ORION_TRAIL_ILLNESS)
|
||||
eventdat += "A deadly illness has been contracted!"
|
||||
var/deadname = remove_crewmember()
|
||||
@@ -687,7 +801,7 @@
|
||||
|
||||
|
||||
//Add Random/Specific crewmember
|
||||
/obj/machinery/computer/arcade/orion_trail/proc/add_crewmember(var/specific = "")
|
||||
/obj/machinery/computer/arcade/orion_trail/proc/add_crewmember(specific = "")
|
||||
var/newcrew = ""
|
||||
if(specific)
|
||||
newcrew = specific
|
||||
@@ -703,7 +817,7 @@
|
||||
|
||||
|
||||
//Remove Random/Specific crewmember
|
||||
/obj/machinery/computer/arcade/orion_trail/proc/remove_crewmember(var/specific = "", var/dont_remove = "")
|
||||
/obj/machinery/computer/arcade/orion_trail/proc/remove_crewmember(specific = "", dont_remove = "")
|
||||
var/list/safe2remove = settlers
|
||||
var/removed = ""
|
||||
if(dont_remove)
|
||||
@@ -779,14 +893,14 @@
|
||||
to_chat(user, "<span class='warning'>You flip the switch on the underside of [src].</span>")
|
||||
active = 1
|
||||
visible_message("<span class='notice'>[src] softly beeps and whirs to life!</span>")
|
||||
playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, 1)
|
||||
playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, TRUE)
|
||||
say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.")
|
||||
sleep(20)
|
||||
visible_message("<span class='warning'>[src] begins to vibrate...</span>")
|
||||
say("Uh, Port? Having some issues with our reactor, could you check it out? Over.")
|
||||
sleep(30)
|
||||
say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-")
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, 1)
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, TRUE)
|
||||
sleep(3.6)
|
||||
visible_message("<span class='userdanger'>[src] explodes!</span>")
|
||||
explosion(loc, 2,4,8, flame_range = 16)
|
||||
|
||||
@@ -92,6 +92,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
icon_screen = "tank"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
var/frequency = FREQ_ATMOS_STORAGE
|
||||
var/list/sensors = list(
|
||||
@@ -102,6 +103,20 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_AIR = "Mixed Air Tank",
|
||||
ATMOS_GAS_MONITOR_SENSOR_MIX = "Mix Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_BZ = "BZ Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_FREON = "Freon Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_HALON = "Halon Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_HEALIUM = "Healium Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_H2 = "Hydrogen Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM = "Hypernoblium Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_MIASMA = "Miasma Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_NO2 = "Nitryl Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM = "Pluoxium Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE = "Proto-Nitrate Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_STIMULUM = "Stimulum Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_TRITIUM = "Tritium Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_H2O = "Water Vapor Tank",
|
||||
// ATMOS_GAS_MONITOR_SENSOR_ZAUKER = "Zauker Tank",
|
||||
ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION = "Distribution Loop",
|
||||
ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE = "Atmos Waste Loop",
|
||||
ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber",
|
||||
@@ -110,7 +125,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
var/list/sensor_information = list()
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
light_color = LIGHT_COLOR_CYAN
|
||||
|
||||
/obj/machinery/computer/atmos_control/Initialize()
|
||||
. = ..()
|
||||
@@ -165,15 +179,10 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
/obj/machinery/computer/atmos_control/incinerator
|
||||
name = "Incinerator Air Control"
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber")
|
||||
ui_x = 400
|
||||
ui_y = 300
|
||||
|
||||
//Toxins mix sensor only
|
||||
/obj/machinery/computer/atmos_control/toxinsmix
|
||||
name = "Toxins Mixing Air Control"
|
||||
sensors = list(ATMOS_GAS_MONITOR_SENSOR_TOXINS_LAB = "Toxins Mixing Chamber")
|
||||
ui_x = 400
|
||||
ui_y = 300
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// LARGE TANK CONTROL
|
||||
@@ -184,13 +193,9 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
var/output_tag
|
||||
frequency = FREQ_ATMOS_STORAGE
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control/tank
|
||||
|
||||
var/list/input_info
|
||||
var/list/output_info
|
||||
|
||||
ui_x = 500
|
||||
ui_y = 315
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/oxygen_tank
|
||||
name = "Oxygen Supply Control"
|
||||
input_tag = ATMOS_GAS_MONITOR_INPUT_O2
|
||||
@@ -236,7 +241,7 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
// This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this
|
||||
/obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user)
|
||||
var/list/IO = list()
|
||||
var/datum/radio_frequency/freq = SSradio.return_frequency(FREQ_ATMOS_STORAGE)
|
||||
var/datum/radio_frequency/freq = SSradio.return_frequency(frequency)
|
||||
var/list/devices = freq.devices["_default"]
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
|
||||
var/list/text = splittext(U.id_tag, "_")
|
||||
@@ -252,10 +257,11 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
src.output_tag = "[S]_out"
|
||||
name = "[uppertext(S)] Supply Control"
|
||||
var/list/new_devices = freq.devices["4"]
|
||||
sensors.Cut()
|
||||
for(var/obj/machinery/air_sensor/U in new_devices)
|
||||
var/list/text = splittext(U.id_tag, "_")
|
||||
if(text[1] == S)
|
||||
sensors = list("[S]_sensor" = "Tank")
|
||||
sensors = list("[S]_sensor" = "[S] Tank")
|
||||
break
|
||||
|
||||
for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices)
|
||||
@@ -268,13 +274,16 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
data["tank"] = TRUE
|
||||
data["inputting"] = input_info ? input_info["power"] : FALSE
|
||||
data["inputRate"] = input_info ? input_info["volume_rate"] : 0
|
||||
data["maxInputRate"] = input_info ? MAX_TRANSFER_RATE : 0
|
||||
data["outputting"] = output_info ? output_info["power"] : FALSE
|
||||
data["outputPressure"] = output_info ? output_info["internal"] : 0
|
||||
|
||||
data["maxOutputPressure"] = output_info ? MAX_OUTPUT_PRESSURE : 0
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/atmos_control/tank/ui_act(action, params)
|
||||
if(..() || !radio_connection)
|
||||
. = ..()
|
||||
|
||||
if(. || !radio_connection)
|
||||
return
|
||||
var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr))
|
||||
switch(action)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define DEFAULT_MAP_SIZE 15
|
||||
|
||||
/obj/machinery/computer/security
|
||||
name = "security camera console"
|
||||
desc = "Used to access the various cameras on the station."
|
||||
@@ -8,15 +10,19 @@
|
||||
|
||||
var/list/network = list("ss13")
|
||||
var/obj/machinery/camera/active_camera
|
||||
/// The turf where the camera was last updated.
|
||||
var/turf/last_camera_turf
|
||||
var/list/concurrent_users = list()
|
||||
|
||||
// Stuff needed to render the map
|
||||
var/map_name
|
||||
var/const/default_map_size = 15
|
||||
var/obj/screen/cam_screen
|
||||
var/obj/screen/plane_master/lighting/cam_plane_master
|
||||
var/obj/screen/map_view/cam_screen
|
||||
/// All the plane masters that need to be applied.
|
||||
var/list/cam_plane_masters
|
||||
var/obj/screen/background/cam_background
|
||||
|
||||
interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_SET_MACHINE //| INTERACT_MACHINE_REQUIRES_SIGHT
|
||||
|
||||
/obj/machinery/computer/security/Initialize()
|
||||
. = ..()
|
||||
// Map name has to start and end with an A-Z character,
|
||||
@@ -33,18 +39,20 @@
|
||||
cam_screen.assigned_map = map_name
|
||||
cam_screen.del_on_map_removal = FALSE
|
||||
cam_screen.screen_loc = "[map_name]:1,1"
|
||||
cam_plane_master = new
|
||||
cam_plane_master.name = "plane_master"
|
||||
cam_plane_master.assigned_map = map_name
|
||||
cam_plane_master.del_on_map_removal = FALSE
|
||||
cam_plane_master.screen_loc = "[map_name]:CENTER"
|
||||
cam_plane_masters = list()
|
||||
for(var/plane in subtypesof(/obj/screen/plane_master))
|
||||
var/obj/screen/instance = new plane()
|
||||
instance.assigned_map = map_name
|
||||
instance.del_on_map_removal = FALSE
|
||||
instance.screen_loc = "[map_name]:CENTER"
|
||||
cam_plane_masters += instance
|
||||
cam_background = new
|
||||
cam_background.assigned_map = map_name
|
||||
cam_background.del_on_map_removal = FALSE
|
||||
|
||||
/obj/machinery/computer/security/Destroy()
|
||||
qdel(cam_screen)
|
||||
qdel(cam_plane_master)
|
||||
QDEL_LIST(cam_plane_masters)
|
||||
qdel(cam_background)
|
||||
return ..()
|
||||
|
||||
@@ -56,9 +64,10 @@
|
||||
/obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui)
|
||||
// Update UI
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
// Show static if can't use the camera
|
||||
if(!active_camera?.can_use())
|
||||
show_camera_static()
|
||||
|
||||
// Update the camera, showing static if necessary and updating data if the location has moved.
|
||||
update_active_camera_screen()
|
||||
|
||||
if(!ui)
|
||||
var/user_ref = REF(user)
|
||||
var/is_living = isliving(user)
|
||||
@@ -72,7 +81,7 @@
|
||||
use_power(active_power_usage)
|
||||
// Register map objects
|
||||
user.client.register_map_obj(cam_screen)
|
||||
for(var/plane in cam_plane_master)
|
||||
for(var/plane in cam_plane_masters)
|
||||
user.client.register_map_obj(plane)
|
||||
user.client.register_map_obj(cam_background)
|
||||
// Open UI
|
||||
@@ -100,6 +109,7 @@
|
||||
data["cameras"] += list(list(
|
||||
name = C.c_tag,
|
||||
))
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/security/ui_act(action, params)
|
||||
@@ -110,31 +120,51 @@
|
||||
if(action == "switch_camera")
|
||||
var/c_tag = params["name"]
|
||||
var/list/cameras = get_available_cameras()
|
||||
var/obj/machinery/camera/C = cameras[c_tag]
|
||||
active_camera = C
|
||||
var/obj/machinery/camera/selected_camera = cameras[c_tag]
|
||||
active_camera = selected_camera
|
||||
playsound(src, get_sfx("terminal_type"), 25, FALSE)
|
||||
|
||||
// Show static if can't use the camera
|
||||
if(!active_camera?.can_use())
|
||||
show_camera_static()
|
||||
if(!selected_camera)
|
||||
return TRUE
|
||||
|
||||
var/list/visible_turfs = list()
|
||||
for(var/turf/T in (C.isXRay() \
|
||||
? range(C.view_range, C) \
|
||||
: view(C.view_range, C)))
|
||||
visible_turfs += T
|
||||
|
||||
var/list/bbox = get_bbox_of_atoms(visible_turfs)
|
||||
var/size_x = bbox[3] - bbox[1] + 1
|
||||
var/size_y = bbox[4] - bbox[2] + 1
|
||||
|
||||
cam_screen.vis_contents = visible_turfs
|
||||
cam_background.icon_state = "clear"
|
||||
cam_background.fill_rect(1, 1, size_x, size_y)
|
||||
update_active_camera_screen()
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/security/proc/update_active_camera_screen()
|
||||
// Show static if can't use the camera
|
||||
if(!active_camera?.can_use())
|
||||
show_camera_static()
|
||||
return
|
||||
|
||||
var/list/visible_turfs = list()
|
||||
|
||||
// Is this camera located in or attached to a living thing? If so, assume the camera's loc is the living thing.
|
||||
var/cam_location = isliving(active_camera.loc) ? active_camera.loc : active_camera
|
||||
|
||||
// If we're not forcing an update for some reason and the cameras are in the same location,
|
||||
// we don't need to update anything.
|
||||
// Most security cameras will end here as they're not moving.
|
||||
var/newturf = get_turf(cam_location)
|
||||
if(last_camera_turf == newturf)
|
||||
return
|
||||
|
||||
// Cameras that get here are moving, and are likely attached to some moving atom such as cyborgs.
|
||||
last_camera_turf = get_turf(cam_location)
|
||||
|
||||
var/list/visible_things = active_camera.isXRay() ? range(active_camera.view_range, cam_location) : view(active_camera.view_range, cam_location)
|
||||
|
||||
for(var/turf/visible_turf in visible_things)
|
||||
visible_turfs += visible_turf
|
||||
|
||||
var/list/bbox = get_bbox_of_atoms(visible_turfs)
|
||||
var/size_x = bbox[3] - bbox[1] + 1
|
||||
var/size_y = bbox[4] - bbox[2] + 1
|
||||
|
||||
cam_screen.vis_contents = visible_turfs
|
||||
cam_background.icon_state = "clear"
|
||||
cam_background.fill_rect(1, 1, size_x, size_y)
|
||||
|
||||
/obj/machinery/computer/security/ui_close(mob/user)
|
||||
var/user_ref = REF(user)
|
||||
var/is_living = isliving(user)
|
||||
@@ -151,7 +181,7 @@
|
||||
/obj/machinery/computer/security/proc/show_camera_static()
|
||||
cam_screen.vis_contents.Cut()
|
||||
cam_background.icon_state = "scanline2"
|
||||
cam_background.fill_rect(1, 1, default_map_size, default_map_size)
|
||||
cam_background.fill_rect(1, 1, DEFAULT_MAP_SIZE, DEFAULT_MAP_SIZE)
|
||||
|
||||
// Returns the list of cameras accessible from this computer
|
||||
/obj/machinery/computer/security/proc/get_available_cameras()
|
||||
@@ -179,7 +209,7 @@
|
||||
name = "security camera monitor"
|
||||
desc = "An old TV hooked into the station's camera network."
|
||||
icon_state = "television"
|
||||
icon_keyboard = null
|
||||
icon_keyboard = "no_keyboard"
|
||||
icon_screen = "detective_tv"
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
@@ -211,7 +241,7 @@
|
||||
|
||||
/obj/machinery/computer/security/qm
|
||||
name = "\improper Quartermaster's camera console"
|
||||
desc = "A console with access to the mining, auxillary base and vault camera networks."
|
||||
desc = "A console with access to the mining, auxiliary base and vault camera networks."
|
||||
network = list("mine", "auxbase", "vault")
|
||||
circuit = null
|
||||
|
||||
@@ -222,17 +252,12 @@
|
||||
desc = "Used for watching an empty arena."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "telescreen"
|
||||
layer = SIGN_LAYER
|
||||
network = list("thunder")
|
||||
density = FALSE
|
||||
circuit = null
|
||||
light_power = 0
|
||||
|
||||
/obj/machinery/computer/security/telescreen/Initialize()
|
||||
. = ..()
|
||||
var/turf/T = get_turf_pixel(src)
|
||||
if(iswallturf(T))
|
||||
plane = ABOVE_WALL_PLANE
|
||||
|
||||
/obj/machinery/computer/security/telescreen/update_icon_state()
|
||||
icon_state = initial(icon_state)
|
||||
if(stat & BROKEN)
|
||||
@@ -246,21 +271,19 @@
|
||||
network = list("thunder")
|
||||
density = FALSE
|
||||
circuit = null
|
||||
//interaction_flags_atom = NONE // interact() is called by BigClick()
|
||||
interaction_flags_atom = NONE // interact() is called by BigClick()
|
||||
var/icon_state_off = "entertainment_blank"
|
||||
var/icon_state_on = "entertainment"
|
||||
|
||||
/* If someone would like to try to get this long-distance viewing thing working, be my guest. I tried everything I could possibly think of and it just refused to operate correctly.
|
||||
|
||||
/obj/machinery/computer/security/telescreen/entertainment/Initialize()
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_CLICK, .proc/BigClick)
|
||||
|
||||
// Bypass clickchain to allow humans to use the telescreen from a distance
|
||||
/obj/machinery/computer/security/telescreen/entertainment/proc/BigClick()
|
||||
interact(usr)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
*/
|
||||
INVOKE_ASYNC(src, /atom.proc/interact, usr)
|
||||
|
||||
/obj/machinery/computer/security/telescreen/entertainment/proc/notify(on)
|
||||
if(on && icon_state == icon_state_off)
|
||||
@@ -279,8 +302,8 @@
|
||||
network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/circuitry
|
||||
name = "circuitry telescreen"
|
||||
desc = "Used for watching the other eggheads from the safety of the circuitry lab."
|
||||
name = "research telescreen"
|
||||
desc = "A telescreen with access to the research division's camera network."
|
||||
network = list("rd")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/ce
|
||||
@@ -324,8 +347,8 @@
|
||||
network = list("prison")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/auxbase
|
||||
name = "auxillary base monitor"
|
||||
desc = "A telescreen that connects to the auxillary base's camera."
|
||||
name = "auxiliary base monitor"
|
||||
desc = "A telescreen that connects to the auxiliary base's camera."
|
||||
network = list("auxbase")
|
||||
|
||||
/obj/machinery/computer/security/telescreen/minisat
|
||||
@@ -346,3 +369,5 @@
|
||||
for(var/i in network)
|
||||
network -= i
|
||||
network += "[idnum][i]"
|
||||
|
||||
#undef DEFAULT_MAP_SIZE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,38 @@
|
||||
/obj/machinery/computer/pod
|
||||
name = "mass driver launch control"
|
||||
desc = "A combined blastdoor and mass driver control unit."
|
||||
// processing_flags = START_PROCESSING_MANUALLY
|
||||
/// Connected mass driver
|
||||
var/obj/machinery/mass_driver/connected = null
|
||||
var/title = "Mass Driver Controls"
|
||||
/// ID of the launch control
|
||||
var/id = 1
|
||||
var/timing = 0
|
||||
/// If the launch timer counts down
|
||||
var/timing = FALSE
|
||||
/// Time before auto launch
|
||||
var/time = 30
|
||||
/// Range in which we search for a mass drivers and poddoors nearby
|
||||
var/range = 4
|
||||
|
||||
/// Countdown timer for the mass driver's delayed launch functionality.
|
||||
COOLDOWN_DECLARE(massdriver_countdown)
|
||||
|
||||
/obj/machinery/computer/pod/Initialize()
|
||||
. = ..()
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
connected = M
|
||||
break
|
||||
|
||||
/obj/machinery/computer/pod/process(delta_time)
|
||||
if(COOLDOWN_FINISHED(src, massdriver_countdown))
|
||||
timing = FALSE
|
||||
// alarm() sleeps, so we want to end processing first and can't rely on return PROCESS_KILL
|
||||
// end_processing()
|
||||
STOP_PROCESSING(SSmachines, src)
|
||||
alarm()
|
||||
|
||||
/**
|
||||
* Initiates launching sequence by checking if all components are functional, opening poddoors, firing mass drivers and then closing poddoors
|
||||
*/
|
||||
/obj/machinery/computer/pod/proc/alarm()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
@@ -39,92 +56,112 @@
|
||||
if(M.id == id)
|
||||
M.close()
|
||||
|
||||
/obj/machinery/computer/pod/ui_interact(mob/user)
|
||||
/obj/machinery/computer/pod/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "MassDriverControl", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/pod/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
// If the cooldown has finished, just display the time. If the cooldown hasn't finished, display the cooldown.
|
||||
var/display_time = COOLDOWN_FINISHED(src, massdriver_countdown) ? time : COOLDOWN_TIMELEFT(src, massdriver_countdown) * 0.1
|
||||
data["connected"] = connected ? TRUE : FALSE
|
||||
data["seconds"] = round(display_time % 60)
|
||||
data["minutes"] = round((display_time - data["seconds"]) / 60)
|
||||
data["timing"] = timing
|
||||
data["power"] = connected ? connected.power : 0.25
|
||||
data["poddoor"] = FALSE
|
||||
for(var/obj/machinery/door/poddoor/door in range(range, src))
|
||||
if(door.id == id)
|
||||
data["poddoor"] = TRUE
|
||||
break
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/pod/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='warning'>Access denied.</span>")
|
||||
if(.)
|
||||
return
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
|
||||
var/dat = ""
|
||||
if(connected)
|
||||
var/d2
|
||||
if(timing) //door controls do not need timers.
|
||||
d2 = "<A href='?src=[REF(src)];time=0'>Stop Time Launch</A>"
|
||||
else
|
||||
d2 = "<A href='?src=[REF(src)];time=1'>Initiate Time Launch</A>"
|
||||
dat += "<HR>\nTimer System: [d2]\nTime Left: [DisplayTimeText(time)] <A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
|
||||
var/temp = ""
|
||||
var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 )
|
||||
for(var/t in L)
|
||||
if(t == connected.power)
|
||||
temp += "[t] "
|
||||
switch(action)
|
||||
if("set_power")
|
||||
if(!connected)
|
||||
return
|
||||
var/value = text2num(params["power"])
|
||||
if(!value)
|
||||
return
|
||||
value = clamp(value, 0.25, 16)
|
||||
connected.power = value
|
||||
return TRUE
|
||||
if("launch")
|
||||
alarm()
|
||||
return TRUE
|
||||
if("time")
|
||||
timing = !timing
|
||||
if(timing)
|
||||
COOLDOWN_START(src, massdriver_countdown, time SECONDS)
|
||||
// begin_processing()
|
||||
START_PROCESSING(SSmachines, src)
|
||||
else
|
||||
temp += "<A href = '?src=[REF(src)];power=[t]'>[t]</A> "
|
||||
dat += "<HR>\nPower Level: [temp]<BR>\n<A href = '?src=[REF(src)];alarm=1'>Firing Sequence</A><BR>\n<A href = '?src=[REF(src)];drive=1'>Test Fire Driver</A><BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
|
||||
else
|
||||
dat += "<BR>\n<A href = '?src=[REF(src)];door=1'>Toggle Outer Door</A><BR>"
|
||||
dat += "<BR><BR><A href='?src=[REF(user)];mach_close=computer'>Close</A>"
|
||||
add_fingerprint(usr)
|
||||
var/datum/browser/popup = new(user, "computer", title, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/computer/pod/process()
|
||||
if(!..())
|
||||
return
|
||||
if(timing)
|
||||
if(time > 0)
|
||||
time = round(time) - 1
|
||||
else
|
||||
alarm()
|
||||
time = 0
|
||||
timing = 0
|
||||
updateDialog()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
|
||||
usr.set_machine(src)
|
||||
if(href_list["power"])
|
||||
var/t = text2num(href_list["power"])
|
||||
t = min(max(0.25, t), 16)
|
||||
if(connected)
|
||||
connected.power = t
|
||||
if(href_list["alarm"])
|
||||
alarm()
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
time += tp
|
||||
time = min(max(round(time), 0), 120)
|
||||
if(href_list["door"])
|
||||
time = COOLDOWN_TIMELEFT(src, massdriver_countdown) * 0.1
|
||||
COOLDOWN_RESET(src, massdriver_countdown)
|
||||
// end_processing()
|
||||
STOP_PROCESSING(SSmachines, src)
|
||||
return TRUE
|
||||
if("input")
|
||||
var/value = text2num(params["adjust"])
|
||||
if(!value)
|
||||
return
|
||||
value = round(time + value)
|
||||
time = clamp(value, 0, 120)
|
||||
return TRUE
|
||||
if("door")
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
if(M.density)
|
||||
M.open()
|
||||
else
|
||||
M.close()
|
||||
if(href_list["drive"])
|
||||
return TRUE
|
||||
if("driver_test")
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.power = connected.power
|
||||
M.power = connected?.power
|
||||
M.drive()
|
||||
updateUsrDialog()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/pod/old
|
||||
name = "\improper DoorMex control console"
|
||||
title = "Door Controls"
|
||||
icon_state = "oldcomp"
|
||||
icon_screen = "library"
|
||||
icon_keyboard = null
|
||||
icon_keyboard = "no_keyboard"
|
||||
|
||||
// /obj/machinery/computer/pod/old/mass_driver_controller
|
||||
// name = "\improper Mass Driver Controller"
|
||||
// icon = 'icons/obj/airlock_machines.dmi'
|
||||
// icon_state = "airlock_control_standby"
|
||||
// icon_keyboard = "no_keyboard"
|
||||
// density = FALSE
|
||||
|
||||
// /obj/machinery/computer/pod/old/mass_driver_controller/toxinsdriver
|
||||
// id = MASSDRIVER_TOXINS
|
||||
|
||||
// //for maps where pod doors are outside of the standard 4 tile controller detection range (ie Pubbystation)
|
||||
// /obj/machinery/computer/pod/old/mass_driver_controller/toxinsdriver/longrange
|
||||
// range = 6
|
||||
|
||||
// /obj/machinery/computer/pod/old/mass_driver_controller/chapelgun
|
||||
// id = MASSDRIVER_CHAPEL
|
||||
|
||||
// /obj/machinery/computer/pod/old/mass_driver_controller/trash
|
||||
// id = MASSDRIVER_DISPOSALS
|
||||
|
||||
/obj/machinery/computer/pod/old/syndicate
|
||||
name = "\improper ProComp Executive IIc"
|
||||
desc = "The Syndicate operate on a tight budget. Operates external airlocks."
|
||||
title = "External Airlock Controls"
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/machinery/computer/pod/old/swf
|
||||
|
||||
@@ -11,8 +11,24 @@
|
||||
var/id = 1
|
||||
var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess.
|
||||
|
||||
/obj/machinery/mass_driver/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
|
||||
id = "[idnum][id]"
|
||||
// /obj/machinery/mass_driver/chapelgun
|
||||
// name = "holy driver"
|
||||
// id = MASSDRIVER_CHAPEL
|
||||
|
||||
// /obj/machinery/mass_driver/toxins
|
||||
// id = MASSDRIVER_TOXINS
|
||||
|
||||
// /obj/machinery/mass_driver/trash
|
||||
// id = MASSDRIVER_DISPOSALS
|
||||
|
||||
// /obj/machinery/mass_driver/Destroy()
|
||||
// for(var/obj/machinery/computer/pod/control in GLOB.machines)
|
||||
// if(control.id == id)
|
||||
// control.connected = null
|
||||
// return ..()
|
||||
|
||||
/obj/machinery/mass_driver/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
|
||||
id = "[port.id]_[id]"
|
||||
|
||||
/obj/machinery/mass_driver/proc/drive(amount)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
@@ -22,6 +38,8 @@
|
||||
var/atom/target = get_edge_target_turf(src, dir)
|
||||
for(var/atom/movable/O in loc)
|
||||
if(!O.anchored || ismecha(O)) //Mechs need their launch platforms.
|
||||
if(ismob(O) && !isliving(O))
|
||||
continue
|
||||
O_limit++
|
||||
if(O_limit >= 20)
|
||||
audible_message("<span class='notice'>[src] lets out a screech, it doesn't seem to be able to handle the load.</span>")
|
||||
@@ -30,7 +48,6 @@
|
||||
O.throw_at(target, drive_range * power, power)
|
||||
flick("mass_driver1", src)
|
||||
|
||||
|
||||
/obj/machinery/mass_driver/emp_act(severity)
|
||||
. = ..()
|
||||
if (. & EMP_PROTECT_SELF)
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/Initialize(mapload)
|
||||
stored_research = new
|
||||
rmat = AddComponent(/datum/component/remote_materials, "mechfab", mapload && link_on_init)
|
||||
rmat = AddComponent(/datum/component/remote_materials, "mechfab", mapload && link_on_init, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
|
||||
RefreshParts() //Recalculating local material sizes if the fab isn't linked
|
||||
return ..()
|
||||
@@ -676,4 +676,3 @@
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/offstation
|
||||
link_on_init = FALSE
|
||||
circuit = /obj/item/circuitboard/machine/mechfab/offstation
|
||||
|
||||
@@ -133,7 +133,6 @@
|
||||
icon_state += "-open"
|
||||
add_radio()
|
||||
add_cabin()
|
||||
add_airtank()
|
||||
spark_system.set_up(2, 0, src)
|
||||
spark_system.attach(src)
|
||||
smoke_system.set_up(3, src)
|
||||
@@ -149,6 +148,11 @@
|
||||
diag_hud_set_mechhealth()
|
||||
diag_hud_set_mechcell()
|
||||
diag_hud_set_mechstat()
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/mecha/LateInitialize()
|
||||
. = ..()
|
||||
add_airtank()
|
||||
|
||||
/obj/mecha/get_cell()
|
||||
return cell
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
integrity = round((M.obj_integrity / M.max_integrity) * 100),
|
||||
charge = M.cell ? round(M.cell.percent()) : null,
|
||||
airtank = M.internal_tank ? M.return_pressure() : null,
|
||||
pilot = M.occupant,
|
||||
pilot = list(M.occupant),
|
||||
location = get_area_name(M, TRUE),
|
||||
active_equipment = M.selected,
|
||||
emp_recharging = MT.recharging,
|
||||
@@ -38,7 +38,7 @@
|
||||
if(istype(M, /obj/mecha/working/ripley))
|
||||
var/obj/mecha/working/ripley/RM = M
|
||||
mech_data += list(
|
||||
cargo_space = round((RM.cargo.len / RM.cargo_capacity) * 100)
|
||||
cargo_space = round((LAZYLEN(RM.cargo) / RM.cargo_capacity) * 100)
|
||||
)
|
||||
|
||||
data["mechs"] += list(mech_data)
|
||||
@@ -46,7 +46,8 @@
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/mecha/ui_act(action, params)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
@@ -57,7 +58,7 @@
|
||||
var/message = stripped_input(usr, "Input message", "Transmit message")
|
||||
var/obj/mecha/M = MT.chassis
|
||||
if(trim(message) && M)
|
||||
M.occupant_message(message)
|
||||
to_chat(M.occupant, message)
|
||||
to_chat(usr, "<span class='notice'>Message sent.</span>")
|
||||
. = TRUE
|
||||
if("shock")
|
||||
@@ -67,8 +68,8 @@
|
||||
var/obj/mecha/M = MT.chassis
|
||||
if(M)
|
||||
MT.shock()
|
||||
log_game("[key_name(usr)] has activated remote EMP on exosuit [M], located at [loc_name(M)], which is currently [M.occupant? "being piloted by [key_name(M.occupant)]." : "without a pilot."] ")
|
||||
message_admins("[key_name_admin(usr)][ADMIN_FLW(usr)] has activated remote EMP on exosuit [M][ADMIN_JMP(M)], which is currently [M.occupant ? "being piloted by [key_name_admin(M.occupant)][ADMIN_FLW(M.occupant)]." : "without a pilot."] ")
|
||||
log_game("[key_name(usr)] has activated remote EMP on exosuit [M], located at [loc_name(M)], which [M.occupant ? "has the occupants [M.occupant]." : "without a pilot."] ")
|
||||
message_admins("[key_name_admin(usr)][ADMIN_FLW(usr)] has activated remote EMP on exosuit [M][ADMIN_JMP(M)], which is currently [M.occupant ? "occupied by [M.occupant][ADMIN_FLW(M)]." : "without a pilot."] ")
|
||||
. = TRUE
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking
|
||||
@@ -85,8 +86,8 @@
|
||||
var/obj/mecha/chassis
|
||||
|
||||
/**
|
||||
* Returns a html formatted string describing attached mech status
|
||||
*/
|
||||
* Returns a html formatted string describing attached mech status
|
||||
*/
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info()
|
||||
if(!chassis)
|
||||
return FALSE
|
||||
@@ -101,7 +102,7 @@
|
||||
<b>Active Equipment:</b> [chassis.selected || "None"]"}
|
||||
if(istype(chassis, /obj/mecha/working/ripley))
|
||||
var/obj/mecha/working/ripley/RM = chassis
|
||||
answer += "<br><b>Used Cargo Space:</b> [round((RM.cargo.len / RM.cargo_capacity * 100), 0.01)]%"
|
||||
answer += "<br><b>Used Cargo Space:</b> [round((LAZYLEN(RM.cargo) / RM.cargo_capacity * 100), 0.01)]%"
|
||||
|
||||
return answer
|
||||
|
||||
@@ -125,8 +126,8 @@
|
||||
chassis = M
|
||||
|
||||
/**
|
||||
* Attempts to EMP mech that the tracker is attached to, if there is one and tracker is not on cooldown
|
||||
*/
|
||||
* Attempts to EMP mech that the tracker is attached to, if there is one and tracker is not on cooldown
|
||||
*/
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/shock()
|
||||
if(recharging)
|
||||
return
|
||||
@@ -136,8 +137,8 @@
|
||||
recharging = TRUE
|
||||
|
||||
/**
|
||||
* Resets recharge variable, allowing tracker to be EMP pulsed again
|
||||
*/
|
||||
* Resets recharge variable, allowing tracker to be EMP pulsed again
|
||||
*/
|
||||
/obj/item/mecha_parts/mecha_tracking/proc/recharge()
|
||||
recharging = FALSE
|
||||
|
||||
|
||||
@@ -14,8 +14,41 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
grind_results = list(/datum/reagent/silicon = 20)
|
||||
var/build_path = null
|
||||
///determines if the circuit board originated from a vendor off station or not.
|
||||
var/onstation = TRUE
|
||||
|
||||
/obj/item/circuitboard/proc/apply_default_parts(obj/machinery/M)
|
||||
if(LAZYLEN(M.component_parts))
|
||||
// This really shouldn't happen. If it somehow does, print out a stack trace and gracefully handle it.
|
||||
stack_trace("apply_defauly_parts called on machine that already had component_parts: [M]")
|
||||
|
||||
// Move to nullspace so you don't trigger handle_atom_del logic and remove existing parts.
|
||||
for(var/obj/item/part in M.component_parts)
|
||||
part.moveToNullspace(loc)
|
||||
qdel(part)
|
||||
|
||||
// List of components always contains the circuit board used to build it.
|
||||
M.component_parts = list(src)
|
||||
forceMove(M)
|
||||
|
||||
if(M.circuit != src)
|
||||
// This really shouldn't happen. If it somehow does, print out a stack trace and gracefully handle it.
|
||||
stack_trace("apply_default_parts called from a circuit board that does not belong to machine: [M]")
|
||||
|
||||
// Move to nullspace so you don't trigger handle_atom_del logic, remove old circuit, add new circuit.
|
||||
M.circuit.moveToNullspace()
|
||||
qdel(M.circuit)
|
||||
M.circuit = src
|
||||
|
||||
return
|
||||
|
||||
/**
|
||||
* Used to allow the circuitboard to configure a machine in some way, shape or form.
|
||||
*
|
||||
* Arguments:
|
||||
* * machine - The machine to attempt to configure.
|
||||
*/
|
||||
/obj/item/circuitboard/proc/configure_machine(obj/machinery/machine)
|
||||
return
|
||||
|
||||
// Circuitboard/machine
|
||||
@@ -36,8 +69,8 @@ micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells.
|
||||
if(!req_components)
|
||||
return
|
||||
|
||||
M.component_parts = list(src) // List of components always contains a board
|
||||
moveToNullspace()
|
||||
. = ..()
|
||||
moveToNullspace() // thorw ourselves in nullspace
|
||||
|
||||
for(var/comp_path in req_components)
|
||||
var/comp_amt = req_components[comp_path]
|
||||
|
||||
@@ -1,58 +1,22 @@
|
||||
/obj/item/circuitboard/computer/turbine_computer
|
||||
name = "Turbine Computer (Computer Board)"
|
||||
build_path = /obj/machinery/computer/turbine_computer
|
||||
|
||||
/obj/item/circuitboard/computer/launchpad_console
|
||||
name = "Launchpad Control Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/launchpad
|
||||
|
||||
/obj/item/circuitboard/computer/message_monitor
|
||||
name = "Message Monitor (Computer Board)"
|
||||
build_path = /obj/machinery/computer/message_monitor
|
||||
|
||||
/obj/item/circuitboard/computer/security
|
||||
name = "Security Cameras (Computer Board)"
|
||||
build_path = /obj/machinery/computer/security
|
||||
|
||||
/obj/item/circuitboard/computer/security/shuttle
|
||||
name = "Shuttlelinking Security Cameras (Computer Board)"
|
||||
build_path = /obj/machinery/computer/security/shuttle
|
||||
|
||||
/obj/item/circuitboard/computer/xenobiology
|
||||
name = "circuit board (Xenobiology Console)"
|
||||
build_path = /obj/machinery/computer/camera_advanced/xenobio
|
||||
|
||||
/obj/item/circuitboard/computer/base_construction
|
||||
name = "circuit board (Aux Mining Base Construction Console)"
|
||||
build_path = /obj/machinery/computer/camera_advanced/base_construction
|
||||
//Command
|
||||
|
||||
/obj/item/circuitboard/computer/aiupload
|
||||
name = "AI Upload (Computer Board)"
|
||||
icon_state = "command"
|
||||
build_path = /obj/machinery/computer/upload/ai
|
||||
|
||||
/obj/item/circuitboard/computer/borgupload
|
||||
name = "Cyborg Upload (Computer Board)"
|
||||
icon_state = "command"
|
||||
build_path = /obj/machinery/computer/upload/borg
|
||||
|
||||
/obj/item/circuitboard/computer/med_data
|
||||
name = "Medical Records Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/med_data
|
||||
|
||||
/obj/item/circuitboard/computer/pandemic
|
||||
name = "PanD.E.M.I.C. 2200 (Computer Board)"
|
||||
build_path = /obj/machinery/computer/pandemic
|
||||
|
||||
/obj/item/circuitboard/computer/scan_consolenew
|
||||
name = "DNA Machine (Computer Board)"
|
||||
build_path = /obj/machinery/computer/scan_consolenew
|
||||
|
||||
/obj/item/circuitboard/computer/communications
|
||||
name = "Communications (Computer Board)"
|
||||
build_path = /obj/machinery/computer/communications
|
||||
var/lastTimeUsed = 0
|
||||
/obj/item/circuitboard/computer/bsa_control
|
||||
name = "Bluespace Artillery Controls (Computer Board)"
|
||||
build_path = /obj/machinery/computer/bsa_control
|
||||
|
||||
/obj/item/circuitboard/computer/card
|
||||
name = "ID Console (Computer Board)"
|
||||
icon_state = "command"
|
||||
build_path = /obj/machinery/computer/card
|
||||
|
||||
/obj/item/circuitboard/computer/card/centcom
|
||||
@@ -73,266 +37,238 @@
|
||||
return ..()
|
||||
|
||||
/obj/item/circuitboard/computer/card/minor/examine(user)
|
||||
. = ..()
|
||||
. += "Currently set to \"[dept_list[target_dept]]\"."
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Currently set to \"[dept_list[target_dept]]\".</span>")
|
||||
|
||||
|
||||
//obj/item/circuitboard/computer/shield
|
||||
// name = "Shield Control (Computer Board)"
|
||||
// icon_state = "command"
|
||||
// build_path = /obj/machinery/computer/stationshield
|
||||
/obj/item/circuitboard/computer/teleporter
|
||||
name = "Teleporter (Computer Board)"
|
||||
build_path = /obj/machinery/computer/teleporter
|
||||
|
||||
/obj/item/circuitboard/computer/secure_data
|
||||
name = "Security Records Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/secure_data
|
||||
//Engineering
|
||||
|
||||
/obj/item/circuitboard/computer/stationalert
|
||||
name = "Station Alerts (Computer Board)"
|
||||
build_path = /obj/machinery/computer/station_alert
|
||||
/obj/item/circuitboard/computer/apc_control
|
||||
name = "\improper Power Flow Control Console (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/apc_control
|
||||
|
||||
/obj/item/circuitboard/computer/atmos_alert
|
||||
name = "Atmospheric Alert (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/atmos_alert
|
||||
|
||||
/obj/item/circuitboard/computer/atmos_control
|
||||
name = "Atmospheric Monitor (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/atmos_control
|
||||
|
||||
/obj/item/circuitboard/computer/atmos_control/incinerator
|
||||
name = "Incinerator Air Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/incinerator
|
||||
|
||||
/obj/item/circuitboard/computer/atmos_control/toxinsmix
|
||||
name = "Toxins Mixing Air Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/toxinsmix
|
||||
|
||||
/obj/item/circuitboard/computer/atmos_control/tank
|
||||
name = "Tank Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/tank
|
||||
|
||||
/obj/item/circuitboard/computer/atmos_alert
|
||||
name = "Atmospheric Alert (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_alert
|
||||
/obj/item/circuitboard/computer/atmos_control/tank/oxygen_tank
|
||||
name = "Oxygen Supply Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/tank/oxygen_tank
|
||||
|
||||
/obj/item/circuitboard/computer/pod
|
||||
name = "Massdriver control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/pod
|
||||
/obj/item/circuitboard/computer/atmos_control/tank/toxin_tank
|
||||
name = "Plasma Supply Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/tank/toxin_tank
|
||||
|
||||
/obj/item/circuitboard/computer/robotics
|
||||
name = "Robotics Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/robotics
|
||||
/obj/item/circuitboard/computer/atmos_control/tank/air_tank
|
||||
name = "Mixed Air Supply Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/tank/air_tank
|
||||
|
||||
/obj/item/circuitboard/computer/cloning
|
||||
name = "Cloning (Computer Board)"
|
||||
build_path = /obj/machinery/computer/cloning
|
||||
var/list/records = list()
|
||||
/obj/item/circuitboard/computer/atmos_control/tank/mix_tank
|
||||
name = "Gas Mix Supply Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/tank/mix_tank
|
||||
|
||||
/obj/item/circuitboard/computer/cloning/prototype
|
||||
name = "Prototype Cloning (Computer Board)"
|
||||
build_path = /obj/machinery/computer/cloning/prototype
|
||||
/obj/item/circuitboard/computer/atmos_control/tank/nitrous_tank
|
||||
name = "Nitrous Oxide Supply Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/tank/nitrous_tank
|
||||
|
||||
/obj/item/circuitboard/computer/arcade/battle
|
||||
name = "Arcade Battle (Computer Board)"
|
||||
build_path = /obj/machinery/computer/arcade/battle
|
||||
/obj/item/circuitboard/computer/atmos_control/tank/nitrogen_tank
|
||||
name = "Nitrogen Supply Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/tank/nitrogen_tank
|
||||
|
||||
/obj/item/circuitboard/computer/arcade/orion_trail
|
||||
name = "Orion Trail (Computer Board)"
|
||||
build_path = /obj/machinery/computer/arcade/orion_trail
|
||||
/obj/item/circuitboard/computer/atmos_control/tank/carbon_tank
|
||||
name = "Carbon Dioxide Supply Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/atmos_control/tank/carbon_tank
|
||||
|
||||
/obj/item/circuitboard/computer/arcade/minesweeper
|
||||
name = "Minesweeper (Computer Board)"
|
||||
build_path = /obj/machinery/computer/arcade/minesweeper
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/bz_tank
|
||||
// name = "BZ Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/bz_tank
|
||||
|
||||
/obj/item/circuitboard/computer/arcade/amputation
|
||||
name = "Mediborg's Amputation Adventure (Computer Board)"
|
||||
build_path = /obj/machinery/computer/arcade/amputation
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/freon_tank
|
||||
// name = "Freon Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/freon_tank
|
||||
|
||||
/obj/item/circuitboard/computer/turbine_control
|
||||
name = "Turbine control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/turbine_computer
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/halon_tank
|
||||
// name = "Halon Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/halon_tank
|
||||
|
||||
/obj/item/circuitboard/computer/solar_control
|
||||
name = "Solar Control (Computer Board)" //name fixed 250810
|
||||
build_path = /obj/machinery/power/solar_control
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/healium_tank
|
||||
// name = "Healium Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/healium_tank
|
||||
|
||||
/obj/item/circuitboard/computer/powermonitor
|
||||
name = "Power Monitor (Computer Board)" //name fixed 250810
|
||||
build_path = /obj/machinery/computer/monitor
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/hydrogen_tank
|
||||
// name = "Hydrogen Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/hydrogen_tank
|
||||
|
||||
/obj/item/circuitboard/computer/powermonitor/secret
|
||||
name = "Outdated Power Monitor (Computer Board)" //Variant used on ruins to prevent them from showing up on PDA's.
|
||||
build_path = /obj/machinery/computer/monitor/secret
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/hypernoblium_tank
|
||||
// name = "Hypernoblium Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/hypernoblium_tank
|
||||
|
||||
/obj/item/circuitboard/computer/olddoor
|
||||
name = "DoorMex (Computer Board)"
|
||||
build_path = /obj/machinery/computer/pod/old
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/miasma_tank
|
||||
// name = "Miasma Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/miasma_tank
|
||||
|
||||
/obj/item/circuitboard/computer/syndicatedoor
|
||||
name = "ProComp Executive (Computer Board)"
|
||||
build_path = /obj/machinery/computer/pod/old/syndicate
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/nitryl_tank
|
||||
// name = "Nitryl Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/nitryl_tank
|
||||
|
||||
/obj/item/circuitboard/computer/swfdoor
|
||||
name = "Magix (Computer Board)"
|
||||
build_path = /obj/machinery/computer/pod/old/swf
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/pluoxium_tank
|
||||
// name = "Pluoxium Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/pluoxium_tank
|
||||
|
||||
/obj/item/circuitboard/computer/prisoner
|
||||
name = "Prisoner Management Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/prisoner/management
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/proto_nitrate_tank
|
||||
// name = "Proto-Nitrate Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/proto_nitrate_tank
|
||||
|
||||
/obj/item/circuitboard/computer/gulag_teleporter_console
|
||||
name = "Labor Camp teleporter console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/prisoner/gulag_teleporter_computer
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/stimulum_tank
|
||||
// name = "Stimulum Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/stimulum_tank
|
||||
|
||||
/obj/item/circuitboard/computer/rdconsole/production
|
||||
name = "R&D Console Production Only (Computer Board)"
|
||||
build_path = /obj/machinery/computer/rdconsole/production
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/tritium_tank
|
||||
// name = "Tritium Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/tritium_tank
|
||||
|
||||
/obj/item/circuitboard/computer/rdconsole
|
||||
name = "R&D Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/rdconsole/core
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/water_vapor
|
||||
// name = "Water Vapor Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/water_vapor
|
||||
|
||||
/obj/item/circuitboard/computer/rdconsole/attackby(obj/item/I, mob/user, params)
|
||||
if(I.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
if(build_path == /obj/machinery/computer/rdconsole/core)
|
||||
name = "R&D Console - Robotics (Computer Board)"
|
||||
build_path = /obj/machinery/computer/rdconsole/robotics
|
||||
to_chat(user, "<span class='notice'>Access protocols successfully updated.</span>")
|
||||
else
|
||||
name = "R&D Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/rdconsole/core
|
||||
to_chat(user, "<span class='notice'>Defaulting access protocols.</span>")
|
||||
else
|
||||
return ..()
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/zauker_tank
|
||||
// name = "Zauker Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/zauker_tank
|
||||
|
||||
/obj/item/circuitboard/computer/mecha_control
|
||||
name = "Exosuit Control Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/mecha
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/helium_tank
|
||||
// name = "Helium Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/helium_tank
|
||||
|
||||
/obj/item/circuitboard/computer/rdservercontrol
|
||||
name = "R&D Server Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/rdservercontrol
|
||||
// /obj/item/circuitboard/computer/atmos_control/tank/antinoblium_tank
|
||||
// name = "Antinoblium Supply Control (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/atmos_control/tank/antinoblium_tank
|
||||
|
||||
/obj/item/circuitboard/computer/crew
|
||||
name = "Crew Monitoring Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/crew
|
||||
/obj/item/circuitboard/computer/auxiliary_base
|
||||
name = "Auxiliary Base Management Console (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/auxillary_base
|
||||
|
||||
/obj/item/circuitboard/computer/mech_bay_power_console
|
||||
name = "Mech Bay Power Control Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/mech_bay_power_console
|
||||
/obj/item/circuitboard/computer/base_construction
|
||||
name = "circuit board (Generic Base Construction Console)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/camera_advanced/base_construction
|
||||
|
||||
/obj/item/circuitboard/computer/cargo
|
||||
name = "Supply Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/cargo
|
||||
var/contraband = FALSE
|
||||
// /obj/item/circuitboard/computer/base_construction/aux
|
||||
// name = "circuit board (Aux Mining Base Construction Console)"
|
||||
// icon_state = "engineering"
|
||||
// build_path = /obj/machinery/computer/camera_advanced/base_construction/aux
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/multitool_act(mob/living/user)
|
||||
if(!(obj_flags & EMAGGED))
|
||||
contraband = !contraband
|
||||
to_chat(user, "<span class='notice'>Receiver spectrum set to [contraband ? "Broad" : "Standard"].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>The spectrum chip is unresponsive.</span>")
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/emag_act(mob/living/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
contraband = TRUE
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='notice'>You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/express
|
||||
name = "Express Supply Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/cargo/express
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/express/multitool_act(mob/living/user)
|
||||
if (!(obj_flags & EMAGGED))
|
||||
to_chat(user, "<span class='notice'>Routing protocols are already set to: \"factory defaults\".</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You reset the routing protocols to: \"factory defaults\".</span>")
|
||||
obj_flags &= ~EMAGGED
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user)
|
||||
. = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You change the routing protocols, allowing the Drop Pod to land anywhere on the station.</span>")
|
||||
obj_flags |= EMAGGED
|
||||
return TRUE
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/request
|
||||
name = "Supply Request Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/cargo/request
|
||||
|
||||
/obj/item/circuitboard/computer/bounty
|
||||
name = "Nanotrasen Bounty Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/bounty
|
||||
|
||||
/obj/item/circuitboard/computer/operating
|
||||
name = "Operating Computer (Computer Board)"
|
||||
build_path = /obj/machinery/computer/operating
|
||||
|
||||
/obj/item/circuitboard/computer/mining
|
||||
name = "Outpost Status Display (Computer Board)"
|
||||
build_path = /obj/machinery/computer/security/mining
|
||||
|
||||
/obj/item/circuitboard/computer/research
|
||||
name = "Research Monitor (Computer Board)"
|
||||
build_path = /obj/machinery/computer/security/research
|
||||
// /obj/item/circuitboard/computer/base_construction/centcom
|
||||
// name = "circuit board (Centcom Base Construction Console)"
|
||||
// icon_state = "engineering"
|
||||
// build_path = /obj/machinery/computer/camera_advanced/base_construction/centcom
|
||||
|
||||
/obj/item/circuitboard/computer/comm_monitor
|
||||
name = "Telecommunications Monitor (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/telecomms/monitor
|
||||
|
||||
/obj/item/circuitboard/computer/comm_server
|
||||
name = "Telecommunications Server Monitor (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/telecomms/server
|
||||
|
||||
/obj/item/circuitboard/computer/labor_shuttle
|
||||
name = "Labor Shuttle (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/labor
|
||||
/obj/item/circuitboard/computer/communications
|
||||
name = "Communications (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/communications
|
||||
|
||||
/obj/item/circuitboard/computer/labor_shuttle/one_way
|
||||
name = "Prisoner Shuttle Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/labor/one_way
|
||||
/obj/item/circuitboard/computer/message_monitor
|
||||
name = "Message Monitor (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/message_monitor
|
||||
|
||||
/obj/item/circuitboard/computer/ferry
|
||||
name = "Transport Ferry (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/ferry
|
||||
/obj/item/circuitboard/computer/powermonitor
|
||||
name = "Power Monitor (Computer Board)" //name fixed 250810
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/monitor
|
||||
|
||||
/obj/item/circuitboard/computer/ferry/request
|
||||
name = "Transport Ferry Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/ferry/request
|
||||
/obj/item/circuitboard/computer/powermonitor/secret
|
||||
name = "Outdated Power Monitor (Computer Board)" //Variant used on ruins to prevent them from showing up on PDA's.
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/monitor/secret
|
||||
|
||||
/obj/item/circuitboard/computer/mining_shuttle
|
||||
name = "Mining Shuttle (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/mining
|
||||
/obj/item/circuitboard/computer/sat_control
|
||||
name = "Satellite Network Control (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/sat_control
|
||||
|
||||
/obj/item/circuitboard/computer/mining_shuttle/common
|
||||
name = "Lavaland Shuttle (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/mining/common
|
||||
/obj/item/circuitboard/computer/solar_control
|
||||
name = "Solar Control (Computer Board)" //name fixed 250810
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/power/solar_control
|
||||
|
||||
/obj/item/circuitboard/computer/snow_taxi
|
||||
name = "Snow Taxi (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/snow_taxi
|
||||
/obj/item/circuitboard/computer/stationalert
|
||||
name = "Station Alerts (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/station_alert
|
||||
|
||||
/obj/item/circuitboard/computer/white_ship
|
||||
name = "White Ship (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/white_ship
|
||||
/obj/item/circuitboard/computer/turbine_computer
|
||||
name = "Turbine Computer (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/turbine_computer
|
||||
|
||||
/obj/item/circuitboard/computer/white_ship/pod
|
||||
name = "Salvage Pod (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/white_ship/pod
|
||||
/obj/item/circuitboard/computer/turbine_control
|
||||
name = "Turbine control (Computer Board)"
|
||||
icon_state = "engineering"
|
||||
build_path = /obj/machinery/computer/turbine_computer
|
||||
|
||||
/obj/item/circuitboard/computer/white_ship/pod/recall
|
||||
name = "Salvage Pod Recall (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/white_ship/pod/recall
|
||||
//Generic
|
||||
|
||||
/obj/item/circuitboard/computer/auxillary_base
|
||||
name = "Auxillary Base Management Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/auxillary_base
|
||||
/obj/item/circuitboard/computer/arcade/amputation
|
||||
name = "Mediborg's Amputation Adventure (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/arcade/amputation
|
||||
|
||||
/obj/item/circuitboard/computer/arcade/battle
|
||||
name = "Arcade Battle (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/arcade/battle
|
||||
|
||||
/obj/item/circuitboard/computer/arcade/orion_trail
|
||||
name = "Orion Trail (Computer Board)"
|
||||
|
||||
build_path = /obj/machinery/computer/arcade/orion_trail
|
||||
|
||||
/obj/item/circuitboard/computer/arcade/minesweeper
|
||||
name = "Minesweeper (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/arcade/minesweeper
|
||||
|
||||
/obj/item/circuitboard/computer/holodeck// Not going to let people get this, but it's just here for future
|
||||
name = "Holodeck Control (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/holodeck
|
||||
|
||||
/obj/item/circuitboard/computer/aifixer
|
||||
name = "AI Integrity Restorer (Computer Board)"
|
||||
build_path = /obj/machinery/computer/aifixer
|
||||
|
||||
/obj/item/circuitboard/computer/slot_machine
|
||||
name = "Slot Machine (Computer Board)"
|
||||
build_path = /obj/machinery/computer/slot_machine
|
||||
|
||||
/obj/item/circuitboard/computer/libraryconsole
|
||||
name = "Library Visitor Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/libraryconsole
|
||||
@@ -350,16 +286,34 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/circuitboard/computer/apc_control
|
||||
name = "\improper Power Flow Control Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/apc_control
|
||||
|
||||
/obj/item/circuitboard/computer/monastery_shuttle
|
||||
name = "Monastery Shuttle (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/shuttle/monastery_shuttle
|
||||
|
||||
/obj/item/circuitboard/computer/olddoor
|
||||
name = "DoorMex (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/pod/old
|
||||
|
||||
/obj/item/circuitboard/computer/pod
|
||||
name = "Massdriver control (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/pod
|
||||
|
||||
/obj/item/circuitboard/computer/slot_machine
|
||||
name = "Slot Machine (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/slot_machine
|
||||
|
||||
/obj/item/circuitboard/computer/swfdoor
|
||||
name = "Magix (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/pod/old/swf
|
||||
|
||||
/obj/item/circuitboard/computer/syndicate_shuttle
|
||||
name = "Syndicate Shuttle (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/shuttle/syndicate
|
||||
var/challenge = FALSE
|
||||
var/moved = FALSE
|
||||
@@ -372,26 +326,296 @@
|
||||
GLOB.syndicate_shuttle_boards -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/circuitboard/computer/bsa_control
|
||||
name = "Bluespace Artillery Controls (Computer Board)"
|
||||
build_path = /obj/machinery/computer/bsa_control
|
||||
/obj/item/circuitboard/computer/syndicatedoor
|
||||
name = "ProComp Executive (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/pod/old/syndicate
|
||||
|
||||
/obj/item/circuitboard/computer/sat_control
|
||||
name = "Satellite Network Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/sat_control
|
||||
/obj/item/circuitboard/computer/white_ship
|
||||
name = "White Ship (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/shuttle/white_ship
|
||||
|
||||
// /obj/item/circuitboard/computer/white_ship/bridge
|
||||
// name = "White Ship Bridge (Computer Board)"
|
||||
// icon_state = "generic"
|
||||
// build_path = /obj/machinery/computer/shuttle/white_ship/bridge
|
||||
|
||||
/obj/item/circuitboard/computer/white_ship/pod
|
||||
name = "Salvage Pod (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/white_ship/pod
|
||||
|
||||
/obj/item/circuitboard/computer/white_ship/pod/recall
|
||||
name = "Salvage Pod Recall (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/white_ship/pod/recall
|
||||
|
||||
/obj/item/circuitboard/computer/snow_taxi
|
||||
name = "Snow Taxi (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/snow_taxi
|
||||
|
||||
// /obj/item/circuitboard/computer/bountypad
|
||||
// name = "Bounty Pad (Computer Board)"
|
||||
// build_path = /obj/machinery/computer/piratepad_control/civilian
|
||||
|
||||
/obj/item/circuitboard/computer/security/shuttle
|
||||
name = "Shuttlelinking Security Cameras (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/security/shuttle
|
||||
|
||||
//Medical
|
||||
|
||||
/obj/item/circuitboard/computer/crew
|
||||
name = "Crew Monitoring Console (Computer Board)"
|
||||
icon_state = "medical"
|
||||
build_path = /obj/machinery/computer/crew
|
||||
|
||||
/obj/item/circuitboard/computer/med_data
|
||||
name = "Medical Records Console (Computer Board)"
|
||||
icon_state = "medical"
|
||||
build_path = /obj/machinery/computer/med_data
|
||||
|
||||
/obj/item/circuitboard/computer/operating
|
||||
name = "Operating Computer (Computer Board)"
|
||||
icon_state = "medical"
|
||||
build_path = /obj/machinery/computer/operating
|
||||
|
||||
/obj/item/circuitboard/computer/pandemic
|
||||
name = "PanD.E.M.I.C. 2200 (Computer Board)"
|
||||
icon_state = "medical"
|
||||
build_path = /obj/machinery/computer/pandemic
|
||||
|
||||
/obj/item/circuitboard/computer/cloning
|
||||
name = "Cloning (Computer Board)"
|
||||
icon_state = "medical"
|
||||
build_path = /obj/machinery/computer/cloning
|
||||
var/list/records = list()
|
||||
|
||||
/obj/item/circuitboard/computer/cloning/prototype
|
||||
name = "Prototype Cloning (Computer Board)"
|
||||
build_path = /obj/machinery/computer/cloning/prototype
|
||||
|
||||
//Science
|
||||
|
||||
/obj/item/circuitboard/computer/aifixer
|
||||
name = "AI Integrity Restorer (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/aifixer
|
||||
|
||||
/obj/item/circuitboard/computer/launchpad_console
|
||||
name = "Launchpad Control Console (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/launchpad
|
||||
|
||||
/obj/item/circuitboard/computer/mech_bay_power_console
|
||||
name = "Mech Bay Power Control Console (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/mech_bay_power_console
|
||||
|
||||
/obj/item/circuitboard/computer/mecha_control
|
||||
name = "Exosuit Control Console (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/mecha
|
||||
|
||||
/obj/item/circuitboard/computer/nanite_chamber_control
|
||||
name = "Nanite Chamber Control (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/nanite_chamber_control
|
||||
|
||||
/obj/item/circuitboard/computer/nanite_cloud_controller
|
||||
name = "Nanite Cloud Control (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/nanite_cloud_controller
|
||||
/obj/item/circuitboard/computer/rdconsole/production
|
||||
name = "R&D Console Production Only (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/rdconsole/production
|
||||
|
||||
/obj/item/circuitboard/computer/shuttle/flight_control
|
||||
name = "Shuttle Flight Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/custom_shuttle
|
||||
/obj/item/circuitboard/computer/rdconsole
|
||||
name = "R&D Console (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/rdconsole/core
|
||||
|
||||
/obj/item/circuitboard/computer/rdconsole/attackby(obj/item/I, mob/user, params)
|
||||
if(I.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
if(build_path == /obj/machinery/computer/rdconsole/core)
|
||||
name = "R&D Console - Robotics (Computer Board)"
|
||||
build_path = /obj/machinery/computer/rdconsole/robotics
|
||||
to_chat(user, "<span class='notice'>Access protocols successfully updated.</span>")
|
||||
else
|
||||
name = "R&D Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/rdconsole/core
|
||||
to_chat(user, "<span class='notice'>Defaulting access protocols.</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/circuitboard/computer/rdservercontrol
|
||||
name = "R&D Server Control (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/rdservercontrol
|
||||
|
||||
/obj/item/circuitboard/computer/research
|
||||
name = "Research Monitor (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/security/research
|
||||
|
||||
/obj/item/circuitboard/computer/robotics
|
||||
name = "Robotics Control (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/robotics
|
||||
|
||||
/obj/item/circuitboard/computer/teleporter
|
||||
name = "Teleporter (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/teleporter
|
||||
|
||||
/obj/item/circuitboard/computer/xenobiology
|
||||
name = "Xenobiology Console (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/camera_advanced/xenobio
|
||||
|
||||
/obj/item/circuitboard/computer/scan_consolenew
|
||||
name = "DNA Console (Computer Board)"
|
||||
icon_state = "science"
|
||||
build_path = /obj/machinery/computer/scan_consolenew
|
||||
|
||||
// /obj/item/circuitboard/computer/mechpad
|
||||
// name = "Mecha Orbital Pad Console (Computer Board)"
|
||||
// icon_state = "science"
|
||||
// build_path = /obj/machinery/computer/mechpad
|
||||
|
||||
//Security
|
||||
|
||||
/obj/item/circuitboard/computer/labor_shuttle
|
||||
name = "Labor Shuttle (Computer Board)"
|
||||
icon_state = "security"
|
||||
build_path = /obj/machinery/computer/shuttle/labor
|
||||
|
||||
/obj/item/circuitboard/computer/labor_shuttle/one_way
|
||||
name = "Prisoner Shuttle Console (Computer Board)"
|
||||
icon_state = "security"
|
||||
build_path = /obj/machinery/computer/shuttle/labor/one_way
|
||||
|
||||
/obj/item/circuitboard/computer/gulag_teleporter_console
|
||||
name = "Labor Camp teleporter console (Computer Board)"
|
||||
icon_state = "security"
|
||||
build_path = /obj/machinery/computer/prisoner/gulag_teleporter_computer
|
||||
|
||||
/obj/item/circuitboard/computer/prisoner
|
||||
name = "Prisoner Management Console (Computer Board)"
|
||||
icon_state = "security"
|
||||
build_path = /obj/machinery/computer/prisoner/management
|
||||
|
||||
/obj/item/circuitboard/computer/secure_data
|
||||
name = "Security Records Console (Computer Board)"
|
||||
icon_state = "security"
|
||||
build_path = /obj/machinery/computer/secure_data
|
||||
|
||||
// /obj/item/circuitboard/computer/warrant
|
||||
// name = "Security Warrant Viewer (Computer Board)"
|
||||
// icon_state = "security"
|
||||
// build_path = /obj/machinery/computer/warrant
|
||||
|
||||
/obj/item/circuitboard/computer/security
|
||||
name = "Security Cameras (Computer Board)"
|
||||
icon_state = "security"
|
||||
build_path = /obj/machinery/computer/security
|
||||
|
||||
/obj/item/circuitboard/computer/advanced_camera
|
||||
name = "Advanced Camera Console (Computer Board)"
|
||||
icon_state = "security"
|
||||
build_path = /obj/machinery/computer/camera_advanced/syndie
|
||||
|
||||
//Service
|
||||
|
||||
//Supply
|
||||
|
||||
/obj/item/circuitboard/computer/cargo
|
||||
name = "Supply Console (Computer Board)"
|
||||
icon_state = "supply"
|
||||
build_path = /obj/machinery/computer/cargo
|
||||
var/contraband = FALSE
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/multitool_act(mob/living/user)
|
||||
. = ..()
|
||||
if(!(obj_flags & EMAGGED))
|
||||
contraband = !contraband
|
||||
to_chat(user, "<span class='notice'>Receiver spectrum set to [contraband ? "Broad" : "Standard"].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='alert'>The spectrum chip is unresponsive.</span>")
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/emag_act(mob/living/user)
|
||||
. = ..()
|
||||
if(!(obj_flags & EMAGGED))
|
||||
contraband = TRUE
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='notice'>You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.</span>")
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/configure_machine(obj/machinery/computer/cargo/machine)
|
||||
if(!istype(machine))
|
||||
CRASH("Cargo board attempted to configure incorrect machine type: [machine] ([machine?.type])")
|
||||
|
||||
machine.contraband = contraband
|
||||
if (obj_flags & EMAGGED)
|
||||
machine.obj_flags |= EMAGGED
|
||||
else
|
||||
machine.obj_flags &= ~EMAGGED
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/express
|
||||
name = "Express Supply Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/cargo/express
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user)
|
||||
if(!(obj_flags & EMAGGED))
|
||||
contraband = TRUE
|
||||
obj_flags |= EMAGGED
|
||||
to_chat(user, "<span class='notice'>You change the routing protocols, allowing the Drop Pod to land anywhere on the station.</span>")
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/express/multitool_act(mob/living/user)
|
||||
if (!(obj_flags & EMAGGED))
|
||||
contraband = !contraband
|
||||
to_chat(user, "<span class='notice'>Receiver spectrum set to [contraband ? "Broad" : "Standard"].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You reset the destination-routing protocols and receiver spectrum to factory defaults.</span>")
|
||||
contraband = FALSE
|
||||
obj_flags &= ~EMAGGED
|
||||
|
||||
/obj/item/circuitboard/computer/cargo/request
|
||||
name = "Supply Request Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/cargo/request
|
||||
|
||||
/obj/item/circuitboard/computer/bounty
|
||||
name = "Nanotrasen Bounty Console (Computer Board)"
|
||||
build_path = /obj/machinery/computer/bounty
|
||||
|
||||
/obj/item/circuitboard/computer/ferry
|
||||
name = "Transport Ferry (Computer Board)"
|
||||
icon_state = "supply"
|
||||
build_path = /obj/machinery/computer/shuttle/ferry
|
||||
|
||||
/obj/item/circuitboard/computer/ferry/request
|
||||
name = "Transport Ferry Console (Computer Board)"
|
||||
icon_state = "supply"
|
||||
build_path = /obj/machinery/computer/shuttle/ferry/request
|
||||
|
||||
/obj/item/circuitboard/computer/mining
|
||||
name = "Outpost Status Display (Computer Board)"
|
||||
icon_state = "supply"
|
||||
build_path = /obj/machinery/computer/security/mining
|
||||
|
||||
/obj/item/circuitboard/computer/mining_shuttle
|
||||
name = "Mining Shuttle (Computer Board)"
|
||||
icon_state = "supply"
|
||||
build_path = /obj/machinery/computer/shuttle/mining
|
||||
|
||||
/obj/item/circuitboard/computer/mining_shuttle/common
|
||||
name = "Lavaland Shuttle (Computer Board)"
|
||||
build_path = /obj/machinery/computer/shuttle/mining/common
|
||||
|
||||
/obj/item/circuitboard/computer/shuttle/docker
|
||||
name = "Shuttle Navigation Computer (Computer Board)"
|
||||
build_path = /obj/machinery/computer/camera_advanced/shuttle_docker/custom
|
||||
|
||||
// DIY shuttle
|
||||
/obj/item/circuitboard/computer/shuttle/flight_control
|
||||
name = "Shuttle Flight Control (Computer Board)"
|
||||
build_path = /obj/machinery/computer/custom_shuttle
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
||||
lefthand_file = 'icons/mob/inhands/equipment/toolbox_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
w_class = WEIGHT_CLASS_GIGANTIC
|
||||
force = 12
|
||||
total_mass = TOTAL_MASS_NORMAL_ITEM // average toolbox
|
||||
attack_verb = list("robusted")
|
||||
@@ -70,19 +70,19 @@
|
||||
else
|
||||
. += "<span class='his_grace'>[src] is latched closed.</span>"
|
||||
|
||||
/obj/item/his_grace/relaymove(mob/living/user) //Allows changelings, etc. to climb out of Him after they revive, provided He isn't active
|
||||
/obj/item/his_grace/relaymove(mob/living/user, direction) //Allows changelings, etc. to climb out of Him after they revive, provided He isn't active
|
||||
if(!awakened)
|
||||
user.forceMove(get_turf(src))
|
||||
user.visible_message("<span class='warning'>[user] scrambles out of [src]!</span>", "<span class='notice'>You climb out of [src]!</span>")
|
||||
|
||||
/obj/item/his_grace/process()
|
||||
/obj/item/his_grace/process(delta_time)
|
||||
if(!bloodthirst)
|
||||
drowse()
|
||||
return
|
||||
if(bloodthirst < HIS_GRACE_CONSUME_OWNER && !ascended)
|
||||
adjust_bloodthirst(1 + FLOOR(LAZYLEN(contents) * 0.5, 1)) //Maybe adjust this?
|
||||
adjust_bloodthirst((1 + FLOOR(LAZYLEN(contents) * 0.5, 1)) * delta_time) //Maybe adjust this?
|
||||
else
|
||||
adjust_bloodthirst(1) //don't cool off rapidly once we're at the point where His Grace consumes all.
|
||||
adjust_bloodthirst(1 * delta_time) //don't cool off rapidly once we're at the point where His Grace consumes all.
|
||||
var/mob/living/master = get_atom_on_turf(src, /mob/living)
|
||||
if(istype(master) && (src in master.held_items))
|
||||
switch(bloodthirst)
|
||||
@@ -94,7 +94,7 @@
|
||||
REMOVE_TRAIT(src, TRAIT_NODROP, HIS_GRACE_TRAIT)
|
||||
master.DefaultCombatKnockdown(60)
|
||||
master.adjustBruteLoss(master.maxHealth)
|
||||
playsound(master, 'sound/effects/splat.ogg', 100, 0)
|
||||
playsound(master, 'sound/effects/splat.ogg', 100, FALSE)
|
||||
else
|
||||
master.apply_status_effect(STATUS_EFFECT_HISGRACE)
|
||||
return
|
||||
@@ -115,8 +115,8 @@
|
||||
if(!L.stat)
|
||||
L.visible_message("<span class='warning'>[src] lunges at [L]!</span>", "<span class='his_grace big bold'>[src] lunges at you!</span>")
|
||||
do_attack_animation(L, null, src)
|
||||
playsound(L, 'sound/weapons/smash.ogg', 50, 1)
|
||||
playsound(L, 'sound/misc/desceration-01.ogg', 50, 1)
|
||||
playsound(L, 'sound/weapons/smash.ogg', 50, TRUE)
|
||||
playsound(L, 'sound/misc/desceration-01.ogg', 50, TRUE)
|
||||
L.adjustBruteLoss(force)
|
||||
adjust_bloodthirst(-5) //Don't stop attacking they're right there!
|
||||
else
|
||||
@@ -137,6 +137,8 @@
|
||||
move_gracefully()
|
||||
|
||||
/obj/item/his_grace/proc/move_gracefully()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!awakened)
|
||||
return
|
||||
var/static/list/transforms
|
||||
@@ -161,7 +163,7 @@
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
T.visible_message("<span class='boldwarning'>[src] slowly stops rattling and falls still, His latch snapping shut.</span>")
|
||||
playsound(loc, 'sound/weapons/batonextend.ogg', 100, 1)
|
||||
playsound(loc, 'sound/weapons/batonextend.ogg', 100, TRUE)
|
||||
name = initial(name)
|
||||
desc = initial(desc)
|
||||
icon_state = initial(icon_state)
|
||||
@@ -178,8 +180,8 @@
|
||||
var/victims = 0
|
||||
meal.visible_message("<span class='warning'>[src] swings open and devours [meal]!</span>", "<span class='his_grace big bold'>[src] consumes you!</span>")
|
||||
meal.adjustBruteLoss(200)
|
||||
playsound(meal, 'sound/misc/desceration-02.ogg', 75, 1)
|
||||
playsound(src, 'sound/items/eatfood.ogg', 100, 1)
|
||||
playsound(meal, 'sound/misc/desceration-02.ogg', 75, TRUE)
|
||||
playsound(src, 'sound/items/eatfood.ogg', 100, TRUE)
|
||||
meal.forceMove(src)
|
||||
force_bonus += HIS_GRACE_FORCE_BONUS
|
||||
prev_bloodthirst = bloodthirst
|
||||
@@ -253,3 +255,4 @@
|
||||
if(istype(master))
|
||||
master.visible_message("<span class='his_grace big bold'>Gods will be watching.</span>")
|
||||
name = "[master]'s mythical toolbox of three powers"
|
||||
master.client?.give_award(/datum/award/achievement/misc/ascension, master)
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
|
||||
/obj/item/melee/proc/check_martial_counter(mob/living/carbon/human/target, mob/living/carbon/human/user)
|
||||
if(target.check_martial_melee_block())
|
||||
target.visible_message("<span class='danger'>[target.name] blocks [src] and twists [user]'s arm behind [user.p_their()] back!</span>",
|
||||
target.visible_message("<span class='danger'>[target.name] blocks your attack!</span>",
|
||||
"<span class='userdanger'>You block the attack!</span>")
|
||||
user.Stun(40)
|
||||
return TRUE
|
||||
|
||||
/obj/item/melee/chainofcommand
|
||||
|
||||
@@ -328,6 +328,9 @@
|
||||
REMOVE_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
|
||||
REMOVE_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
|
||||
name = initial(name)
|
||||
if(iscarbon(occupant))
|
||||
to_chat(occupant, "You pop out of the [src], slightly dazed!")
|
||||
occupant.Stun(5 SECONDS)
|
||||
|
||||
/obj/item/pet_carrier/bluespace/return_air()
|
||||
if(!occupant_gas_supply)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
grind_results = list(/datum/reagent/cellulose = 10)
|
||||
var/value = 0
|
||||
|
||||
/obj/item/stack/spacecash/Initialize()
|
||||
/obj/item/stack/spacecash/Initialize(mapload, new_amount, merge = TRUE)
|
||||
. = ..()
|
||||
update_desc()
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
material_type = /datum/material/glass
|
||||
point_value = 1
|
||||
tableVariant = /obj/structure/table/glass
|
||||
matter_amount = 4
|
||||
cost = 500
|
||||
shard_type = /obj/item/shard
|
||||
|
||||
/obj/item/stack/sheet/glass/suicide_act(mob/living/carbon/user)
|
||||
@@ -69,12 +71,13 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
if (get_amount() < 1 || CC.get_amount() < 5)
|
||||
to_chat(user, "<span class='warning>You need five lengths of coil and one sheet of glass to make wired glass!</span>")
|
||||
return
|
||||
CC.use_tool(src, user, 0, 5, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)
|
||||
CC.use(5)
|
||||
use(1)
|
||||
to_chat(user, "<span class='notice'>You attach wire to the [name].</span>")
|
||||
var/obj/item/stack/light_w/new_tile = new(user.loc)
|
||||
new_tile.add_fingerprint(user)
|
||||
else if(istype(W, /obj/item/stack/rods))
|
||||
return
|
||||
if(istype(W, /obj/item/stack/rods))
|
||||
var/obj/item/stack/rods/V = W
|
||||
if (V.get_amount() >= 1 && get_amount() >= 1)
|
||||
var/obj/item/stack/sheet/rglass/RG = new (get_turf(user))
|
||||
@@ -86,9 +89,8 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
user.put_in_hands(RG)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need one rod and one sheet of glass to make reinforced glass!</span>")
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
@@ -164,6 +166,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
|
||||
merge_type = /obj/item/stack/sheet/rglass
|
||||
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/iron = 10)
|
||||
point_value = 4
|
||||
matter_amount = 6
|
||||
shard_type = /obj/item/shard
|
||||
|
||||
/obj/item/stack/sheet/rglass/attackby(obj/item/W, mob/user, params)
|
||||
@@ -211,6 +214,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
|
||||
merge_type = /obj/item/stack/sheet/plasmarglass
|
||||
grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10, /datum/reagent/iron = 10)
|
||||
point_value = 23
|
||||
matter_amount = 8
|
||||
shard_type = /obj/item/shard/plasma
|
||||
|
||||
/obj/item/stack/sheet/plasmarglass/get_main_recipes()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
///What type of wall does this sheet spawn
|
||||
var/walltype
|
||||
|
||||
/obj/item/stack/sheet/Initialize(mapload, new_amount, merge)
|
||||
/obj/item/stack/sheet/Initialize(mapload, new_amount, merge = TRUE)
|
||||
. = ..()
|
||||
pixel_x = rand(-4, 4)
|
||||
pixel_y = rand(-4, 4)
|
||||
|
||||
@@ -8,15 +8,18 @@
|
||||
/*
|
||||
* Stacks
|
||||
*/
|
||||
|
||||
/obj/item/stack
|
||||
icon = 'icons/obj/stack_objects.dmi'
|
||||
gender = PLURAL
|
||||
material_modifier = 0.01
|
||||
// material_modifier = 0.05 //5%, so that a 50 sheet stack has the effect of 5k materials instead of 100k.
|
||||
max_integrity = 100
|
||||
var/list/datum/stack_recipe/recipes
|
||||
var/singular_name
|
||||
var/amount = 1
|
||||
var/max_amount = 50 //also see stack recipes initialisation, param "max_res_amount" must be equal to this max_amount
|
||||
var/is_cyborg = 0 // It's 1 if module is used by a cyborg, and uses its storage
|
||||
var/is_cyborg = FALSE // It's TRUE if module is used by a cyborg, and uses its storage
|
||||
var/datum/robot_energy_storage/source
|
||||
var/cost = 1 // How much energy from storage it costs
|
||||
var/merge_type = null // This path and its children should merge with this stack, defaults to src.type
|
||||
@@ -25,7 +28,6 @@
|
||||
var/list/mats_per_unit //list that tells you how much is in a single unit.
|
||||
///Datum material type that this stack is made of
|
||||
var/material_type
|
||||
max_integrity = 100
|
||||
//NOTE: When adding grind_results, the amounts should be for an INDIVIDUAL ITEM - these amounts will be multiplied by the stack size in on_grind()
|
||||
var/obj/structure/table/tableVariant // we tables now (stores table variant to be built from this stack)
|
||||
|
||||
@@ -36,16 +38,8 @@
|
||||
var/absorption_capacity
|
||||
/// How quickly we lower the blood flow on a cut wound we're bandaging. Expected lifetime of this bandage in ticks is thus absorption_capacity/absorption_rate, or until the cut heals, whichever comes first
|
||||
var/absorption_rate
|
||||
|
||||
/obj/item/stack/on_grind()
|
||||
for(var/i in 1 to grind_results.len) //This should only call if it's ground, so no need to check if grind_results exists
|
||||
grind_results[grind_results[i]] *= get_amount() //Gets the key at position i, then the reagent amount of that key, then multiplies it by stack size
|
||||
|
||||
/obj/item/stack/grind_requirements()
|
||||
if(is_cyborg)
|
||||
to_chat(usr, "<span class='danger'>[src] is electronically synthesized in your chassis and can't be ground up!</span>")
|
||||
return
|
||||
return TRUE
|
||||
/// Amount of matter for RCD
|
||||
var/matter_amount = 0
|
||||
|
||||
/obj/item/stack/Initialize(mapload, new_amount, merge = TRUE)
|
||||
if(new_amount != null)
|
||||
@@ -55,16 +49,19 @@
|
||||
new type(loc, max_amount, FALSE)
|
||||
if(!merge_type)
|
||||
merge_type = type
|
||||
if(custom_materials && custom_materials.len)
|
||||
mats_per_unit = list()
|
||||
var/in_process_mat_list = custom_materials.Copy()
|
||||
|
||||
if(LAZYLEN(mats_per_unit))
|
||||
set_mats_per_unit(mats_per_unit, 1)
|
||||
else if(LAZYLEN(custom_materials))
|
||||
// DO NOT REMOVE! we have to inflate the values first
|
||||
for(var/i in custom_materials)
|
||||
mats_per_unit[SSmaterials.GetMaterialRef(i)] = in_process_mat_list[i]
|
||||
custom_materials[i] *= amount
|
||||
set_mats_per_unit(custom_materials, amount ? 1/amount : 1)
|
||||
|
||||
. = ..()
|
||||
if(merge)
|
||||
for(var/obj/item/stack/S in loc)
|
||||
if(S.merge_type == merge_type)
|
||||
if(can_merge(S))
|
||||
INVOKE_ASYNC(src, .proc/merge, S)
|
||||
var/list/temp_recipes = get_main_recipes()
|
||||
recipes = temp_recipes.Copy()
|
||||
@@ -73,12 +70,48 @@
|
||||
for(var/i in M.categories)
|
||||
switch(i)
|
||||
if(MAT_CATEGORY_BASE_RECIPES)
|
||||
var/list/temp = SSmaterials.base_stack_recipes.Copy()
|
||||
recipes += temp
|
||||
if(MAT_CATEGORY_RIGID)
|
||||
var/list/temp = SSmaterials.rigid_stack_recipes.Copy()
|
||||
recipes += temp
|
||||
update_weight()
|
||||
update_icon()
|
||||
|
||||
/** Sets the amount of materials per unit for this stack.
|
||||
*
|
||||
* Arguments:
|
||||
* - [mats][/list]: The value to set the mats per unit to.
|
||||
* - multiplier: The amount to multiply the mats per unit by. Defaults to 1.
|
||||
*/
|
||||
/obj/item/stack/proc/set_mats_per_unit(list/mats, multiplier=1)
|
||||
mats_per_unit = SSmaterials.FindOrCreateMaterialCombo(mats, multiplier)
|
||||
update_custom_materials()
|
||||
|
||||
/** Updates the custom materials list of this stack.
|
||||
*/
|
||||
/obj/item/stack/proc/update_custom_materials()
|
||||
set_custom_materials(mats_per_unit, amount, is_update=TRUE)
|
||||
|
||||
/**
|
||||
* Override to make things like metalgen accurately set custom materials
|
||||
*/
|
||||
/obj/item/stack/set_custom_materials(list/materials, multiplier=1, is_update=FALSE)
|
||||
return is_update ? ..() : set_mats_per_unit(materials, multiplier / (amount || 1))
|
||||
|
||||
/obj/item/stack/on_grind()
|
||||
. = ..()
|
||||
for(var/i in 1 to length(grind_results)) //This should only call if it's ground, so no need to check if grind_results exists
|
||||
grind_results[grind_results[i]] *= get_amount() //Gets the key at position i, then the reagent amount of that key, then multiplies it by stack size
|
||||
|
||||
/obj/item/stack/grind_requirements()
|
||||
if(is_cyborg)
|
||||
to_chat(usr, "<span class='warning'>[src] is electronically synthesized in your chassis and can't be ground up!</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/item/stack/proc/get_main_recipes()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
return list()//empty list
|
||||
|
||||
/obj/item/stack/proc/update_weight()
|
||||
@@ -99,12 +132,6 @@
|
||||
else
|
||||
icon_state = "[initial(icon_state)]_3"
|
||||
|
||||
|
||||
/obj/item/stack/Destroy()
|
||||
if (usr && usr.machine==src)
|
||||
usr << browse(null, "window=stack")
|
||||
. = ..()
|
||||
|
||||
/obj/item/stack/examine(mob/user)
|
||||
. = ..()
|
||||
if (is_cyborg)
|
||||
@@ -126,196 +153,208 @@
|
||||
|
||||
/obj/item/stack/proc/get_amount()
|
||||
if(is_cyborg)
|
||||
. = round(source.energy / cost)
|
||||
. = round(source?.energy / cost)
|
||||
else
|
||||
. = (amount)
|
||||
|
||||
/obj/item/stack/attack_self(mob/user)
|
||||
interact(user)
|
||||
/**
|
||||
* Builds all recipes in a given recipe list and returns an association list containing them
|
||||
*
|
||||
* Arguments:
|
||||
* * recipe_to_iterate - The list of recipes we are using to build recipes
|
||||
*/
|
||||
/obj/item/stack/proc/recursively_build_recipes(list/recipe_to_iterate)
|
||||
var/list/L = list()
|
||||
for(var/recipe in recipe_to_iterate)
|
||||
if(istype(recipe, /datum/stack_recipe_list))
|
||||
var/datum/stack_recipe_list/R = recipe
|
||||
L["[R.title]"] = recursively_build_recipes(R.recipes)
|
||||
if(istype(recipe, /datum/stack_recipe))
|
||||
var/datum/stack_recipe/R = recipe
|
||||
L["[R.title]"] = build_recipe(R)
|
||||
return L
|
||||
|
||||
/obj/item/stack/interact(mob/user, sublist)
|
||||
ui_interact(user, sublist)
|
||||
/**
|
||||
* Returns a list of properties of a given recipe
|
||||
*
|
||||
* Arguments:
|
||||
* * R - The stack recipe we are using to get a list of properties
|
||||
*/
|
||||
/obj/item/stack/proc/build_recipe(datum/stack_recipe/R)
|
||||
return list(
|
||||
"res_amount" = R.res_amount,
|
||||
"max_res_amount" = R.max_res_amount,
|
||||
"req_amount" = R.req_amount,
|
||||
"ref" = "\ref[R]",
|
||||
)
|
||||
|
||||
/obj/item/stack/ui_interact(mob/user, recipes_sublist)
|
||||
/**
|
||||
* Checks if the recipe is valid to be used
|
||||
*
|
||||
* Arguments:
|
||||
* * R - The stack recipe we are checking if it is valid
|
||||
* * recipe_list - The list of recipes we are using to check the given recipe
|
||||
*/
|
||||
/obj/item/stack/proc/is_valid_recipe(datum/stack_recipe/R, list/recipe_list)
|
||||
for(var/S in recipe_list)
|
||||
if(S == R)
|
||||
return TRUE
|
||||
if(istype(S, /datum/stack_recipe_list))
|
||||
var/datum/stack_recipe_list/L = S
|
||||
if(is_valid_recipe(R, L.recipes))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/stack/ui_state(mob/user)
|
||||
return GLOB.hands_state
|
||||
|
||||
/obj/item/stack/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Stack", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/stack/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["amount"] = get_amount()
|
||||
return data
|
||||
|
||||
/obj/item/stack/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["recipes"] = recursively_build_recipes(recipes)
|
||||
return data
|
||||
|
||||
/obj/item/stack/ui_act(action, params)
|
||||
. = ..()
|
||||
if (!recipes)
|
||||
if(.)
|
||||
return
|
||||
if (!src || get_amount() <= 0)
|
||||
user << browse(null, "window=stack")
|
||||
user.set_machine(src) //for correct work of onclose
|
||||
var/list/recipe_list = recipes
|
||||
if (recipes_sublist && recipe_list[recipes_sublist] && istype(recipe_list[recipes_sublist], /datum/stack_recipe_list))
|
||||
var/datum/stack_recipe_list/srl = recipe_list[recipes_sublist]
|
||||
recipe_list = srl.recipes
|
||||
var/t1 = "Amount Left: [get_amount()]<br>"
|
||||
for(var/i in 1 to length(recipe_list))
|
||||
var/E = recipe_list[i]
|
||||
if (isnull(E))
|
||||
t1 += "<hr>"
|
||||
continue
|
||||
if (i>1 && !isnull(recipe_list[i-1]))
|
||||
t1+="<br>"
|
||||
|
||||
if (istype(E, /datum/stack_recipe_list))
|
||||
var/datum/stack_recipe_list/srl = E
|
||||
t1 += "<a href='?src=[REF(src)];sublist=[i]'>[srl.title]</a>"
|
||||
|
||||
if (istype(E, /datum/stack_recipe))
|
||||
var/datum/stack_recipe/R = E
|
||||
var/max_multiplier = round(get_amount() / R.req_amount)
|
||||
var/title
|
||||
var/can_build = 1
|
||||
can_build = can_build && (max_multiplier>0)
|
||||
|
||||
if (R.res_amount>1)
|
||||
title+= "[R.res_amount]x [R.title]\s"
|
||||
else
|
||||
title+= "[R.title]"
|
||||
title+= " ([R.req_amount] [singular_name]\s)"
|
||||
if (can_build)
|
||||
t1 += text("<A href='?src=[REF(src)];sublist=[recipes_sublist];make=[i];multiplier=1'>[title]</A> ")
|
||||
else
|
||||
t1 += text("[]", title)
|
||||
continue
|
||||
if (R.max_res_amount>1 && max_multiplier>1)
|
||||
max_multiplier = min(max_multiplier, round(R.max_res_amount/R.res_amount))
|
||||
t1 += " |"
|
||||
var/list/multipliers = list(5,10,25)
|
||||
for (var/n in multipliers)
|
||||
if (max_multiplier>=n)
|
||||
t1 += " <A href='?src=[REF(src)];make=[i];multiplier=[n]'>[n*R.res_amount]x</A>"
|
||||
if (!(max_multiplier in multipliers))
|
||||
t1 += " <A href='?src=[REF(src)];make=[i];multiplier=[max_multiplier]'>[max_multiplier*R.res_amount]x</A>"
|
||||
|
||||
var/datum/browser/popup = new(user, "stack", name, 400, 400)
|
||||
popup.set_content(t1)
|
||||
popup.open(0)
|
||||
onclose(user, "stack")
|
||||
|
||||
/obj/item/stack/Topic(href, href_list)
|
||||
..()
|
||||
if (usr.restrained() || usr.stat || usr.get_active_held_item() != src)
|
||||
return
|
||||
if (href_list["sublist"] && !href_list["make"])
|
||||
interact(usr, text2num(href_list["sublist"]))
|
||||
if (href_list["make"])
|
||||
if (get_amount() < 1 && !is_cyborg)
|
||||
qdel(src)
|
||||
|
||||
var/list/recipes_list = recipes
|
||||
if (href_list["sublist"])
|
||||
var/datum/stack_recipe_list/srl = recipes_list[text2num(href_list["sublist"])]
|
||||
recipes_list = srl.recipes
|
||||
var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
|
||||
var/multiplier = text2num(href_list["multiplier"])
|
||||
if (!multiplier ||(multiplier <= 0)) //href protection
|
||||
return
|
||||
if(!building_checks(R, multiplier))
|
||||
return
|
||||
if (R.time)
|
||||
var/adjusted_time = 0
|
||||
usr.visible_message("<span class='notice'>[usr] starts building [R.title].</span>", "<span class='notice'>You start building [R.title]...</span>")
|
||||
if(HAS_TRAIT(usr, R.trait_booster))
|
||||
adjusted_time = (R.time * R.trait_modifier)
|
||||
else
|
||||
adjusted_time = R.time
|
||||
if (!do_after(usr, adjusted_time, target = usr))
|
||||
switch(action)
|
||||
if("make")
|
||||
if(get_amount() < 1 && !is_cyborg)
|
||||
qdel(src)
|
||||
return
|
||||
var/datum/stack_recipe/R = locate(params["ref"])
|
||||
if(!is_valid_recipe(R, recipes)) //href exploit protection
|
||||
return
|
||||
var/multiplier = text2num(params["multiplier"])
|
||||
if(!multiplier || (multiplier <= 0)) //href exploit protection
|
||||
return
|
||||
if(!building_checks(R, multiplier))
|
||||
return
|
||||
if(R.time)
|
||||
var/adjusted_time = 0
|
||||
usr.visible_message("<span class='notice'>[usr] starts building \a [R.title].</span>", "<span class='notice'>You start building \a [R.title]...</span>")
|
||||
if(HAS_TRAIT(usr, R.trait_booster))
|
||||
adjusted_time = (R.time * R.trait_modifier)
|
||||
else
|
||||
adjusted_time = R.time
|
||||
if(!do_after(usr, adjusted_time, target = usr))
|
||||
return
|
||||
if(!building_checks(R, multiplier))
|
||||
return
|
||||
|
||||
var/obj/O
|
||||
if(R.max_res_amount > 1) //Is it a stack?
|
||||
O = new R.result_type(usr.drop_location(), R.res_amount * multiplier)
|
||||
else if(ispath(R.result_type, /turf))
|
||||
var/turf/T = usr.drop_location()
|
||||
if(!isturf(T))
|
||||
return
|
||||
T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR)
|
||||
var/obj/O
|
||||
if(R.max_res_amount > 1) //Is it a stack?
|
||||
O = new R.result_type(usr.drop_location(), R.res_amount * multiplier)
|
||||
else if(ispath(R.result_type, /turf))
|
||||
var/turf/T = usr.drop_location()
|
||||
if(!isturf(T))
|
||||
return
|
||||
T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
O = new R.result_type(usr.drop_location())
|
||||
if(O)
|
||||
O.setDir(usr.dir)
|
||||
use(R.req_amount * multiplier)
|
||||
|
||||
if(R.applies_mats && LAZYLEN(mats_per_unit))
|
||||
if(isstack(O))
|
||||
var/obj/item/stack/crafted_stack = O
|
||||
crafted_stack.set_mats_per_unit(mats_per_unit, R.req_amount / R.res_amount)
|
||||
else
|
||||
O.set_custom_materials(mats_per_unit, R.req_amount / R.res_amount)
|
||||
|
||||
if(istype(O, /obj/structure/windoor_assembly))
|
||||
var/obj/structure/windoor_assembly/W = O
|
||||
W.ini_dir = W.dir
|
||||
else if(istype(O, /obj/structure/window))
|
||||
var/obj/structure/window/W = O
|
||||
W.ini_dir = W.dir
|
||||
|
||||
if(QDELETED(O))
|
||||
return //It's a stack and has already been merged
|
||||
|
||||
if(isitem(O))
|
||||
usr.put_in_hands(O)
|
||||
O.add_fingerprint(usr)
|
||||
|
||||
//BubbleWrap - so newly formed boxes are empty
|
||||
if(istype(O, /obj/item/storage))
|
||||
for (var/obj/item/I in O)
|
||||
qdel(I)
|
||||
//BubbleWrap END
|
||||
return TRUE
|
||||
|
||||
/obj/item/stack/vv_edit_var(vname, vval)
|
||||
if(vname == NAMEOF(src, amount))
|
||||
add(clamp(vval, 1-amount, max_amount - amount)) //there must always be one.
|
||||
return TRUE
|
||||
else if(vname == NAMEOF(src, max_amount))
|
||||
max_amount = max(vval, 1)
|
||||
add((max_amount < amount) ? (max_amount - amount) : 0) //update icon, weight, ect
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/stack/proc/building_checks(datum/stack_recipe/recipe, multiplier)
|
||||
if (get_amount() < recipe.req_amount*multiplier)
|
||||
if (recipe.req_amount*multiplier>1)
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [recipe.req_amount*multiplier] [recipe.title]\s!</span>")
|
||||
else
|
||||
O = new R.result_type(get_turf(usr))
|
||||
if(O)
|
||||
O.setDir(usr.dir)
|
||||
log_craft("[O] crafted by [usr] at [loc_name(O.loc)]")
|
||||
|
||||
use(R.req_amount * multiplier)
|
||||
|
||||
if(R.applies_mats && custom_materials && custom_materials.len)
|
||||
var/list/used_materials = list()
|
||||
for(var/i in custom_materials)
|
||||
used_materials[SSmaterials.GetMaterialRef(i)] = R.req_amount / R.res_amount * (MINERAL_MATERIAL_AMOUNT / custom_materials.len)
|
||||
O.set_custom_materials(used_materials)
|
||||
|
||||
//START: oh fuck i'm so sorry
|
||||
if(istype(O, /obj/structure/windoor_assembly))
|
||||
var/obj/structure/windoor_assembly/W = O
|
||||
W.ini_dir = W.dir
|
||||
else if(istype(O, /obj/structure/window))
|
||||
var/obj/structure/window/W = O
|
||||
W.ini_dir = W.dir
|
||||
//END: oh fuck i'm so sorry
|
||||
|
||||
else if(istype(O, /obj/item/restraints/handcuffs/cable))
|
||||
var/obj/item/cuffs = O
|
||||
cuffs.color = color
|
||||
|
||||
if (QDELETED(O))
|
||||
return //It's a stack and has already been merged
|
||||
|
||||
if (isitem(O))
|
||||
usr.put_in_hands(O)
|
||||
O.add_fingerprint(usr)
|
||||
|
||||
//BubbleWrap - so newly formed boxes are empty
|
||||
if ( istype(O, /obj/item/storage) )
|
||||
for (var/obj/item/I in O)
|
||||
qdel(I)
|
||||
//BubbleWrap END
|
||||
|
||||
/obj/item/stack/proc/building_checks(datum/stack_recipe/R, multiplier)
|
||||
if (get_amount() < R.req_amount*multiplier)
|
||||
if (R.req_amount*multiplier>1)
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.req_amount*multiplier] [R.title]\s!</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [R.title]!</span>")
|
||||
to_chat(usr, "<span class='warning'>You haven't got enough [src] to build \the [recipe.title]!</span>")
|
||||
return FALSE
|
||||
var/turf/T = get_turf(usr)
|
||||
var/turf/dest_turf = get_turf(usr)
|
||||
|
||||
var/obj/D = R.result_type
|
||||
if(R.window_checks && !valid_window_location(T, initial(D.dir) == FULLTILE_WINDOW_DIR ? FULLTILE_WINDOW_DIR : usr.dir))
|
||||
to_chat(usr, "<span class='warning'>The [R.title] won't fit here!</span>")
|
||||
return FALSE
|
||||
if(R.one_per_turf && (locate(R.result_type) in T))
|
||||
to_chat(usr, "<span class='warning'>There is another [R.title] here!</span>")
|
||||
return FALSE
|
||||
if(R.on_floor)
|
||||
if(!isfloorturf(T))
|
||||
to_chat(usr, "<span class='warning'>\The [R.title] must be constructed on the floor!</span>")
|
||||
// If we're making a window, we have some special snowflake window checks to do.
|
||||
if(ispath(recipe.result_type, /obj/structure/window))
|
||||
var/obj/structure/window/result_path = recipe.result_type
|
||||
if(!valid_window_location(dest_turf, usr.dir, is_fulltile = initial(result_path.fulltile)))
|
||||
to_chat(usr, "<span class='warning'>The [recipe.title] won't fit here!</span>")
|
||||
return FALSE
|
||||
for(var/obj/AM in T)
|
||||
if(istype(AM,/obj/structure/grille))
|
||||
|
||||
if(recipe.one_per_turf && (locate(recipe.result_type) in dest_turf))
|
||||
to_chat(usr, "<span class='warning'>There is another [recipe.title] here!</span>")
|
||||
return FALSE
|
||||
|
||||
if(recipe.on_floor)
|
||||
if(!isfloorturf(dest_turf))
|
||||
to_chat(usr, "<span class='warning'>\The [recipe.title] must be constructed on the floor!</span>")
|
||||
return FALSE
|
||||
|
||||
for(var/obj/object in dest_turf)
|
||||
if(istype(object, /obj/structure/grille))
|
||||
continue
|
||||
if(istype(AM,/obj/structure/table))
|
||||
if(istype(object, /obj/structure/table))
|
||||
continue
|
||||
if(istype(AM,/obj/structure/window))
|
||||
var/obj/structure/window/W = AM
|
||||
if(!W.fulltile)
|
||||
if(istype(object, /obj/structure/window))
|
||||
var/obj/structure/window/window_structure = object
|
||||
if(!window_structure.fulltile)
|
||||
continue
|
||||
if(AM.density)
|
||||
to_chat(usr, "<span class='warning'>Theres a [AM.name] here. You cant make a [R.title] here!</span>")
|
||||
if(object.density)
|
||||
to_chat(usr, "<span class='warning'>There is \a [object.name] here. You cant make \a [recipe.title] here!</span>")
|
||||
return FALSE
|
||||
if(R.placement_checks)
|
||||
switch(R.placement_checks)
|
||||
if(recipe.placement_checks)
|
||||
switch(recipe.placement_checks)
|
||||
if(STACK_CHECK_CARDINALS)
|
||||
var/turf/step
|
||||
for(var/direction in GLOB.cardinals)
|
||||
step = get_step(T, direction)
|
||||
if(locate(R.result_type) in step)
|
||||
to_chat(usr, "<span class='warning'>\The [R.title] must not be built directly adjacent to another!</span>")
|
||||
step = get_step(dest_turf, direction)
|
||||
if(locate(recipe.result_type) in step)
|
||||
to_chat(usr, "<span class='warning'>\The [recipe.title] must not be built directly adjacent to another!</span>")
|
||||
return FALSE
|
||||
if(STACK_CHECK_ADJACENT)
|
||||
if(locate(R.result_type) in range(1, T))
|
||||
to_chat(usr, "<span class='warning'>\The [R.title] must be constructed at least one tile away from others of its type!</span>")
|
||||
if(locate(recipe.result_type) in range(1, dest_turf))
|
||||
to_chat(usr, "<span class='warning'>\The [recipe.title] must be constructed at least one tile away from others of its type!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -330,10 +369,7 @@
|
||||
if(check && zero_amount())
|
||||
return TRUE
|
||||
if(length(mats_per_unit))
|
||||
var/temp_materials = custom_materials.Copy()
|
||||
for(var/i in mats_per_unit)
|
||||
temp_materials[i] = mats_per_unit[i] * src.amount
|
||||
set_custom_materials(temp_materials)
|
||||
update_custom_materials()
|
||||
update_icon()
|
||||
update_weight()
|
||||
return TRUE
|
||||
@@ -357,22 +393,36 @@
|
||||
return source.energy < cost
|
||||
if(amount < 1)
|
||||
qdel(src)
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/stack/proc/add(amount)
|
||||
/** Adds some number of units to this stack.
|
||||
*
|
||||
* Arguments:
|
||||
* - _amount: The number of units to add to this stack.
|
||||
*/
|
||||
/obj/item/stack/proc/add(_amount)
|
||||
if (is_cyborg)
|
||||
source.add_charge(amount * cost)
|
||||
source.add_charge(_amount * cost)
|
||||
else
|
||||
src.amount += amount
|
||||
amount += _amount
|
||||
if(length(mats_per_unit))
|
||||
var/temp_materials = custom_materials.Copy()
|
||||
for(var/i in mats_per_unit)
|
||||
temp_materials[i] = mats_per_unit[i] * src.amount
|
||||
set_custom_materials(temp_materials)
|
||||
update_custom_materials()
|
||||
update_icon()
|
||||
update_weight()
|
||||
|
||||
/** Checks whether this stack can merge itself into another stack.
|
||||
*
|
||||
* Arguments:
|
||||
* - [check][/obj/item/stack]: The stack to check for mergeability.
|
||||
*/
|
||||
/obj/item/stack/proc/can_merge(obj/item/stack/check)
|
||||
if(!istype(check, merge_type))
|
||||
return FALSE
|
||||
if(!check.is_cyborg && (mats_per_unit != check.mats_per_unit)) // Cyborg stacks don't have materials. This lets them recycle sheets and floor tiles.
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/stack/proc/merge(obj/item/stack/S) //Merge src into S, as much as possible
|
||||
if(QDELETED(S) || QDELETED(src) || S == src) //amusingly this can cause a stack to consume itself, let's not allow that.
|
||||
return
|
||||
@@ -388,50 +438,53 @@
|
||||
S.add(transfer)
|
||||
return transfer
|
||||
|
||||
/obj/item/stack/Crossed(obj/o)
|
||||
if(istype(o, merge_type) && !o.throwing)
|
||||
merge(o)
|
||||
/obj/item/stack/Crossed(atom/movable/crossing)
|
||||
if(!crossing.throwing && can_merge(crossing))
|
||||
merge(crossing)
|
||||
. = ..()
|
||||
|
||||
/obj/item/stack/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
if(istype(AM, merge_type))
|
||||
merge(AM)
|
||||
/obj/item/stack/hitby(atom/movable/hitting, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
if(can_merge(hitting))
|
||||
merge(hitting)
|
||||
. = ..()
|
||||
|
||||
/obj/item/stack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/obj/item/stack/on_attack_hand(mob/user)
|
||||
if(user.get_inactive_held_item() == src)
|
||||
if(zero_amount())
|
||||
return
|
||||
return change_stack(user,1)
|
||||
return split_stack(user, 1)
|
||||
else
|
||||
. = ..()
|
||||
|
||||
/obj/item/stack/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
if(isturf(loc)) // to prevent people that are alt clicking a tile to see its content from getting undesidered pop ups
|
||||
return
|
||||
if(is_cyborg)
|
||||
if(is_cyborg || !user.canUseTopic(src, BE_CLOSE, TRUE, FALSE) || zero_amount()) //, !iscyborg(user)
|
||||
return
|
||||
else
|
||||
if(zero_amount())
|
||||
return
|
||||
//get amount from user
|
||||
var/max = get_amount()
|
||||
var/stackmaterial = round(input(user,"How many sheets do you wish to take out of this stack? (Maximum [max])") as null|num)
|
||||
max = get_amount()
|
||||
stackmaterial = min(max, stackmaterial)
|
||||
if(stackmaterial == null || stackmaterial <= 0 || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return TRUE
|
||||
else
|
||||
change_stack(user, stackmaterial)
|
||||
to_chat(user, "<span class='notice'>You take [stackmaterial] sheets out of the stack</span>")
|
||||
return TRUE
|
||||
//get amount from user
|
||||
var/max = get_amount()
|
||||
var/stackmaterial = round(input(user,"How many sheets do you wish to take out of this stack? (Maximum [max])") as null|num)
|
||||
max = get_amount()
|
||||
stackmaterial = min(max, stackmaterial)
|
||||
if(stackmaterial == null || stackmaterial <= 0 || !user.canUseTopic(src, BE_CLOSE, TRUE, FALSE)) //, !iscyborg(user)
|
||||
return
|
||||
split_stack(user, stackmaterial)
|
||||
to_chat(user, "<span class='notice'>You take [stackmaterial] sheets out of the stack.</span>")
|
||||
|
||||
/obj/item/stack/proc/change_stack(mob/user, amount)
|
||||
/** Splits the stack into two stacks.
|
||||
*
|
||||
* Arguments:
|
||||
* - [user][/mob]: The mob splitting the stack.
|
||||
* - amount: The number of units to split from this stack.
|
||||
*/
|
||||
/obj/item/stack/proc/split_stack(mob/user, amount)
|
||||
if(!use(amount, TRUE, FALSE))
|
||||
return FALSE
|
||||
return null
|
||||
var/obj/item/stack/F = new type(user? user : drop_location(), amount, FALSE)
|
||||
. = F
|
||||
F.set_mats_per_unit(mats_per_unit, 1) // Required for greyscale sheets and tiles.
|
||||
F.copy_evidences(src)
|
||||
if(user)
|
||||
if(!user.put_in_hands(F, merge_stacks = FALSE))
|
||||
@@ -441,7 +494,7 @@
|
||||
zero_amount()
|
||||
|
||||
/obj/item/stack/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, merge_type))
|
||||
if(can_merge(W))
|
||||
var/obj/item/stack/S = W
|
||||
if(merge(S))
|
||||
to_chat(user, "<span class='notice'>Your [S.name] stack now contains [S.get_amount()] [S.singular_name]\s.</span>")
|
||||
@@ -455,8 +508,8 @@
|
||||
fingerprints = from.fingerprints.Copy()
|
||||
if(from.fingerprintshidden)
|
||||
fingerprintshidden = from.fingerprintshidden.Copy()
|
||||
if(from.fingerprintslast)
|
||||
fingerprintslast = from.fingerprintslast
|
||||
fingerprintslast = from.fingerprintslast
|
||||
//TODO bloody overlay
|
||||
|
||||
/obj/item/stack/microwave_act(obj/machinery/microwave/M)
|
||||
if(istype(M) && M.dirty < 100)
|
||||
@@ -474,15 +527,12 @@
|
||||
var/time = 0
|
||||
var/one_per_turf = FALSE
|
||||
var/on_floor = FALSE
|
||||
var/window_checks = FALSE
|
||||
var/placement_checks = FALSE
|
||||
var/applies_mats = FALSE
|
||||
var/trait_booster = null
|
||||
var/trait_modifier = 1
|
||||
|
||||
/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1,time = 0, one_per_turf = FALSE, on_floor = FALSE, window_checks = FALSE, placement_checks = FALSE, applies_mats = FALSE, trait_booster = null, trait_modifier = 1)
|
||||
|
||||
|
||||
src.title = title
|
||||
src.result_type = result_type
|
||||
src.req_amount = req_amount
|
||||
@@ -491,7 +541,6 @@
|
||||
src.time = time
|
||||
src.one_per_turf = one_per_turf
|
||||
src.on_floor = on_floor
|
||||
src.window_checks = window_checks
|
||||
src.placement_checks = placement_checks
|
||||
src.applies_mats = applies_mats
|
||||
src.trait_booster = trait_booster
|
||||
|
||||
@@ -1143,9 +1143,9 @@
|
||||
desc = "A box containing a gift for worthy golems."
|
||||
|
||||
/obj/item/storage/box/rndboards/PopulateContents()
|
||||
new /obj/item/circuitboard/machine/protolathe/offstation(src)
|
||||
new /obj/item/circuitboard/machine/protolathe(src)
|
||||
new /obj/item/circuitboard/machine/destructive_analyzer(src)
|
||||
new /obj/item/circuitboard/machine/circuit_imprinter/offstation(src)
|
||||
new /obj/item/circuitboard/machine/circuit_imprinter(src)
|
||||
new /obj/item/circuitboard/computer/rdconsole(src)
|
||||
|
||||
/obj/item/storage/box/silver_sulf
|
||||
|
||||
@@ -164,11 +164,15 @@
|
||||
/obj/item/storage/secure/briefcase/hos/mws_pack_hos/PopulateContents()
|
||||
new /obj/item/gun/ballistic/revolver/mws(src)
|
||||
new /obj/item/ammo_box/magazine/mws_mag(src)
|
||||
new /obj/item/ammo_box/magazine/mws_mag(src)
|
||||
new /obj/item/ammo_casing/mws_batt/lethal(src)
|
||||
new /obj/item/ammo_casing/mws_batt/lethal(src)
|
||||
new /obj/item/ammo_casing/mws_batt/lethal(src)
|
||||
new /obj/item/ammo_casing/mws_batt/stun(src)
|
||||
new /obj/item/ammo_casing/mws_batt/stun(src)
|
||||
new /obj/item/ammo_casing/mws_batt/stun(src)
|
||||
new /obj/item/ammo_casing/mws_batt/ion(src)
|
||||
new /obj/item/ammo_casing/mws_batt/taser(src)
|
||||
|
||||
/obj/item/storage/secure/briefcase/hos/multiphase_box
|
||||
name = "\improper X-01 Multiphase energy gun box"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/obj/item/tank
|
||||
name = "tank"
|
||||
icon = 'icons/obj/tank.dmi'
|
||||
icon_state = "generic"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tanks_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tanks_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
// worn_icon = 'icons/mob/clothing/back.dmi' //since these can also get thrown into suit storage slots. if something goes on the belt, set this to null.
|
||||
hitsound = 'sound/weapons/smash.ogg'
|
||||
pressure_resistance = ONE_ATMOSPHERE * 5
|
||||
force = 5
|
||||
@@ -18,6 +20,8 @@
|
||||
var/distribute_pressure = ONE_ATMOSPHERE
|
||||
var/integrity = 3
|
||||
var/volume = 70
|
||||
/// Icon state when in a tank holder. Null makes it incompatible with tank holder.
|
||||
var/tank_holder_icon_state = "holder_generic"
|
||||
|
||||
/obj/item/tank/ui_action_click(mob/user)
|
||||
toggle_internals(user)
|
||||
@@ -84,18 +88,23 @@
|
||||
|
||||
/obj/item/tank/Destroy()
|
||||
if(air_contents)
|
||||
qdel(air_contents)
|
||||
QDEL_NULL(air_contents)
|
||||
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
// /obj/item/tank/ComponentInitialize()
|
||||
// . = ..()
|
||||
// if(tank_holder_icon_state)
|
||||
// AddComponent(/datum/component/container_item/tank_holder, tank_holder_icon_state)
|
||||
|
||||
/obj/item/tank/examine(mob/user)
|
||||
var/obj/icon = src
|
||||
. = ..()
|
||||
if(istype(src.loc, /obj/item/assembly))
|
||||
icon = src.loc
|
||||
if(!in_range(src, user) && !isobserver(user))
|
||||
if (icon == src)
|
||||
if(icon == src)
|
||||
. += "<span class='notice'>If you want any more information you'll need to get closer.</span>"
|
||||
return
|
||||
|
||||
@@ -140,14 +149,14 @@
|
||||
if(T)
|
||||
T.assume_air(air_contents)
|
||||
air_update_turf()
|
||||
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
|
||||
playsound(src.loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/tank/suicide_act(mob/user)
|
||||
var/mob/living/carbon/human/H = user
|
||||
user.visible_message("<span class='suicide'>[user] is putting [src]'s valve to [user.p_their()] lips! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
playsound(loc, 'sound/effects/spray.ogg', 10, 1, -3)
|
||||
if (!QDELETED(H) && air_contents && air_contents.return_pressure() >= 1000)
|
||||
playsound(loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
|
||||
if(!QDELETED(H) && air_contents && air_contents.return_pressure() >= 1000)
|
||||
for(var/obj/item/W in H)
|
||||
H.dropItemToGround(W)
|
||||
if(prob(50))
|
||||
@@ -159,12 +168,10 @@
|
||||
H.spawn_gibs()
|
||||
H.spill_organs()
|
||||
H.spread_bodyparts()
|
||||
|
||||
return (BRUTELOSS)
|
||||
|
||||
/obj/item/tank/attack_ghost(mob/dead/observer/O)
|
||||
. = ..()
|
||||
atmosanalyzer_scan(air_contents, O, src, FALSE)
|
||||
return MANUAL_SUICIDE
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There isn't enough pressure in [src] to commit suicide with...</span>")
|
||||
return SHAME
|
||||
|
||||
/obj/item/tank/attackby(obj/item/W, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
@@ -182,27 +189,30 @@
|
||||
ui = new(user, src, "Tank", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/tank/ui_static_data(mob/user)
|
||||
. = list (
|
||||
"defaultReleasePressure" = round(TANK_DEFAULT_RELEASE_PRESSURE),
|
||||
"minReleasePressure" = round(TANK_MIN_RELEASE_PRESSURE),
|
||||
"maxReleasePressure" = round(TANK_MAX_RELEASE_PRESSURE),
|
||||
"leakPressure" = round(TANK_LEAK_PRESSURE),
|
||||
"fragmentPressure" = round(TANK_FRAGMENT_PRESSURE)
|
||||
)
|
||||
|
||||
/obj/item/tank/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
|
||||
data["releasePressure"] = round(distribute_pressure ? distribute_pressure : 0)
|
||||
data["defaultReleasePressure"] = round(TANK_DEFAULT_RELEASE_PRESSURE)
|
||||
data["minReleasePressure"] = round(TANK_MIN_RELEASE_PRESSURE)
|
||||
data["maxReleasePressure"] = round(TANK_MAX_RELEASE_PRESSURE)
|
||||
. = list(
|
||||
"tankPressure" = round(air_contents.return_pressure()),
|
||||
"releasePressure" = round(distribute_pressure)
|
||||
)
|
||||
|
||||
var/mob/living/carbon/C = user
|
||||
if(!istype(C))
|
||||
C = loc.loc
|
||||
if(!istype(C))
|
||||
return data
|
||||
|
||||
if(C.internal == src)
|
||||
data["connected"] = TRUE
|
||||
|
||||
return data
|
||||
if(istype(C) && C.internal == src)
|
||||
.["connected"] = TRUE
|
||||
|
||||
/obj/item/tank/ui_act(action, params)
|
||||
if(..())
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("pressure")
|
||||
@@ -228,6 +238,9 @@
|
||||
/obj/item/tank/return_air()
|
||||
return air_contents
|
||||
|
||||
// /obj/item/tank/return_analyzable_air()
|
||||
// return air_contents
|
||||
|
||||
/obj/item/tank/assume_air(datum/gas_mixture/giver)
|
||||
air_contents.merge(giver)
|
||||
|
||||
@@ -239,10 +252,9 @@
|
||||
return null
|
||||
|
||||
var/tank_pressure = air_contents.return_pressure()
|
||||
if(tank_pressure < distribute_pressure)
|
||||
distribute_pressure = tank_pressure
|
||||
var/actual_distribute_pressure = clamp(tank_pressure, 0, distribute_pressure)
|
||||
|
||||
var/moles_needed = distribute_pressure*volume_to_return/(R_IDEAL_GAS_EQUATION*air_contents.return_temperature())
|
||||
var/moles_needed = actual_distribute_pressure*volume_to_return/(R_IDEAL_GAS_EQUATION*air_contents.return_temperature())
|
||||
|
||||
return remove_air(moles_needed)
|
||||
|
||||
@@ -267,7 +279,7 @@
|
||||
//Give the gas a chance to build up more pressure through reacting
|
||||
air_contents.react(src)
|
||||
air_contents.react(src)
|
||||
//Citadel Edit: removing extra react for "balance"
|
||||
|
||||
pressure = air_contents.return_pressure()
|
||||
var/range = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE
|
||||
var/turf/epicenter = get_turf(loc)
|
||||
@@ -285,7 +297,7 @@
|
||||
if(!T)
|
||||
return
|
||||
T.assume_air(air_contents)
|
||||
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
|
||||
playsound(src.loc, 'sound/effects/spray.ogg', 10, TRUE, -3)
|
||||
qdel(src)
|
||||
else
|
||||
integrity--
|
||||
|
||||
@@ -24,9 +24,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
*/
|
||||
/obj/item/banhammer/attack(mob/M, mob/user)
|
||||
if(user.zone_selected == BODY_ZONE_HEAD)
|
||||
M.visible_message("<span class='danger'>[user] are stroking the head of [M] with a bangammer</span>", "<span class='userdanger'>[user] are stroking the head with a bangammer</span>", "you hear a bangammer stroking a head");
|
||||
M.visible_message("<span class='danger'>[user] are stroking the head of [M] with a bangammer.</span>", "<span class='userdanger'>[user] are stroking your head with a bangammer.</span>", "<span class='hear'>You hear a bangammer stroking a head.</span>") // see above comment
|
||||
else
|
||||
M.visible_message("<span class='danger'>[M] has been banned FOR NO REISIN by [user]</span>", "<span class='userdanger'>You have been banned FOR NO REISIN by [user]</span>", "you hear a banhammer banning someone")
|
||||
M.visible_message("<span class='danger'>[M] has been banned FOR NO REISIN by [user]!</span>", "<span class='userdanger'>You have been banned FOR NO REISIN by [user]!</span>", "<span class='hear'>You hear a banhammer banning someone.</span>")
|
||||
playsound(loc, 'sound/effects/adminhelp.ogg', 15) //keep it at 15% volume so people don't jump out of their skin too much
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return ..(M, user)
|
||||
@@ -89,7 +89,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/obj/item/claymore/highlander //ALL COMMENTS MADE REGARDING THIS SWORD MUST BE MADE IN ALL CAPS
|
||||
desc = "<b><i>THERE CAN BE ONLY ONE, AND IT WILL BE YOU!!!</i></b>\nActivate it in your hand to point to the nearest victim."
|
||||
flags_1 = CONDUCT_1
|
||||
item_flags = DROPDEL
|
||||
item_flags = DROPDEL //WOW BRO YOU LOST AN ARM, GUESS WHAT YOU DONT GET YOUR SWORD ANYMORE //I CANT BELIEVE SPOOKYDONUT WOULD BREAK THE REQUIREMENTS
|
||||
slot_flags = null
|
||||
block_chance = 0 //RNG WON'T HELP YOU NOW, PANSY
|
||||
light_range = 3
|
||||
@@ -130,8 +130,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/obj/item/claymore/highlander/dropped(mob/living/user)
|
||||
. = ..()
|
||||
user.unignore_slowdown(HIGHLANDER)
|
||||
if(!QDELETED(src))
|
||||
qdel(src) //If this ever happens, it's because you lost an arm
|
||||
|
||||
/obj/item/claymore/highlander/examine(mob/user)
|
||||
. = ..()
|
||||
@@ -141,8 +139,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
|
||||
/obj/item/claymore/highlander/attack(mob/living/target, mob/living/user)
|
||||
. = ..()
|
||||
if(!QDELETED(target) && iscarbon(target) && target.stat == DEAD && target.mind && target.mind.special_role == "highlander")
|
||||
user.fully_heal() //STEAL THE LIFE OF OUR FALLEN FOES
|
||||
if(!QDELETED(target) && target.stat == DEAD && target.mind && target.mind.special_role == "highlander")
|
||||
user.fully_heal(admin_revive = FALSE) //STEAL THE LIFE OF OUR FALLEN FOES
|
||||
add_notch(user)
|
||||
target.visible_message("<span class='warning'>[target] crumbles to dust beneath [user]'s blows!</span>", "<span class='userdanger'>As you fall, your body crumbles to dust!</span>")
|
||||
target.dust()
|
||||
@@ -150,9 +148,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/obj/item/claymore/highlander/attack_self(mob/living/user)
|
||||
var/closest_victim
|
||||
var/closest_distance = 255
|
||||
for(var/mob/living/carbon/human/H in GLOB.player_list - user)
|
||||
if(H.client && H.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
|
||||
closest_victim = H
|
||||
for(var/mob/living/carbon/human/scot in GLOB.player_list - user)
|
||||
if(scot.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
|
||||
closest_victim = scot
|
||||
for(var/mob/living/silicon/robot/siliscot in GLOB.player_list - user)
|
||||
if(siliscot.mind.special_role == "highlander" && (!closest_victim || get_dist(user, closest_victim) < closest_distance))
|
||||
closest_victim = siliscot
|
||||
|
||||
if(!closest_victim)
|
||||
to_chat(user, "<span class='warning'>[src] thrums for a moment and falls dark. Perhaps there's nobody nearby.</span>")
|
||||
return
|
||||
@@ -161,7 +163,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/obj/item/claymore/highlander/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
|
||||
if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object))
|
||||
return BLOCK_SUCCESS | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED
|
||||
return ..()
|
||||
return ..() //YOU THINK YOUR PUNY LASERS CAN STOP ME?
|
||||
|
||||
/obj/item/claymore/highlander/proc/add_notch(mob/living/user) //DYNAMIC CLAYMORE PROGRESSION SYSTEM - THIS IS THE FUTURE
|
||||
notches++
|
||||
@@ -214,7 +216,22 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
remove_atom_colour(ADMIN_COLOUR_PRIORITY)
|
||||
|
||||
name = new_name
|
||||
playsound(user, 'sound/items/screwdriver2.ogg', 50, 1)
|
||||
playsound(user, 'sound/items/screwdriver2.ogg', 50, TRUE)
|
||||
|
||||
/obj/item/claymore/highlander/robot //BLOODTHIRSTY BORGS NOW COME IN PLAID
|
||||
icon = 'icons/obj/items_cyborg.dmi'
|
||||
icon_state = "claymore_cyborg"
|
||||
var/mob/living/silicon/robot/robot
|
||||
|
||||
/obj/item/claymore/highlander/robot/Initialize()
|
||||
var/obj/item/robot_module/kiltkit = loc
|
||||
robot = kiltkit.loc
|
||||
if(!istype(robot))
|
||||
qdel(src)
|
||||
return ..()
|
||||
|
||||
/obj/item/claymore/highlander/robot/process()
|
||||
loc.layer = LARGE_MOB_LAYER
|
||||
|
||||
/obj/item/katana
|
||||
name = "katana"
|
||||
@@ -227,7 +244,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
|
||||
force = 40
|
||||
throwforce = 10
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
block_chance = 50
|
||||
@@ -417,7 +434,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
desc = "A misnomer of sorts, this is effectively a blunt katana made from steelwood, a dense organic wood derived from steelcaps. Why steelwood? Druids can use it. Duh."
|
||||
icon_state = "bokken_steel"
|
||||
item_state = "bokken_steel"
|
||||
force = 12
|
||||
force = 12
|
||||
stamina_damage_increment = 3
|
||||
|
||||
/obj/item/melee/bokken/waki
|
||||
@@ -427,7 +444,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
item_state = "wakibokken"
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
force = 6
|
||||
force = 6
|
||||
stamina_damage_increment = 4
|
||||
block_parry_data = /datum/block_parry_data/bokken/waki
|
||||
default_parry_data = /datum/block_parry_data/bokken/waki
|
||||
@@ -442,7 +459,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
parry_time_perfect_leeway = 1
|
||||
parry_imperfect_falloff_percent = 7.5
|
||||
parry_efficiency_to_counterattack = 120
|
||||
parry_efficiency_considered_successful = 65
|
||||
parry_efficiency_considered_successful = 65
|
||||
parry_efficiency_perfect = 120
|
||||
parry_efficiency_perfect_override = list(
|
||||
TEXT_ATTACK_TYPE_PROJECTILE = 30,
|
||||
@@ -455,10 +472,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/datum/block_parry_data/bokken/waki/quick_parry //For the parry spammer in you
|
||||
parry_stamina_cost = 2 // Slam that parry button
|
||||
parry_time_active = 2.5
|
||||
parry_time_perfect = 1
|
||||
parry_time_perfect = 1
|
||||
parry_time_perfect_leeway = 1
|
||||
parry_failed_stagger_duration = 1 SECONDS
|
||||
parry_failed_clickcd_duration = 1 SECONDS
|
||||
parry_failed_clickcd_duration = 1 SECONDS
|
||||
|
||||
/datum/block_parry_data/bokken/waki/quick_parry/proj
|
||||
parry_efficiency_perfect_override = list()
|
||||
@@ -468,7 +485,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
desc = "A misnomer of sorts, this is effectively a blunt wakizashi made from steelwood, a dense organic wood derived from steelcaps. Why steelwood? Druids can use it. Duh."
|
||||
icon_state = "wakibokken_steel"
|
||||
item_state = "wakibokken_steel"
|
||||
force = 8
|
||||
force = 8
|
||||
stamina_damage_increment = 2
|
||||
|
||||
/obj/item/melee/bokken/debug
|
||||
@@ -575,7 +592,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
user.put_in_hands(S)
|
||||
to_chat(user, "<span class='notice'>You fasten the glass shard to the top of the rod with the cable.</span>")
|
||||
|
||||
else if(istype(I, /obj/item/assembly/igniter) && !HAS_TRAIT(I, TRAIT_NODROP))
|
||||
else if(istype(I, /obj/item/assembly/igniter) && !(HAS_TRAIT(I, TRAIT_NODROP)))
|
||||
var/obj/item/melee/baton/cattleprod/P = new /obj/item/melee/baton/cattleprod
|
||||
|
||||
remove_item_from_storage(user)
|
||||
@@ -598,13 +615,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
force = 2
|
||||
throwforce = 10 //This is never used on mobs since this has a 100% embed chance.
|
||||
throwforce = 10 //10 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = 18 damage on hit due to guaranteed embedding
|
||||
throw_speed = 4
|
||||
embedding = list("pain_mult" = 4, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15)
|
||||
armour_penetration = 40
|
||||
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
sharpness = SHARP_EDGED
|
||||
sharpness = SHARP_POINTY
|
||||
custom_materials = list(/datum/material/iron=500, /datum/material/glass=500)
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
@@ -639,27 +656,23 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
attack_verb = list("stubbed", "poked")
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/extended = 0
|
||||
var/extended_force = 20
|
||||
var/extended_throwforce = 23
|
||||
var/extended_icon_state = "switchblade_ext"
|
||||
var/retracted_icon_state = "switchblade"
|
||||
|
||||
/obj/item/switchblade/attack_self(mob/user)
|
||||
extended = !extended
|
||||
playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1)
|
||||
playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
|
||||
if(extended)
|
||||
force = extended_force
|
||||
force = 20
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
throwforce = extended_throwforce
|
||||
icon_state = extended_icon_state
|
||||
throwforce = 23
|
||||
icon_state = "switchblade_ext"
|
||||
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
sharpness = SHARP_EDGED
|
||||
else
|
||||
force = initial(force)
|
||||
force = 3
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throwforce = initial(throwforce)
|
||||
icon_state = retracted_icon_state
|
||||
throwforce = 5
|
||||
icon_state = "switchblade"
|
||||
attack_verb = list("stubbed", "poked")
|
||||
hitsound = 'sound/weapons/genhit.ogg'
|
||||
sharpness = SHARP_NONE
|
||||
@@ -750,6 +763,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
user.visible_message("<span class='suicide'>[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane!</span>")
|
||||
return (OXYLOSS)
|
||||
|
||||
// /obj/item/ectoplasm/angelic
|
||||
// icon = 'icons/obj/wizard.dmi'
|
||||
// icon_state = "angelplasm"
|
||||
|
||||
/obj/item/mounted_chainsaw
|
||||
name = "mounted chainsaw"
|
||||
desc = "A chainsaw that has replaced your arm."
|
||||
@@ -758,7 +775,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi'
|
||||
item_flags = ABSTRACT | DROPDEL
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
force = 24
|
||||
throwforce = 0
|
||||
throw_range = 0
|
||||
@@ -801,7 +818,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/obj/item/statuebust/Initialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/art, impressiveness)
|
||||
addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 1000)), 0)
|
||||
// AddComponent(/datum/component/beauty, 1000)
|
||||
|
||||
// /obj/item/statuebust/hippocratic
|
||||
// name = "hippocrates bust"
|
||||
// desc = "A bust of the famous Greek physician Hippocrates of Kos, often referred to as the father of western medicine."
|
||||
// icon_state = "hippocratic"
|
||||
// impressiveness = 50
|
||||
|
||||
/obj/item/tailclub
|
||||
name = "tail club"
|
||||
@@ -825,8 +848,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
icon_state = "catwhip"
|
||||
|
||||
/obj/item/melee/skateboard
|
||||
name = "improvised skateboard"
|
||||
desc = "A skateboard. It can be placed on its wheels and ridden, or used as a strong weapon."
|
||||
name = "skateboard"
|
||||
desc = "A skateboard. It can be placed on its wheels and ridden, or used as a radical weapon."
|
||||
icon_state = "skateboard"
|
||||
item_state = "skateboard"
|
||||
force = 12
|
||||
@@ -839,17 +862,22 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/obj/item/melee/skateboard/attack_self(mob/user)
|
||||
if(!user.canUseTopic(src, TRUE, FALSE, TRUE))
|
||||
return
|
||||
var/obj/vehicle/ridden/scooter/skateboard/S = new board_item_type(get_turf(user))
|
||||
var/obj/vehicle/ridden/scooter/skateboard/S = new board_item_type(get_turf(user))//this probably has fucky interactions with telekinesis but for the record it wasn't my fault
|
||||
S.buckle_mob(user)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/melee/skateboard/improvised
|
||||
name = "improvised skateboard"
|
||||
desc = "A jury-rigged skateboard. It can be placed on its wheels and ridden, or used as a radical weapon."
|
||||
// board_item_type = /obj/vehicle/ridden/scooter/skateboard/improvised
|
||||
|
||||
/obj/item/melee/skateboard/pro
|
||||
name = "skateboard"
|
||||
desc = "A RaDSTORMz brand professional skateboard. It looks sturdy and well made."
|
||||
desc = "An EightO brand professional skateboard. It looks sturdy and well made."
|
||||
icon_state = "skateboard2"
|
||||
item_state = "skateboard2"
|
||||
board_item_type = /obj/vehicle/ridden/scooter/skateboard/pro
|
||||
custom_premium_price = 500
|
||||
custom_premium_price = PAYCHECK_HARD * 5
|
||||
|
||||
/obj/item/melee/skateboard/hoverboard
|
||||
name = "hoverboard"
|
||||
@@ -857,10 +885,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
icon_state = "hoverboard_red"
|
||||
item_state = "hoverboard_red"
|
||||
board_item_type = /obj/vehicle/ridden/scooter/skateboard/hoverboard
|
||||
custom_premium_price = 2015
|
||||
custom_premium_price = PAYCHECK_COMMAND * 5.4 //If I can't make it a meme I'll make it RAD
|
||||
|
||||
/obj/item/melee/skateboard/hoverboard/admin
|
||||
name = "\improper Board Of Directors"
|
||||
name = "Board Of Directors"
|
||||
desc = "The engineering complexity of a spaceship concentrated inside of a board. Just as expensive, too."
|
||||
icon_state = "hoverboard_nt"
|
||||
item_state = "hoverboard_nt"
|
||||
@@ -879,11 +907,19 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
throwforce = 12
|
||||
attack_verb = list("beat", "smacked")
|
||||
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 3.5)
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
var/homerun_ready = 0
|
||||
var/homerun_able = 0
|
||||
total_mass = 2.7 //a regular wooden major league baseball bat weighs somewhere between 2 to 3.4 pounds, according to google
|
||||
|
||||
/obj/item/melee/baseball_bat/Initialize()
|
||||
. = ..()
|
||||
if(prob(1))
|
||||
name = "cricket bat"
|
||||
desc = "You've got red on you."
|
||||
icon_state = "baseball_bat_brit"
|
||||
item_state = "baseball_bat_brit"
|
||||
|
||||
/obj/item/melee/baseball_bat/chaplain
|
||||
name = "blessed baseball bat"
|
||||
desc = "There ain't a cult in the league that can withstand a swatter."
|
||||
@@ -908,11 +944,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
..()
|
||||
return
|
||||
if(homerun_ready)
|
||||
to_chat(user, "<span class='notice'>You're already ready to do a home run!</span>")
|
||||
to_chat(user, "<span class='warning'>You're already ready to do a home run!</span>")
|
||||
..()
|
||||
return
|
||||
to_chat(user, "<span class='warning'>You begin gathering strength...</span>")
|
||||
playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, 1)
|
||||
playsound(get_turf(src), 'sound/magic/lightning_chargeup.ogg', 65, TRUE)
|
||||
if(do_after(user, 90, target = src))
|
||||
to_chat(user, "<span class='userdanger'>You gather power! Time for a home run!</span>")
|
||||
homerun_ready = 1
|
||||
@@ -920,12 +956,14 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
|
||||
/obj/item/melee/baseball_bat/attack(mob/living/target, mob/living/user)
|
||||
. = ..()
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
return
|
||||
var/atom/throw_target = get_edge_target_turf(target, user.dir)
|
||||
if(homerun_ready)
|
||||
user.visible_message("<span class='userdanger'>It's a home run!</span>")
|
||||
target.throw_at(throw_target, rand(8,10), 14, user)
|
||||
target.ex_act(EXPLODE_HEAVY)
|
||||
playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1)
|
||||
playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, TRUE)
|
||||
homerun_ready = 0
|
||||
return
|
||||
else if(!target.anchored)
|
||||
@@ -956,7 +994,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
|
||||
/obj/item/melee/flyswatter
|
||||
name = "flyswatter"
|
||||
desc = "Useful for killing insects of all sizes."
|
||||
desc = "Useful for killing pests of all sizes."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "flyswatter"
|
||||
item_state = "flyswatter"
|
||||
@@ -969,7 +1007,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
//Things in this list will be instantly splatted. Flyman weakness is handled in the flyman species weakness proc.
|
||||
var/list/strong_against
|
||||
var/list/spider_panic
|
||||
|
||||
/obj/item/melee/flyswatter/Initialize()
|
||||
. = ..()
|
||||
@@ -977,13 +1014,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/mob/living/simple_animal/hostile/poison/bees/,
|
||||
/mob/living/simple_animal/butterfly,
|
||||
/mob/living/simple_animal/cockroach,
|
||||
/obj/item/queen_bee
|
||||
))
|
||||
spider_panic = typecacheof(list(
|
||||
/mob/living/simple_animal/banana_spider,
|
||||
/mob/living/simple_animal/hostile/poison/giant_spider,
|
||||
/obj/item/queen_bee,
|
||||
/obj/structure/spider/spiderling
|
||||
))
|
||||
|
||||
|
||||
/obj/item/melee/flyswatter/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(proximity_flag)
|
||||
@@ -993,11 +1028,6 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
if(istype(target, /mob/living/))
|
||||
var/mob/living/bug = target
|
||||
bug.death(1)
|
||||
if(is_type_in_typecache(target, spider_panic))
|
||||
to_chat(user, "<span class='warning'>You easily land a critical blow on the [target].</span>")
|
||||
if(istype(target, /mob/living/))
|
||||
var/mob/living/bug = target
|
||||
bug.adjustBruteLoss(35) //What kinda mad man would go into melee with a spider?!
|
||||
else
|
||||
qdel(target)
|
||||
|
||||
@@ -1007,7 +1037,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
icon_state = "madeyoulook"
|
||||
force = 0
|
||||
throwforce = 0
|
||||
item_flags = DROPDEL | ABSTRACT
|
||||
item_flags = DROPDEL | ABSTRACT // | HAND_ITEM
|
||||
attack_verb = list("bopped")
|
||||
|
||||
/obj/item/circlegame/Initialize()
|
||||
@@ -1030,6 +1060,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
|
||||
/// Stage 1: The mistake is made
|
||||
/obj/item/circlegame/proc/ownerExamined(mob/living/owner, mob/living/sucker)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!istype(sucker) || !in_range(owner, sucker))
|
||||
return
|
||||
addtimer(CALLBACK(src, .proc/waitASecond, owner, sucker), 4)
|
||||
@@ -1076,6 +1108,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
to_chat(owner, "<span class='warning'>[sucker] looks down at your [src.name] before trying to avert [sucker.p_their()] eyes, but it's too late!</span>")
|
||||
to_chat(sucker, "<span class='danger'><b>[owner] sees the fear in your eyes as you try to look away from [owner.p_their()] [src.name]!</b></span>")
|
||||
|
||||
owner.face_atom(sucker)
|
||||
if(owner.client)
|
||||
owner.client.give_award(/datum/award/achievement/misc/gottem, owner) // then everybody clapped
|
||||
|
||||
playsound(get_turf(owner), 'sound/effects/hit_punch.ogg', 50, TRUE, -1)
|
||||
owner.do_attack_animation(sucker)
|
||||
|
||||
@@ -1103,7 +1139,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
item_state = "nothing"
|
||||
force = 0
|
||||
throwforce = 0
|
||||
item_flags = DROPDEL | ABSTRACT
|
||||
item_flags = DROPDEL | ABSTRACT // | HAND_ITEM
|
||||
attack_verb = list("slapped")
|
||||
hitsound = 'sound/effects/snap.ogg'
|
||||
|
||||
@@ -1112,16 +1148,12 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
var/mob/living/carbon/human/L = M
|
||||
if(L && L.dna && L.dna.species)
|
||||
L.dna.species.stop_wagging_tail(M)
|
||||
if(user.a_intent != INTENT_HARM && ((user.zone_selected == BODY_ZONE_PRECISE_MOUTH) || (user.zone_selected == BODY_ZONE_PRECISE_EYES) || (user.zone_selected == BODY_ZONE_HEAD)))
|
||||
user.do_attack_animation(M)
|
||||
playsound(M, 'sound/weapons/slap.ogg', 50, 1, -1)
|
||||
user.visible_message("<span class='danger'>[user] slaps [M]!</span>",
|
||||
"<span class='notice'>You slap [M]!</span>",\
|
||||
"You hear a slap.")
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
user.do_attack_animation(M)
|
||||
playsound(M, 'sound/weapons/slap.ogg', 50, TRUE, -1)
|
||||
user.visible_message("<span class='danger'>[user] slaps [M]!</span>",
|
||||
"<span class='notice'>You slap [M]!</span>",\
|
||||
"<span class='hear'>You hear a slap.</span>")
|
||||
return
|
||||
/obj/item/proc/can_trigger_gun(mob/living/user)
|
||||
if(!user.can_use_guns(src))
|
||||
return FALSE
|
||||
@@ -1138,6 +1170,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
force = 0
|
||||
throwforce = 5
|
||||
reach = 2
|
||||
var/min_reach = 2
|
||||
|
||||
/obj/item/extendohand/acme
|
||||
name = "\improper ACME Extendo-Hand"
|
||||
@@ -1145,13 +1178,26 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
|
||||
/obj/item/extendohand/attack(atom/M, mob/living/carbon/human/user)
|
||||
var/dist = get_dist(M, user)
|
||||
if(dist < reach)
|
||||
if(dist < min_reach)
|
||||
to_chat(user, "<span class='warning'>[M] is too close to use [src] on.</span>")
|
||||
return
|
||||
M.attack_hand(user)
|
||||
|
||||
//HF blade
|
||||
// /obj/item/gohei
|
||||
// name = "gohei"
|
||||
// desc = "A wooden stick with white streamers at the end. Originally used by shrine maidens to purify things. Now used by the station's valued weeaboos."
|
||||
// force = 5
|
||||
// throwforce = 5
|
||||
// hitsound = "swing_hit"
|
||||
// attack_verb_continuous = list("whacks", "thwacks", "wallops", "socks")
|
||||
// attack_verb_simple = list("whack", "thwack", "wallop", "sock")
|
||||
// icon = 'icons/obj/items_and_weapons.dmi'
|
||||
// icon_state = "gohei"
|
||||
// inhand_icon_state = "gohei"
|
||||
// lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
|
||||
// righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
|
||||
|
||||
//HF blade
|
||||
/obj/item/vibro_weapon
|
||||
icon_state = "hfrequency0"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
@@ -1160,6 +1206,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
desc = "A potent weapon capable of cutting through nearly anything. Wielding it in two hands will allow you to deflect gunfire."
|
||||
armour_penetration = 100
|
||||
block_chance = 40
|
||||
force = 20
|
||||
throwforce = 20
|
||||
throw_speed = 4
|
||||
sharpness = SHARP_EDGED
|
||||
@@ -1182,10 +1229,14 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
|
||||
/// triggered on wield of two handed item
|
||||
/obj/item/vibro_weapon/proc/on_wield(obj/item/source, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
wielded = TRUE
|
||||
|
||||
/// triggered on unwield of two handed item
|
||||
/obj/item/vibro_weapon/proc/on_unwield(obj/item/source, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
wielded = FALSE
|
||||
|
||||
/obj/item/vibro_weapon/update_icon_state()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user