diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index a5b1484486b..295cdfce5cb 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -479,8 +479,6 @@ in the SQL/updates folder. * You are expected to help maintain the code that you add, meaning that if there is a problem then you are likely to be approached in order to fix any issues, runtimes, or bugs. -* Do not divide when you can easily convert it to multiplication. (ie `4/2` should be done as `4*0.5`) - * If you used regex to replace code during development of your code, post the regex in your PR for the benefit of future developers and downstream users. * All new var/proc names should use the American English spelling of words. This is for consistency with BYOND. diff --git a/.github/workflows/label_merge_conflicts.yml b/.github/workflows/label_merge_conflicts.yml new file mode 100644 index 00000000000..d2a56e2ef3d --- /dev/null +++ b/.github/workflows/label_merge_conflicts.yml @@ -0,0 +1,13 @@ +name: 'Merge Conflict Detection' +on: + push: + branches: + - master +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: mschilde/auto-label-merge-conflicts@master + with: + CONFLICT_LABEL_NAME: 'Merge Conflict' + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 74660294c3b..648359d0a36 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,9 @@ /config/* !config/**/*/ +# ignore cfg, an internal BYOND folder +/cfg/* + #ignore other, specific files and folers *.before data/ @@ -32,7 +35,6 @@ stddef.dm /tools/dmitool/.project # ignore midi2piano build cache -/tools/midi2piano/obj/* - +/tools/midi2piano/midi2piano/obj/* diff --git a/.travis.yml b/.travis.yml index 7f74746d15f..2c2b9dec61d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,72 +1,41 @@ -#pretending we're C because otherwise ruby will initialize, even with "language: dm". language: generic -sudo: false +dist: xenial +os: linux git: depth: 1 -cache: - directories: - - $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR} - -addons: - apt: - packages: - - libc6-i386 - - libgcc1:i386 - - libstdc++6:i386 - -env: - global: - - BYOND_MAJOR="513" - - BYOND_MINOR="1505" - - BYOND_MACRO_COUNT=4 - matrix: - - DM_MAPFILE="cyberiad" - - DM_MAPFILE="metastation" - - DM_MAPFILE="delta" - - DM_MAPFILE="test_all_maps" - -stages: - - File Checks - - test - -before_script: - - chmod +x ./install-byond.sh - - ./install-byond.sh -script: - - source $HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin/byondsetup - - bash dm.sh -M${DM_MAPFILE} paradise.dme - jobs: include: - # Basic styling/functionality checks - - stage: File Checks - env: + - name: "Run Linters" addons: + apt: + packages: + - python3 + - python3-pip + - python3-setuptools install: - - pip install --user PyYaml -q - - pip install --user beautifulsoup4 -q - before_script: skip + - tools/travis/install_build_deps.sh + - tools/travis/install_dreamchecker.sh script: - shopt -s globstar + - find . -name "*.php" -print0 | xargs -0 -n1 php -l + - find . -name "*.json" -not -path "./nano/node_modules/*" -print0 | xargs -0 python3 ./tools/travis/json_verifier.py + - tools/travis/build_nanoui.sh + - tools/travis/check_grep.sh - python3 tools/travis/check_line_endings.py - - (num=$(grep -Ern '\\(red|blue|green|black|italic|bold|b|i[^mc])' code/ | wc -l); echo "$num BYOND text macros (expecting ${BYOND_MACRO_COUNT} or fewer)"; [ $num -le ${BYOND_MACRO_COUNT} ]) - - md5sum -c - <<< "6dc1b6bf583f3bd4176b6df494caa5f1 *html/changelogs/example.yml" - - python tools/ss13_genchangelog.py html/changelog.html html/changelogs + - ~/dreamchecker - # Compile NanoUI to make sure it works - - stage: NanoUI - language: node_js - node_js: - - "9" - env: + - name: "Compile All Maps" addons: - before_install: - - npm install -g gulp-cli - - cd ./nano/ + apt: + packages: + - libstdc++6:i386 + cache: + directories: + - $HOME/BYOND install: - - npm install --loglevel=error - before_script: + - tools/travis/install_byond.sh + - source $HOME/BYOND/byond/bin/byondsetup script: - - node node_modules/gulp/bin/gulp.js --require less-loader + - tools/travis/dm.sh -Mtravis_map_testing paradise.dme diff --git a/README.md b/README.md index eafdb5ffe91..943397b0fa8 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,16 @@ Make sure to set the port to the one you specified in the config.txt, and set the Security box to 'Trusted'. Then press GO and the server should start up and be ready to join. +### Installation (Linux) + +The code is able to run on Linux server side, however the libraries for MySQL and logging do require extra packages. + +For MySQL, run the following: `apt-get install libmysqlclient-dev:i386` + +For RustG, run the following: `apt-get install libssl-dev:i386 pkg-config:i386 zlib1g-dev:i386` + +After installing these packages, these libraries should function as intended. + --- ### UPDATING diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql index 837f8f440d6..a447c7993ba 100644 --- a/SQL/paradise_schema.sql +++ b/SQL/paradise_schema.sql @@ -594,4 +594,18 @@ CREATE TABLE `connection_log` ( `ip` varchar(32) NOT NULL, `computerid` varchar(32) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- +-- Table structure for table `changelog` +-- +DROP TABLE IF EXISTS `changelog`; +CREATE TABLE `changelog` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `pr_number` INT(11) NOT NULL, + `date_merged` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `author` VARCHAR(32) NOT NULL, + `cl_type` ENUM('FIX','WIP','TWEAK','SOUNDADD','SOUNDDEL','CODEADD','CODEDEL','IMAGEADD','IMAGEDEL','SPELLCHECK','EXPERIMENT') NOT NULL, + `cl_entry` TEXT NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql index b43141f6784..6096f0547e6 100644 --- a/SQL/paradise_schema_prefixed.sql +++ b/SQL/paradise_schema_prefixed.sql @@ -591,4 +591,18 @@ CREATE TABLE `SS13_connection_log` ( `ip` varchar(32) NOT NULL, `computerid` varchar(32) NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +-- +-- Table structure for table `SS13_changelog` +-- +DROP TABLE IF EXISTS `SS13_changelog`; +CREATE TABLE `SS13_changelog` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `pr_number` INT(11) NOT NULL, + `date_merged` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `author` VARCHAR(32) NOT NULL, + `cl_type` ENUM('FIX','WIP','TWEAK','SOUNDADD','SOUNDDEL','CODEADD','CODEDEL','IMAGEADD','IMAGEDEL','SPELLCHECK','EXPERIMENT') NOT NULL, + `cl_entry` TEXT NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/SQL/updates/10-11.sql b/SQL/updates/10-11.sql index 9564d3efaad..b2718db85e6 100644 --- a/SQL/updates/10-11.sql +++ b/SQL/updates/10-11.sql @@ -38,4 +38,4 @@ ALTER TABLE feedback.population CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4 ALTER TABLE feedback.privacy CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ALTER TABLE feedback.vpn_whitelist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ALTER TABLE feedback.watch CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -ALTER TABLE feedback.whitelist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; \ No newline at end of file +ALTER TABLE feedback.whitelist CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; diff --git a/SQL/updates/11-12.sql b/SQL/updates/11-12.sql new file mode 100644 index 00000000000..f6e9ac01baa --- /dev/null +++ b/SQL/updates/11-12.sql @@ -0,0 +1,13 @@ +#Updating the SQL from version 11 to version 12. -AffectedArc07 +#Creating a table for the new changelog system + +DROP TABLE IF EXISTS `changelog`; +CREATE TABLE IF NOT EXISTS `changelog` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `pr_number` INT(11) NOT NULL, + `date_merged` TIMESTAMP NOT NULL DEFAULT current_timestamp(), + `author` VARCHAR(32) NOT NULL, + `cl_type` ENUM('FIX','WIP','TWEAK','SOUNDADD','SOUNDDEL','CODEADD','CODEDEL','IMAGEADD','IMAGEDEL','SPELLCHECK','EXPERIMENT') NOT NULL, + `cl_entry` TEXT NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/_build_dependencies.sh b/_build_dependencies.sh new file mode 100644 index 00000000000..24a33ed3644 --- /dev/null +++ b/_build_dependencies.sh @@ -0,0 +1,11 @@ +# This file has all the information on what versions of libraries are thrown into the code +# For dreamchecker +export SPACEMANDMM_TAG=suite-1.2 +# For NanoUI +export NODE_VERSION=9 +# For the scripts in tools +export PHP_VERSION=5.6 +# Byond Major +export BYOND_MAJOR=513 +# Byond Minor +export BYOND_MINOR=1505 diff --git a/_maps/cyberiad.dm b/_maps/cyberiad.dm index df0f02f03b2..6de0a6a8492 100644 --- a/_maps/cyberiad.dm +++ b/_maps/cyberiad.dm @@ -15,7 +15,7 @@ z7 = empty #if !defined(USING_MAP_DATUM) #include "map_files\cyberiad\cyberiad.dmm" #include "map_files\cyberiad\z2.dmm" - #include "map_files\cyberiad\z3.dmm" + #include "map_files\generic\tcommsat-blown.dmm" #include "map_files\cyberiad\z4.dmm" #include "map_files\generic\Lavaland.dmm" #include "map_files\cyberiad\z6.dmm" @@ -24,7 +24,7 @@ z7 = empty #define MAP_TRANSITION_CONFIG list(\ DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\ DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\ -DECLARE_LEVEL(TELECOMMS, CROSSLINKED, list(REACHABLE, BOOSTS_SIGNAL, AI_OK)),\ +DECLARE_LEVEL(TELECOMMS, CROSSLINKED, list(REACHABLE)),\ DECLARE_LEVEL(CONSTRUCTION, CROSSLINKED, list(REACHABLE)),\ DECLARE_LEVEL(MINING, SELFLOOPING, list(REACHABLE, STATION_CONTACT, HAS_WEATHER, ORE_LEVEL, AI_OK)),\ DECLARE_LEVEL(DERELICT, CROSSLINKED, list(REACHABLE)),\ diff --git a/_maps/delta.dm b/_maps/delta.dm index f0d9fca6db0..723bc5ea7c9 100644 --- a/_maps/delta.dm +++ b/_maps/delta.dm @@ -18,7 +18,7 @@ Lovingly ported by Purpose2 to Paradise #if !defined(USING_MAP_DATUM) #include "map_files\delta\delta.dmm" #include "map_files\cyberiad\z2.dmm" - #include "map_files\cyberiad\z3.dmm" + #include "map_files\generic\tcommsat-blown.dmm" #include "map_files\cyberiad\z4.dmm" #include "map_files\generic\Lavaland.dmm" #include "map_files\cyberiad\z6.dmm" @@ -29,7 +29,7 @@ Lovingly ported by Purpose2 to Paradise #define MAP_TRANSITION_CONFIG list(\ DECLARE_LEVEL(MAIN_STATION, CROSSLINKED, list(STATION_LEVEL, STATION_CONTACT, REACHABLE, AI_OK)),\ DECLARE_LEVEL(CENTCOMM, SELFLOOPING, list(ADMIN_LEVEL, BLOCK_TELEPORT, IMPEDES_MAGIC)),\ -DECLARE_LEVEL(TELECOMMS, CROSSLINKED, list(REACHABLE, BOOSTS_SIGNAL, AI_OK)),\ +DECLARE_LEVEL(TELECOMMS, CROSSLINKED, list(REACHABLE)),\ DECLARE_LEVEL(CONSTRUCTION, CROSSLINKED, list(REACHABLE)),\ DECLARE_LEVEL(MINING, SELFLOOPING, list(REACHABLE, STATION_CONTACT, HAS_WEATHER, ORE_LEVEL, AI_OK)),\ DECLARE_LEVEL(DERELICT, CROSSLINKED, list(REACHABLE)),\ diff --git a/_maps/map_files/Delta/delta.dmm b/_maps/map_files/Delta/delta.dmm index 723bccd48f9..a8fefed799d 100644 --- a/_maps/map_files/Delta/delta.dmm +++ b/_maps/map_files/Delta/delta.dmm @@ -2607,14 +2607,6 @@ icon_state = "floor4" }, /area/shuttle/syndicate) -"afF" = ( -/obj/machinery/telecomms/allinone{ - intercept = 1 - }, -/turf/simulated/shuttle/floor{ - icon_state = "floor4" - }, -/area/shuttle/syndicate) "afG" = ( /obj/machinery/door/airlock/centcom{ id_tag = "adminshuttle"; @@ -49043,27 +49035,6 @@ tag = "icon-vault (NORTHEAST)" }, /area/storage/tech) -"bKz" = ( -/obj/structure/rack, -/obj/item/circuitboard/telecomms/server, -/obj/item/circuitboard/telecomms/relay, -/obj/item/circuitboard/telecomms/receiver, -/obj/item/circuitboard/telecomms/processor, -/obj/item/circuitboard/telecomms/hub{ - pixel_x = -3; - pixel_y = 3 - }, -/obj/item/circuitboard/telecomms/bus, -/obj/item/circuitboard/telecomms/broadcaster{ - pixel_x = 3; - pixel_y = -3 - }, -/obj/effect/decal/warning_stripes/yellow/hollow, -/turf/simulated/floor/plasteel{ - dir = 8; - icon_state = "neutralfull" - }, -/area/storage/tech) "bKA" = ( /obj/structure/rack, /obj/item/book/manual/engineering_hacking, @@ -49216,14 +49187,8 @@ }, /area/bridge/meeting_room) "bKP" = ( -/obj/machinery/blackbox_recorder, -/turf/simulated/floor/bluegrid, -/area/turret_protected/ai_upload) -"bKQ" = ( /obj/machinery/porta_turret, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, +/turf/simulated/floor/bluegrid, /area/turret_protected/ai_upload) "bKR" = ( /obj/machinery/ai_status_display{ @@ -49264,10 +49229,6 @@ }, /turf/simulated/floor/bluegrid, /area/turret_protected/ai_upload) -"bKW" = ( -/obj/machinery/message_server, -/turf/simulated/floor/bluegrid, -/area/turret_protected/ai_upload) "bKX" = ( /obj/machinery/vending/boozeomat, /turf/simulated/floor/plasteel{ @@ -52171,6 +52132,7 @@ /obj/structure/table/reinforced, /obj/item/folder/blue, /obj/item/stamp/ce, +/obj/item/paper/tcommskey, /turf/simulated/floor/plasteel{ dir = 8; icon_state = "neutralfull" @@ -57923,8 +57885,8 @@ pixel_y = 0 }, /obj/machinery/door/airlock/highsecurity{ - name = "AI Upload Access"; - req_access_txt = "16" + name = "Telecommunications"; + req_access_txt = "61" }, /turf/simulated/floor/plasteel{ icon_state = "vault"; @@ -58884,19 +58846,6 @@ /obj/effect/decal/warning_stripes/yellow, /turf/simulated/floor/plasteel, /area/security/armoury) -"caT" = ( -/obj/machinery/ai_status_display, -/turf/simulated/wall/r_wall, -/area/turret_protected/ai_upload) -"caU" = ( -/obj/machinery/porta_turret{ - dir = 8 - }, -/turf/simulated/floor/plasteel{ - icon_state = "vault"; - dir = 8 - }, -/area/turret_protected/ai_upload) "caV" = ( /obj/item/twohanded/required/kirbyplants, /obj/machinery/light{ @@ -58906,13 +58855,13 @@ /turf/simulated/floor/plasteel{ icon_state = "dark" }, -/area/turret_protected/ai_upload) +/area/tcommsat/chamber) "caW" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /turf/simulated/floor/plasteel{ icon_state = "dark" }, -/area/turret_protected/ai_upload) +/area/tcommsat/chamber) "caX" = ( /obj/structure/cable{ d1 = 1; @@ -58923,7 +58872,7 @@ icon_state = "vault"; dir = 8 }, -/area/turret_protected/ai_upload) +/area/tcommsat/chamber) "caY" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/camera/motion{ @@ -58934,19 +58883,7 @@ /turf/simulated/floor/plasteel{ icon_state = "dark" }, -/area/turret_protected/ai_upload) -"caZ" = ( -/obj/machinery/porta_turret{ - dir = 8 - }, -/obj/machinery/firealarm{ - pixel_y = 24 - }, -/turf/simulated/floor/plasteel{ - icon_state = "vault"; - dir = 8 - }, -/area/turret_protected/ai_upload) +/area/tcommsat/chamber) "cba" = ( /obj/structure/grille, /obj/effect/decal/warning_stripes/west, @@ -60126,94 +60063,28 @@ tag = "icon-redfull (NORTHWEST)" }, /area/security/brig) -"ccT" = ( -/obj/structure/table/reinforced, -/obj/machinery/door/window{ - base_state = "leftsecure"; - dir = 4; - icon_state = "leftsecure"; - name = "Core Modules"; - req_access_txt = "20" - }, -/obj/item/aiModule/paladin{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/aiModule/asimov, -/obj/item/aiModule/corp{ - pixel_x = -3; - pixel_y = -3 - }, +"ccU" = ( /turf/simulated/floor/plasteel{ icon_state = "dark" }, -/area/turret_protected/ai_upload) -"ccU" = ( -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) -"ccV" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 5; - level = 1 - }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) +/area/tcommsat/chamber) "ccW" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4; - level = 1 - }, /obj/structure/cable{ d1 = 1; d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"ccX" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4; - level = 1 - }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) -"ccY" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 10; - initialize_directions = 10; - level = 1 - }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) -"ccZ" = ( -/obj/structure/table/reinforced, -/obj/structure/sign/electricshock{ - pixel_x = 32; + icon_state = "1-2"; pixel_y = 0 }, -/obj/machinery/door/window{ - base_state = "rightsecure"; - dir = 8; - icon_state = "rightsecure"; - name = "High-Risk Modules"; - req_access_txt = "20" - }, -/obj/item/aiModule/antimov{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/aiModule/oxygen, -/obj/item/aiModule/protectStation{ - pixel_x = -3; - pixel_y = -3 - }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, -/area/turret_protected/ai_upload) +/area/tcommsat/chamber) +"ccX" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/tcommsat/chamber) "cda" = ( /obj/machinery/power/grounding_rod{ anchored = 1 @@ -61227,183 +61098,50 @@ /obj/effect/spawner/window/reinforced, /turf/simulated/floor/plating, /area/security/brig) -"ceJ" = ( -/obj/effect/spawner/window/reinforced, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4"; - tag = "" - }, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/turf/simulated/floor/plating, -/area/turret_protected/ai_upload) -"ceK" = ( -/obj/structure/table/reinforced, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/obj/structure/window/reinforced, -/obj/machinery/door/window{ - base_state = "rightsecure"; - dir = 4; - icon_state = "rightsecure"; - name = "Core Modules"; - req_access_txt = "20" - }, -/obj/item/aiModule/freeformcore{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/aiModule/safeguard, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) "ceL" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 +/obj/machinery/light{ + dir = 8 }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" +/obj/machinery/atmospherics/unary/vent_scrubber{ + dir = 4; + on = 1 }, -/area/turret_protected/ai_upload) +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) "ceM" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4"; - tag = "" +/turf/simulated/floor/plasteel{ + icon_state = "dark" }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) +/area/tcommsat/chamber) "ceN" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ +/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ dir = 4; + initialize_directions = 11; level = 1 }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"ceO" = ( -/obj/machinery/hologram/holopad, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4; - level = 1 - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) +/obj/machinery/porta_turret, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) "ceP" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9 - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"ceQ" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) -"ceR" = ( -/obj/structure/table/reinforced, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0 - }, -/obj/structure/window/reinforced, -/obj/machinery/door/window{ - base_state = "leftsecure"; +/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 8; - icon_state = "leftsecure"; - name = "High-Risk Modules"; - req_access_txt = "20" + initialize_directions = 11 }, -/obj/item/aiModule/tyrant{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/aiModule/oneCrewMember, -/obj/item/aiModule/purge{ - pixel_x = -3; - pixel_y = -3 +/obj/machinery/porta_turret, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) +"ceQ" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4; + level = 1 }, /turf/simulated/floor/plasteel{ icon_state = "dark" }, -/area/turret_protected/ai_upload) -"ceS" = ( -/obj/effect/spawner/window/reinforced, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plating, -/area/turret_protected/ai_upload) +/area/tcommsat/chamber) "ceT" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4; @@ -62252,76 +61990,14 @@ /obj/machinery/vending/security, /turf/simulated/floor/plasteel, /area/security/brig) -"cgt" = ( -/obj/effect/spawner/window/reinforced, -/obj/structure/cable, -/turf/simulated/floor/plating, -/area/turret_protected/ai_upload) "cgu" = ( -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 4; - external_pressure_bound = 101.325; - on = 1; - pressure_checks = 1 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"cgv" = ( -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 4; - initialize_directions = 11; - level = 1 - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) -"cgw" = ( -/obj/machinery/computer/aiupload, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"cgx" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"cgy" = ( -/obj/machinery/computer/borgupload, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"cgz" = ( -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 8; - initialize_directions = 11; - level = 1 - }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) +/obj/machinery/tcomms/core/station, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) "cgA" = ( -/obj/machinery/atmospherics/unary/vent_scrubber{ - dir = 8; - on = 1; - scrub_N2O = 1; - scrub_Toxins = 1 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) +/obj/machinery/ntnet_relay, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) "cgB" = ( /obj/machinery/camera{ c_tag = "Singularity NorthEast"; @@ -63022,60 +62698,44 @@ icon_state = "dark" }, /area/construction/hallway) -"chT" = ( -/obj/structure/table/reinforced, -/obj/item/aiModule/reset, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"chU" = ( -/obj/machinery/ai_status_display{ - pixel_x = -32; - pixel_y = -32 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) "chV" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 6 }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) +/obj/item/twohanded/required/kirbyplants, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/tcommsat/chamber) "chW" = ( -/obj/machinery/ai_slipper, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4; + level = 1 + }, /obj/structure/cable{ d1 = 1; - d2 = 2; - icon_state = "1-2" + d2 = 8; + icon_state = "1-8"; + tag = "" }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/tcommsat/chamber) "chX" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) -"chY" = ( -/obj/machinery/status_display{ - pixel_x = 32; - pixel_y = -32 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 10; + initialize_directions = 10; + level = 1 }, +/obj/item/twohanded/required/kirbyplants, /turf/simulated/floor/plasteel{ icon_state = "dark" }, -/area/turret_protected/ai_upload) -"chZ" = ( -/obj/structure/table/reinforced, -/obj/item/aiModule/quarantine, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) +/area/tcommsat/chamber) "cia" = ( /obj/structure/cable{ d1 = 1; @@ -63931,54 +63591,14 @@ /obj/effect/decal/warning_stripes/northwest, /turf/simulated/floor/plating, /area/security/range) -"cjC" = ( -/obj/structure/table/reinforced, -/obj/item/aiModule/freeform, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) "cjD" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/flasher{ - id = null; - pixel_x = -24; - pixel_y = -24 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"cjE" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/greengrid, -/area/turret_protected/ai_upload) +/turf/simulated/wall/r_wall, +/area/tcommsat/chamber) "cjF" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/flasher{ - id = null; - pixel_x = 24; - pixel_y = -24 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"cjG" = ( -/obj/structure/table/reinforced, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) +/turf/simulated/wall/r_wall, +/area/tcommsat/chamber) "cjH" = ( /obj/effect/decal/warning_stripes/northwestcorner, /turf/simulated/floor/plating/airless, @@ -64978,58 +64598,6 @@ }, /turf/simulated/floor/plating, /area/security/range) -"clk" = ( -/obj/item/twohanded/required/kirbyplants, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/power/apc{ - dir = 2; - name = "south bump"; - pixel_y = -24 - }, -/obj/structure/cable, -/obj/machinery/light, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"cll" = ( -/obj/machinery/porta_turret{ - dir = 8 - }, -/obj/structure/sign/electricshock{ - pixel_y = -32 - }, -/turf/simulated/floor/plasteel{ - icon_state = "vault"; - dir = 8 - }, -/area/turret_protected/ai_upload) -"clm" = ( -/obj/structure/table/reinforced, -/obj/item/twohanded/required/kirbyplants, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) -"cln" = ( -/obj/item/twohanded/required/kirbyplants, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/obj/machinery/light, -/obj/machinery/alarm{ - dir = 1; - icon_state = "alarm0"; - pixel_x = 0; - pixel_y = -22 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/turret_protected/ai_upload) "clo" = ( /obj/structure/cable{ d1 = 1; @@ -65816,14 +65384,6 @@ "cmI" = ( /turf/simulated/wall/rust, /area/security/range) -"cmJ" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/wall/r_wall, -/area/turret_protected/ai_upload) -"cmK" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, -/turf/simulated/wall/r_wall, -/area/turret_protected/ai_upload) "cmL" = ( /obj/structure/lattice, /turf/space, @@ -70022,22 +69582,6 @@ icon_state = "dark" }, /area/crew_quarters/courtroom) -"cuj" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "AI Minisatellite SouthWest"; - dir = 8; - network = list("SS13","Minisat") - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/construction/hallway) "cuk" = ( /obj/structure/closet/secure_closet/exile, /obj/effect/decal/warning_stripes/yellow/hollow, @@ -70948,23 +70492,6 @@ icon_state = "dark" }, /area/gateway) -"cvS" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "AI Minisatellite SouthEast"; - dir = 4; - network = list("MiniSat","SS13"); - pixel_y = -22 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/construction/hallway) "cvT" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -112667,17 +112194,6 @@ /obj/effect/decal/warning_stripes/west, /turf/simulated/floor/plasteel, /area/shuttle/escape) -"dTU" = ( -/obj/docking_port/stationary{ - dir = 8; - dwidth = 3; - height = 5; - id = "sit_scimaint"; - name = "Cyberiad Science Maint"; - width = 11 - }, -/turf/space, -/area/space/nearstation) "dTV" = ( /obj/machinery/power/solar{ name = "Aft Starboard Solar Panel" @@ -115991,12 +115507,82 @@ }, /turf/space, /area/space) +"eaH" = ( +/obj/machinery/blackbox_recorder, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) +"fBl" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4; + level = 1 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 5 + }, +/obj/structure/cable{ + d2 = 4; + icon_state = "0-4" + }, +/obj/machinery/power/apc{ + dir = 2; + name = "south bump"; + pixel_y = -24 + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/tcommsat/chamber) +"hng" = ( +/obj/machinery/message_server, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) +"lVO" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/machinery/turretid/lethal{ + control_area = "\improper Telecoms Central Compartment"; + name = "Telecommunications Turret Control"; + pixel_y = -22 + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/turret_protected/aisat) +"qrT" = ( +/turf/simulated/wall/r_wall, +/area/tcommsat/chamber) "udT" = ( /obj/structure/chair/comfy/shuttle{ dir = 8 }, /turf/simulated/shuttle/floor4/vox, /area/shuttle/vox) +"vzz" = ( +/obj/machinery/light{ + icon_state = "tube1"; + dir = 4 + }, +/obj/machinery/atmospherics/unary/vent_pump/on{ + dir = 8 + }, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) +"vDg" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 9 + }, +/obj/machinery/alarm{ + dir = 1; + icon_state = "alarm0"; + pixel_x = 0; + pixel_y = -22 + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/tcommsat/chamber) (1,1,1) = {" aaa @@ -122816,8 +122402,6 @@ abi abi abi abi -abj -abi abi aaa aaa @@ -122936,6 +122520,8 @@ aaa aaa aaa aaa +aaa +aaa "} (28,1,1) = {" aaa @@ -123072,8 +122658,6 @@ bpm bmo bmo bpm -bmo -bpm aaa abi aaa @@ -123193,6 +122777,8 @@ aaa aaa aaa aaa +aaa +aaa "} (29,1,1) = {" aaa @@ -123327,8 +122913,6 @@ bzu bzu chS brp -cuj -brp brp cpb brs @@ -123450,6 +123034,8 @@ aaa aaa aaa aaa +aaa +aaa "} (30,1,1) = {" aaa @@ -123584,8 +123170,6 @@ bms bms bpu bms -bms -bpu bPC bpo brr @@ -123707,6 +123291,8 @@ aaa aaa aaa aaa +aaa +aaa "} (31,1,1) = {" aaa @@ -123835,13 +123421,11 @@ bTy bVN cmx bNM -bJh -bJh -ceJ -cgt -bJh -bJh -abj +qrT +qrT +qrT +qrT +qrT abj bku bpo @@ -123964,6 +123548,8 @@ aaa aaa aaa aaa +aaa +aaa "} (32,1,1) = {" aaa @@ -124006,7 +123592,7 @@ abB abB abB afr -afF +abB afV agt aaa @@ -124092,14 +123678,12 @@ bTz bVI bNM bNM -caT -ccT -ceK -caU -chT -bJh -bJh -abj +qrT +qrT +qrT +qrT +qrT +qrT bkt bpo brr @@ -124221,6 +123805,8 @@ aaa aaa aaa aaa +aaa +aaa "} (33,1,1) = {" aaa @@ -124349,14 +123935,12 @@ bTA bVO bPI bNM -caU -bMY +qrT +eaH ceL cgu -chU -cjC -bJh -bJh +qrT +qrT bkt bpo bLS @@ -124478,6 +124062,8 @@ aaa aaa aaa aaa +aaa +aaa "} (34,1,1) = {" aaa @@ -124609,11 +124195,9 @@ bNM caV ccU ceM -cgv +ccU chV cjD -clk -cmJ cnV cpc cqK @@ -124735,6 +124319,8 @@ aaa aaa aaa aaa +aaa +aaa "} (35,1,1) = {" aaa @@ -124864,13 +124450,11 @@ bVQ bXI bNO caW -ccV +caW ceN -cgw -ccU -bMY -cll -bJh +caW +fBl +qrT bkt bmq cqL @@ -124992,6 +124576,8 @@ aaa aaa aaa aaa +aaa +aaa "} (36,1,1) = {" aaa @@ -125122,12 +124708,10 @@ bXJ bZh caX ccW -ceO -cgx +ccW +ccW chW -cjE -clm -cgt +qrT cKl bmq bnP @@ -125249,6 +124833,8 @@ aaa aaa aaa aaa +aaa +aaa "} (37,1,1) = {" aaa @@ -125375,16 +124961,14 @@ bPM bRC bTE bVS -bPM +lVO bNQ caY ccX ceP -cgy -ccU -bMY -caU -bJh +ccX +vDg +qrT bkt bmq cqL @@ -125506,6 +125090,8 @@ aaa aaa aaa aaa +aaa +aaa "} (38,1,1) = {" aaa @@ -125635,13 +125221,11 @@ bVP bXK bNM caV -ccY +ccU ceQ -cgz +ccU chX cjF -cln -cmK cnX cpd cqM @@ -125763,6 +125347,8 @@ aaa aaa aaa aaa +aaa +aaa "} (39,1,1) = {" aaa @@ -125891,14 +125477,12 @@ bTG bVT bXL bNM -caZ -bMY -ceL +qrT +hng +vzz cgA -chY -cjG -bJh -bJh +qrT +qrT bkt bpo bLM @@ -126020,6 +125604,8 @@ aaa aaa aaa aaa +aaa +aaa "} (40,1,1) = {" aaa @@ -126148,14 +125734,12 @@ bTH bVI bNM bNM -caT -ccZ -ceR -caU -chZ -bJh -bJh -abj +qrT +qrT +qrT +qrT +qrT +qrT bkt bpo brr @@ -126277,6 +125861,8 @@ aaa aaa aaa aaa +aaa +aaa "} (41,1,1) = {" aaa @@ -126405,13 +125991,11 @@ bTI bVU bPN bNM -bJh -bJh -ceS -cgt -bJh -bJh -abj +qrT +qrT +qrT +qrT +qrT abj bku bpo @@ -126534,6 +126118,8 @@ aaa aaa aaa aaa +aaa +aaa "} (42,1,1) = {" aaa @@ -126668,8 +126254,6 @@ bmo bmo bpm bmo -bmo -bpm cnY bpo brr @@ -126791,6 +126375,8 @@ aaa aaa aaa aaa +aaa +aaa "} (43,1,1) = {" aaa @@ -126925,8 +126511,6 @@ bzu bzu chS brp -cvS -brp brp cpe brs @@ -127048,6 +126632,8 @@ aaa aaa aaa aaa +aaa +aaa "} (44,1,1) = {" aaa @@ -127183,8 +126769,6 @@ bms bpu bms bms -bpu -bms bms aaa abi @@ -127305,6 +126889,8 @@ aaa aaa aaa aaa +aaa +aaa "} (45,1,1) = {" aaa @@ -127442,8 +127028,6 @@ abj abi abi abi -abj -abi abi aaa aaa @@ -127562,6 +127146,8 @@ aaa aaa aaa aaa +aaa +aaa "} (46,1,1) = {" aaa @@ -146956,7 +146542,7 @@ bDJ bFk bGW bIO -bKz +bBR bBR bOt brW @@ -154923,7 +154509,7 @@ bEd bFF bHp bJh -bKQ +bMY bMX bOP bMY @@ -156465,7 +156051,7 @@ bEj bFL bHv bJh -bKQ +bMY bMX bOR bMY @@ -156722,7 +156308,7 @@ bEk bFM bHw bJh -bKW +bKP bNa bOS bQN @@ -170947,7 +170533,7 @@ aaa aaa aaa aaa -dTU +aaa aaa aaa aaa diff --git a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm index 864981494ac..773ff5cb937 100644 --- a/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm +++ b/_maps/map_files/MetaStation/MetaStation.v41A.II.dmm @@ -858,14 +858,6 @@ icon_state = "floor4" }, /area/shuttle/syndicate) -"abK" = ( -/obj/machinery/telecomms/allinone{ - intercept = 1 - }, -/turf/simulated/shuttle/floor{ - icon_state = "floor4" - }, -/area/shuttle/syndicate) "abL" = ( /obj/structure/cable, /obj/structure/lattice/catwalk, @@ -2017,7 +2009,7 @@ /obj/machinery/vending/sustenance{ desc = "A vending machine normally reserved for work camps."; name = "\improper sustenance vendor"; - product_slogans = "Enjoy your meal.;Enough calories to support any worker." + slogan_list = list("Enjoy your meal.","Enough calories to support any worker.") }, /turf/simulated/floor/plasteel{ icon_state = "floorgrime" @@ -32261,6 +32253,7 @@ charge = 100; maxcharge = 15000 }, +/obj/item/paper/tcommskey, /turf/simulated/floor/plasteel{ dir = 8; icon_state = "neutralcorner" @@ -48613,15 +48606,17 @@ /turf/simulated/wall/r_wall, /area/space/nearstation) "bFd" = ( -/obj/machinery/computer/security/telescreen{ - dir = 8; - name = "Telecoms Camera Monitor"; - network = list("tcomm"); +/obj/machinery/power/apc{ + cell_type = 5000; + dir = 4; + name = "Telecoms Control Room APC"; pixel_x = 26 }, -/obj/machinery/computer/telecomms/monitor{ - network = "tcommsat" +/obj/structure/cable/yellow{ + d2 = 8; + icon_state = "0-8" }, +/obj/structure/filingcabinet, /turf/simulated/floor/plasteel{ icon_state = "grimy" }, @@ -48675,21 +48670,13 @@ /area/construction/hallway{ name = "\improper MiniSat Exterior" }) -"bFh" = ( -/obj/machinery/computer/telecomms/traffic, -/turf/simulated/floor/plasteel{ - icon_state = "grimy" - }, -/area/tcommsat/computer{ - name = "\improper Telecoms Control Room" - }) "bFi" = ( /obj/machinery/atmospherics/unary/vent_pump{ dir = 4; on = 1 }, /obj/structure/chair/office/dark{ - dir = 1 + dir = 8 }, /turf/simulated/floor/plasteel{ icon_state = "grimy" @@ -48701,7 +48688,9 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 5 + }, /turf/simulated/floor/plasteel{ icon_state = "grimy" }, @@ -48715,14 +48704,18 @@ /obj/structure/lattice, /turf/space, /area/space/nearstation) -"bFl" = ( -/turf/simulated/floor/plasteel{ - icon_state = "grimy" - }, -/area/tcommsat/computer{ - name = "\improper Telecoms Control Room" - }) "bFm" = ( +/obj/machinery/atmospherics/unary/vent_scrubber{ + dir = 8; + on = 1; + scrub_N2O = 0; + scrub_Toxins = 0 + }, +/obj/structure/cable/yellow{ + d1 = 4; + d2 = 8; + icon_state = "4-8" + }, /obj/structure/chair/office/dark{ dir = 4 }, @@ -49623,26 +49616,6 @@ dir = 5 }, /area/atmos) -"bGQ" = ( -/obj/structure/chair/office/dark{ - dir = 8 - }, -/turf/simulated/floor/plasteel{ - icon_state = "grimy" - }, -/area/tcommsat/computer{ - name = "\improper Telecoms Control Room" - }) -"bGR" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 5 - }, -/turf/simulated/floor/plasteel{ - icon_state = "grimy" - }, -/area/tcommsat/computer{ - name = "\improper Telecoms Control Room" - }) "bGS" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/window/reinforced{ @@ -49666,25 +49639,6 @@ d2 = 8; icon_state = "4-8" }, -/turf/simulated/floor/plasteel{ - icon_state = "grimy" - }, -/area/tcommsat/computer{ - name = "\improper Telecoms Control Room" - }) -"bGU" = ( -/obj/machinery/atmospherics/unary/vent_scrubber{ - dir = 8; - on = 1; - scrub_N2O = 0; - scrub_Toxins = 0 - }, -/obj/structure/cable/yellow{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/structure/chair/office/dark, /turf/simulated/floor/plasteel{ icon_state = "grimy" }, @@ -49863,26 +49817,6 @@ /area/crew_quarters/toilet{ name = "\improper Auxiliary Restrooms" }) -"bHo" = ( -/obj/machinery/power/apc{ - cell_type = 5000; - dir = 4; - name = "Telecoms Control Room APC"; - pixel_x = 26 - }, -/obj/machinery/computer/telecomms/server{ - network = "tcommsat" - }, -/obj/structure/cable/yellow{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plasteel{ - icon_state = "grimy" - }, -/area/tcommsat/computer{ - name = "\improper Telecoms Control Room" - }) "bHp" = ( /obj/structure/rack, /obj/item/flashlight, @@ -51417,14 +51351,22 @@ /turf/simulated/floor/carpet, /area/crew_quarters/theatre) "bKn" = ( +/obj/machinery/hologram/holopad, +/obj/structure/cable/yellow{ + d1 = 1; + d2 = 4; + icon_state = "1-4" + }, /obj/structure/cable/yellow{ d1 = 1; d2 = 2; icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 4; - initialize_directions = 11 + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 8 }, /turf/simulated/floor/plasteel{ icon_state = "grimy" @@ -52870,48 +52812,6 @@ /obj/structure/window/reinforced, /turf/space, /area/space/nearstation) -"bMo" = ( -/obj/machinery/telecomms/processor/preset_one, -/turf/simulated/floor/bluegrid{ - icon_state = "gcircuit"; - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bMp" = ( -/obj/machinery/hologram/holopad, -/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ - dir = 4 - }, -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/floor/plasteel{ - icon_state = "grimy" - }, -/area/tcommsat/computer{ - name = "\improper Telecoms Control Room" - }) -"bMq" = ( -/obj/machinery/telecomms/receiver/preset_left, -/turf/simulated/floor/bluegrid{ - icon_state = "gcircuit"; - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bMr" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ @@ -52923,16 +52823,6 @@ /area/construction/hallway{ name = "\improper MiniSat Exterior" }) -"bMs" = ( -/obj/machinery/telecomms/receiver/preset_right, -/turf/simulated/floor/bluegrid{ - icon_state = "gcircuit"; - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bMt" = ( /obj/structure/window/reinforced{ dir = 8 @@ -52954,16 +52844,6 @@ /area/construction/hallway{ name = "\improper MiniSat Exterior" }) -"bMu" = ( -/obj/machinery/telecomms/processor/preset_three, -/turf/simulated/floor/bluegrid{ - icon_state = "gcircuit"; - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bMv" = ( /obj/structure/shuttle/engine/propulsion{ dir = 8; @@ -53859,16 +53739,6 @@ }, /turf/space, /area/space/nearstation) -"bNZ" = ( -/obj/machinery/telecomms/bus/preset_one, -/turf/simulated/floor/bluegrid{ - icon_state = "gcircuit"; - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bOa" = ( /turf/simulated/floor/bluegrid{ icon_state = "dark"; @@ -53879,19 +53749,12 @@ }, /area/tcommsat/server) "bOb" = ( -/turf/simulated/floor/bluegrid{ - icon_state = "gcircuit"; - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 +/obj/machinery/light{ + dir = 8 }, -/area/tcommsat/server) -"bOc" = ( -/obj/machinery/telecomms/bus/preset_three, /turf/simulated/floor/bluegrid{ - icon_state = "gcircuit"; - name = "Mainframe Base"; + icon_state = "dark"; + name = "Mainframe Floor"; nitrogen = 100; oxygen = 0; temperature = 80 @@ -54769,18 +54632,6 @@ /obj/structure/lattice, /turf/space, /area/space/nearstation) -"bPI" = ( -/obj/machinery/light/small{ - dir = 8 - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bPJ" = ( /obj/structure/cable/yellow{ d1 = 1; @@ -54794,18 +54645,6 @@ /area/tcommsat/computer{ name = "\improper Telecoms Control Room" }) -"bPK" = ( -/obj/machinery/light/small{ - dir = 4 - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bPL" = ( /obj/structure/cable/yellow{ d1 = 4; @@ -55577,15 +55416,6 @@ /obj/structure/lattice, /turf/simulated/wall/r_wall, /area/space/nearstation) -"bRn" = ( -/obj/machinery/message_server, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bRo" = ( /obj/machinery/light/small, /obj/item/folder, @@ -55626,23 +55456,6 @@ icon_state = "dark" }, /area/tcommsat/server) -"bRr" = ( -/obj/machinery/light/small{ - dir = 1 - }, -/obj/machinery/camera{ - c_tag = "Telecoms - Server Room - Fore-Port"; - dir = 2; - network = list("SS13","tcomm") - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bRs" = ( /obj/structure/cable/yellow{ d1 = 1; @@ -55654,15 +55467,6 @@ icon_state = "dark" }, /area/tcommsat/server) -"bRt" = ( -/obj/machinery/blackbox_recorder, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bRu" = ( /obj/machinery/atmospherics/unary/vent_pump{ dir = 1; @@ -56350,23 +56154,15 @@ /turf/simulated/floor/plating, /area/maintenance/starboard) "bSD" = ( -/obj/structure/rack, -/obj/item/circuitboard/telecomms/processor, -/obj/item/circuitboard/telecomms/processor, -/obj/item/circuitboard/telecomms/receiver, -/obj/item/circuitboard/telecomms/server, -/obj/item/circuitboard/telecomms/server, -/obj/item/circuitboard/telecomms/bus, -/obj/item/circuitboard/telecomms/bus, -/obj/item/circuitboard/telecomms/broadcaster, /obj/machinery/atmospherics/unary/vent_pump{ dir = 1; on = 1 }, /obj/machinery/camera{ - c_tag = "Telecoms - Storage"; + c_tag = "Gravity Generation Access"; dir = 4; - network = list("SS13") + network = list("Engineering","SS13"); + pixel_y = -22 }, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -56587,114 +56383,6 @@ icon_state = "neutralcorner" }, /area/hallway/primary/central) -"bSX" = ( -/obj/machinery/light/small{ - dir = 1 - }, -/obj/machinery/camera{ - c_tag = "Telecoms - Server Room - Fore-Starboard"; - dir = 2; - network = list("SS13","tcomm") - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bSY" = ( -/obj/structure/cable/yellow{ - d1 = 2; - d2 = 8; - icon_state = "2-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 10 - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bSZ" = ( -/obj/machinery/hologram/holopad, -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 5 - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bTa" = ( -/obj/machinery/telecomms/bus/preset_two, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bTb" = ( -/obj/machinery/telecomms/hub/preset, -/turf/simulated/floor/bluegrid{ - icon_state = "gcircuit"; - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bTc" = ( -/obj/machinery/telecomms/processor/preset_two, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bTd" = ( -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bTe" = ( -/obj/item/folder, -/obj/item/folder, -/obj/structure/table/glass, -/obj/item/pen/multi, -/turf/simulated/floor/bluegrid{ - icon_state = "gcircuit"; - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bTf" = ( /obj/structure/table/reinforced, /obj/item/flashlight, @@ -57244,10 +56932,6 @@ }, /area/crew_quarters/kitchen) "bUg" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/analyzer, -/obj/item/stock_parts/subspace/analyzer, -/obj/item/stock_parts/subspace/analyzer, /obj/machinery/light_switch{ pixel_y = 26 }, @@ -57345,10 +57029,6 @@ name = "Telecoms Storage" }) "bUq" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/treatment, -/obj/item/stock_parts/subspace/treatment, -/obj/item/stock_parts/subspace/treatment, /obj/machinery/light/small{ dir = 4 }, @@ -57419,45 +57099,6 @@ icon_state = "dark" }, /area/atmos) -"bUx" = ( -/obj/machinery/alarm/server{ - dir = 4; - pixel_x = -22 - }, -/obj/machinery/light/small{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Telecoms - Server Room - Aft-Port"; - dir = 4; - network = list("SS13","tcomm") - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bUy" = ( -/obj/machinery/telecomms/bus/preset_four, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bUz" = ( -/obj/machinery/telecomms/processor/preset_four, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bUA" = ( /obj/structure/window/reinforced{ dir = 4 @@ -57659,33 +57300,6 @@ /area/hallway/secondary/entry{ name = "Arrivals" }) -"bUR" = ( -/obj/machinery/power/apc{ - cell_type = 5000; - dir = 4; - name = "Telecoms Server Room APC"; - pixel_x = 25 - }, -/obj/machinery/light/small{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Telecoms - Server Room - Aft-Starboard"; - dir = 8; - network = list("SS13","tcomm") - }, -/obj/structure/cable/yellow{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bUS" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -57916,33 +57530,6 @@ }, /turf/simulated/floor/plating, /area/maintenance/fore) -"bVj" = ( -/obj/machinery/telecomms/server/presets/common, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bVk" = ( -/obj/machinery/telecomms/server/presets/engineering, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bVl" = ( -/obj/machinery/telecomms/server/presets/medical, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bVm" = ( /obj/machinery/door/firedoor, /obj/structure/cable/yellow{ @@ -57999,12 +57586,6 @@ }, /area/crew_quarters/kitchen) "bVr" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/transmitter, -/obj/item/stock_parts/subspace/transmitter, -/obj/item/stock_parts/subspace/amplifier, -/obj/item/stock_parts/subspace/amplifier, -/obj/item/stock_parts/subspace/amplifier, /obj/machinery/light/small{ dir = 8 }, @@ -58176,13 +57757,6 @@ name = "\improper Teleporter Room" }) "bVG" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/ansible, -/obj/item/stock_parts/subspace/ansible, -/obj/item/stock_parts/subspace/ansible, -/obj/item/stock_parts/subspace/crystal, -/obj/item/stock_parts/subspace/crystal, -/obj/item/stock_parts/subspace/crystal, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -58190,34 +57764,10 @@ name = "Telecoms Storage" }) "bVH" = ( -/obj/structure/table, -/obj/item/stock_parts/micro_laser, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/capacitor, -/obj/item/stock_parts/micro_laser/high, -/obj/item/stock_parts/micro_laser/high, -/obj/item/stock_parts/micro_laser/high, -/obj/item/stock_parts/micro_laser/high, /obj/machinery/alarm{ dir = 1; pixel_y = -22 }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/maintenance/atmos_control{ - name = "Telecoms Storage" - }) -"bVI" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/subspace/filter, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -58387,15 +57937,6 @@ toxins = 70000 }, /area/atmos) -"bVX" = ( -/obj/machinery/telecomms/server/presets/science, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bVY" = ( /obj/structure/window/reinforced{ dir = 4 @@ -58422,35 +57963,6 @@ /area/construction/hallway{ name = "\improper MiniSat Exterior" }) -"bVZ" = ( -/obj/structure/cable/yellow{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9 - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bWa" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bWb" = ( /obj/machinery/keycard_auth{ pixel_x = -24 @@ -59315,56 +58827,6 @@ toxins = 70000 }, /area/atmos) -"bXC" = ( -/obj/structure/cable/yellow{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bXD" = ( -/obj/machinery/telecomms/broadcaster/preset_left, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bXE" = ( -/obj/machinery/telecomms/server/presets/security, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bXF" = ( -/obj/machinery/telecomms/server/presets/command, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) -"bXG" = ( -/obj/machinery/telecomms/server/presets/service, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bXH" = ( /obj/structure/cable/yellow{ d1 = 1; @@ -60015,23 +59477,6 @@ /obj/effect/decal/warning_stripes/yellow/hollow, /turf/simulated/floor/plasteel, /area/gateway) -"bYQ" = ( -/obj/machinery/light/small, -/obj/machinery/camera{ - c_tag = "Telecoms - Server Room - Aft"; - dir = 1; - network = list("SS13","tcomm") - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/machinery/ntnet_relay, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bYR" = ( /obj/effect/decal/warning_stripes/south, /turf/simulated/floor/plasteel, @@ -60539,15 +59984,6 @@ toxins = 70000 }, /area/atmos) -"bZO" = ( -/obj/machinery/telecomms/broadcaster/preset_right, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "bZP" = ( /turf/simulated/wall, /area/maintenance/portsolar) @@ -61935,15 +61371,6 @@ oxygen = 0 }, /area/atmos) -"cck" = ( -/obj/machinery/telecomms/server/presets/supply, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/server) "ccl" = ( /obj/effect/landmark{ name = "JoinLateGateway" @@ -63190,12 +62617,6 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply, /turf/simulated/wall/r_wall, /area/tcommsat/server) -"ceq" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/wall, -/area/construction/hallway{ - name = "\improper MiniSat Exterior" - }) "cer" = ( /obj/structure/window/reinforced{ dir = 8 @@ -97119,6 +96540,19 @@ icon_state = "dark" }, /area/atmos) +"dRN" = ( +/obj/machinery/light{ + icon_state = "tube1"; + dir = 4 + }, +/turf/simulated/floor/bluegrid{ + icon_state = "dark"; + name = "Mainframe Floor"; + nitrogen = 100; + oxygen = 0; + temperature = 80 + }, +/area/tcommsat/server) "elK" = ( /obj/effect/spawner/airlock/w_to_e, /turf/simulated/wall/r_wall, @@ -97154,11 +96588,47 @@ /obj/structure/lattice, /turf/space, /area/space) +"fZV" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable/yellow{ + d1 = 1; + d2 = 2; + icon_state = "1-2" + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/tcommsat/server) +"gIG" = ( +/obj/machinery/ntnet_relay, +/turf/simulated/floor/bluegrid, +/area/tcommsat/server) "gRw" = ( /obj/effect/spawner/window/reinforced, /obj/effect/spawner/airlock/s_to_n, /turf/simulated/floor/plating, /area/maintenance/auxsolarstarboard) +"hxv" = ( +/obj/machinery/camera{ + c_tag = "Telecoms - Server Room - Aft"; + dir = 1; + network = list("SS13","tcomm") + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable/yellow, +/obj/machinery/power/apc{ + dir = 2; + name = "south bump"; + pixel_y = -24 + }, +/turf/simulated/floor/bluegrid{ + icon_state = "dark"; + name = "Mainframe Floor"; + nitrogen = 100; + oxygen = 0; + temperature = 80 + }, +/area/tcommsat/server) "hLL" = ( /obj/structure/lattice, /turf/simulated/wall, @@ -97186,6 +96656,10 @@ /area/maintenance/fpmaint2{ name = "Port Maintenance" }) +"kwJ" = ( +/obj/machinery/message_server, +/turf/simulated/floor/bluegrid, +/area/tcommsat/server) "kBq" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ @@ -97244,6 +96718,10 @@ }, /turf/simulated/floor/plasteel, /area/quartermaster/storage) +"odO" = ( +/obj/machinery/blackbox_recorder, +/turf/simulated/floor/bluegrid, +/area/tcommsat/server) "onG" = ( /obj/effect/spawner/window/reinforced, /obj/effect/spawner/airlock/s_to_n, @@ -97360,6 +96838,10 @@ }, /turf/space, /area/solar/starboard) +"rUQ" = ( +/obj/machinery/tcomms/core/station, +/turf/simulated/floor/bluegrid, +/area/tcommsat/server) "sjF" = ( /obj/structure/window/reinforced{ dir = 1 @@ -106033,7 +105515,7 @@ aak aak aak abE -abK +aak abQ acd aaa @@ -136952,7 +136434,7 @@ bPl bQV bUg bUq -bVI +bVG bQV asJ bZI @@ -149804,11 +149286,11 @@ abd abd abd abd -abd -abd -abd -abd -abd +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -150058,11 +149540,6 @@ clH aXH aXH aXH -aXH -clH -aXH -aXH -aXH clH aaa abd @@ -150091,6 +149568,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa abq abq abq @@ -150312,14 +149794,9 @@ bdM bdM bdM bdM -bdM bUA bdM bdM -bdM -bdM -bdM -bdM cer bPH abd @@ -150349,6 +149826,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa abq abq abq @@ -150568,14 +150050,9 @@ beW beW beW beW -beW -beW bfb beW beW -beW -beW -beW bKk bMr bsd @@ -150607,6 +150084,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa abq aaa aaa @@ -150825,14 +150307,9 @@ beX beX beX beX -beX -beX bgN beX beX -beX -beX -beX bvh bMr bsd @@ -150864,6 +150341,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa abq aaa aaa @@ -151082,12 +150564,7 @@ aXL aXL aXL aXL -aXL -aXL -aXL -bIF -bIF -beX +bgN beX beX bvh @@ -151207,6 +150684,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (210,1,1) = {" aaa @@ -151335,12 +150817,7 @@ bsM bBl bBl bBl -bBl bKl -bMo -bNZ -bPI -bRn bKl bKl bKl @@ -151464,6 +150941,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (211,1,1) = {" aaa @@ -151590,17 +151072,12 @@ bxA bBo bri bDb -bFh bHi bJl bKl -bRr -bOa -bOa -bTa -bVj -bUx -bXD +bKl +bKl +bKl aXL beX beX @@ -151721,6 +151198,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (212,1,1) = {" aaa @@ -151848,18 +151330,13 @@ bAA bri bDf bFi -bGQ bIz bKl -bMq +gIG bOb -bOa -bTc -bVk -bOa -bXF +odO bKl -bIF +aXL beX bvh cLL @@ -151978,6 +151455,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (213,1,1) = {" aaa @@ -152105,18 +151587,13 @@ bCX bIC bDd bFj -bGR bIA bHN -bHN -bHN bOa bOa bOa -bOa -bXE bKl -bIF +aXL beX bvh cLL @@ -152235,6 +151712,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (214,1,1) = {" aaa @@ -152362,18 +151844,13 @@ bDa bBk bDe bKn -bMp bPJ bRq bRs -bRq -bSZ -bTe -bTb -bWa -bYQ +fZV +hxv cep -ceq +aXM bdO bdO cQc @@ -152492,6 +151969,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (215,1,1) = {" aaa @@ -152618,19 +152100,14 @@ bxE bCZ bri bDg -bFl bGT bIB bHN -bHN -bHN -bSY -bTd -bTd -bVZ -bXG +bOa +bOa +bOa bKl -bIF +aXL beX bvh cLL @@ -152749,6 +152226,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (216,1,1) = {" aaa @@ -152876,18 +152358,13 @@ bDi bri bDj bFm -bGU bRo bKl -bMs -bOb -bOa -bUz -bVX -bXC -cck +rUQ +dRN +kwJ bKl -bIF +aXL beX bvh cLL @@ -153006,6 +152483,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (217,1,1) = {" aaa @@ -153133,16 +152615,11 @@ bDc brk bDh bFd -bHo bJm bKl -bSX -bOa -bOa -bUy -bVl -bUR -bZO +bKl +bKl +bKl aXL beX beX @@ -153263,6 +152740,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (218,1,1) = {" aaa @@ -153391,12 +152873,7 @@ brk bBl bBl bBl -bBl bKl -bMu -bOc -bPK -bRt bKl bKl bKl @@ -153520,6 +152997,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (219,1,1) = {" aaa @@ -153652,12 +153134,7 @@ aXL aXL aXL aXL -aXL -aXL -aXL -bIF -bIF -beX +bgN beX beX bvh @@ -153777,6 +153254,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (220,1,1) = {" aaa @@ -153909,14 +153391,9 @@ beX beX beX beX -beX -beX bgN beX beX -beX -beX -beX bvh bMr aaa @@ -154034,6 +153511,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (221,1,1) = {" aaa @@ -154166,14 +153648,9 @@ beY beY beY beY -beY -beY bgQ beY beY -beY -beY -beY bvi bMr aaa @@ -154291,6 +153768,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (222,1,1) = {" aaa @@ -154424,14 +153906,9 @@ bdM bdM bdM bdM -bdM bVY bdM bdM -bdM -bdM -bdM -bdM bNX abq abd @@ -154548,6 +154025,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (223,1,1) = {" aaa @@ -154681,14 +154163,9 @@ aXO aXO aXO aXO -aXO aWC aXO aXO -aXO -aXO -aXO -aXO aWC aaa abd @@ -154805,6 +154282,11 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa "} (224,1,1) = {" aaa @@ -154944,11 +154426,11 @@ abd abd abd abd -abd -abd -abd -abd -abd +aaa +aaa +aaa +aaa +aaa aaa aaa aaa diff --git a/_maps/map_files/MetaStation/z4.dmm b/_maps/map_files/MetaStation/z4.dmm index 6b7523f801d..9e7522e161d 100644 --- a/_maps/map_files/MetaStation/z4.dmm +++ b/_maps/map_files/MetaStation/z4.dmm @@ -33,10 +33,10 @@ /turf/simulated/floor/plating, /area/djstation) "ai" = ( -/obj/machinery/telecomms/relay/preset/ruskie, /obj/machinery/light{ dir = 1 }, +/obj/machinery/tcomms/relay/ruskie, /turf/simulated/floor/plating, /area/djstation) "aj" = ( @@ -453,6 +453,7 @@ icon_state = "1-2" }, /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "bk" = ( /obj/structure/disposalpipe/trunk{ @@ -490,6 +491,7 @@ /area/solar/derelict_starboard) "bo" = ( /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "bp" = ( /obj/structure/cable{ @@ -503,6 +505,7 @@ icon_state = "1-4" }, /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "bq" = ( /obj/structure/cable{ @@ -521,6 +524,7 @@ icon_state = "1-4" }, /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "br" = ( /obj/structure/cable{ @@ -529,6 +533,7 @@ icon_state = "4-8" }, /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "bs" = ( /obj/structure/cable{ @@ -547,6 +552,7 @@ icon_state = "2-8" }, /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "bt" = ( /obj/structure/cable{ @@ -560,6 +566,7 @@ icon_state = "2-8" }, /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "bu" = ( /obj/structure/cable{ @@ -573,6 +580,7 @@ icon_state = "2-8" }, /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "bv" = ( /obj/machinery/power/solar{ @@ -585,6 +593,7 @@ "bw" = ( /obj/structure/cable, /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "bx" = ( /obj/structure/cable{ @@ -592,6 +601,7 @@ d2 = 2 }, /obj/structure/lattice/catwalk, +/turf/space, /area/solar/derelict_starboard) "by" = ( /turf/simulated/wall, diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index 279afa9713d..e99384893a1 100644 --- a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -1241,21 +1241,6 @@ /obj/structure/sign/securearea, /turf/simulated/wall/mineral/plastitanium/explosive, /area/ruin/unpowered/syndicate_lava_base/main) -"cf" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/item/radio/intercom/syndicate, -/turf/simulated/floor/plasteel/dark, -/area/ruin/unpowered/syndicate_lava_base/telecomms) "cg" = ( /obj/machinery/portable_atmospherics/canister/nitrogen, /turf/simulated/floor/engine{ @@ -1789,7 +1774,6 @@ /area/ruin/unpowered/syndicate_lava_base/cargo) "ed" = ( /obj/structure/table, -/obj/item/paper_bin, /obj/item/pen, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, @@ -1803,6 +1787,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/item/paper_bin/syndicate, /turf/simulated/floor/plasteel/dark, /area/ruin/unpowered/syndicate_lava_base/cargo) "ef" = ( @@ -1898,7 +1883,6 @@ "ep" = ( /obj/structure/table/reinforced, /obj/effect/decal/cleanable/dirt, -/obj/item/paper_bin, /obj/item/pen, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, @@ -1912,6 +1896,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/item/paper_bin/syndicate, /turf/simulated/floor/plasteel/dark, /area/ruin/unpowered/syndicate_lava_base/testlab) "eq" = ( @@ -3529,10 +3514,6 @@ /obj/machinery/alarm/syndicate{ pixel_y = 24 }, -/obj/item/radio/headset/syndicate/alt{ - pixel_x = -3; - pixel_y = 3 - }, /turf/simulated/floor/plasteel/grimy, /area/ruin/unpowered/syndicate_lava_base/dormitories) "hN" = ( @@ -3558,10 +3539,6 @@ /obj/machinery/alarm/syndicate{ pixel_y = 24 }, -/obj/item/radio/headset/syndicate/alt{ - pixel_x = -3; - pixel_y = 3 - }, /turf/simulated/floor/plasteel/grimy, /area/ruin/unpowered/syndicate_lava_base/dormitories) "hR" = ( @@ -4479,10 +4456,6 @@ /obj/structure/table/wood, /obj/item/ammo_box/magazine/m10mm, /obj/item/ammo_box/magazine/sniper_rounds, -/obj/item/radio/headset/syndicate/alt{ - pixel_x = -3; - pixel_y = 3 - }, /turf/simulated/floor/plasteel/grimy, /area/ruin/unpowered/syndicate_lava_base/dormitories) "jB" = ( @@ -5952,9 +5925,6 @@ /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, /area/ruin/unpowered/syndicate_lava_base/engineering) -"mM" = ( -/turf/simulated/floor/greengrid, -/area/ruin/unpowered/syndicate_lava_base/telecomms) "mN" = ( /obj/structure/sign/securearea, /turf/simulated/wall/mineral/plastitanium/nodiagonal, @@ -6078,55 +6048,6 @@ }, /turf/simulated/floor/plasteel/dark, /area/ruin/unpowered/syndicate_lava_base/telecomms) -"nh" = ( -/obj/machinery/telecomms/relay/preset/ruskie{ - use_power = 0 - }, -/obj/machinery/light/small{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/simulated/floor/plasteel/dark, -/area/ruin/unpowered/syndicate_lava_base/telecomms) -"ni" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/simulated/floor/plasteel/dark, -/area/ruin/unpowered/syndicate_lava_base/telecomms) -"nj" = ( -/obj/machinery/door/airlock/hatch{ - name = "Telecommunications Control"; - req_access_txt = "150" - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/simulated/floor/plasteel/dark, -/area/ruin/unpowered/syndicate_lava_base/telecomms) "nk" = ( /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 4 @@ -6785,13 +6706,12 @@ /obj/machinery/computer/message_monitor{ dir = 1 }, -/obj/item/paper/monitorkey, /turf/simulated/floor/plasteel/dark, /area/ruin/unpowered/syndicate_lava_base/telecomms) "ov" = ( /obj/structure/table/reinforced, -/obj/item/paper_bin, /obj/item/pen, +/obj/item/paper_bin/syndicate, /turf/simulated/floor/plasteel/dark, /area/ruin/unpowered/syndicate_lava_base/telecomms) "ox" = ( @@ -6954,7 +6874,7 @@ ab ab ab ab -aa +ab aa aa aa @@ -7096,11 +7016,11 @@ ab ab ab ab -mn -mn -mn -mn -mn +ab +ab +ab +ab +ab ab ab ab @@ -7145,13 +7065,13 @@ ab ab ab ab -mn -mo -mM -nh -mM -mn -mn +ab +ab +ab +ab +ab +ab +ab ab ab ab @@ -7195,13 +7115,13 @@ ab ab ab ab -mn -mM -mM -ni -mM -mM -mn +ab +ab +ab +ab +ab +ab +ab ab ab ab @@ -7245,10 +7165,10 @@ ab ab ab ab -mn +ab mn mN -nj +mn mn mn mn @@ -7400,7 +7320,7 @@ mp mQ nl nJ -cf +nJ ov mn ab diff --git a/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm b/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm index 62a22425926..43aa3cd98c7 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm @@ -832,6 +832,10 @@ /obj/item/shard, /turf/space, /area/space/nearstation) +"Hv" = ( +/obj/item/gps/ruin, +/turf/simulated/wall/r_wall, +/area/ruin/unpowered) (1,1,1) = {" aa @@ -973,7 +977,7 @@ aa at at aF -at +Hv aU ay ay diff --git a/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm b/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm index a998609e8d5..392592e56a5 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/deepstorage.dmm @@ -612,10 +612,6 @@ /obj/machinery/power/smes, /turf/simulated/floor/plasteel, /area/ruin/unpowered) -"bt" = ( -/obj/machinery/telecomms/relay/preset/telecomms, -/turf/simulated/floor/plasteel, -/area/ruin/unpowered) "bu" = ( /obj/machinery/light/small{ dir = 1 @@ -870,6 +866,12 @@ "ce" = ( /turf/simulated/floor/plating/asteroid/airless, /area/ruin/unpowered) +"mL" = ( +/obj/machinery/tcomms/relay/ruskie{ + network_id = "STORAGE-RELAY" + }, +/turf/simulated/floor/plasteel, +/area/ruin/unpowered) (1,1,1) = {" aa @@ -2780,7 +2782,7 @@ ac ar ar ac -bt +mL ar ar ar diff --git a/_maps/map_files/RandomRuins/SpaceRuins/gasthelizards.dmm b/_maps/map_files/RandomRuins/SpaceRuins/gasthelizards.dmm index d869d21f539..0f7c36fe634 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/gasthelizards.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/gasthelizards.dmm @@ -99,14 +99,14 @@ "m" = ( /obj/structure/closet/crate/freezer, /obj/item/stack/sheet/animalhide/lizard, -/obj/item/reagent_containers/food/snacks/lizardmeat, +/obj/item/reagent_containers/food/snacks/monstermeat/lizardmeat, /turf/simulated/floor/plasteel{ icon_state = "dark" }, /area/ruin/unpowered) "n" = ( /obj/structure/closet/crate/freezer, -/obj/item/reagent_containers/food/snacks/lizardmeat, +/obj/item/reagent_containers/food/snacks/monstermeat/lizardmeat, /obj/machinery/light{ dir = 1 }, @@ -116,7 +116,7 @@ /area/ruin/unpowered) "o" = ( /obj/structure/closet/crate/freezer, -/obj/item/reagent_containers/food/snacks/lizardmeat, +/obj/item/reagent_containers/food/snacks/monstermeat/lizardmeat, /turf/simulated/floor/plasteel{ icon_state = "dark" }, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm b/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm index 22d4c0798aa..17d49d666bc 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/listeningpost.dmm @@ -269,6 +269,10 @@ icon_state = "freezerfloor" }, /area/ruin/powered) +"Y" = ( +/obj/item/gps/ruin, +/turf/simulated/wall/r_wall, +/area/ruin/powered) (1,1,1) = {" a @@ -960,7 +964,7 @@ b f f p -f +Y f f j diff --git a/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm b/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm index 2a5c0eae533..b4e36942d6a 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm @@ -240,6 +240,13 @@ /obj/structure/shuttle/engine/propulsion, /turf/simulated/shuttle/plating, /area/ruin/powered) +"U" = ( +/obj/item/gps/ruin, +/turf/simulated/shuttle/wall{ + tag = "icon-swall12"; + icon_state = "swall12" + }, +/area/ruin/powered) (1,1,1) = {" a @@ -313,7 +320,7 @@ a c g l -q +U r u t diff --git a/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm index 58eae91a94f..6562103334e 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm @@ -510,10 +510,10 @@ /area/template_noop) "bu" = ( /turf/simulated/wall/rust, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "bv" = ( /turf/simulated/wall, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "bw" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, @@ -615,7 +615,7 @@ "bM" = ( /obj/effect/spawner/window/reinforced, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "bN" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/blood/old, @@ -623,16 +623,16 @@ /obj/effect/decal/cleanable/cobweb, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "bO" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "bP" = ( /obj/structure/sign/poster/official/science, /turf/simulated/wall/rust, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "bQ" = ( /turf/simulated/wall/rust, /area/ruin/space/ancientstation/hivebot) @@ -647,7 +647,7 @@ "bS" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "bT" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/closet/crate, @@ -662,7 +662,7 @@ /obj/item/bonesetter, /obj/item/stack/medical/bruise_pack/advanced, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "bU" = ( /obj/machinery/door/airlock/command, /turf/simulated/floor/plasteel/airless, @@ -764,7 +764,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/command{ - name = "Delta Station Access" + name = "Theta Station Access" }, /turf/simulated/floor/plasteel, /area/ruin/space/ancientstation/powered) @@ -779,7 +779,7 @@ /obj/effect/spawner/window/reinforced, /obj/structure/transit_tube, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ck" = ( /obj/structure/lattice/catwalk, /turf/simulated/floor/plating/airless, @@ -789,19 +789,19 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cm" = ( /obj/effect/decal/cleanable/dirt, /obj/item/stack/medical/bruise_pack, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cn" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/command, /obj/structure/barricade/wooden, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "co" = ( /obj/effect/decal/cleanable/blood/oil, /mob/living/simple_animal/hostile/hivebot, @@ -818,7 +818,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cq" = ( /obj/structure/cable{ d1 = 4; @@ -830,7 +830,7 @@ /obj/machinery/door/airlock/science, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cr" = ( /obj/structure/cable{ d1 = 1; @@ -840,14 +840,14 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cs" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/firedoor, /obj/machinery/door/airlock/science, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ct" = ( /obj/item/twohanded/required/kirbyplants{ icon_state = "plant-dead" @@ -855,12 +855,12 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cu" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/maintenance_hatch, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cv" = ( /obj/effect/decal/cleanable/blood/oil, /obj/effect/decal/remains/robot{ @@ -964,7 +964,7 @@ /obj/item/pickaxe, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cJ" = ( /obj/machinery/light{ icon_state = "tube1"; @@ -973,7 +973,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cK" = ( /obj/effect/decal/remains/robot{ icon_state = "gib5" @@ -998,7 +998,7 @@ /obj/machinery/door/airlock/science, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cN" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -1006,7 +1006,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cO" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -1015,7 +1015,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cP" = ( /obj/effect/decal/cleanable/blood/oil, /mob/living/simple_animal/hostile/hivebot/strong, @@ -1033,7 +1033,7 @@ /obj/item/tank/plasma/full, /obj/item/tank/plasma/full, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "cR" = ( /obj/structure/table, /obj/item/storage/firstaid/ancient, @@ -1065,7 +1065,7 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/power/apc{ dir = 1; - name = "Delta Prototype Lab APC"; + name = "Thete Prototype Lab APC"; pixel_y = 24; report_power_alarm = 0; start_charge = 0 @@ -1165,7 +1165,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "di" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 4 @@ -1173,7 +1173,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "dj" = ( /turf/simulated/wall/rust, /area/ruin/space/ancientstation/rnd) @@ -1206,7 +1206,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "dp" = ( /obj/machinery/power/solar, /obj/structure/cable/yellow{ @@ -1227,7 +1227,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "dr" = ( /obj/item/roller, /obj/effect/decal/cleanable/dirt, @@ -1314,7 +1314,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "dD" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel{ @@ -1344,7 +1344,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "dI" = ( /obj/machinery/door/airlock/medical/glass{ name = "Medical Bay" @@ -1368,7 +1368,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot/strong, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "dL" = ( /obj/structure/table, /obj/effect/decal/cleanable/dirt, @@ -1514,7 +1514,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "eb" = ( /obj/machinery/light{ dir = 8 @@ -1575,7 +1575,7 @@ pixel_x = 28 }, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ei" = ( /obj/item/circuitboard/sleeper, /obj/effect/decal/cleanable/dirt, @@ -1695,13 +1695,13 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ew" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ex" = ( /obj/machinery/firealarm{ dir = 4; @@ -1719,12 +1719,12 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ez" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/power/emitter, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "eA" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel/airless{ @@ -1888,7 +1888,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "eT" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/r_n_d/protolathe, @@ -1926,7 +1926,7 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/field/generator, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "eY" = ( /obj/structure/cable/yellow{ d1 = 1; @@ -2009,7 +2009,7 @@ /obj/item/apc_electronics, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "fj" = ( /obj/structure/cable{ d1 = 1; @@ -2035,12 +2035,12 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "fl" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "fm" = ( /obj/machinery/light{ dir = 8 @@ -2079,7 +2079,7 @@ "fq" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "fr" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 6 @@ -2134,7 +2134,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "fx" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 6 @@ -2143,7 +2143,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "fy" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -2152,7 +2152,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "fz" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -2162,7 +2162,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "fA" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -2519,7 +2519,7 @@ icon_state = "4-8" }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ga" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -2531,7 +2531,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gb" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -2548,7 +2548,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gc" = ( /mob/living/simple_animal/hostile/carp, /turf/template_noop, @@ -2574,7 +2574,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ge" = ( /obj/structure/table, /obj/structure/cable{ @@ -2724,14 +2724,14 @@ /obj/item/trash/plate, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gx" = ( /obj/structure/chair{ dir = 8 }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gy" = ( /obj/effect/spawner/window/reinforced, /turf/simulated/floor/plating, @@ -2746,7 +2746,7 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/power/rad_collector, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gB" = ( /obj/item/solar_assembly, /turf/simulated/floor/plating/airless, @@ -2816,7 +2816,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gK" = ( /obj/machinery/processor, /obj/effect/decal/cleanable/dirt, @@ -2860,13 +2860,13 @@ /obj/machinery/door/firedoor, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gP" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/door/firedoor, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gQ" = ( /obj/structure/cable{ d1 = 1; @@ -2906,7 +2906,7 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/door/firedoor, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gU" = ( /obj/machinery/light{ icon_state = "tube1"; @@ -2915,7 +2915,7 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/door/firedoor, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gV" = ( /obj/structure/cable{ d1 = 1; @@ -2932,7 +2932,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot/strong, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "gX" = ( /obj/machinery/computer{ desc = "A computer long since rendered non-functional due to lack of maintenance. Spitting out error messages."; @@ -3035,7 +3035,7 @@ }, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "hk" = ( /obj/structure/table, /obj/effect/decal/cleanable/dirt, @@ -3072,7 +3072,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot/strong, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ho" = ( /obj/machinery/light/small{ dir = 8 @@ -3145,7 +3145,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "hu" = ( /obj/structure/table, /obj/effect/decal/cleanable/dirt, @@ -3265,7 +3265,7 @@ req_one_access_txt = "271" }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "hF" = ( /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel{ @@ -3414,14 +3414,14 @@ icon = 'icons/obj/machines/particle_accelerator3.dmi' }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "hV" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/particle_accelerator/particle_emitter/right{ icon = 'icons/obj/machines/particle_accelerator3.dmi' }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "hW" = ( /obj/machinery/light/small{ dir = 8 @@ -3508,13 +3508,13 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/power/apc{ dir = 1; - name = "Delta Main Corridor APC"; + name = "Theta Main Corridor APC"; pixel_y = 24; report_power_alarm = 0; start_charge = 0 }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ie" = ( /obj/machinery/atmospherics/unary/vent_pump/on{ dir = 4 @@ -3529,14 +3529,14 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "if" = ( /obj/machinery/atmospherics/pipe/manifold/hidden/supply{ dir = 4 }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ig" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/chair{ @@ -3602,7 +3602,7 @@ pixel_x = 28 }, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "in" = ( /turf/simulated/floor/plating/airless, /area/ruin/space/ancientstation/atmo) @@ -3676,7 +3676,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ix" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/effect/decal/cleanable/dirt, @@ -3690,19 +3690,19 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iz" = ( /obj/machinery/atmospherics/unary/vent_pump{ dir = 8 }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iA" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/recharge_station, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iB" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -3821,7 +3821,7 @@ id_tag = "ancient" }, /obj/machinery/door/airlock/command{ - name = "Delta Station Access" + name = "Theta Station Access" }, /turf/simulated/floor/plasteel, /area/ruin/space/ancientstation/powered) @@ -3856,7 +3856,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iS" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -3865,14 +3865,14 @@ /obj/machinery/door/firedoor, /obj/machinery/door/airlock/science, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iT" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iU" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -3880,7 +3880,7 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/door/firedoor, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iV" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -3891,7 +3891,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iW" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -3921,7 +3921,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iY" = ( /obj/machinery/light/small{ dir = 4 @@ -3931,7 +3931,7 @@ /obj/item/flash, /obj/item/flash, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "iZ" = ( /obj/structure/closet/crate/radiation, /obj/item/stack/sheet/mineral/uranium{ @@ -4005,7 +4005,7 @@ icon_state = "plant-dead" }, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "ji" = ( /obj/structure/cable{ d1 = 4; @@ -4014,7 +4014,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "jj" = ( /obj/structure/cable{ d1 = 4; @@ -4025,7 +4025,7 @@ /obj/machinery/door/firedoor, /obj/machinery/door/airlock/science, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "jk" = ( /obj/structure/cable{ d1 = 4; @@ -4035,7 +4035,7 @@ /obj/effect/decal/cleanable/dirt, /obj/machinery/door/firedoor, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "jl" = ( /obj/structure/cable{ d1 = 2; @@ -4044,27 +4044,27 @@ }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "jm" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/particle_accelerator/particle_emitter/center{ icon = 'icons/obj/machines/particle_accelerator3.dmi' }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "jn" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/firedoor, /obj/machinery/door/airlock/science, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "jo" = ( /obj/effect/decal/cleanable/dirt, /obj/item/twohanded/required/kirbyplants{ icon_state = "plant-dead" }, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "jp" = ( /obj/structure/cable{ d1 = 1; @@ -4241,7 +4241,7 @@ }, /obj/machinery/power/apc{ dir = 4; - name = "Delta RnD APC"; + name = "Theta RnD APC"; pixel_x = 24; report_power_alarm = 0; start_charge = 0 @@ -4726,7 +4726,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kN" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/machinery/door/firedoor, @@ -4734,14 +4734,14 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kO" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /obj/machinery/door/firedoor, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kP" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, @@ -4757,39 +4757,39 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kR" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kS" = ( /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kT" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/particle_accelerator/particle_emitter/left{ icon = 'icons/obj/machines/particle_accelerator3.dmi' }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kU" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/particle_accelerator/fuel_chamber{ icon = 'icons/obj/machines/particle_accelerator3.dmi' }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kV" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/particle_accelerator/end_cap{ icon = 'icons/obj/machines/particle_accelerator3.dmi' }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kW" = ( /obj/structure/table, /obj/effect/decal/cleanable/dirt, @@ -4813,7 +4813,7 @@ icon = 'icons/obj/machines/particle_accelerator3.dmi' }, /turf/simulated/floor/plating, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "kZ" = ( /obj/structure/lattice/catwalk, /turf/simulated/floor/plating, @@ -4860,13 +4860,13 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "le" = ( /obj/machinery/atmospherics/pipe/manifold4w/hidden/supply, /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "lf" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply{ dir = 4 @@ -4878,7 +4878,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "lg" = ( /obj/structure/cable{ d1 = 4; @@ -4888,7 +4888,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "lh" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/firealarm{ @@ -4897,7 +4897,7 @@ }, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "li" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/effect/decal/cleanable/dirt, @@ -5151,7 +5151,7 @@ /obj/effect/decal/cleanable/dirt, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "lE" = ( /obj/machinery/light/small{ dir = 4 @@ -5207,7 +5207,7 @@ }, /mob/living/simple_animal/hostile/hivebot, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) "lL" = ( /obj/structure/rack, /obj/item/clothing/suit/armor/vest/old, @@ -5240,7 +5240,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/warning_stripes/arrow, /turf/simulated/floor/plasteel, -/area/ruin/space/ancientstation/deltacorridor) +/area/ruin/space/ancientstation/thetacorridor) (1,1,1) = {" aa diff --git a/_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm b/_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm index fef87df8950..ebfaf3b94b4 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/wizardcrash.dmm @@ -209,7 +209,6 @@ "aI" = ( /obj/structure/table/wood, /obj/item/toy/character/wizard, -/obj/item/paper/spells, /turf/simulated/floor/carpet, /area/ruin/unpowered) "aJ" = ( diff --git a/_maps/map_files/RandomZLevels/academy.dmm b/_maps/map_files/RandomZLevels/academy.dmm index 920c9bacffd..1520866efbc 100644 --- a/_maps/map_files/RandomZLevels/academy.dmm +++ b/_maps/map_files/RandomZLevels/academy.dmm @@ -3040,17 +3040,6 @@ "if" = ( /turf/simulated/floor/grass, /area/awaymission/academy/academyaft) -"ig" = ( -/obj/structure/rack, -/obj/item/circuitboard/telecomms/broadcaster, -/obj/item/circuitboard/telecomms/receiver, -/obj/item/circuitboard/telecomms/processor, -/obj/item/circuitboard/telecomms/bus, -/obj/item/circuitboard/telecomms/relay, -/turf/simulated/floor/plasteel{ - icon_state = "hydrofloor" - }, -/area/awaymission/academy/academyaft) "ih" = ( /obj/structure/cable{ d1 = 1; @@ -3093,18 +3082,6 @@ dir = 2 }, /area/awaymission/academy/academyaft) -"il" = ( -/obj/structure/rack, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/subspace/crystal, -/obj/item/stock_parts/micro_laser/high, -/obj/item/stock_parts/micro_laser/high, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/subspace/analyzer, -/turf/simulated/floor/plasteel, -/area/awaymission/academy/academyaft) "im" = ( /obj/machinery/power/smes/magical, /obj/structure/cable, @@ -3122,30 +3099,6 @@ dir = 2 }, /area/awaymission/academy/academyaft) -"ip" = ( -/obj/structure/rack, -/obj/item/stock_parts/subspace/ansible, -/obj/item/stock_parts/micro_laser/high, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/subspace/amplifier, -/obj/item/stock_parts/subspace/filter, -/turf/simulated/floor/plasteel, -/area/awaymission/academy/academyaft) -"iq" = ( -/obj/structure/rack, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/subspace/filter, -/turf/simulated/floor/plasteel{ - icon_state = "hydrofloor" - }, -/area/awaymission/academy/academyaft) "ir" = ( /obj/structure/rack, /obj/item/storage/toolbox/mechanical, @@ -3215,23 +3168,6 @@ icon_state = "hydrofloor" }, /area/awaymission/academy/academyaft) -"iy" = ( -/obj/machinery/light{ - icon_state = "tube1"; - dir = 8 - }, -/obj/structure/rack, -/obj/item/stack/sheet/metal{ - amount = 50 - }, -/obj/item/stock_parts/subspace/treatment, -/obj/item/stock_parts/subspace/treatment, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/turf/simulated/floor/plasteel{ - icon_state = "hydrofloor" - }, -/area/awaymission/academy/academyaft) "iz" = ( /obj/structure/toilet{ dir = 8 @@ -15173,11 +15109,11 @@ gZ hp jk ia -ig -il -ip -iq -iy +hp +hl +hl +hp +ia hl hl gZ diff --git a/_maps/map_files/RandomZLevels/centcomAway.dmm b/_maps/map_files/RandomZLevels/centcomAway.dmm index 27ddb6f8a93..84515f06d49 100644 --- a/_maps/map_files/RandomZLevels/centcomAway.dmm +++ b/_maps/map_files/RandomZLevels/centcomAway.dmm @@ -2235,13 +2235,6 @@ }, /turf/simulated/floor/plating, /area/awaymission/centcomAway/general) -"fK" = ( -/obj/machinery/telecomms/relay/preset/ruskie, -/obj/effect/decal/warning_stripes/yellow, -/turf/simulated/floor/plasteel{ - icon_state = "floor" - }, -/area/awaymission/centcomAway/general) "fL" = ( /obj/structure/table, /obj/item/storage/box/donkpockets{ @@ -6819,6 +6812,15 @@ }, /turf/simulated/shuttle/floor, /area/awaymission/centcomAway/hangar) +"JB" = ( +/obj/effect/decal/warning_stripes/yellow, +/obj/machinery/tcomms/relay/ruskie{ + network_id = "XCC-P5831-RELAY" + }, +/turf/simulated/floor/plasteel{ + icon_state = "floor" + }, +/area/awaymission/centcomAway/general) (1,1,1) = {" aa @@ -14280,7 +14282,7 @@ ak ff eF gd -fK +JB eO il iL diff --git a/_maps/map_files/RandomZLevels/evil_santa.dmm b/_maps/map_files/RandomZLevels/evil_santa.dmm index ff5d4df54b9..0a92eaa1b29 100644 --- a/_maps/map_files/RandomZLevels/evil_santa.dmm +++ b/_maps/map_files/RandomZLevels/evil_santa.dmm @@ -650,7 +650,7 @@ /area/awaymission/challenge/start) "bT" = ( /obj/structure/dispenser/oxygen{ - oxygentanks = 9 + starting_oxygen_tanks = 9 }, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /turf/simulated/floor/plasteel, diff --git a/_maps/map_files/RandomZLevels/moonoutpost19.dmm b/_maps/map_files/RandomZLevels/moonoutpost19.dmm index affcac8c979..26ff48b4d88 100644 --- a/_maps/map_files/RandomZLevels/moonoutpost19.dmm +++ b/_maps/map_files/RandomZLevels/moonoutpost19.dmm @@ -2432,7 +2432,7 @@ }) "dy" = ( /obj/structure/dispenser/oxygen{ - oxygentanks = 9 + starting_oxygen_tanks = 9 }, /obj/machinery/light/small{ active_power_usage = 0; diff --git a/_maps/map_files/RandomZLevels/spacebattle.dmm b/_maps/map_files/RandomZLevels/spacebattle.dmm index c48e4632627..7afcae60122 100644 --- a/_maps/map_files/RandomZLevels/spacebattle.dmm +++ b/_maps/map_files/RandomZLevels/spacebattle.dmm @@ -410,12 +410,6 @@ icon_state = "floor4" }, /area/awaymission/spacebattle/syndicate1) -"bh" = ( -/obj/structure/table/reinforced, -/turf/simulated/shuttle/floor{ - icon_state = "floor4" - }, -/area/awaymission/spacebattle/syndicate1) "bi" = ( /obj/structure/table/reinforced, /obj/item/clothing/gloves/combat, @@ -720,10 +714,6 @@ icon_state = "engine" }, /area/awaymission/spacebattle/cruiser) -"bW" = ( -/obj/machinery/computer/telecomms/monitor, -/turf/simulated/floor/plasteel, -/area/awaymission/spacebattle/cruiser) "bX" = ( /obj/effect/landmark/damageturf, /turf/simulated/floor/plasteel, @@ -21503,11 +21493,11 @@ aZ bj aZ aV -bh +bg bo bo -bh -bh +bg +bg bv aV bj @@ -21760,7 +21750,7 @@ aZ aZ aZ aV -bh +bg aZ aZ aZ @@ -22008,7 +21998,7 @@ aW aZ aZ aZ -bh +bg aV aZ aZ @@ -22017,7 +22007,7 @@ aZ aZ aZ aV -bh +bg aZ aZ aZ @@ -22068,7 +22058,7 @@ ab ab ab bQ -bW +bZ cd cd cs @@ -22105,7 +22095,7 @@ cs cs cd cd -bW +bZ bQ ab ab @@ -22265,7 +22255,7 @@ aW aZ aZ aZ -bh +bg aV aZ aZ @@ -22274,7 +22264,7 @@ aZ aZ aZ aV -bh +bg aZ aZ aZ @@ -22522,7 +22512,7 @@ aW aZ aZ aZ -bh +bg aV bj aZ @@ -22531,10 +22521,10 @@ aZ aZ aZ aV -bh -bh -bh -bh +bg +bg +bg +bg aZ aZ aV @@ -22779,7 +22769,7 @@ aW aZ aZ aZ -bh +bg aV aV aV @@ -23550,7 +23540,7 @@ aW aZ aZ aZ -bh +bg aV aV aV @@ -23816,10 +23806,10 @@ aZ aZ aZ aV -bh -bh -bh -bh +bg +bg +bg +bg aZ aZ aV @@ -24064,7 +24054,7 @@ aW aZ aZ aZ -bh +bg aV aZ aZ @@ -24073,7 +24063,7 @@ aZ aZ aZ aV -bh +bg aZ aZ aZ @@ -24321,7 +24311,7 @@ aW aZ aZ aZ -bh +bg aV aZ aZ @@ -24330,7 +24320,7 @@ aZ aZ aZ aV -bh +bg aZ aZ aZ @@ -24578,7 +24568,7 @@ aW aZ aZ aZ -bh +bg aV aZ aZ @@ -24587,7 +24577,7 @@ aZ aZ aZ aV -bh +bg aZ aZ aZ @@ -24835,7 +24825,7 @@ aW aZ aZ aZ -bh +bg aV bj aZ @@ -24844,12 +24834,12 @@ aZ bj aZ aV -bh -bh -bh -bh -bh -bh +bg +bg +bg +bg +bg +bg aV bj bj diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm index 74e179255ce..36dbb929ff9 100644 --- a/_maps/map_files/cyberiad/cyberiad.dmm +++ b/_maps/map_files/cyberiad/cyberiad.dmm @@ -1619,15 +1619,12 @@ /area/security/range) "adH" = ( /obj/structure/table/wood, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, /obj/item/pen/multi, /obj/machinery/light{ dir = 1; on = 1 }, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -3804,14 +3801,6 @@ icon_state = "floor4" }, /area/shuttle/syndicate) -"ahi" = ( -/obj/machinery/telecomms/allinone{ - intercept = 1 - }, -/turf/simulated/shuttle/floor{ - icon_state = "floor4" - }, -/area/shuttle/syndicate) "ahj" = ( /obj/structure/disposalpipe/segment{ dir = 2; @@ -16077,16 +16066,13 @@ /area/lawoffice) "aAI" = ( /obj/structure/table/reinforced, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, /obj/item/pen, /obj/machinery/alarm{ dir = 8; pixel_x = 25; pixel_y = 0 }, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/plasteel{ tag = "icon-cult"; icon_state = "cult"; @@ -16863,11 +16849,8 @@ /area/magistrateoffice) "aCj" = ( /obj/structure/table/reinforced, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, /obj/item/stamp/magistrate, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/carpet, /area/magistrateoffice) "aCk" = ( @@ -21875,11 +21858,8 @@ /area/maintenance/fpmaint2) "aMO" = ( /obj/structure/table/reinforced, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, /obj/item/pen, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/plasteel{ tag = "icon-cult"; icon_state = "cult"; @@ -27795,16 +27775,14 @@ /obj/item/folder/yellow, /obj/item/stamp/ce, /obj/item/book/manual/sop_engineering, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, /obj/item/storage/fancy/cigarettes, /obj/item/lighter/zippo, /obj/item/pen/multi, /obj/item/enginepicker{ layer = 3.1 }, +/obj/item/paper_bin/nanotrasen, +/obj/item/paper/tcommskey, /turf/simulated/floor/plasteel{ dir = 8; icon_state = "neutralfull" @@ -43355,12 +43333,9 @@ }, /area/hallway/primary/central/west) "bCG" = ( -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, /obj/item/pen, /obj/structure/table/wood, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/carpet, /area/bridge/meeting_room) "bCH" = ( @@ -47113,10 +47088,6 @@ /area/shuttle/constructionsite) "bJN" = ( /obj/structure/table/wood, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 10 - }, /obj/item/pen/multi/fountain, /obj/machinery/door_control{ id = "captainofficedoor"; @@ -47129,6 +47100,7 @@ /obj/item/radio/intercom{ pixel_x = -28 }, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/wood, /area/crew_quarters/captain) "bJO" = ( @@ -50576,15 +50548,12 @@ }, /area/toxins/lab) "bPE" = ( -/obj/item/paper_bin{ - pixel_x = 1; - pixel_y = 9 - }, /obj/structure/table/glass, /obj/item/pen/multi, /obj/item/book/manual/sop_science{ pixel_y = -14 }, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/plasteel{ dir = 2; icon_state = "cafeteria"; @@ -54151,10 +54120,6 @@ /area/hallway/primary/central/se) "bVy" = ( /obj/structure/table, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, /obj/item/pen/multi, /obj/item/pen/multi, /obj/item/megaphone, @@ -55112,6 +55077,7 @@ /obj/item/book/manual/sop_service, /obj/item/book/manual/sop_supply, /obj/item/book/manual/sop_command, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/plasteel, /area/crew_quarters/heads) "bXa" = ( @@ -60880,7 +60846,6 @@ /area/medical/cmo) "cfW" = ( /obj/structure/table/glass, -/obj/item/paper_bin, /obj/item/pen/multi, /obj/item/folder/white{ pixel_y = 7 @@ -60890,6 +60855,7 @@ pixel_x = 32; pixel_y = 0 }, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/plasteel{ dir = 4; icon_state = "darkblue" @@ -67468,12 +67434,12 @@ /area/blueshield) "cqS" = ( /obj/structure/table/wood, -/obj/item/paper_bin, /obj/item/flashlight/lamp/green{ pixel_x = -5; pixel_y = 12 }, /obj/item/paper/ntrep, +/obj/item/paper_bin/nanotrasen, /turf/simulated/floor/carpet, /area/ntrep) "cqT" = ( @@ -91810,26 +91776,18 @@ }, /area/turret_protected/aisat_interior) "diM" = ( +/obj/machinery/hologram/holopad, +/obj/effect/landmark/start{ + name = "Cyborg" + }, /obj/structure/cable{ d1 = 2; d2 = 8; icon_state = "2-8"; tag = "" }, -/obj/machinery/hologram/holopad, -/obj/effect/landmark/start{ - name = "Cyborg" - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{ - dir = 8; - initialize_directions = 11; - level = 1 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 8; - initialize_directions = 11; - level = 1 - }, +/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers, +/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply, /turf/simulated/floor/plasteel{ icon_state = "grimy" }, @@ -92219,12 +92177,6 @@ /turf/simulated/floor/plating, /area/maintenance/asmaint2) "djD" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, /obj/structure/cable{ d1 = 2; d2 = 4; @@ -92236,6 +92188,12 @@ level = 1 }, /obj/machinery/atmospherics/pipe/simple/hidden/supply, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2"; + pixel_y = 0 + }, /turf/simulated/floor/plasteel{ icon_state = "grimy" }, @@ -92520,6 +92478,12 @@ pixel_x = 28 }, /obj/machinery/atmospherics/unary/vent_pump/on, +/obj/structure/cable{ + d1 = 1; + d2 = 2; + icon_state = "1-2"; + pixel_y = 0 + }, /turf/simulated/floor/plasteel{ dir = 4; icon_state = "darkbluecorners" @@ -93055,6 +93019,12 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/manifold/hidden/supply, +/obj/structure/cable{ + d1 = 1; + d2 = 4; + icon_state = "1-4"; + tag = "" + }, /turf/simulated/floor/plasteel{ dir = 5; icon_state = "dark"; @@ -95151,14 +95121,18 @@ /area/shuttle/pod_4) "doW" = ( /obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 + d1 = 4; + d2 = 8; + icon_state = "4-8"; + pixel_x = 0; + tag = "" }, -/obj/machinery/computer/monitor{ - name = "Grid Power Monitoring Computer" +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4; + level = 1 }, -/obj/machinery/computer/security/telescreen/entertainment{ - pixel_x = -32 +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, /turf/simulated/floor/plasteel{ dir = 5; @@ -95171,11 +95145,15 @@ d1 = 4; d2 = 8; icon_state = "4-8"; - pixel_y = 0; + pixel_x = 0; tag = "" }, -/obj/structure/chair/office/dark{ - dir = 8 +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4; + level = 1 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 }, /turf/simulated/floor/plasteel{ icon_state = "grimy" @@ -95191,8 +95169,8 @@ name = "\improper AI Satellite Atmospherics" }) "dpe" = ( -/obj/machinery/atmospherics/pipe/simple/visible/yellow, /obj/machinery/meter, +/obj/machinery/atmospherics/pipe/simple/hidden/yellow, /turf/simulated/wall/r_wall, /area/aisat/entrance{ name = "\improper AI Satellite Atmospherics" @@ -95328,10 +95306,21 @@ name = "\improper AI Satellite Atmospherics" }) "dpF" = ( +/obj/structure/cable{ + icon_state = "0-4"; + d2 = 4 + }, +/obj/machinery/computer/monitor{ + name = "Grid Power Monitoring Computer" + }, /obj/structure/extinguisher_cabinet{ pixel_x = -5; pixel_y = 30 }, +/obj/structure/cable{ + d2 = 2; + icon_state = "0-2" + }, /turf/simulated/floor/plating, /area/aisat/entrance{ name = "\improper AI Satellite Atmospherics" @@ -96333,6 +96322,27 @@ }, /turf/space, /area/space/nearstation) +"dQC" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/yellow, +/obj/machinery/atmospherics/unary/vent_pump/on{ + dir = 4 + }, +/obj/machinery/light{ + dir = 1; + in_use = 1 + }, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) +"fAw" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/yellow, +/obj/machinery/tcomms/core/station, +/obj/machinery/camera{ + c_tag = "Telecommunications Core"; + dir = 4; + network = list("SS13") + }, +/turf/simulated/floor/plasteel/dark, +/area/tcommsat/chamber) "gMZ" = ( /obj/machinery/atmospherics/pipe/simple/insulated{ dir = 6 @@ -96378,6 +96388,18 @@ }, /turf/simulated/floor/plating, /area/toxins/mixing) +"hyv" = ( +/obj/structure/cable, +/obj/machinery/power/apc{ + dir = 2; + name = "south bump"; + pixel_y = -24 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 9 + }, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) "izn" = ( /obj/machinery/atmospherics/unary/passive_vent{ dir = 1 @@ -96411,6 +96433,9 @@ /area/toxins/launch{ name = "Toxins Launch Room" }) +"iUc" = ( +/turf/simulated/wall/r_wall, +/area/tcommsat/chamber) "jnJ" = ( /obj/machinery/light/spot{ tag = "icon-tube1 (NORTH)"; @@ -96455,6 +96480,18 @@ }, /turf/simulated/floor/plasteel, /area/atmos) +"mkE" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/yellow, +/obj/machinery/atmospherics/unary/vent_scrubber{ + dir = 4; + name = "standard air scrubber"; + on = 1; + scrub_N2O = 1; + scrub_Toxins = 1 + }, +/obj/machinery/light, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) "mMw" = ( /obj/structure/chair/comfy/shuttle{ dir = 8 @@ -96467,6 +96504,36 @@ }, /turf/space, /area/space/nearstation) +"oOZ" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/yellow, +/turf/simulated/wall/r_wall, +/area/tcommsat/chamber) +"oQe" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/hatch{ + name = "Telecommunications Access"; + req_access_txt = "61" + }, +/obj/structure/cable{ + d1 = 4; + d2 = 8; + icon_state = "4-8"; + pixel_y = 0; + tag = "" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 4; + level = 1 + }, +/turf/simulated/floor/plasteel{ + dir = 5; + icon_state = "dark"; + tag = "icon-vault (NORTHEAST)" + }, +/area/tcommsat/chamber) "oZV" = ( /obj/machinery/door/airlock/centcom{ id_tag = "adminshuttle"; @@ -96518,6 +96585,11 @@ icon_state = "floor4" }, /area/shuttle/administration) +"rOX" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/yellow, +/obj/machinery/ntnet_relay, +/turf/simulated/floor/plasteel/dark, +/area/tcommsat/chamber) "rSv" = ( /obj/structure/shuttle/engine/propulsion{ dir = 8; @@ -96526,6 +96598,15 @@ }, /turf/space, /area/shuttle/administration) +"rTy" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 10 + }, +/obj/machinery/alarm{ + pixel_y = 22 + }, +/turf/simulated/floor/bluegrid, +/area/tcommsat/chamber) "rYq" = ( /obj/machinery/door/airlock/centcom{ id_tag = "adminshuttle"; @@ -96537,6 +96618,10 @@ icon_state = "floor4" }, /area/shuttle/administration) +"sag" = ( +/obj/machinery/atmospherics/pipe/simple/hidden/supply, +/turf/simulated/floor/plasteel/dark, +/area/tcommsat/chamber) "sUK" = ( /obj/structure/chair/comfy/shuttle{ dir = 8 @@ -96582,6 +96667,21 @@ icon_state = "floor2" }, /area/shuttle/constructionsite) +"wbr" = ( +/obj/structure/cable{ + d1 = 2; + d2 = 4; + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/simple/hidden/supply{ + dir = 5; + level = 1 + }, +/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ + dir = 6 + }, +/turf/simulated/floor/plasteel/dark, +/area/tcommsat/chamber) "wOS" = ( /obj/structure/table, /obj/item/clothing/gloves/color/black, @@ -109037,7 +109137,7 @@ abV abV abV agH -ahi +abV ahy ahP aaa @@ -131801,11 +131901,11 @@ dmW aaa aab aaa -aaa -aaa -aaa -aaa -aab +iUc +iUc +iUc +iUc +iUc dpd dpd dpC @@ -132058,11 +132158,11 @@ ddC doE ddM ddO -cPw -djd -djd -djd -djE +oOZ +dQC +fAw +rOX +mkE dpe dpl dpE @@ -132315,11 +132415,11 @@ dmW dmB bfu dnT -dnZ -aaa -aaa -aaa -aab +dpf +rTy +sag +wbr +hyv dpd dpm dpD @@ -132572,11 +132672,11 @@ dmW dmB bjb dnW -dnZ -dnZ -dnZ -dnZ -dnZ +dpf +iUc +iUc +oQe +iUc dpf dpd dpF diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm index 684365ada39..7abe416f576 100644 --- a/_maps/map_files/cyberiad/z2.dmm +++ b/_maps/map_files/cyberiad/z2.dmm @@ -2060,7 +2060,16 @@ icon_opened = "cabinet_open"; icon_state = "cabinet_closed" }, +/obj/item/clothing/under/color/lightpurple, +/obj/item/clothing/under/color/purple, /obj/item/storage/backpack/satchel, +/obj/item/storage/backpack/satchel, +/obj/item/clothing/head/wizard/red, +/obj/item/clothing/suit/wizrobe/red, +/obj/item/clothing/head/wizard, +/obj/item/clothing/suit/wizrobe, +/obj/item/clothing/shoes/sandal, +/obj/item/clothing/shoes/sandal, /turf/unsimulated/floor{ dir = 9; icon_state = "carpetside" @@ -2148,8 +2157,6 @@ /area/wizard_station) "fC" = ( /obj/structure/table/wood, -/obj/item/trash/tray, -/obj/item/paper/spells, /turf/unsimulated/floor{ dir = 10; icon_state = "carpetside" @@ -3248,10 +3255,10 @@ /area/shuttle/assault_pod) "iw" = ( /obj/structure/rack, +/obj/item/clothing/under/plasmaman/wizard, +/obj/item/clothing/head/helmet/space/plasmaman/wizard, /obj/item/clothing/mask/breath, -/obj/item/clothing/mask/breath/vox, -/obj/item/tank/plasma/plasmaman, -/obj/item/tank/emergency_oxygen/vox, +/obj/item/tank/plasma/plasmaman/belt/full, /turf/unsimulated/floor{ icon_state = "grimy" }, @@ -3895,10 +3902,8 @@ /area/centcom/gamma) "ke" = ( /obj/structure/rack, -/obj/item/clothing/suit/wizrobe/red, -/obj/item/clothing/shoes/sandal, -/obj/item/clothing/head/wizard/red, -/obj/item/twohanded/staff, +/obj/item/tank/emergency_oxygen/vox, +/obj/item/clothing/mask/breath/vox, /turf/unsimulated/floor{ icon_state = "grimy" }, @@ -5006,6 +5011,20 @@ name = "grass" }, /area/centcom/control) +"nc" = ( +/obj/machinery/door/airlock/centcom{ + name = "Gamma Armory"; + opacity = 1; + req_access_txt = "114" + }, +/obj/machinery/door/poddoor/impassable{ + id_tag = "CCGAMMA"; + name = "Gamma Security" + }, +/turf/simulated/floor/plasteel{ + icon_state = "dark" + }, +/area/centcom/gamma) "nd" = ( /obj/structure/flora/ausbushes/lavendergrass, /turf/unsimulated/floor{ @@ -5381,7 +5400,7 @@ }, /area/syndicate_mothership) "nQ" = ( -/obj/machinery/door/poddoor{ +/obj/machinery/door/poddoor/impassable{ id_tag = "GRAVPULTS"; name = "Gravity Catapults" }, @@ -5391,7 +5410,7 @@ }, /area/centcom/specops) "nR" = ( -/obj/machinery/door/poddoor{ +/obj/machinery/door/poddoor/impassable{ id_tag = "GRAVPULTS"; name = "Gravity Catapults" }, @@ -5408,7 +5427,7 @@ }, /area/syndicate_mothership) "nT" = ( -/obj/machinery/door/poddoor{ +/obj/machinery/door/poddoor/impassable{ id_tag = "ASSAULT"; name = "Assault Armor" }, @@ -5854,7 +5873,7 @@ }, /area/centcom/gamma) "oR" = ( -/obj/machinery/door/poddoor{ +/obj/machinery/door/poddoor/impassable{ id_tag = "SPECOPS"; name = "Ready Room" }, @@ -5979,7 +5998,7 @@ opacity = 1; req_access_txt = "114" }, -/obj/machinery/door/poddoor{ +/obj/machinery/door/poddoor/impassable{ id_tag = "specopsoffice"; name = "Super Privacy Shutters" }, @@ -6118,7 +6137,7 @@ /turf/simulated/floor/mech_bay_recharge_floor, /area/shuttle/gamma/space) "pv" = ( -/obj/machinery/door/poddoor{ +/obj/machinery/door/poddoor/impassable{ id_tag = "CCTELE"; name = "Specops Teleporter" }, @@ -6314,13 +6333,6 @@ icon_state = "dark" }, /area/centcom/specops) -"pR" = ( -/obj/machinery/telecomms/server/presets/centcomm, -/turf/unsimulated/floor{ - icon_state = "green"; - dir = 8 - }, -/area/centcom/control) "pS" = ( /obj/machinery/door/airlock/centcom{ name = "Telecommunications"; @@ -6365,7 +6377,7 @@ /area/centcom/specops) "pX" = ( /obj/machinery/door_control{ - desc = "A remote control switch to block view of the singularity."; + desc = "A remote control switch to connect the ready room to the rest of Centcom."; icon_state = "doorctrl0"; id = "SPECOPS"; name = "Ready Room"; @@ -6415,13 +6427,6 @@ dir = 2 }, /area/centcom/specops) -"qa" = ( -/obj/machinery/telecomms/processor/preset_cent, -/turf/unsimulated/floor{ - icon_state = "green"; - dir = 8 - }, -/area/centcom/control) "qb" = ( /obj/structure/sink{ dir = 4; @@ -6474,20 +6479,6 @@ icon_state = "carpetside" }, /area/centcom/specops) -"qh" = ( -/obj/machinery/telecomms/bus/preset_cent, -/turf/unsimulated/floor{ - icon_state = "green"; - dir = 8 - }, -/area/centcom/control) -"qi" = ( -/obj/machinery/telecomms/hub/preset_cent, -/turf/unsimulated/floor{ - icon_state = "green"; - dir = 4 - }, -/area/centcom/control) "qj" = ( /turf/unsimulated/wall/fakeglass{ dir = 1; @@ -6537,25 +6528,11 @@ name = "bookcase (Reports)" }, /area/centcom/specops) -"qn" = ( -/obj/machinery/telecomms/receiver/preset_cent, -/turf/unsimulated/floor{ - icon_state = "green"; - dir = 10 - }, -/area/centcom/control) "qo" = ( /turf/simulated/floor/plasteel{ icon_state = "white" }, /area/centcom/evac) -"qp" = ( -/obj/machinery/telecomms/broadcaster/preset_cent, -/turf/unsimulated/floor{ - icon_state = "green"; - dir = 6 - }, -/area/centcom/control) "qq" = ( /turf/unsimulated/floor{ icon_state = "green"; @@ -9423,12 +9400,6 @@ tag = "icon-window5_end (WEST)" }, /area/admin) -"wg" = ( -/obj/machinery/telecomms/relay/preset/centcom, -/turf/unsimulated/floor{ - icon_state = "grimy" - }, -/area/centcom/specops) "wh" = ( /obj/machinery/recharge_station/upgraded, /turf/unsimulated/floor{ @@ -12461,6 +12432,12 @@ icon_state = "floor4" }, /area/shuttle/escape) +"KK" = ( +/obj/machinery/tcomms/relay/cc, +/turf/unsimulated/floor{ + icon_state = "floor" + }, +/area/centcom/control) "KR" = ( /obj/machinery/light/small, /obj/structure/chair/comfy/shuttle{ @@ -12766,6 +12743,13 @@ /obj/structure/chair/comfy/shuttle, /turf/simulated/shuttle/floor, /area/centcom/evac) +"WW" = ( +/obj/structure/flora/ausbushes/pointybush, +/turf/unsimulated/floor{ + icon_state = "grass1"; + name = "grass" + }, +/area/centcom/control) "Xj" = ( /obj/structure/bed, /turf/unsimulated/floor{ @@ -29642,7 +29626,7 @@ fm fm md md -oO +nc fm pv sX @@ -32476,7 +32460,7 @@ pD pN pX qe -wg +vd sX sX sX @@ -34272,10 +34256,10 @@ VC pl sX pH -pR -qa -qh -qn +nC +qq +su +mY sq qz wC @@ -34529,10 +34513,10 @@ VC pj sX nD -tR -tR -tR +KK ud +su +nd sq qy wC @@ -34787,9 +34771,9 @@ pm sX pI tR -nH -qi -qp +qr +su +WW sq qB qE @@ -35042,7 +35026,7 @@ sq oU sq sq -sq +su pS su su diff --git a/_maps/map_files/cyberiad/z3.dmm b/_maps/map_files/cyberiad/z3.dmm deleted file mode 100644 index 26d46280ae3..00000000000 --- a/_maps/map_files/cyberiad/z3.dmm +++ /dev/null @@ -1,69219 +0,0 @@ -//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE -"aa" = ( -/turf/space, -/area/space) -"ab" = ( -/obj/item/trash/cheesie, -/turf/space, -/area/space/nearstation) -"ac" = ( -/obj/docking_port/stationary{ - dir = 8; - dwidth = 10; - height = 35; - id = "whiteship_away"; - name = "Deep Space"; - width = 21 - }, -/turf/space, -/area/space) -"ad" = ( -/obj/docking_port/stationary{ - dheight = 9; - dir = 2; - dwidth = 5; - height = 22; - id = "syndicate_z3"; - name = "south of telecomms"; - width = 18 - }, -/turf/space, -/area/space) -"ae" = ( -/obj/machinery/atmospherics/pipe/simple/visible{ - dir = 4 - }, -/obj/machinery/access_button{ - command = "cycle_interior"; - frequency = 1381; - master_tag = "telecoms_airlock"; - name = "interior access button"; - pixel_x = -25; - pixel_y = -25; - req_access_txt = "61" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"af" = ( -/obj/machinery/access_button{ - command = "cycle_exterior"; - frequency = 1381; - master_tag = "telecoms_airlock"; - name = "exterior access button"; - pixel_x = 25; - pixel_y = 25; - req_access_txt = "61" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating/airless, -/area/tcommsat/powercontrol) -"ag" = ( -/obj/item/stack/spacecash, -/turf/simulated/floor/engine, -/area/tcommsat/computer) -"ah" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/machinery/ntnet_relay, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"ai" = ( -/obj/machinery/power/apc{ - dir = 1; - name = "Telecoms Sat. Foyer APC"; - pixel_x = 1; - pixel_y = 26 - }, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/obj/effect/decal/warning_stripes/northwestcorner, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"aj" = ( -/obj/structure/sign/securearea{ - desc = "A warning sign which reads 'LETHAL TURRETS'. Enter at your own risk!"; - name = "LETHAL TURRETS"; - pixel_x = -32; - pixel_y = 0 - }, -/obj/machinery/porta_turret{ - dir = 4 - }, -/obj/effect/decal/warning_stripes/northwest, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"ak" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/machinery/turretid/lethal{ - ailock = 1; - check_synth = 1; - control_area = "\improper Telecoms Satellite"; - desc = "A firewall prevents AI's from interacting with this device."; - icon_state = "control_kill"; - lethal = 1; - name = "Telecomms Lethal Turret Control"; - pixel_y = 30; - req_access = list(61) - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Telecomms Foyer"; - dir = 2; - network = list("Telecomms") - }, -/obj/effect/decal/warning_stripes/north, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"al" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/obj/effect/decal/warning_stripes/northeastcorner, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"am" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 10 - }, -/obj/machinery/status_display{ - pixel_x = 0; - pixel_y = 32 - }, -/obj/effect/decal/warning_stripes/northeastcorner, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"an" = ( -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 1; - level = 1 - }, -/obj/item/radio/intercom{ - pixel_y = 25 - }, -/obj/effect/decal/warning_stripes/northwestcorner, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"ao" = ( -/obj/structure/sign/securearea{ - desc = "A warning sign which reads 'LETHAL TURRETS'. Enter at your own risk!"; - name = "LETHAL TURRETS"; - pixel_x = 32; - pixel_y = 0 - }, -/obj/machinery/porta_turret{ - dir = 8 - }, -/obj/effect/decal/warning_stripes/northeast, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"ap" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/effect/decal/warning_stripes/west, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"aq" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/effect/decal/warning_stripes/east, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"ar" = ( -/obj/machinery/light/small, -/obj/machinery/light_switch{ - pixel_y = -28 - }, -/obj/effect/decal/warning_stripes/southwestcorner, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"as" = ( -/obj/structure/sign/securearea{ - desc = "A warning sign which reads 'LETHAL TURRETS'. Enter at your own risk!"; - name = "LETHAL TURRETS"; - pixel_x = -32; - pixel_y = 0 - }, -/obj/effect/decal/warning_stripes/southwest, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"at" = ( -/obj/machinery/light/small, -/obj/effect/decal/warning_stripes/southeastcorner, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"au" = ( -/obj/structure/sign/securearea{ - desc = "A warning sign which reads 'LETHAL TURRETS'. Enter at your own risk!"; - name = "LETHAL TURRETS"; - pixel_x = 32; - pixel_y = 0 - }, -/obj/effect/decal/warning_stripes/southeast, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"av" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/effect/decal/warning_stripes/north, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"aw" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - req_access_txt = "0" - }, -/obj/effect/decal/warning_stripes/northwest, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"ax" = ( -/obj/machinery/camera{ - c_tag = "Telecomms Entrance North"; - dir = 2; - network = list("Telecomms") - }, -/obj/effect/decal/warning_stripes/northeast, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"ay" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - req_access_txt = "0" - }, -/obj/effect/decal/warning_stripes/northwestcorner, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"az" = ( -/obj/effect/decal/warning_stripes/northeastcorner, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"aA" = ( -/obj/effect/decal/warning_stripes/northwest, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"aB" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4; - level = 1 - }, -/obj/effect/decal/warning_stripes/west, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"aC" = ( -/obj/effect/decal/warning_stripes/southwestcorner, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"aD" = ( -/obj/structure/closet/crate, -/obj/machinery/light_switch{ - pixel_y = -28 - }, -/obj/item/clothing/glasses/night, -/obj/effect/decal/warning_stripes/southwest, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"aE" = ( -/obj/structure/closet/crate, -/obj/item/aicard, -/obj/item/multitool, -/obj/machinery/camera{ - c_tag = "Telecomms Entrance South"; - dir = 1; - network = list("Telecomms") - }, -/obj/effect/decal/warning_stripes/southwest, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"aF" = ( -/obj/effect/decal/warning_stripes/south, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"aG" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/structure/closet/emcloset, -/obj/effect/decal/warning_stripes/southeast, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"aH" = ( -/obj/machinery/atmospherics/pipe/simple/visible{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Telecomms Power Control"; - dir = 2; - network = list("Telecomms") - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"aT" = ( -/obj/structure/lattice, -/turf/space, -/area/space/nearstation) -"ba" = ( -/turf/simulated/shuttle/wall{ - tag = "icon-swall_s6"; - icon_state = "swall_s6"; - dir = 2 - }, -/area/space/nearstation) -"bb" = ( -/turf/simulated/shuttle/wall{ - tag = "icon-swall14"; - icon_state = "swall14"; - dir = 2 - }, -/area/space/nearstation) -"bc" = ( -/turf/simulated/shuttle/wall{ - tag = "icon-swall12"; - icon_state = "swall12"; - dir = 2 - }, -/area/space/nearstation) -"bd" = ( -/turf/simulated/shuttle/wall{ - tag = "icon-swall_s10"; - icon_state = "swall_s10"; - dir = 2 - }, -/area/space/nearstation) -"bi" = ( -/turf/simulated/shuttle/wall{ - tag = "icon-swall7"; - icon_state = "swall7"; - dir = 2 - }, -/area/space/nearstation) -"bj" = ( -/turf/simulated/shuttle/floor{ - icon_state = "floor3" - }, -/turf/simulated/shuttle/wall{ - tag = "icon-swall_f9"; - icon_state = "swall_f9"; - dir = 2 - }, -/area/space/nearstation) -"bk" = ( -/turf/simulated/shuttle/floor{ - icon_state = "floor3" - }, -/area/space/nearstation) -"bl" = ( -/turf/simulated/shuttle/floor{ - icon_state = "floor3" - }, -/turf/simulated/shuttle/wall{ - tag = "icon-swall_f5"; - icon_state = "swall_f5"; - dir = 2 - }, -/area/space/nearstation) -"bm" = ( -/turf/simulated/shuttle/wall{ - tag = "icon-swall11"; - icon_state = "swall11"; - dir = 2 - }, -/area/space/nearstation) -"bp" = ( -/obj/machinery/door/unpowered/shuttle, -/turf/simulated/shuttle/floor{ - icon_state = "floor3" - }, -/area/space/nearstation) -"bs" = ( -/turf/simulated/shuttle/floor{ - icon_state = "floor3" - }, -/turf/simulated/shuttle/wall{ - tag = "icon-swall_f10"; - icon_state = "swall_f10"; - dir = 2 - }, -/area/space/nearstation) -"bu" = ( -/turf/simulated/shuttle/floor{ - icon_state = "floor3" - }, -/turf/simulated/shuttle/wall{ - tag = "icon-swall_f6"; - icon_state = "swall_f6"; - dir = 2 - }, -/area/space/nearstation) -"bx" = ( -/turf/simulated/shuttle/wall{ - tag = "icon-swall_s5"; - icon_state = "swall_s5"; - dir = 2 - }, -/area/space/nearstation) -"by" = ( -/turf/simulated/shuttle/wall{ - tag = "icon-swall13"; - icon_state = "swall13"; - dir = 2 - }, -/area/space/nearstation) -"bz" = ( -/turf/simulated/shuttle/wall{ - tag = "icon-swall_s9"; - icon_state = "swall_s9"; - dir = 2 - }, -/area/space/nearstation) -"bW" = ( -/obj/structure/lattice, -/obj/structure/grille, -/turf/space, -/area/space/nearstation) -"bX" = ( -/obj/machinery/power/solar, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/turf/simulated/floor/plasteel/airless{ - icon_state = "solarpanel" - }, -/area/space/nearstation) -"bY" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"bZ" = ( -/obj/machinery/power/solar, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plasteel/airless{ - icon_state = "solarpanel" - }, -/area/space/nearstation) -"ca" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"cb" = ( -/obj/structure/lattice, -/obj/structure/grille/broken, -/turf/space, -/area/space/nearstation) -"cc" = ( -/obj/machinery/camera{ - c_tag = "Telecomms North Solars"; - dir = 8; - network = list("Telecomms") - }, -/turf/space, -/area/space/nearstation) -"cd" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"ce" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"cf" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"cg" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"ch" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"ci" = ( -/obj/structure/lattice, -/obj/structure/grille, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"cj" = ( -/obj/structure/lattice, -/obj/structure/grille, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"ck" = ( -/obj/structure/grille, -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"cl" = ( -/obj/structure/lattice, -/obj/structure/grille, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"cm" = ( -/obj/structure/lattice, -/obj/structure/grille, -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"cn" = ( -/turf/simulated/wall/r_wall, -/area/space/nearstation) -"co" = ( -/obj/structure/lattice, -/obj/structure/grille, -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"cp" = ( -/turf/simulated/wall/r_wall, -/area/turret_protected/tcomsat) -"cq" = ( -/turf/simulated/wall/r_wall, -/area/tcommsat/computer) -"cr" = ( -/obj/structure/lattice, -/obj/structure/grille, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"cs" = ( -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"ct" = ( -/turf/space, -/area/turret_protected/tcomsat) -"cu" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Telecomms West Wing North"; - dir = 2; - network = list("Telecomms") - }, -/turf/space, -/area/turret_protected/tcomsat) -"cv" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/item/radio/intercom{ - pixel_y = 25 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cw" = ( -/obj/machinery/power/apc{ - dir = 1; - name = "Telecoms Sat. APC"; - pixel_x = 1; - pixel_y = 26 - }, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/obj/machinery/atmospherics/pipe/simple/visible{ - dir = 6; - level = 1 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cx" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/obj/machinery/atmospherics/pipe/simple/visible{ - dir = 4 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cy" = ( -/obj/machinery/atmospherics/pipe/manifold/visible{ - dir = 1 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cz" = ( -/obj/machinery/atmospherics/unary/tank/air{ - dir = 8 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cA" = ( -/obj/item/coin/clown, -/turf/simulated/floor/engine, -/area/tcommsat/computer) -"cB" = ( -/obj/structure/bed, -/obj/item/bedsheet/green, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cC" = ( -/obj/machinery/light{ - dir = 1 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cD" = ( -/obj/structure/bed, -/obj/item/bedsheet/brown, -/obj/machinery/status_display{ - pixel_x = 0; - pixel_y = 32 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cE" = ( -/obj/machinery/camera{ - c_tag = "Telecomms Lounge"; - dir = 2; - network = list("Telecomms") - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cF" = ( -/obj/structure/bed, -/obj/item/bedsheet/red, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cG" = ( -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cH" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/space, -/area/turret_protected/tcomsat) -"cI" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/unary/vent_pump{ - on = 1 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cJ" = ( -/obj/machinery/meter, -/obj/machinery/atmospherics/pipe/simple/visible, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cK" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cL" = ( -/obj/machinery/atmospherics/pipe/simple/visible{ - dir = 5 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cM" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/atmospherics/unary/tank/air{ - dir = 8 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cN" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/space, -/area/turret_protected/tcomsat) -"cO" = ( -/obj/structure/filingcabinet, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cP" = ( -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 1; - external_pressure_bound = 140; - on = 1; - pressure_checks = 0 - }, -/obj/machinery/camera{ - c_tag = "Telecomms Control Room"; - dir = 2; - network = list("Telecomms") - }, -/obj/structure/table, -/obj/item/folder/yellow, -/obj/item/folder/yellow, -/obj/machinery/light{ - dir = 1 - }, -/obj/machinery/status_display{ - pixel_x = 0; - pixel_y = 32 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cQ" = ( -/obj/structure/table, -/obj/item/paper_bin, -/obj/item/pen/blue{ - pixel_x = -3; - pixel_y = 2 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cR" = ( -/obj/machinery/light_switch{ - pixel_y = 28 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cS" = ( -/obj/structure/table, -/obj/item/flashlight/lamp, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cT" = ( -/turf/simulated/floor/engine, -/area/tcommsat/computer) -"cU" = ( -/obj/item/radio/intercom{ - name = "station intercom (General)"; - pixel_x = -28; - pixel_y = 0 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"cV" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/space, -/area/turret_protected/tcomsat) -"cW" = ( -/obj/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - req_access_txt = "0" - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cX" = ( -/obj/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/visible/universal, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cY" = ( -/obj/structure/window/reinforced, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"cZ" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/closet, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"da" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/space, -/area/turret_protected/tcomsat) -"db" = ( -/obj/item/radio/intercom{ - dir = 8; - name = "station intercom (General)"; - pixel_x = -28 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dc" = ( -/obj/structure/chair/office/dark{ - dir = 1 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dd" = ( -/obj/machinery/computer/telecomms/monitor{ - network = list("tcommsat") - }, -/obj/item/radio/intercom{ - name = "station intercom (General)"; - pixel_x = 29; - pixel_y = 0 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"de" = ( -/obj/structure/bed, -/obj/item/bedsheet/orange, -/obj/machinery/light{ - dir = 8 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"df" = ( -/obj/machinery/hologram/holopad, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dg" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 5 - }, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"dh" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 4; - initialize_directions = 11; - level = 1 - }, -/turf/space, -/area/turret_protected/tcomsat) -"di" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"dj" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/space, -/area/turret_protected/tcomsat) -"dk" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/space, -/area/turret_protected/tcomsat) -"dl" = ( -/obj/structure/window/reinforced, -/turf/space, -/area/turret_protected/tcomsat) -"dm" = ( -/obj/structure/sign/securearea, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 - }, -/turf/simulated/wall/r_wall, -/area/tcommsat/computer) -"dn" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/computer/telecomms/traffic, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"do" = ( -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 8; - on = 1 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dp" = ( -/obj/structure/chair/office/dark{ - dir = 4 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dq" = ( -/obj/machinery/computer/telecomms/server{ - network = list("tcommsat") - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"ds" = ( -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 4; - layer = 2.4; - on = 1 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dt" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 10 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"du" = ( -/obj/structure/chair{ - dir = 4 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dv" = ( -/obj/structure/table, -/obj/item/storage/fancy/cigarettes, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dw" = ( -/obj/structure/chair{ - dir = 8 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dx" = ( -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"dy" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - level = 1 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"dz" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/structure/window/reinforced, -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"dA" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"dB" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9; - level = 1 - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/obj/machinery/door/airlock/hatch{ - name = "Telecoms Control Room"; - req_access_txt = "61" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dC" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dD" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dE" = ( -/obj/machinery/power/apc{ - dir = 4; - name = "Telecoms Sat. Control APC"; - pixel_x = 25 - }, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dF" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/structure/table, -/obj/item/multitool, -/obj/structure/sign/electricshock{ - pixel_x = -32 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dG" = ( -/obj/effect/spawner/window/reinforced, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/turf/simulated/floor/plating, -/area/tcommsat/chamber) -"dH" = ( -/turf/simulated/wall/r_wall, -/area/tcommsat/chamber) -"dI" = ( -/obj/machinery/vending/snack, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dJ" = ( -/obj/machinery/vending/cola, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dK" = ( -/obj/item/cigbutt, -/obj/machinery/light, -/obj/machinery/light_switch{ - pixel_y = -28 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dL" = ( -/obj/structure/chair{ - dir = 1 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dM" = ( -/obj/machinery/disposal, -/obj/structure/disposalpipe/trunk{ - dir = 4 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dN" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/simulated/wall/r_wall, -/area/tcommsat/computer) -"dO" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/simulated/wall/r_wall, -/area/space/nearstation) -"dP" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/grille, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"dQ" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"dR" = ( -/obj/structure/disposaloutlet{ - dir = 4 - }, -/obj/structure/disposalpipe/trunk{ - dir = 8 - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"dS" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - level = 1 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"dT" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/space, -/area/turret_protected/tcomsat) -"dU" = ( -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/structure/lattice, -/obj/machinery/light, -/turf/space, -/area/turret_protected/tcomsat) -"dV" = ( -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/space, -/area/turret_protected/tcomsat) -"dW" = ( -/obj/effect/spawner/window/reinforced, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plating, -/area/tcommsat/chamber) -"dX" = ( -/obj/machinery/power/solar, -/obj/structure/cable{ - icon_state = "0-2"; - pixel_y = 1; - d2 = 2 - }, -/turf/simulated/floor/plasteel/airless{ - icon_state = "solarpanel" - }, -/area/space/nearstation) -"dY" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/computer) -"dZ" = ( -/obj/machinery/power/solar, -/obj/structure/cable, -/turf/simulated/floor/plasteel/airless{ - icon_state = "solarpanel" - }, -/area/space/nearstation) -"ea" = ( -/obj/machinery/door/window/brigdoor{ - dir = 8; - name = "Telecomms Server Access"; - req_access = null; - req_access_txt = "61" - }, -/obj/machinery/door/window/brigdoor{ - dir = 4; - name = "Telecomms Server Access"; - req_access_txt = "61" - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/tcommsat/chamber) -"eb" = ( -/obj/machinery/light/small{ - dir = 1 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/tcommsat/chamber) -"ec" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/wall/r_wall, -/area/tcommsat/computer) -"ed" = ( -/obj/machinery/door/airlock/hatch{ - name = "Telecoms Lounge"; - req_access_txt = "61" - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/tcommsat/computer) -"ee" = ( -/obj/machinery/porta_turret/stationary, -/turf/simulated/floor/plating/airless, -/area/turret_protected/tcomsat) -"ef" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"eg" = ( -/obj/machinery/telecomms/relay/preset/station, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"eh" = ( -/obj/effect/spawner/window/reinforced, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plating, -/area/tcommsat/chamber) -"ei" = ( -/obj/effect/spawner/window/reinforced, -/obj/structure/cable{ - icon_state = "0-2"; - pixel_y = 1; - d2 = 2 - }, -/obj/structure/cable, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plating, -/area/tcommsat/chamber) -"el" = ( -/obj/machinery/door/window/brigdoor{ - dir = 1; - name = "Telecomms Server Access"; - req_access_txt = "61" - }, -/obj/machinery/door/window/brigdoor{ - dir = 2; - name = "Telecomms Server Access"; - req_access_txt = "61" - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/tcommsat/chamber) -"em" = ( -/obj/structure/sign/securearea{ - desc = "A warning sign which reads 'SERVER ROOM'."; - name = "SERVER ROOM"; - pixel_y = 0 - }, -/turf/simulated/wall/r_wall, -/area/tcommsat/chamber) -"en" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"eo" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"ep" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"er" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 5; - level = 1 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"es" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 10 - }, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"et" = ( -/obj/item/radio/intercom{ - pixel_y = 25 - }, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"eu" = ( -/obj/machinery/status_display{ - pixel_x = 0; - pixel_y = 32 - }, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"ev" = ( -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"ew" = ( -/obj/machinery/power/apc{ - cell_type = 5000; - dir = 1; - name = "Telecoms Sat. Central Compartment APC"; - pixel_x = -1; - pixel_y = 26 - }, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"ey" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"ez" = ( -/obj/machinery/camera{ - c_tag = "Telecomms Server Room North"; - dir = 2; - network = list("Telecomms") - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/machinery/light{ - dir = 1 - }, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"eB" = ( -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"eC" = ( -/obj/machinery/light_switch{ - pixel_y = 28 - }, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"eD" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"eE" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"eF" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"eG" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 4; - layer = 2.4; - on = 1 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"eH" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 4; - initialize_directions = 11; - level = 1 - }, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"eJ" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"eK" = ( -/obj/effect/spawner/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"eL" = ( -/obj/effect/spawner/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"eM" = ( -/obj/effect/spawner/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 10 - }, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"eN" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"eO" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"eP" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"eR" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 6 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"eS" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9; - level = 1 - }, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"eT" = ( -/obj/machinery/telecomms/server/presets/supply, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (NORTH)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"eU" = ( -/obj/machinery/telecomms/server/presets/service, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"eV" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"eW" = ( -/obj/machinery/telecomms/server/presets/common, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"eX" = ( -/obj/machinery/telecomms/server/presets/engineering, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"eY" = ( -/obj/effect/spawner/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"eZ" = ( -/obj/structure/table, -/obj/item/stock_parts/micro_laser, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/manipulator, -/obj/item/stock_parts/capacitor, -/obj/item/stock_parts/micro_laser/high, -/obj/item/stock_parts/micro_laser/high, -/obj/item/stock_parts/micro_laser/high, -/obj/item/stock_parts/micro_laser/high, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fa" = ( -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 1; - external_pressure_bound = 101.325; - on = 1; - pressure_checks = 1 - }, -/obj/machinery/camera{ - c_tag = "Telecomms Storage"; - network = list("Telecomms") - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fb" = ( -/obj/structure/rack, -/obj/item/circuitboard/telecomms/processor, -/obj/item/circuitboard/telecomms/processor, -/obj/item/circuitboard/telecomms/receiver, -/obj/item/circuitboard/telecomms/server, -/obj/item/circuitboard/telecomms/server, -/obj/item/circuitboard/telecomms/bus, -/obj/item/circuitboard/telecomms/bus, -/obj/item/circuitboard/telecomms/broadcaster, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fc" = ( -/obj/machinery/camera{ - c_tag = "Telecomms West Solars"; - dir = 8; - network = list("Telecomms") - }, -/turf/space, -/area/space/nearstation) -"fd" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - req_access_txt = "0" - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"fe" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Telecomms West Wing Central"; - dir = 8; - network = list("Telecomms") - }, -/turf/space, -/area/turret_protected/tcomsat) -"ff" = ( -/obj/machinery/telecomms/broadcaster/preset_left, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (NORTH)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fg" = ( -/obj/machinery/telecomms/broadcaster/preset_right, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fh" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 8; - initialize_directions = 11; - level = 1 - }, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"fi" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 8; - on = 1 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"fj" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/space, -/area/turret_protected/tcomsat) -"fk" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/treatment, -/obj/item/stock_parts/subspace/treatment, -/obj/item/stock_parts/subspace/treatment, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fl" = ( -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fm" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/analyzer, -/obj/item/stock_parts/subspace/analyzer, -/obj/item/stock_parts/subspace/analyzer, -/obj/machinery/status_display{ - pixel_x = 32; - pixel_y = 0 - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fn" = ( -/obj/machinery/camera{ - c_tag = "Telecomms East Solars"; - dir = 4; - network = list("Telecomms") - }, -/turf/space, -/area/space/nearstation) -"fo" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"fq" = ( -/obj/structure/grille, -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"fr" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - level = 1 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"fs" = ( -/obj/structure/lattice, -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/light{ - dir = 4 - }, -/turf/space, -/area/turret_protected/tcomsat) -"ft" = ( -/obj/structure/sign/nosmoking_2{ - pixel_x = -32; - pixel_y = 0 - }, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"fu" = ( -/obj/machinery/telecomms/processor/preset_two, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (NORTH)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fv" = ( -/obj/machinery/telecomms/bus/preset_two, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (NORTH)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fw" = ( -/obj/machinery/telecomms/relay/preset/telecomms, -/turf/simulated/floor/bluegrid{ - icon_state = "dark"; - name = "Mainframe Floor"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"fx" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/machinery/telecomms/hub/preset, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"fz" = ( -/obj/machinery/telecomms/processor/preset_four, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fA" = ( -/obj/machinery/telecomms/bus/preset_four, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fB" = ( -/obj/structure/sign/nosmoking_2{ - pixel_x = 32; - pixel_y = 0 - }, -/obj/machinery/light{ - dir = 4 - }, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"fC" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 5 - }, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"fD" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 1; - level = 1 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"fE" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"fF" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9 - }, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Telecoms Storage"; - req_access_txt = "61" - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"fG" = ( -/obj/machinery/hologram/holopad, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fH" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/amplifier, -/obj/item/stock_parts/subspace/amplifier, -/obj/item/stock_parts/subspace/amplifier, -/obj/machinery/light/small{ - dir = 4 - }, -/obj/item/radio/intercom{ - name = "station intercom (General)"; - pixel_x = 29; - pixel_y = 0 - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fI" = ( -/obj/structure/grille, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"fJ" = ( -/obj/machinery/telecomms/bus/preset_one, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (NORTH)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fK" = ( -/obj/machinery/telecomms/processor/preset_one, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (NORTH)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fL" = ( -/obj/machinery/telecomms/receiver/preset_left, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (NORTH)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fM" = ( -/obj/machinery/telecomms/receiver/preset_right, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fN" = ( -/obj/machinery/telecomms/bus/preset_three, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fO" = ( -/obj/machinery/telecomms/processor/preset_three, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fP" = ( -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/space, -/area/turret_protected/tcomsat) -"fQ" = ( -/obj/effect/spawner/window/reinforced, -/turf/simulated/floor/plating, -/area/turret_protected/tcomsat) -"fR" = ( -/obj/item/storage/toolbox/mechanical, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fS" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/ansible, -/obj/item/stock_parts/subspace/ansible, -/obj/item/stock_parts/subspace/ansible, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fT" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/transmitter, -/obj/item/stock_parts/subspace/transmitter, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fU" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/subspace/filter, -/obj/item/stock_parts/subspace/filter, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fV" = ( -/obj/structure/table, -/obj/item/stock_parts/subspace/crystal, -/obj/item/stock_parts/subspace/crystal, -/obj/item/stock_parts/subspace/crystal, -/obj/machinery/light_switch{ - pixel_y = -28 - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomsat) -"fW" = ( -/obj/machinery/telecomms/server/presets/science, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (NORTH)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"fX" = ( -/obj/machinery/telecomms/server/presets/medical, -/turf/simulated/floor/plasteel{ - dir = 1; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (NORTH)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"ga" = ( -/obj/machinery/telecomms/server/presets/command, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"gb" = ( -/obj/machinery/telecomms/server/presets/security, -/turf/simulated/floor/plasteel{ - dir = 4; - icon_state = "vault"; - name = "Mainframe floor"; - nitrogen = 100; - oxygen = 0; - tag = "icon-vault (EAST)"; - temperature = 80 - }, -/area/tcommsat/chamber) -"gd" = ( -/obj/machinery/camera{ - c_tag = "Telecomms Server Room South"; - dir = 1; - network = list("Telecomms") - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/machinery/light, -/obj/machinery/hologram/holopad, -/turf/simulated/floor/bluegrid{ - name = "Mainframe Base"; - nitrogen = 100; - oxygen = 0; - temperature = 80 - }, -/area/tcommsat/chamber) -"gf" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/turf/simulated/wall/r_wall, -/area/tcommsat/chamber) -"gg" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - req_access_txt = "0" - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"gh" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced, -/turf/space, -/area/turret_protected/tcomsat) -"gi" = ( -/obj/structure/window/reinforced, -/obj/structure/lattice, -/obj/machinery/light{ - dir = 1 - }, -/turf/space, -/area/turret_protected/tcomsat) -"gj" = ( -/turf/simulated/wall/r_wall, -/area/turret_protected/tcomfoyer) -"gr" = ( -/obj/structure/window/reinforced, -/obj/machinery/light{ - dir = 1 - }, -/turf/space, -/area/turret_protected/tcomsat) -"gs" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/window/reinforced, -/turf/space, -/area/turret_protected/tcomsat) -"gt" = ( -/obj/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 5 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"gu" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"gv" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/door/airlock/hatch{ - name = "Telecoms West Wing"; - req_access_txt = "61" - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomfoyer) -"gx" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"gy" = ( -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 4; - initialize_directions = 11; - level = 1 - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"gz" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/machinery/hologram/holopad, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"gA" = ( -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 1; - external_pressure_bound = 101.325; - on = 1; - pressure_checks = 1 - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"gB" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 5 - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"gD" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/obj/machinery/door/airlock/hatch{ - name = "Telecoms East Wing"; - req_access_txt = "61" - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomfoyer) -"gE" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9 - }, -/turf/simulated/floor/plasteel{ - tag = "icon-vault (NORTHEAST)"; - icon_state = "vault"; - dir = 5 - }, -/area/turret_protected/tcomsat) -"gF" = ( -/obj/machinery/camera{ - c_tag = "Telecomms East Wing South"; - dir = 8; - network = list("Telecomms") - }, -/turf/space, -/area/turret_protected/tcomsat) -"gG" = ( -/obj/machinery/camera{ - c_tag = "Telecomms West Wing South"; - dir = 4; - network = list("Telecomms") - }, -/turf/space, -/area/turret_protected/tcomsat) -"gH" = ( -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/structure/lattice, -/turf/space, -/area/turret_protected/tcomsat) -"gK" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - req_access_txt = "0" - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"gL" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"gM" = ( -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"gP" = ( -/turf/simulated/wall/r_wall, -/area/tcommsat/entrance) -"gQ" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - req_access_txt = "0" - }, -/turf/simulated/wall/r_wall, -/area/turret_protected/tcomfoyer) -"gR" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/machinery/door/airlock/hatch{ - name = "Telecoms Satellite"; - req_access_txt = "61" - }, -/turf/simulated/floor/plasteel, -/area/turret_protected/tcomfoyer) -"gS" = ( -/obj/effect/spawner/window/reinforced, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/turf/simulated/floor/plating, -/area/tcommsat/entrance) -"gT" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"gU" = ( -/obj/machinery/status_display{ - pixel_x = 0; - pixel_y = 32 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"gV" = ( -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 8; - initialize_directions = 11; - level = 1 - }, -/obj/item/radio/intercom{ - pixel_y = 25 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"gW" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"gX" = ( -/obj/machinery/turretid/stun{ - ailock = 1; - check_synth = 1; - control_area = "\improper Telecoms Foyer"; - desc = "A firewall prevents AI's from interacting with this device."; - name = "Telecoms Foyer Turret Control"; - pixel_y = 30; - req_access = list(61) - }, -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 8; - on = 1 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"gY" = ( -/obj/structure/sign/electricshock, -/turf/simulated/wall/r_wall, -/area/tcommsat/entrance) -"gZ" = ( -/obj/machinery/hologram/holopad, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"ha" = ( -/obj/structure/cable{ - icon_state = "0-2"; - pixel_y = 1; - d2 = 2 - }, -/obj/machinery/computer/monitor{ - name = "Telecoms Power Monitoring" - }, -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/turf/simulated/floor/plasteel{ - icon_state = "bot" - }, -/area/tcommsat/entrance) -"hb" = ( -/obj/effect/spawner/window/reinforced, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plating, -/area/tcommsat/entrance) -"hc" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hd" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"he" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/obj/machinery/camera{ - c_tag = "Telecomms Power Room West"; - dir = 1; - network = list("Telecomms") - }, -/obj/machinery/light/small{ - dir = 1 - }, -/obj/machinery/light_switch{ - pixel_y = -28 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hf" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - req_access_txt = "0" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hg" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4"; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hh" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/obj/machinery/camera{ - c_tag = "Telecomms Power Room East"; - dir = 1; - network = list("Telecomms") - }, -/obj/machinery/light/small{ - dir = 1 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hi" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hj" = ( -/obj/structure/sign/securearea, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - req_access_txt = "0" - }, -/turf/simulated/wall/r_wall, -/area/tcommsat/entrance) -"hk" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/obj/machinery/door/airlock/hatch{ - name = "Telecoms Satellite"; - req_access_txt = "61" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hl" = ( -/obj/structure/sign/securearea, -/turf/simulated/wall/r_wall, -/area/tcommsat/entrance) -"hm" = ( -/turf/simulated/wall/r_wall, -/area/tcommsat/powercontrol) -"hq" = ( -/obj/machinery/atmospherics/unary/vent_pump/high_volume{ - dir = 4; - frequency = 1381; - id_tag = "telecoms_pump" - }, -/obj/machinery/light/small{ - dir = 8 - }, -/obj/structure/sign/vacuum{ - pixel_x = 0; - pixel_y = 32 - }, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4"; - tag = "" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hr" = ( -/obj/machinery/camera/xray{ - c_tag = "Telecomms Airlock"; - network = list("Telecomms") - }, -/obj/machinery/atmospherics/pipe/manifold/visible{ - dir = 1 - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hs" = ( -/obj/machinery/door/airlock/external{ - frequency = 1381; - icon_state = "door_locked"; - id_tag = "telecoms_inner"; - locked = 1; - name = "External Access"; - req_access = null; - req_access_txt = "13" - }, -/obj/machinery/atmospherics/pipe/simple/visible{ - dir = 4 - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hu" = ( -/obj/machinery/atmospherics/pipe/simple/visible{ - dir = 4 - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hv" = ( -/obj/machinery/atmospherics/pipe/simple/visible{ - dir = 4 - }, -/obj/machinery/status_display{ - pixel_x = 0; - pixel_y = 32 - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hx" = ( -/obj/machinery/atmospherics/unary/portables_connector{ - dir = 8 - }, -/obj/machinery/portable_atmospherics/canister/air, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hz" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2"; - tag = "" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hB" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/structure/grille, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"hC" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hD" = ( -/obj/machinery/embedded_controller/radio/airlock/airlock_controller{ - tag_airpump = "telecoms_pump"; - tag_exterior_door = "telecoms_outer"; - frequency = 1381; - id_tag = "telecoms_airlock"; - tag_interior_door = "telecoms_inner"; - pixel_x = 0; - pixel_y = -25; - req_access_txt = "13"; - tag_chamber_sensor = "telecoms_sensor" - }, -/obj/machinery/airlock_sensor{ - frequency = 1381; - id_tag = "telecoms_sensor"; - pixel_x = 12; - pixel_y = -25 - }, -/obj/machinery/atmospherics/unary/vent_pump/high_volume{ - dir = 1; - frequency = 1381; - id_tag = "telecoms_pump" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hE" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hF" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hG" = ( -/obj/machinery/power/solar_control/autostart{ - name = "Telecoms Solar Control" - }, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hH" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 4; - layer = 2.4; - on = 1 - }, -/obj/machinery/status_display{ - pixel_x = 0; - pixel_y = 32 - }, -/obj/structure/table, -/obj/machinery/recharger, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hI" = ( -/obj/machinery/atmospherics/pipe/manifold/hidden/supply{ - dir = 4; - initialize_directions = 11; - level = 1 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hJ" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hK" = ( -/obj/machinery/power/apc{ - dir = 1; - name = "Telecoms Sat. Teleporter APC"; - pixel_x = 1; - pixel_y = 26 - }, -/obj/structure/cable{ - d2 = 8; - icon_state = "0-8" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hL" = ( -/obj/machinery/door/airlock/external{ - frequency = 1381; - icon_state = "door_locked"; - id_tag = "telecoms_outer"; - locked = 1; - name = "External Access"; - req_access = null; - req_access_txt = "10;13" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hM" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/structure/closet/crate, -/obj/item/stack/sheet/glass{ - amount = 50 - }, -/obj/item/stack/cable_coil/random, -/obj/item/stack/cable_coil/random, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hN" = ( -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hO" = ( -/obj/machinery/hologram/holopad, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hP" = ( -/obj/structure/cable{ - d2 = 2; - icon_state = "0-2" - }, -/obj/machinery/power/apc{ - dir = 4; - name = "Telecoms Sat. Power Control APC"; - pixel_x = 25 - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"hR" = ( -/obj/item/stock_parts/cell, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hS" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hT" = ( -/obj/machinery/hologram/holopad, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hU" = ( -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hV" = ( -/obj/structure/closet/malf/suits, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"hW" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/obj/machinery/light{ - dir = 1 - }, -/turf/simulated/floor/plating/airless, -/area/tcommsat/powercontrol) -"hY" = ( -/obj/machinery/light{ - dir = 1 - }, -/turf/simulated/floor/plating/airless, -/area/tcommsat/powercontrol) -"hZ" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/unary/vent_pump{ - dir = 4; - layer = 2.4; - on = 1 - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"ia" = ( -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4; - level = 1 - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"ib" = ( -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4; - level = 1 - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"ic" = ( -/obj/machinery/door/airlock/hatch{ - name = "Telecoms Power Control"; - req_access_txt = "61" - }, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4; - level = 1 - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"ie" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 4; - level = 1 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"if" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/hidden/supply{ - dir = 9 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"ig" = ( -/obj/machinery/bluespace_beacon, -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8" - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"ih" = ( -/obj/item/radio/intercom{ - name = "station intercom (General)"; - pixel_x = 29; - pixel_y = 0 - }, -/turf/simulated/floor/plasteel, -/area/tcommsat/entrance) -"ii" = ( -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"ij" = ( -/obj/structure/cable, -/obj/machinery/power/terminal{ - dir = 4 - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"ik" = ( -/obj/machinery/power/smes{ - charge = 2.5e+006; - input_attempt = 1; - input_level = 250000; - inputting = 1; - output_level = 250000 - }, -/obj/structure/cable{ - d2 = 4; - icon_state = "0-4" - }, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"il" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8" - }, -/obj/structure/table, -/obj/machinery/cell_charger, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"im" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8" - }, -/obj/machinery/light_switch{ - pixel_y = -28 - }, -/obj/structure/closet/emcloset, -/turf/simulated/floor/plating, -/area/tcommsat/powercontrol) -"in" = ( -/obj/structure/sign/electricshock, -/turf/simulated/wall/r_wall, -/area/tcommsat/powercontrol) -"it" = ( -/obj/structure/cable{ - icon_state = "0-4"; - d2 = 4 - }, -/obj/machinery/power/tracker, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"iu" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"iv" = ( -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/obj/structure/grille, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"iw" = ( -/obj/machinery/computer/teleporter, -/turf/simulated/floor/plating, -/area/tcommsat/entrance) -"ix" = ( -/obj/machinery/teleport/station, -/turf/simulated/floor/plating, -/area/tcommsat/entrance) -"iy" = ( -/obj/machinery/teleport/hub, -/turf/simulated/floor/plating, -/area/tcommsat/entrance) -"iz" = ( -/obj/structure/lattice, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/obj/structure/grille, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"iA" = ( -/obj/structure/grille, -/obj/structure/cable{ - d1 = 4; - d2 = 8; - icon_state = "4-8"; - pixel_x = 0; - tag = "" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 4; - icon_state = "2-4" - }, -/obj/structure/cable{ - d1 = 2; - d2 = 8; - icon_state = "2-8"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"iB" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"iC" = ( -/obj/structure/cable{ - d1 = 1; - d2 = 8; - icon_state = "1-8"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 4; - icon_state = "1-4"; - tag = "" - }, -/obj/structure/cable{ - d1 = 1; - d2 = 2; - icon_state = "1-2" - }, -/turf/simulated/floor/plating/airless, -/area/space/nearstation) -"iD" = ( -/obj/machinery/camera{ - c_tag = "Telecomms South Solars"; - dir = 4; - network = list("Telecomms") - }, -/turf/space, -/area/space/nearstation) -"iF" = ( -/turf/simulated/wall/r_wall, -/area/AIsattele) -"iG" = ( -/obj/structure/computerframe, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iH" = ( -/obj/machinery/teleport/station, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iI" = ( -/obj/machinery/teleport/hub, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iJ" = ( -/obj/item/shard{ - icon_state = "medium" - }, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iK" = ( -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iL" = ( -/obj/structure/rack, -/obj/item/clothing/gloves/color/yellow, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iM" = ( -/obj/effect/spawner/window/reinforced, -/turf/simulated/floor/plating, -/area/AIsattele) -"iN" = ( -/obj/item/stock_parts/cell, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iO" = ( -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iP" = ( -/obj/effect/decal/cleanable/blood/gibs/robot, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iQ" = ( -/obj/machinery/door/airlock/external, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iR" = ( -/obj/item/flashlight, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iS" = ( -/obj/item/radio/beacon, -/obj/effect/decal/cleanable/dirt, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iT" = ( -/obj/machinery/portable_atmospherics/canister/air, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iU" = ( -/obj/effect/decal/cleanable/blood/oil, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iV" = ( -/obj/item/shard, -/obj/item/apc_electronics, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iW" = ( -/obj/structure/closet, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iX" = ( -/obj/item/storage/toolbox/electrical{ - pixel_x = 1; - pixel_y = -1 - }, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iY" = ( -/obj/structure/closet/crate, -/obj/item/aicard, -/obj/item/multitool, -/obj/item/weldingtool, -/obj/item/wrench, -/obj/item/circuitboard/teleporter, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"iZ" = ( -/obj/structure/reagent_dispensers/fueltank, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"ja" = ( -/obj/structure/lattice, -/turf/space, -/area/AIsattele) -"jb" = ( -/obj/structure/girder, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"we" = ( -/obj/machinery/atmospherics/unary/portables_connector{ - dir = 1 - }, -/turf/simulated/floor/plating/airless, -/area/AIsattele) -"LU" = ( -/obj/machinery/atmospherics/unary/tank/oxygen_agent_b, -/turf/simulated/floor/plating/airless, -/area/AIsattele) - -(1,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(2,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(3,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(4,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(5,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(6,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(7,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(8,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(9,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(10,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(11,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(12,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(13,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(14,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(15,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(16,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(17,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(18,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(19,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(20,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(21,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(22,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(23,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(24,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(25,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(26,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(27,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(28,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(29,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(30,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(31,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(32,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(33,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(34,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(35,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(36,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(37,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(38,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(39,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(40,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(41,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(42,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(43,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(44,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(45,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(46,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(47,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(48,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(49,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(50,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(51,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(52,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(53,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(54,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(55,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(56,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(57,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(58,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(59,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(60,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(61,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(62,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(63,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(64,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ac -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(65,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -aT -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(66,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -aa -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(67,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -aa -aT -aT -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(68,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ba -bi -bp -bi -bx -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(69,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bb -bj -bk -bs -by -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(70,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bc -bk -bk -bk -bc -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(71,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bc -bk -bk -bk -bc -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(72,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bc -bk -bk -bk -bc -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(73,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bc -bk -bk -bk -bc -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(74,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bc -bk -bk -bk -bc -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(75,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bc -bk -bk -bk -bc -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(76,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bc -bk -bk -bk -bc -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(77,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bb -bl -bk -bu -by -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(78,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bd -bm -bp -bm -bz -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(79,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(80,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(81,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(82,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(83,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(84,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(85,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(86,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(87,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(88,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(89,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(90,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(91,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(92,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aT -aa -aa -aa -aa -aa -aa -aa -aT -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(93,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eD -dZ -aa -aa -aa -dX -eD -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(94,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(95,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(96,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(97,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(98,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aT -aT -aT -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(99,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(100,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cb -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(101,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(102,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(103,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aT -aT -aT -dX -eE -dZ -aa -cb -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(104,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(105,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(106,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(107,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(108,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eE -dZ -aa -aa -aa -dX -eE -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(109,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aa -eF -ch -ch -fo -ch -ch -cg -aa -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(110,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aT -aa -aa -aa -fc -ce -aa -aa -aa -aa -bW -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(111,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ci -cr -cr -cr -cr -cr -cr -cr -cr -cr -cr -cr -fq -cr -cr -cr -cr -cr -cr -cr -cr -cr -cr -cr -co -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(112,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ci -cm -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cn -cl -co -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(113,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ci -cm -cn -cn -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cp -cn -cn -cl -cr -hB -hB -cd -ii -ii -it -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(114,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cn -cp -cs -ct -ct -ct -ct -cs -ct -ct -ct -ct -cs -ct -ct -ct -ct -cs -ct -ct -gG -ct -cs -cp -cn -hm -hm -hm -hm -hW -ii -ii -ce -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(115,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cp -cs -cs -cs -cs -cs -cs -ee -cs -cs -cs -cs -cs -cs -cs -cs -cs -ee -cs -cs -cs -cs -cs -cs -cp -hm -hq -hC -hL -af -ch -ch -iu -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ad -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(116,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cp -ct -cs -ct -ct -ct -ct -cs -ct -ct -ct -ct -cs -ct -ct -ct -ct -cs -ct -ct -ct -ct -cs -ct -cp -hm -hr -hD -hm -hY -ii -ii -ce -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(117,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cp -cu -cH -cV -ct -cV -cV -ef -cV -cV -cV -cV -ef -cV -cV -cV -cV -ef -cV -cV -ct -ct -cs -ct -cp -hm -hs -hm -hm -hm -hm -hm -iv -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(118,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cp -cv -cI -cW -dg -dx -dS -dS -er -eG -eR -fd -fr -fr -fd -dS -dS -fd -gg -gt -dV -ct -cs -ct -cp -hm -ae -hE -hM -hZ -ij -hm -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(119,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cp -cw -cJ -cX -dh -dy -dT -cN -es -eH -eS -fe -fs -da -da -da -da -cN -gh -gu -dV -ct -cs -ct -cp -hm -hu -hF -hN -ia -ik -hm -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(120,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cp -cx -cK -cK -di -dz -dU -dH -dH -dH -dH -dH -dH -dH -dH -dH -dH -dH -gi -gu -gH -cs -cs -ct -cp -hm -hv -hF -hO -ia -hF -hm -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(121,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -cb -bW -bW -bW -bW -cj -cn -cp -cy -cL -cY -dj -dA -dV -dH -et -ev -ev -ev -ft -ev -ev -ev -ev -dH -dl -gu -dV -ct -cs -cp -cp -hm -aH -hF -hN -ia -il -hm -cj -bW -bW -bW -bW -bW -bW -bW -bW -bW -cb -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(122,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -aa -cj -cn -cp -cz -cM -cZ -dk -dA -dV -dH -eu -eB -eT -eB -fu -fJ -eB -fW -ev -dH -dl -gu -dV -gP -gS -gP -gP -hm -hx -hG -hP -ib -im -hm -cj -bW -bW -aa -aa -aa -aa -aa -iD -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(123,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -aT -aa -cj -cn -cp -cp -cN -da -dl -dA -dV -dH -ev -eB -eU -eB -fv -fK -eB -fX -ev -dH -gj -gv -gj -gj -gT -hc -gP -hm -hm -hm -hm -ic -in -hm -cl -co -aa -aa -aT -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(124,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aT -bY -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -cd -aT -cj -cn -cn -cq -cq -cq -dm -dB -cq -dH -ew -eB -eB -eB -fw -eB -eB -eB -ev -dH -aj -ap -as -gj -gU -hd -gP -gP -gP -gP -aA -aB -aD -gP -gP -cl -co -aT -eN -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iu -aT -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(125,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -ce -aa -cj -cn -cn -cq -cG -db -dn -dC -dF -dG -ey -eB -eB -eB -ev -eB -eB -eB -ev -dH -ai -gx -ar -gj -gP -he -gP -gP -gP -hH -hR -ie -aC -aE -gP -gP -iz -aa -ce -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(126,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aa -aa -aa -aa -aa -aT -aa -aa -aa -aa -aT -aa -aa -aa -aa -aa -ce -aa -cj -cn -cn -cq -cO -cG -do -dC -cG -eh -ey -eB -eB -ff -ev -fL -eB -eB -ev -dH -al -gy -gK -gQ -gV -hf -hj -aw -ay -hI -hS -if -hU -aF -iw -gP -cj -aa -ce -aa -aa -aa -aa -aa -aT -aa -aa -aa -aa -aT -aa -aa -aa -aa -aa -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(127,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aa -aa -aa -aa -aa -aT -aa -aa -aa -aa -aT -aa -aa -aa -aa -aa -cf -ch -ck -cn -cn -cq -cP -dc -df -dD -dY -ei -ez -eJ -eV -eV -fx -eV -eV -ah -gd -gf -ak -gz -gL -gR -gW -hg -hk -av -hz -hJ -hT -ig -hU -aF -ix -gP -iA -ch -iB -aa -aa -aa -aa -aa -aT -aa -aa -aa -aa -aT -aa -aa -aa -aa -aa -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(128,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aa -aa -aa -aa -aa -aT -aa -aa -aa -aa -aT -aa -aa -aa -aa -aa -ce -aa -cj -cn -cn -cq -cQ -cG -cG -dC -cG -eh -ev -eB -eB -fg -ev -fM -eB -eB -ev -dH -an -gA -gM -gj -gX -hd -hl -ax -az -hd -hU -hU -hU -aF -iy -gP -cj -aa -ce -aa -aa -aa -aa -aa -aT -aa -aa -aa -aa -aT -aa -aa -aa -aa -aa -aa -cb -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(129,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -ce -aa -cj -cn -cn -cq -cR -cG -dp -dE -cG -dW -ev -eB -eB -eB -ev -eB -eB -eB -ev -dH -am -gB -at -gj -gY -hh -gP -gP -gP -hK -hU -hU -hU -aG -gP -gP -cj -aa -ce -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -bX -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(130,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aT -bY -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -ca -cg -aT -cj -cn -cn -cq -cS -dd -dq -dH -ea -em -ev -eB -eB -eB -eg -eB -eB -eB -ev -dH -ao -aq -au -gj -gZ -hd -gP -cn -gP -gP -hV -ih -hV -gP -gP -ci -cm -aT -eF -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iC -iu -aT -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(131,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -aT -aa -cj -cn -cn -cq -cq -cq -cq -dH -eb -el -eB -eB -eW -eB -fz -fN -eB -ga -ev -dH -gj -gD -gj -gj -ha -hi -gP -cn -bW -gP -gP -gP -gP -gP -ci -cm -aa -aa -aT -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -bZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(132,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cc -aa -aT -aa -cj -cn -cn -cA -cT -cT -ag -dH -dH -em -ev -eB -eX -eB -fA -fO -eB -gb -ev -dH -dl -gu -dV -gP -hb -gP -gP -cn -ci -cr -cr -cr -cr -cr -cm -bW -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(133,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -bW -bW -bW -bW -bW -bW -bW -cb -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -cj -cn -cq -cq -cq -cq -cq -cq -cq -dH -eC -ev -ev -ev -fB -ev -ev -ev -ev -dH -dl -fE -dV -ct -cs -cp -cp -cn -cj -bW -aT -aT -bW -bW -bW -bW -bW -aT -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -cb -bW -bW -bW -bW -bW -bW -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(134,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cq -cB -cU -de -ds -dI -cq -dH -dH -dH -dH -dH -dH -dH -dH -dH -dH -dH -gr -gu -dV -ct -cs -ct -cp -cn -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(135,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cq -cC -cG -cG -dt -dJ -ec -en -en -en -en -fh -fC -cV -cV -cV -cV -ef -gs -gu -dV -ct -cs -ct -cp -cn -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(136,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cq -cD -cG -df -cG -cG -ed -eo -eo -eo -eo -fi -fD -fd -fd -fd -fd -fd -fd -gE -dV -ct -cs -ct -cp -cn -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(137,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cq -cE -cG -cG -du -dK -cq -ep -da -da -da -fj -fE -fP -da -da -da -cN -da -da -ct -ct -cs -ct -cp -cn -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(138,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cq -cF -cG -cG -dv -dL -cq -cs -ct -eK -eY -eY -fF -fQ -fQ -fQ -ct -cs -ct -ct -ct -ct -cs -ct -cp -cn -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(139,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cq -cG -cG -cG -dw -dM -cq -ee -cs -eL -eZ -fk -fl -fl -fT -fQ -cs -ee -cs -cs -cs -cs -cs -cs -cp -cn -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(140,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cj -cn -cq -cq -cq -cq -cq -dN -cq -cs -ct -eM -fa -fl -fG -fR -fU -fQ -ct -cs -ct -gF -ct -ct -cs -cp -cn -cn -cj -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(141,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cl -co -cn -cn -cn -cn -cn -dO -cn -cp -cp -cp -fb -fm -fH -fS -fV -cp -cp -cp -cp -cp -cp -cp -cp -cn -cn -ci -cm -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(142,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cl -co -cn -cn -cn -cn -dO -cn -cn -cn -cn -cp -cp -cp -cp -cp -cn -cn -cn -cn -cn -cn -cn -cn -cn -ci -cm -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(143,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cl -cr -cr -cr -cr -dP -cr -cr -co -cn -cn -cn -cn -cn -cn -cn -ci -cr -cr -cr -cr -cr -cr -cr -cm -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(144,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -dQ -bW -bW -cl -cr -cr -cr -fI -cr -cr -cr -cm -bW -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(145,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -dR -bW -bW -aa -aT -aa -fn -ce -aa -aa -aT -aa -bW -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(146,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aT -eN -ch -ch -eP -ch -ch -cd -aT -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(147,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(148,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(149,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(150,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -cb -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(151,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(152,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aT -aT -aT -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(153,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(154,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(155,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(156,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(157,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aT -aT -aT -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(158,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(159,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(160,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -cb -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(161,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eO -dZ -aa -aa -aa -dX -eO -dZ -aa -cb -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(162,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -dX -eP -dZ -aa -aa -aa -dX -eP -dZ -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(163,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -aa -aa -aT -aa -aa -aa -aa -aa -aT -aa -aa -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(164,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -bW -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(165,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(166,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(167,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(168,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(169,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(170,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(171,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(172,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(173,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(174,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(175,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(176,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(177,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(178,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(179,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(180,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(181,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(182,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(183,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(184,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(185,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(186,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(187,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(188,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(189,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(190,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(191,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(192,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(193,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(194,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(195,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(196,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(197,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(198,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(199,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(200,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(201,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(202,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -aa -aT -aa -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(203,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -iM -iQ -iM -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(204,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -aT -iM -iK -iM -aT -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(205,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -iF -iF -iQ -iF -iF -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(206,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -iF -iF -iK -iK -iT -iF -iF -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(207,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -iF -iF -iJ -iN -iR -iK -iK -iF -iF -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(208,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -iF -iG -iK -iO -iP -iK -iK -iY -iF -aT -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(209,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -iF -iH -iK -iK -iS -iU -iO -iK -ja -aT -aa -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(210,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -iF -iI -iK -iP -iK -iK -iK -iZ -iK -aa -aa -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(211,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -iF -iF -iL -iO -iK -iV -iX -iF -jb -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(212,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aT -iF -iF -LU -we -iW -iF -iF -aT -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(213,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -iF -iF -iF -iF -iF -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(214,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(215,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(216,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(217,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(218,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(219,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(220,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(221,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(222,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(223,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(224,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(225,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(226,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(227,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(228,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(229,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(230,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(231,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(232,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(233,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(234,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(235,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(236,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(237,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(238,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(239,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(240,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(241,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(242,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(243,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(244,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(245,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(246,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(247,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(248,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(249,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(250,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(251,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(252,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(253,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(254,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(255,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} diff --git a/_maps/map_files/cyberiad/z4.dmm b/_maps/map_files/cyberiad/z4.dmm index cf0e350181d..1cece671fda 100644 --- a/_maps/map_files/cyberiad/z4.dmm +++ b/_maps/map_files/cyberiad/z4.dmm @@ -1094,7 +1094,7 @@ /area/engiestation/solars) "de" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/telecomms/relay/preset/engioutpost, +/obj/machinery/tcomms/relay/engineering, /turf/simulated/floor/plasteel{ icon_state = "dark" }, diff --git a/_maps/map_files/cyberiad/z6.dmm b/_maps/map_files/cyberiad/z6.dmm index b2171008b2b..8c10b145dbc 100644 --- a/_maps/map_files/cyberiad/z6.dmm +++ b/_maps/map_files/cyberiad/z6.dmm @@ -229,11 +229,11 @@ /obj/machinery/light{ dir = 1 }, -/obj/machinery/telecomms/relay/preset/ruskie, /obj/machinery/status_display{ layer = 4; pixel_y = 32 }, +/obj/machinery/tcomms/relay/ruskie, /turf/simulated/floor/plasteel{ icon_state = "vault"; dir = 8 @@ -761,7 +761,7 @@ /area/derelict/bridge) "bK" = ( /obj/machinery/vending/cigarette/free{ - product_slogans = "Just remember! No capitalist.;Best enjoyed with Vodka!.;Smoke!;Nine out of ten USSP scientists agree, smoking reduces stress!;There's no cigarette like a Russian cigarette!;Cigarettes! Now with 100% less capitalism." + slogan_list = list("Just remember! No capitalist.","Best enjoyed with Vodka!.","Smoke!","Nine out of ten USSP scientists agree, smoking reduces stress!","There's no cigarette like a Russian cigarette!","Cigarettes! Now with 100% less capitalism.") }, /turf/simulated/floor/plasteel{ dir = 9; @@ -1441,7 +1441,7 @@ pixel_y = 32 }, /obj/machinery/vending/cigarette/free{ - product_slogans = "Just remember! No capitalist.;Best enjoyed with Vodka!.;Smoke!;Nine out of ten USSP scientists agree, smoking reduces stress!;There's no cigarette like a Russian cigarette!;Cigarettes! Now with 100% less capitalism." + slogan_list = list("Just remember! No capitalist.","Best enjoyed with Vodka!.","Smoke!","Nine out of ten USSP scientists agree, smoking reduces stress!","There's no cigarette like a Russian cigarette!","Cigarettes! Now with 100% less capitalism.") }, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel{ @@ -4163,7 +4163,7 @@ name = "suspicious button" }, /obj/machinery/vending/cigarette/free{ - product_slogans = "Just remember! No capitalist.;Best enjoyed with Vodka!.;Smoke!;Nine out of ten USSP scientists agree, smoking reduces stress!;There's no cigarette like a Russian cigarette!;Cigarettes! Now with 100% less capitalism." + slogan_list = list("Just remember! No capitalist.","Best enjoyed with Vodka!.","Smoke!","Nine out of ten USSP scientists agree, smoking reduces stress!","There's no cigarette like a Russian cigarette!","Cigarettes! Now with 100% less capitalism.") }, /turf/simulated/floor/wood{ broken = 1; @@ -5186,7 +5186,7 @@ "kW" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/vending/cigarette/free{ - product_slogans = "Just remember! No capitalist.;Best enjoyed with Vodka!.;Smoke!;Nine out of ten USSP scientists agree, smoking reduces stress!;There's no cigarette like a Russian cigarette!;Cigarettes! Now with 100% less capitalism." + slogan_list = list("Just remember! No capitalist.","Best enjoyed with Vodka!.","Smoke!","Nine out of ten USSP scientists agree, smoking reduces stress!","There's no cigarette like a Russian cigarette!","Cigarettes! Now with 100% less capitalism.") }, /turf/simulated/floor/plasteel{ dir = 5; @@ -5598,7 +5598,7 @@ }, /area/syndicate_depot/outer) "lZ" = ( -/obj/item/reagent_containers/food/snacks/spiderleg, +/obj/item/reagent_containers/food/snacks/monstermeat/spiderleg, /obj/structure/spider, /turf/simulated/floor/plasteel{ icon_state = "dark" @@ -6363,7 +6363,7 @@ icon_state = "sink"; pixel_x = 12 }, -/turf/simulated/floor/mineral/plasma, +/turf/simulated/floor/mineral/silver, /area/syndicate_depot/core) "of" = ( /obj/structure/closet/secure_closet/syndicate/depot, @@ -6448,26 +6448,9 @@ icon_state = "wood" }, /area/derelict/crew_quarters) -"oo" = ( -/obj/effect/spawner/random_spawners/syndicate/layout/door/secret, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/syndicate_depot/core) "op" = ( /turf/simulated/floor/mineral/silver, /area/syndicate_depot/core) -"oq" = ( -/obj/machinery/door/airlock/plasma{ - welded = 1 - }, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/syndicate_depot/core) -"or" = ( -/turf/simulated/floor/mineral/plasma, -/area/syndicate_depot/core) "os" = ( /obj/structure/table, /obj/effect/spawner/random_spawners/syndicate/loot/stetchkin, @@ -6543,7 +6526,7 @@ /area/syndicate_depot/core) "oB" = ( /obj/effect/spawner/random_spawners/syndicate/mob, -/turf/simulated/floor/mineral/plasma, +/turf/simulated/floor/mineral/silver, /area/syndicate_depot/core) "oC" = ( /obj/effect/landmark{ @@ -6706,27 +6689,14 @@ icon_state = "dark" }, /area/syndicate_depot/core) -"oZ" = ( -/obj/structure/mirror{ - pixel_x = -32 - }, -/turf/simulated/floor/mineral/plasma, -/area/syndicate_depot/core) "pa" = ( /obj/structure/toilet{ dir = 8 }, /turf/simulated/floor/mineral/silver, /area/syndicate_depot/core) -"pb" = ( -/obj/machinery/portable_atmospherics/canister/toxins, -/turf/simulated/floor/plasteel{ - icon_state = "dark" - }, -/area/syndicate_depot/core) "pc" = ( /obj/machinery/light, -/obj/effect/spawner/random_spawners/syndicate/loot/level3, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -9114,7 +9084,7 @@ }) "tY" = ( /obj/machinery/vending/cigarette/free{ - product_slogans = "Just remember! No capitalist.;Best enjoyed with Vodka!.;Smoke!;Nine out of ten USSP scientists agree, smoking reduces stress!;There's no cigarette like a Russian cigarette!;Cigarettes! Now with 100% less capitalism." + slogan_list = list("Just remember! No capitalist.","Best enjoyed with Vodka!.","Smoke!","Nine out of ten USSP scientists agree, smoking reduces stress!","There's no cigarette like a Russian cigarette!","Cigarettes! Now with 100% less capitalism.") }, /turf/simulated/floor/plasteel{ icon_state = "bar" @@ -10678,7 +10648,7 @@ /area/derelict/arrival) "xe" = ( /obj/machinery/vending/cigarette/free{ - product_slogans = "Just remember! No capitalist.;Best enjoyed with Vodka!.;Smoke!;Nine out of ten USSP scientists agree, smoking reduces stress!;There's no cigarette like a Russian cigarette!;Cigarettes! Now with 100% less capitalism." + slogan_list = list("Just remember! No capitalist.","Best enjoyed with Vodka!.","Smoke!","Nine out of ten USSP scientists agree, smoking reduces stress!","There's no cigarette like a Russian cigarette!","Cigarettes! Now with 100% less capitalism.") }, /turf/simulated/floor/plasteel{ dir = 2; @@ -11582,10 +11552,10 @@ }, /area/space/nearstation) "zR" = ( -/obj/machinery/portable_atmospherics/canister/toxins, /obj/machinery/light/small{ dir = 1 }, +/obj/effect/decal/cleanable/blood, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -57707,7 +57677,7 @@ of ot mA mA -pb +nX pi mA py @@ -59251,7 +59221,7 @@ oE oR oE oz -pb +mA mA mA mm @@ -61558,7 +61528,7 @@ mm mB mm mm -oo +mm mm lV mA @@ -61816,7 +61786,7 @@ mA zP mm zR -oo +mm oL ns mA @@ -62072,7 +62042,7 @@ mA mA mt mm -oq +mm mm mm mm @@ -62332,7 +62302,7 @@ mm op oB oM -oZ +oM ob mA pu @@ -62586,7 +62556,7 @@ zP mA mA ob -or +op nJ oe pa diff --git a/_maps/map_files/generic/Lavaland.dmm b/_maps/map_files/generic/Lavaland.dmm index 142bbcff5f7..a3d4b951265 100644 --- a/_maps/map_files/generic/Lavaland.dmm +++ b/_maps/map_files/generic/Lavaland.dmm @@ -1324,10 +1324,10 @@ /turf/simulated/floor/plasteel/dark, /area/mine/maintenance) "di" = ( -/obj/machinery/telecomms/relay/preset/mining, /obj/machinery/light/small{ dir = 1 }, +/obj/machinery/tcomms/relay/mining, /turf/simulated/floor/plasteel/dark, /area/mine/maintenance) "dj" = ( diff --git a/_maps/map_files/MetaStation/z3.dmm b/_maps/map_files/generic/tcommsat-blown.dmm similarity index 97% rename from _maps/map_files/MetaStation/z3.dmm rename to _maps/map_files/generic/tcommsat-blown.dmm index 1f9801d8b80..e31ba89348a 100644 --- a/_maps/map_files/MetaStation/z3.dmm +++ b/_maps/map_files/generic/tcommsat-blown.dmm @@ -16,109 +16,82 @@ /area/space) "ac" = ( /obj/effect/decal/warning_stripes/northwestcorner, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "ad" = ( /obj/effect/decal/warning_stripes/northwest, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "ae" = ( /obj/effect/decal/warning_stripes/north, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "af" = ( /obj/effect/decal/warning_stripes/northeast, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "ag" = ( /obj/item/paper/crumpled, /obj/effect/decal/warning_stripes/west, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "ah" = ( /obj/effect/decal/warning_stripes/east, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "ai" = ( /obj/machinery/light/small, /obj/item/paper, /obj/effect/decal/warning_stripes/southwestcorner, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "aj" = ( /obj/effect/decal/warning_stripes/southwest, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "ak" = ( /obj/effect/decal/warning_stripes/southeast, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "al" = ( /obj/effect/decal/warning_stripes/north, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "am" = ( /obj/effect/decal/warning_stripes/northwest, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "an" = ( /obj/effect/decal/warning_stripes/northeast, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ao" = ( /obj/effect/decal/warning_stripes/northwestcorner, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ap" = ( /obj/effect/decal/warning_stripes/northeastcorner, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "aq" = ( /obj/structure/closet/emcloset, /obj/effect/decal/warning_stripes/northwest, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ar" = ( /obj/effect/decal/warning_stripes/west, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "as" = ( /obj/effect/decal/warning_stripes/southwestcorner, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "at" = ( /obj/structure/closet/crate, /obj/item/clothing/glasses/night, /obj/effect/decal/warning_stripes/southwest, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "au" = ( /obj/item/storage/toolbox/electrical{ pixel_x = 1; @@ -126,37 +99,26 @@ }, /obj/effect/decal/warning_stripes/southwest, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "av" = ( /obj/effect/decal/warning_stripes/south, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "aw" = ( /obj/machinery/light/small{ dir = 4 }, /obj/effect/decal/warning_stripes/southeast, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ax" = ( /obj/effect/landmark/damageturf, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ay" = ( /obj/structure/lattice, /turf/space, /area/space/nearstation) -"az" = ( -/obj/effect/landmark/damageturf, -/turf/simulated/floor/plating/airless{ - dir = 1; - icon_state = "floor" - }, -/area/tcommsat/chamber) -"be" = ( -/obj/item/trash/cheesie, -/turf/space, -/area/space/nearstation) "bj" = ( /turf/simulated/floor/plating/airless, /area/space/nearstation) @@ -183,16 +145,16 @@ /area/space/nearstation) "bp" = ( /turf/simulated/wall/r_wall, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bq" = ( /obj/structure/girder, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "br" = ( /obj/structure/table, /obj/item/flashlight/lamp, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bs" = ( /obj/structure/window/reinforced{ dir = 4 @@ -204,7 +166,7 @@ dir = 8 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bu" = ( /obj/machinery/power/apc{ cell_type = 2500; @@ -218,7 +180,7 @@ d2 = 4 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bv" = ( /obj/machinery/light/small{ dir = 1 @@ -229,29 +191,29 @@ icon_state = "2-8" }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bw" = ( /obj/item/stock_parts/cell, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bx" = ( /obj/machinery/portable_atmospherics/canister/air, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "by" = ( /obj/item/coin/clown, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bz" = ( /obj/structure/bed, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bA" = ( /obj/machinery/light/small{ dir = 1 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bD" = ( /obj/structure/lattice, /obj/structure/window/reinforced{ @@ -267,18 +229,18 @@ pixel_y = 0 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bF" = ( /obj/item/wrench, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bG" = ( /obj/structure/window/reinforced{ dir = 4 }, /obj/machinery/portable_atmospherics/canister/air, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bH" = ( /obj/structure/lattice, /obj/structure/window/reinforced{ @@ -288,12 +250,12 @@ /area/space/nearstation) "bI" = ( /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bJ" = ( /obj/structure/table, /obj/item/paper, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bK" = ( /obj/structure/table, /obj/item/paper_bin, @@ -302,46 +264,46 @@ dir = 1 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bL" = ( /obj/structure/computerframe, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bM" = ( /obj/structure/table, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bN" = ( /obj/item/reagent_containers/food/snacks/meat/syntiflesh{ name = "Cuban Pete-Meat" }, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bO" = ( /obj/structure/grille, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bP" = ( /obj/structure/grille/broken, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bQ" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ dir = 8 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bR" = ( /obj/structure/window/reinforced, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bS" = ( /obj/item/stack/cable_coil/cut{ amount = 1 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bT" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ @@ -349,7 +311,7 @@ }, /obj/structure/closet, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bU" = ( /obj/structure/window/reinforced{ dir = 8 @@ -359,12 +321,12 @@ "bV" = ( /obj/item/folder/yellow, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bW" = ( /obj/structure/bed, /obj/effect/decal/remains/human, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "bX" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ @@ -392,7 +354,7 @@ dir = 4 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ca" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ @@ -414,34 +376,34 @@ "cd" = ( /obj/structure/sign/securearea, /turf/simulated/wall/r_wall, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ce" = ( /obj/machinery/light/small{ dir = 8 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cf" = ( /obj/item/paper/crumpled, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cg" = ( /obj/structure/chair{ dir = 4 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ch" = ( /obj/structure/table, /obj/item/storage/fancy/cigarettes, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ci" = ( /obj/structure/chair{ dir = 8 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cj" = ( /obj/structure/window/reinforced{ dir = 1 @@ -449,72 +411,60 @@ /obj/structure/window/reinforced{ dir = 8 }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "ck" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ dir = 1 }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) -"cl" = ( -/obj/structure/window/reinforced, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "cm" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ dir = 1 }, /obj/item/airlock_electronics, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "cn" = ( /obj/structure/door_assembly/door_assembly_hatch, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "co" = ( /obj/effect/spawner/window/reinforced{ useFull = 0 }, /turf/simulated/floor/plating, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cp" = ( /obj/machinery/vending/snack, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cq" = ( /obj/machinery/vending/cola, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cr" = ( /obj/structure/chair{ dir = 1 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cs" = ( /obj/machinery/disposal, /obj/structure/disposalpipe/trunk{ dir = 4 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ct" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /turf/simulated/wall/r_wall, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cu" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -543,17 +493,6 @@ }, /turf/simulated/floor/plating/airless, /area/space/nearstation) -"cy" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) "cz" = ( /obj/structure/window/reinforced{ dir = 8 @@ -580,28 +519,23 @@ /obj/structure/table, /obj/item/radio/off, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cD" = ( /obj/structure/chair, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cE" = ( /obj/machinery/door/airlock/maintenance_hatch, /turf/simulated/floor/plating/airless{ icon_state = "dark" }, -/area/tcommsat/chamber) -"cF" = ( -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cG" = ( /obj/machinery/door/airlock/hatch, /turf/simulated/floor/plating/airless{ icon_state = "dark" }, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cH" = ( /turf/simulated/floor/plasteel{ icon_state = "solarpanel" @@ -621,10 +555,8 @@ /obj/item/shard{ icon_state = "medium" }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "cK" = ( /obj/structure/grille, /obj/structure/window/reinforced, @@ -635,14 +567,14 @@ dir = 8 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cL" = ( /obj/structure/grille, /obj/structure/window/reinforced{ dir = 1 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cM" = ( /obj/structure/grille, /obj/structure/window/reinforced, @@ -650,7 +582,7 @@ dir = 1 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cN" = ( /obj/structure/grille, /obj/structure/window/reinforced, @@ -661,7 +593,7 @@ dir = 4 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cO" = ( /obj/structure/window/reinforced{ dir = 4 @@ -669,10 +601,8 @@ /obj/structure/window/reinforced{ dir = 8 }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "cP" = ( /obj/structure/window/reinforced{ dir = 8 @@ -688,33 +618,21 @@ dir = 8 }, /obj/item/stack/rods, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "cR" = ( /obj/item/stack/rods, /obj/item/shard{ icon_state = "medium" }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) -"cS" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "cT" = ( /obj/structure/window/reinforced{ dir = 4 }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "cU" = ( /obj/effect/spawner/window/reinforced{ useFull = 0 @@ -726,10 +644,8 @@ /obj/item/scalpel{ pixel_y = 12 }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "cY" = ( /obj/structure/window/reinforced{ dir = 4 @@ -737,25 +653,21 @@ /obj/item/shard{ icon_state = "medium" }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "da" = ( /obj/structure/rack, /obj/item/circuitboard/teleporter, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "db" = ( /obj/item/radio/off, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "dd" = ( /obj/effect/decal/cleanable/blood/oil, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "de" = ( /obj/effect/decal/cleanable/blood, /obj/structure/chair, @@ -763,71 +675,59 @@ /obj/item/restraints/handcuffs, /obj/effect/decal/remains/human, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dg" = ( /obj/structure/window/reinforced{ dir = 1 }, /obj/structure/window/reinforced, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "dh" = ( /obj/structure/door_assembly/door_assembly_mhatch, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "di" = ( /obj/machinery/light/small{ dir = 4 }, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dj" = ( /obj/item/cigbutt, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dk" = ( /obj/effect/decal/cleanable/blood, /obj/item/assembly/signaler, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "dl" = ( /obj/structure/table, /obj/item/reagent_containers/syringe/lethal{ pixel_y = 4 }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "dn" = ( /obj/item/storage/toolbox/syndicate, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "do" = ( /obj/structure/table, /obj/item/radio/electropack, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dp" = ( /obj/structure/table, /obj/item/hemostat, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "dq" = ( /obj/structure/table, /obj/item/circular_saw, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "ds" = ( /obj/structure/window/reinforced{ dir = 8 @@ -836,10 +736,8 @@ dir = 4 }, /obj/item/stack/rods, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "dt" = ( /obj/structure/window/reinforced{ dir = 8 @@ -859,28 +757,17 @@ /obj/structure/window/reinforced, /turf/space, /area/space/nearstation) -"dA" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) "dC" = ( /obj/item/stack/rods, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dE" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ dir = 4 }, -/turf/simulated/floor/plating/airless{ - icon_state = "dark" - }, -/area/tcommsat/chamber) +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) "dI" = ( /obj/item/shard{ icon_state = "medium" @@ -902,7 +789,7 @@ }, /obj/structure/window/reinforced, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dM" = ( /obj/structure/grille/broken, /turf/space, @@ -910,36 +797,36 @@ "dO" = ( /obj/machinery/door/airlock/hatch, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dT" = ( /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dV" = ( /obj/machinery/light/small{ dir = 8 }, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dW" = ( /obj/structure/sign/vacuum, /turf/simulated/wall/r_wall, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dY" = ( /obj/item/paper/crumpled, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "dZ" = ( /obj/structure/closet/malf/suits, /turf/simulated/floor/plasteel, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ea" = ( /obj/structure/door_assembly/door_assembly_ext, /turf/simulated/floor/plating/airless, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "eb" = ( /obj/machinery/door/airlock/external, /turf/simulated/floor/plating, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ed" = ( /obj/item/crowbar, /turf/simulated/floor/plating/airless, @@ -947,15 +834,15 @@ "ej" = ( /obj/structure/computerframe, /turf/simulated/floor/plating, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "ek" = ( /obj/machinery/teleport/station, /turf/simulated/floor/plating, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "el" = ( /obj/machinery/teleport/hub, /turf/simulated/floor/plating, -/area/tcommsat/chamber) +/area/ruin/tcommsat) "em" = ( /turf/simulated/wall/r_wall, /area/AIsattele) @@ -1066,10 +953,28 @@ }, /turf/simulated/floor/plating/airless, /area/AIsattele) +"ji" = ( +/obj/docking_port/stationary{ + dir = 8; + dwidth = 10; + height = 35; + id = "whiteship_away"; + name = "Deep Space"; + width = 21 + }, +/turf/space, +/area/space) +"yn" = ( +/turf/space, +/area/space/nearstation) "AV" = ( /obj/machinery/atmospherics/unary/tank/oxygen_agent_b, /turf/simulated/floor/plating/airless, /area/AIsattele) +"Fv" = ( +/obj/machinery/door/airlock/maintenance_hatch, +/turf/simulated/floor/plating/airless, +/area/ruin/tcommsat) (1,1,1) = {" aa @@ -8823,7 +8728,7 @@ aa aa aa aa -be +aa aa aa aa @@ -17325,7 +17230,7 @@ aa aa aa aa -aa +ji aa aa aa @@ -31000,23 +30905,23 @@ bn bs bD bs -aa +yn bs bs cI bs bs -aa +yn bs cI bs -aa +yn bs -aa +yn cI bs bs -aa +yn aa ay aa @@ -31259,20 +31164,20 @@ bt bQ bX cj -cy +bZ cJ cQ -cS -cy +bt +bZ cO -cy -cy +bZ +bZ cO -cy +bZ ds cY cO -dA +bQ cB aa ay @@ -31524,12 +31429,12 @@ cP bU bH bU -aa +yn bU bU bH dt -cl +bR cB aa ay @@ -31772,7 +31677,7 @@ bv bE bS bZ -cl +bR cA bp bp @@ -32047,9 +31952,9 @@ ck cB aa dJ -bn -bn -bn +bp +bp +bp bl bl bp @@ -32286,27 +32191,27 @@ bx bG bT cb -cl +bR cB bp bI bI -cF -cF -cF -cF -cF -cF +bI +bI +bI +bI +bI +bI bI bp -aa +yn ck cB bp dK bp bp -bn +bp bl bl bp @@ -32538,7 +32443,7 @@ ay aa bl bn -bn +bp bp bH bU @@ -32547,12 +32452,12 @@ cm cB bp bI -cF -cF -cF -cF -cF -cF +bI +bI +bI +bI +bI +bI bI bI bp @@ -32560,10 +32465,10 @@ bp cG bp bp -az +ax bI bp -bn +bp bl bp dW @@ -32795,7 +32700,7 @@ bj ay bl bn -bn +bp bp bp bp @@ -32804,13 +32709,13 @@ cn bp bp bI -cF -cF -cF -cF bI -cF -cF +bI +bI +bI +bI +bI +bI bI bp ad @@ -32820,7 +32725,7 @@ bp bI bI bp -bn +bp bp bp aq @@ -33052,7 +32957,7 @@ bj aa bl bn -bn +bp bp bI bI @@ -33062,12 +32967,12 @@ bI cK bI bI -cF -cF bI -cF -cF -cF +bI +bI +bI +bI +bI bI bp ac @@ -33309,7 +33214,7 @@ bj aa bl bn -bn +bp bp bI bV @@ -33318,18 +33223,18 @@ bI cC cL cR -cF -cF -cF +bI +bI +bI dd -cF -cF -cF +bI +bI +bI bI bp -az +ax bI -az +ax bp bI bI @@ -33566,7 +33471,7 @@ bj bj bm bn -bn +bp bp bJ bI @@ -33575,20 +33480,20 @@ dj cD cM bI -cF +bI bI bI de dj do -cF +bI bI bp ae bI -az ax -az +ax +ax bI dO al @@ -33823,7 +33728,7 @@ bj aa bl bn -bn +bp bp bK bI @@ -33832,13 +33737,13 @@ bI bI cM bI -cF -cF -cF +bI +bI +bI bI dk dp -cF +bI bI bp ac @@ -34080,7 +33985,7 @@ bj aa bk bn -bn +bp bp bL bI @@ -34089,13 +33994,13 @@ bI bI cN bI -cF +bI cX db br dl dq -cF +bI bI bp ax @@ -34337,7 +34242,7 @@ bj ay bl bn -bn +bp bp bM bL @@ -34346,13 +34251,13 @@ bp cE bp bI -cF -cF -cF -cF -cF -cF -cF +bI +bI +bI +bI +bI +bI +bI bI bp af @@ -34362,7 +34267,7 @@ bp bI bI bp -bn +bp bp bp dZ @@ -34594,22 +34499,22 @@ ay aa bl bn -bn bp bp bp bp bp -cF -cE -cF -cF -cF -cF -cF -cF -cF -cF +bp +bI +Fv +bI +bI +bI +bI +bI +bI +bI +bI bI bp bp @@ -34619,7 +34524,7 @@ bp bL bI bp -bn +bp bl bp bp @@ -34859,14 +34764,14 @@ bN bp bp bp -cF bI -cF -cF -cF -cF bI -cF +bI +bI +bI +bI +bI +bI bI bp cc @@ -34876,7 +34781,7 @@ bp co bp bp -bn +bp bl bl bl @@ -35127,13 +35032,13 @@ bI bI bp cc -cl +bR cB aa ay -bn -bn -bj +bp +bp +bI bl bl bk @@ -35636,7 +35541,7 @@ cI cI cI bs -aa +yn bs bs cI @@ -35891,7 +35796,7 @@ cO cT cY cO -cS +bt cO cO cO @@ -36144,7 +36049,7 @@ cg dj bp cP -aa +yn bU bU cc @@ -36156,7 +36061,7 @@ bU bH bU bU -aa +yn aa aa aa @@ -37430,13 +37335,13 @@ cu bn bn bn -bn bp bp bp bp bp -bn +bp +bp bn bo ay diff --git a/_maps/metastation.dm b/_maps/metastation.dm index ad4c4370d74..22e3335edca 100644 --- a/_maps/metastation.dm +++ b/_maps/metastation.dm @@ -16,7 +16,7 @@ z7 = empty space #if !defined(USING_MAP_DATUM) #include "map_files\MetaStation\MetaStation.v41A.II.dmm" #include "map_files\MetaStation\z2.dmm" - #include "map_files\MetaStation\z3.dmm" + #include "map_files\generic\tcommsat-blown.dmm" #include "map_files\MetaStation\z4.dmm" #include "map_files\generic\Lavaland.dmm" #include "map_files\generic\z6.dmm" diff --git a/_maps/test_all_maps.dm b/_maps/test_all_maps.dm deleted file mode 100644 index 94bd9bac437..00000000000 --- a/_maps/test_all_maps.dm +++ /dev/null @@ -1,145 +0,0 @@ -// This is for Travis testing. DO NOT SET THIS AS THE GAME'S MAP NORMALLY! - -#if !defined(USING_MAP_DATUM) - // Away missions - #include "map_files\RandomZLevels\academy.dmm" - #include "map_files\RandomZLevels\beach.dmm" - #include "map_files\RandomZLevels\blackmarketpackers.dmm" - #include "map_files\RandomZLevels\centcomAway.dmm" - #include "map_files\RandomZLevels\evil_santa.dmm" - #include "map_files\RandomZLevels\example.dmm" - #include "map_files\RandomZLevels\moonoutpost19.dmm" - #include "map_files\RandomZLevels\spacebattle.dmm" - #include "map_files\RandomZLevels\spacehotel.dmm" - #include "map_files\RandomZLevels\stationCollision.dmm" - #include "map_files\RandomZLevels\terrorspiders.dmm" - #include "map_files\RandomZLevels\undergroundoutpost45.dmm" - #include "map_files\RandomZLevels\wildwest.dmm" - - - // Lavaland Ruins - #include "map_files\RandomRuins\LavaRuins\lavaland_biodome_beach.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_biodome_clown_planet.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_biodome_winter.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_animal_hospital.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_ash_walker1.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_blooddrunk1.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_blooddrunk2.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_blooddrunk3.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_cube.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_cultaltar.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_dead_ratvar.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_envy.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_fountain_hall.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_gluttony.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_greed.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_hermit.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_hierophant.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_pizzaparty.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_pride.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_puzzle.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_random_ripley.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_seed_vault.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_sloth.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_survivalpod.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_swarmer_crash.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_syndicate_base1.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_ufo_crash.dmm" - #include "map_files\RandomRuins\LavaRuins\lavaland_surface_xeno_nest.dmm" - - - // Space Ruins - #include "map_files\RandomRuins\SpaceRuins\abandonedzoo.dmm" - #include "map_files\RandomRuins\SpaceRuins\asteroid1.dmm" - #include "map_files\RandomRuins\SpaceRuins\asteroid2.dmm" - #include "map_files\RandomRuins\SpaceRuins\asteroid3.dmm" - #include "map_files\RandomRuins\SpaceRuins\asteroid4.dmm" - #include "map_files\RandomRuins\SpaceRuins\asteroid5.dmm" - #include "map_files\RandomRuins\SpaceRuins\deepstorage.dmm" - #include "map_files\RandomRuins\SpaceRuins\derelict1.dmm" - #include "map_files\RandomRuins\SpaceRuins\derelict2.dmm" - #include "map_files\RandomRuins\SpaceRuins\derelict3.dmm" - #include "map_files\RandomRuins\SpaceRuins\derelict4.dmm" - #include "map_files\RandomRuins\SpaceRuins\derelict5.dmm" - #include "map_files\RandomRuins\SpaceRuins\emptyshell.dmm" - #include "map_files\RandomRuins\SpaceRuins\gasthelizards.dmm" - #include "map_files\RandomRuins\SpaceRuins\intactemptyship.dmm" - #include "map_files\RandomRuins\SpaceRuins\listeningpost.dmm" - #include "map_files\RandomRuins\SpaceRuins\mechtransport.dmm" - #include "map_files\RandomRuins\SpaceRuins\oldstation.dmm" - #include "map_files\RandomRuins\SpaceRuins\onehalf.dmm" - #include "map_files\RandomRuins\SpaceRuins\spacebar.dmm" - #include "map_files\RandomRuins\SpaceRuins\turretedoutpost.dmm" - #include "map_files\RandomRuins\SpaceRuins\way_home.dmm" - - - // Shuttle Templates - #include "map_files\shuttles\cargo_base.dmm" - #include "map_files\shuttles\emergency_bar.dmm" - #include "map_files\shuttles\emergency_clown.dmm" - #include "map_files\shuttles\emergency_cramped.dmm" - #include "map_files\shuttles\emergency_cyb.dmm" - #include "map_files\shuttles\emergency_dept.dmm" - #include "map_files\shuttles\emergency_meta.dmm" - #include "map_files\shuttles\emergency_mil.dmm" - #include "map_files\shuttles\emergency_narnar.dmm" - #include "map_files\shuttles\emergency_old.dmm" - #include "map_files\shuttles\ferry_base.dmm" - #include "map_files\shuttles\ferry_meat.dmm" - - // Other templates - #include "map_files\templates\spacehotel\n_01.dmm" - #include "map_files\templates\spacehotel\n_02.dmm" - #include "map_files\templates\spacehotel\n_03.dmm" - #include "map_files\templates\spacehotel\n_04.dmm" - #include "map_files\templates\spacehotel\n_05.dmm" - #include "map_files\templates\spacehotel\n_06.dmm" - #include "map_files\templates\spacehotel\n_07.dmm" - #include "map_files\templates\spacehotel\n_08.dmm" - #include "map_files\templates\spacehotel\n_09.dmm" - #include "map_files\templates\spacehotel\n_10.dmm" - #include "map_files\templates\spacehotel\n_11.dmm" - #include "map_files\templates\spacehotel\n_12.dmm" - #include "map_files\templates\spacehotel\n_13.dmm" - #include "map_files\templates\spacehotel\n_14.dmm" - #include "map_files\templates\spacehotel\n_15.dmm" - #include "map_files\templates\spacehotel\n_16.dmm" - #include "map_files\templates\spacehotel\n_17.dmm" - #include "map_files\templates\spacehotel\n_18.dmm" - #include "map_files\templates\spacehotel\n_19.dmm" - - #include "map_files\templates\spacehotel\s_01.dmm" - #include "map_files\templates\spacehotel\s_02.dmm" - #include "map_files\templates\spacehotel\s_03.dmm" - #include "map_files\templates\spacehotel\s_04.dmm" - #include "map_files\templates\spacehotel\s_05.dmm" - #include "map_files\templates\spacehotel\s_06.dmm" - - #include "map_files\templates\light_floor_1.dmm" - #include "map_files\templates\light_floor_2.dmm" - #include "map_files\templates\light_floor_3.dmm" - #include "map_files\templates\medium_shuttle1.dmm" - #include "map_files\templates\medium_shuttle2.dmm" - #include "map_files\templates\medium_shuttle3.dmm" - #include "map_files\templates\shelter_1.dmm" - #include "map_files\templates\shelter_2.dmm" - #include "map_files\templates\small_asteroid_1.dmm" - #include "map_files\templates\small_shuttle_1.dmm" - - // This is pointless, we don't run the server - /*#define MAP_TRANSITION_CONFIG list(AWAY_MISSION = UNAFFECTED, - AWAY_MISSION = UNAFFECTED, - AWAY_MISSION = UNAFFECTED, - AWAY_MISSION = UNAFFECTED, - AWAY_MISSION = UNAFFECTED, - AWAY_MISSION = UNAFFECTED, - AWAY_MISSION = UNAFFECTED, - AWAY_MISSION = UNAFFECTED, - AWAY_MISSION = UNAFFECTED, - AWAY_MISSION = UNAFFECTED) - - #define USING_MAP_DATUM /datum/map*/ - -#elif !defined(MAP_OVERRIDE) - #warn a map has already been included. -#endif diff --git a/_maps/travis_map_testing.dm b/_maps/travis_map_testing.dm new file mode 100644 index 00000000000..29f4a738326 --- /dev/null +++ b/_maps/travis_map_testing.dm @@ -0,0 +1,156 @@ +// This is for Travis testing. DO NOT SET THIS AS THE GAME'S MAP NORMALLY! + +#if !defined(USING_MAP_DATUM) + // Cyberiad + #include "map_files/Cyberiad/cyberiad.dmm" + #include "map_files/Cyberiad/z2.dmm" + #include "map_files/Cyberiad/z4.dmm" + #include "map_files/Cyberiad/z6.dmm" + + // Debug Maps + #include "map_files/Debug/singletile.dmm" + #include "map_files/Debug/smoothing.dmm" + + // Delta + #include "map_files/Delta/delta.dmm" + + // Generic Z Levels + #include "map_files/Generic/Lavaland.dmm" + #include "map_files/Generic/tcommsat-blown.dmm" + #include "map_files/Generic/z6.dmm" + #include "map_files/Generic/z7.dmm" + + // MetaStation + #include "map_files/MetaStation/MetaStation.v41A.II.dmm" + #include "map_files/MetaStation/z2.dmm" + #include "map_files/MetaStation/z4.dmm" + + // Lavaland Ruins + #include "map_files/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_biodome_winter.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_blooddrunk1.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_blooddrunk2.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_blooddrunk3.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_cube.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_cultaltar.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_dead_ratvar.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_envy.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_fountain_hall.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_gluttony.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_greed.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_hierophant.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_pride.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_puzzle.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_random_ripley.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_sloth.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_survivalpod.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_swarmer_crash.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_ufo_crash.dmm" + #include "map_files/RandomRuins/LavaRuins/lavaland_surface_xeno_nest.dmm" + + // Space Ruins + #include "map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm" + #include "map_files/RandomRuins/SpaceRuins/asteroid1.dmm" + #include "map_files/RandomRuins/SpaceRuins/asteroid2.dmm" + #include "map_files/RandomRuins/SpaceRuins/asteroid3.dmm" + #include "map_files/RandomRuins/SpaceRuins/asteroid4.dmm" + #include "map_files/RandomRuins/SpaceRuins/asteroid5.dmm" + #include "map_files/RandomRuins/SpaceRuins/deepstorage.dmm" + #include "map_files/RandomRuins/SpaceRuins/derelict1.dmm" + #include "map_files/RandomRuins/SpaceRuins/derelict2.dmm" + #include "map_files/RandomRuins/SpaceRuins/derelict3.dmm" + #include "map_files/RandomRuins/SpaceRuins/derelict4.dmm" + #include "map_files/RandomRuins/SpaceRuins/derelict5.dmm" + #include "map_files/RandomRuins/SpaceRuins/emptyshell.dmm" + #include "map_files/RandomRuins/SpaceRuins/gasthelizards.dmm" + #include "map_files/RandomRuins/SpaceRuins/intactemptyship.dmm" + #include "map_files/RandomRuins/SpaceRuins/listeningpost.dmm" + #include "map_files/RandomRuins/SpaceRuins/mechtransport.dmm" + #include "map_files/RandomRuins/SpaceRuins/oldstation.dmm" + #include "map_files/RandomRuins/SpaceRuins/onehalf.dmm" + #include "map_files/RandomRuins/SpaceRuins/spacebar.dmm" + #include "map_files/RandomRuins/SpaceRuins/turretedoutpost.dmm" + #include "map_files/RandomRuins/SpaceRuins/way_home.dmm" + #include "map_files/RandomRuins/SpaceRuins/wizardcrash.dmm" + + // Gateway Missions + #include "map_files/RandomZLevels/academy.dmm" + #include "map_files/RandomZLevels/beach.dmm" + #include "map_files/RandomZLevels/blackmarketpackers.dmm" + #include "map_files/RandomZLevels/centcomAway.dmm" + #include "map_files/RandomZLevels/evil_santa.dmm" + #include "map_files/RandomZLevels/example.dmm" + #include "map_files/RandomZLevels/moonoutpost19.dmm" + #include "map_files/RandomZLevels/spacebattle.dmm" + #include "map_files/RandomZLevels/spacehotel.dmm" + #include "map_files/RandomZLevels/stationCollision.dmm" + #include "map_files/RandomZLevels/terrorspiders.dmm" + #include "map_files/RandomZLevels/undergroundoutpost45.dmm" + #include "map_files/RandomZLevels/wildwest.dmm" + + // Shuttles + #include "map_files/shuttles/admin_admin.dmm" + #include "map_files/shuttles/admin_hospital.dmm" + #include "map_files/shuttles/cargo_base.dmm" + #include "map_files/shuttles/emergency_bar.dmm" + #include "map_files/shuttles/emergency_clown.dmm" + #include "map_files/shuttles/emergency_cramped.dmm" + #include "map_files/shuttles/emergency_cyb.dmm" + #include "map_files/shuttles/emergency_dept.dmm" + #include "map_files/shuttles/emergency_meta.dmm" + #include "map_files/shuttles/emergency_mil.dmm" + #include "map_files/shuttles/emergency_narnar.dmm" + #include "map_files/shuttles/emergency_old.dmm" + #include "map_files/shuttles/ferry_base.dmm" + #include "map_files/shuttles/ferry_meat.dmm" + + // Templates + #include "map_files/templates/light_floor_1.dmm" + #include "map_files/templates/light_floor_2.dmm" + #include "map_files/templates/light_floor_3.dmm" + #include "map_files/templates/medium_shuttle1.dmm" + #include "map_files/templates/medium_shuttle2.dmm" + #include "map_files/templates/medium_shuttle3.dmm" + #include "map_files/templates/shelter_1.dmm" + #include "map_files/templates/shelter_2.dmm" + #include "map_files/templates/small_asteroid_1.dmm" + #include "map_files/templates/small_shuttle_1.dmm" + + // Spacehotel Rooms + #include "map_files/templates/spacehotel/n_01.dmm" + #include "map_files/templates/spacehotel/n_02.dmm" + #include "map_files/templates/spacehotel/n_03.dmm" + #include "map_files/templates/spacehotel/n_04.dmm" + #include "map_files/templates/spacehotel/n_05.dmm" + #include "map_files/templates/spacehotel/n_06.dmm" + #include "map_files/templates/spacehotel/n_07.dmm" + #include "map_files/templates/spacehotel/n_08.dmm" + #include "map_files/templates/spacehotel/n_09.dmm" + #include "map_files/templates/spacehotel/n_10.dmm" + #include "map_files/templates/spacehotel/n_11.dmm" + #include "map_files/templates/spacehotel/n_12.dmm" + #include "map_files/templates/spacehotel/n_13.dmm" + #include "map_files/templates/spacehotel/n_14.dmm" + #include "map_files/templates/spacehotel/n_15.dmm" + #include "map_files/templates/spacehotel/n_16.dmm" + #include "map_files/templates/spacehotel/n_17.dmm" + #include "map_files/templates/spacehotel/n_18.dmm" + #include "map_files/templates/spacehotel/n_19.dmm" + #include "map_files/templates/spacehotel/s_01.dmm" + #include "map_files/templates/spacehotel/s_02.dmm" + #include "map_files/templates/spacehotel/s_03.dmm" + #include "map_files/templates/spacehotel/s_04.dmm" + #include "map_files/templates/spacehotel/s_05.dmm" + #include "map_files/templates/spacehotel/s_06.dmm" + +#elif !defined(MAP_OVERRIDE) + #warn a map has already been included. +#endif diff --git a/code/ATMOSPHERICS/atmospherics.dm b/code/ATMOSPHERICS/atmospherics.dm index 0e3c1b78798..002b3ecc691 100644 --- a/code/ATMOSPHERICS/atmospherics.dm +++ b/code/ATMOSPHERICS/atmospherics.dm @@ -257,7 +257,7 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new()) #define VENT_SOUND_DELAY 30 /obj/machinery/atmospherics/relaymove(mob/living/user, direction) direction &= initialize_directions - if(!direction || !(direction in cardinal)) //cant go this way. + if(!direction || !(direction in GLOB.cardinal)) //cant go this way. return if(user in buckled_mobs)// fixes buckle ventcrawl edgecase fuck bug @@ -265,7 +265,7 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new()) var/obj/machinery/atmospherics/target_move = findConnecting(direction) if(target_move) - if(is_type_in_list(target_move, ventcrawl_machinery) && target_move.can_crawl_through()) + if(is_type_in_list(target_move, GLOB.ventcrawl_machinery) && target_move.can_crawl_through()) user.remove_ventcrawl() user.forceMove(target_move.loc) //handles entering and so on user.visible_message("You hear something squeezing through the ducts.", "You climb out the ventilation system.") @@ -278,7 +278,7 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new()) user.last_played_vent = world.time playsound(src, 'sound/machines/ventcrawl.ogg', 50, 1, -3) else - if((direction & initialize_directions) || is_type_in_list(src, ventcrawl_machinery)) //if we move in a way the pipe can connect, but doesn't - or we're in a vent + if((direction & initialize_directions) || is_type_in_list(src, GLOB.ventcrawl_machinery)) //if we move in a way the pipe can connect, but doesn't - or we're in a vent user.remove_ventcrawl() user.forceMove(src.loc) user.visible_message("You hear something squeezing through the pipes.", "You climb out the ventilation system.") @@ -287,7 +287,7 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new()) user.canmove = 1 /obj/machinery/atmospherics/AltClick(var/mob/living/L) - if(is_type_in_list(src, ventcrawl_machinery)) + if(is_type_in_list(src, GLOB.ventcrawl_machinery)) L.handle_ventcrawl(src) return ..() @@ -343,3 +343,7 @@ GLOBAL_DATUM_INIT(pipe_icon_manager, /datum/pipe_icon_manager, new()) /obj/machinery/atmospherics/update_remote_sight(mob/user) user.sight |= (SEE_TURFS|BLIND) . = ..() + +//Used for certain children of obj/machinery/atmospherics to not show pipe vision when mob is inside it. +/obj/machinery/atmospherics/proc/can_see_pipes() + return TRUE diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm index 05da130494a..bedea1954ab 100644 --- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm +++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm @@ -142,7 +142,7 @@ /obj/machinery/atmospherics/binary/passive_gate/attack_ghost(mob/user) ui_interact(user) -/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) user.set_machine(src) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) diff --git a/code/ATMOSPHERICS/components/binary_devices/pump.dm b/code/ATMOSPHERICS/components/binary_devices/pump.dm index a579663a3cc..5ea968cde25 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pump.dm @@ -197,7 +197,7 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/binary/pump/attack_ghost(mob/user) ui_interact(user) -/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) user.set_machine(src) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) diff --git a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm index b664b09b320..1c645620cd6 100644 --- a/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/volume_pump.dm @@ -193,7 +193,7 @@ Thus, the two variables affect pump operation are set in New(): /obj/machinery/atmospherics/binary/volume_pump/attack_ghost(mob/user) ui_interact(user) -/obj/machinery/atmospherics/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/obj/machinery/atmospherics/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) user.set_machine(src) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm index cde1c9e80b0..d75e2e683c1 100644 --- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm +++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm @@ -31,7 +31,7 @@ icon_state = "base" ports = new() - for(var/d in cardinal) + for(var/d in GLOB.cardinal) var/datum/omni_port/new_port = new(src, d) switch(d) if(NORTH) diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm index 16897c59b9a..44b3d8daa1b 100755 --- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm @@ -208,7 +208,7 @@ Filter types: add_fingerprint(user) ui_interact(user) -/obj/machinery/atmospherics/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/obj/machinery/atmospherics/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) user.set_machine(src) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) diff --git a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm index 18f27fb9a65..6128c1afa33 100644 --- a/code/ATMOSPHERICS/components/trinary_devices/mixer.dm +++ b/code/ATMOSPHERICS/components/trinary_devices/mixer.dm @@ -58,7 +58,7 @@ /obj/machinery/atmospherics/trinary/mixer/update_icon(safety = 0) ..() - + if(flipped) icon_state = "m" else @@ -165,7 +165,7 @@ add_fingerprint(user) ui_interact(user) -/obj/machinery/atmospherics/trinary/mixer/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/obj/machinery/atmospherics/trinary/mixer/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) user.set_machine(src) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) diff --git a/code/ATMOSPHERICS/datum_icon_manager.dm b/code/ATMOSPHERICS/datum_icon_manager.dm index 75cb0fce8ce..2286b3523a0 100644 --- a/code/ATMOSPHERICS/datum_icon_manager.dm +++ b/code/ATMOSPHERICS/datum_icon_manager.dm @@ -6,26 +6,16 @@ // atmospherics devices. //-------------------------------------------- -#define PIPE_COLOR_GREY "#ffffff" //yes white is grey -#define PIPE_COLOR_RED "#ff0000" -#define PIPE_COLOR_BLUE "#0000ff" -#define PIPE_COLOR_CYAN "#00ffff" -#define PIPE_COLOR_GREEN "#00ff00" -#define PIPE_COLOR_YELLOW "#ffcc00" -#define PIPE_COLOR_PURPLE "#5c1ec0" - -var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE) - /proc/pipe_color_lookup(var/color) - for(var/C in pipe_colors) - if(color == pipe_colors[C]) + for(var/C in GLOB.pipe_colors) + if(color == GLOB.pipe_colors[C]) return "[C]" /proc/pipe_color_check(var/color) if(!color) return 1 - for(var/C in pipe_colors) - if(color == pipe_colors[C]) + for(var/C in GLOB.pipe_colors) + if(color == GLOB.pipe_colors[C]) return 1 return 0 @@ -105,10 +95,10 @@ var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_ var/image/I = image('icons/atmos/pipes.dmi', icon_state = state) pipe_icons[cache_name] = I - for(var/pipe_color in pipe_colors) + for(var/pipe_color in GLOB.pipe_colors) I = image('icons/atmos/pipes.dmi', icon_state = state) - I.color = pipe_colors[pipe_color] - pipe_icons[state + "[pipe_colors[pipe_color]]"] = I + I.color = GLOB.pipe_colors[pipe_color] + pipe_icons[state + "[GLOB.pipe_colors[pipe_color]]"] = I pipe = new ('icons/atmos/heat.dmi') for(var/state in pipe.IconStates()) @@ -137,10 +127,10 @@ var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_ if(findtext(state, "core") || findtext(state, "4way")) var/image/I = image('icons/atmos/manifold.dmi', icon_state = state) manifold_icons[state] = I - for(var/pipe_color in pipe_colors) + for(var/pipe_color in GLOB.pipe_colors) I = image('icons/atmos/manifold.dmi', icon_state = state) - I.color = pipe_colors[pipe_color] - manifold_icons[state + pipe_colors[pipe_color]] = I + I.color = GLOB.pipe_colors[pipe_color] + manifold_icons[state + GLOB.pipe_colors[pipe_color]] = I /datum/pipe_icon_manager/proc/gen_device_icons() if(!device_icons) @@ -185,10 +175,10 @@ var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_ var/cache_name = state - for(var/D in cardinal) + for(var/D in GLOB.cardinal) var/image/I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D)) underlays[cache_name + "[D]"] = I - for(var/pipe_color in pipe_colors) + for(var/pipe_color in GLOB.pipe_colors) I = image(icon('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D)) - I.color = pipe_colors[pipe_color] - underlays[state + "[D]" + "[pipe_colors[pipe_color]]"] = I + I.color = GLOB.pipe_colors[pipe_color] + underlays[state + "[D]" + "[GLOB.pipe_colors[pipe_color]]"] = I diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm index 4d849686851..2cf3edfb275 100644 --- a/code/ATMOSPHERICS/datum_pipeline.dm +++ b/code/ATMOSPHERICS/datum_pipeline.dm @@ -28,7 +28,7 @@ reconcile_air() return -var/pipenetwarnings = 10 +GLOBAL_VAR_INIT(pipenetwarnings, 10) /datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/base) var/volume = 0 diff --git a/code/ATMOSPHERICS/pipes/manifold.dm b/code/ATMOSPHERICS/pipes/manifold.dm index 13e35d10c7b..2eef5ad74c4 100644 --- a/code/ATMOSPHERICS/pipes/manifold.dm +++ b/code/ATMOSPHERICS/pipes/manifold.dm @@ -33,7 +33,7 @@ /obj/machinery/atmospherics/pipe/manifold/atmos_init() ..() - for(var/D in cardinal) + for(var/D in GLOB.cardinal) if(D == dir) continue for(var/obj/machinery/atmospherics/target in get_step(src, D)) @@ -116,7 +116,7 @@ /obj/machinery/atmospherics/pipe/manifold/update_icon(var/safety = 0) ..() - + if(!check_icon_cache()) return diff --git a/code/ATMOSPHERICS/pipes/manifold4w.dm b/code/ATMOSPHERICS/pipes/manifold4w.dm index d2cee29c0ba..2b384b3684b 100644 --- a/code/ATMOSPHERICS/pipes/manifold4w.dm +++ b/code/ATMOSPHERICS/pipes/manifold4w.dm @@ -90,7 +90,7 @@ /obj/machinery/atmospherics/pipe/manifold4w/update_icon(var/safety = 0) ..() - + if(!check_icon_cache()) return @@ -137,7 +137,7 @@ /obj/machinery/atmospherics/pipe/manifold4w/atmos_init() ..() - for(var/D in cardinal) + for(var/D in GLOB.cardinal) for(var/obj/machinery/atmospherics/target in get_step(src, D)) if(target.initialize_directions & get_dir(target,src)) var/c = check_connect_types(target,src) diff --git a/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm b/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm index b966690733b..94983f62acd 100644 --- a/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm +++ b/code/ATMOSPHERICS/pipes/simple/pipe_simple.dm @@ -48,7 +48,7 @@ if(initPipe) normalize_dir() var/N = 2 - for(var/D in cardinal) + for(var/D in GLOB.cardinal) if(D & initialize_directions) N-- for(var/obj/machinery/atmospherics/target in get_step(src, D)) @@ -138,7 +138,7 @@ /obj/machinery/atmospherics/pipe/simple/update_icon(var/safety = 0) ..() - + if(!check_icon_cache()) return diff --git a/code/ATMOSPHERICS/pipes/simple/pipe_simple_he.dm b/code/ATMOSPHERICS/pipes/simple/pipe_simple_he.dm index 35df3c60d23..9c6b0da2121 100644 --- a/code/ATMOSPHERICS/pipes/simple/pipe_simple_he.dm +++ b/code/ATMOSPHERICS/pipes/simple/pipe_simple_he.dm @@ -69,7 +69,7 @@ if(initPipe) normalize_dir() var/N = 2 - for(var/D in cardinal) + for(var/D in GLOB.cardinal) if(D & initialize_directions_he) N-- for(var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/target in get_step(src, D)) diff --git a/code/LINDA/LINDA_fire.dm b/code/LINDA/LINDA_fire.dm index 2fbfb1dff76..6ec505d9f9a 100644 --- a/code/LINDA/LINDA_fire.dm +++ b/code/LINDA/LINDA_fire.dm @@ -66,7 +66,7 @@ if(!fake) SSair.hotspots += src perform_exposure() - dir = pick(cardinal) + dir = pick(GLOB.cardinal) air_update_turf() /obj/effect/hotspot/proc/perform_exposure() @@ -133,7 +133,7 @@ //Possible spread due to radiated heat if(location.air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD) var/radiated_temperature = location.air.temperature*FIRE_SPREAD_RADIOSITY_SCALE - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if(!(location.atmos_adjacent_turfs & direction)) var/turf/simulated/wall/W = get_step(src, direction) if(istype(W)) @@ -309,7 +309,7 @@ if(dist == max_dist) continue - for(var/dir in cardinal) + for(var/dir in GLOB.cardinal) var/turf/link = get_step(T, dir) if (!link) continue diff --git a/code/LINDA/LINDA_system.dm b/code/LINDA/LINDA_system.dm index fd24dcc0c77..c5bc65d3bf7 100644 --- a/code/LINDA/LINDA_system.dm +++ b/code/LINDA/LINDA_system.dm @@ -62,7 +62,7 @@ turf/CanPass(atom/movable/mover, turf/target, height=1.5) /turf/proc/CalculateAdjacentTurfs() atmos_adjacent_turfs_amount = 0 - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) var/turf/T = get_step(src, direction) if(!istype(T)) continue @@ -89,7 +89,7 @@ turf/CanPass(atom/movable/mover, turf/target, height=1.5) var/adjacent_turfs = list() var/turf/simulated/curloc = src - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if(!(curloc.atmos_adjacent_turfs & direction)) continue @@ -99,11 +99,11 @@ turf/CanPass(atom/movable/mover, turf/target, height=1.5) if(!alldir) return adjacent_turfs - for(var/direction in diagonals) + for(var/direction in GLOB.diagonals) var/matchingDirections = 0 var/turf/simulated/S = get_step(curloc, direction) - for(var/checkDirection in cardinal) + for(var/checkDirection in GLOB.cardinal) if(!(S.atmos_adjacent_turfs & checkDirection)) continue var/turf/simulated/checkTurf = get_step(S, checkDirection) diff --git a/code/LINDA/LINDA_turf_tile.dm b/code/LINDA/LINDA_turf_tile.dm index b86ad2299ff..72f77d2440f 100644 --- a/code/LINDA/LINDA_turf_tile.dm +++ b/code/LINDA/LINDA_turf_tile.dm @@ -149,7 +149,7 @@ if (planet_atmos) atmos_adjacent_turfs_amount++ - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if(!(atmos_adjacent_turfs & direction)) continue @@ -260,9 +260,9 @@ /turf/simulated/proc/get_atmos_overlay_by_name(name) switch(name) if("plasma") - return plmaster + return GLOB.plmaster if("sleeping_agent") - return slmaster + return GLOB.slmaster return null /turf/simulated/proc/tile_graphic() @@ -412,13 +412,13 @@ archive() else //Does particate in air exchange so only consider directions not considered during process_cell() - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if(!(atmos_adjacent_turfs & direction) && !(atmos_supeconductivity & direction)) conductivity_directions += direction if(conductivity_directions>0) //Conduct with tiles around me - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if(conductivity_directions&direction) var/turf/neighbor = get_step(src,direction) @@ -499,7 +499,7 @@ turf/simulated/proc/radiate_to_spess() //Radiate excess tile heat to space /turf/simulated/Initialize_Atmos(times_fired) ..() update_visuals() - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if(!(atmos_adjacent_turfs & direction)) continue var/turf/enemy_tile = get_step(src, direction) diff --git a/code/__DEFINES/_spacemandmm.dm b/code/__DEFINES/_spacemandmm.dm new file mode 100644 index 00000000000..ca54ca4b932 --- /dev/null +++ b/code/__DEFINES/_spacemandmm.dm @@ -0,0 +1,26 @@ +// This file contains all the defines related to the spacemanDMM linter (dreamchecker). When running under normal conditions, BYOND will ignore all these +#ifdef SPACEMAN_DMM + #define RETURN_TYPE(X) set SpacemanDMM_return_type = X + #define SHOULD_CALL_PARENT(X) set SpacemanDMM_should_call_parent = X + #define UNLINT(X) SpacemanDMM_unlint(X) + #define SHOULD_NOT_OVERRIDE(X) set SpacemanDMM_should_not_override = X + #define SHOULD_NOT_SLEEP(X) + #define SHOULD_BE_PURE(X) + #define PRIVATE_PROC(X) + #define PROTECTED_PROC(X) + #define VAR_FINAL var/SpacemanDMM_final + #define VAR_PRIVATE var + #define VAR_PROTECTED var +#else + #define RETURN_TYPE(X) + #define SHOULD_CALL_PARENT(X) + #define UNLINT(X) X + #define SHOULD_NOT_OVERRIDE(X) + #define SHOULD_NOT_SLEEP(X) + #define SHOULD_BE_PURE(X) + #define PRIVATE_PROC(X) + #define PROTECTED_PROC(X) + #define VAR_FINAL var + #define VAR_PRIVATE var + #define VAR_PROTECTED var +#endif diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index bbf394c6c0b..95494fb88cf 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -40,10 +40,11 @@ #define R_MOD 8192 #define R_MENTOR 16384 #define R_PROCCALL 32768 +#define R_VIEWRUNTIMES 65536 -#define R_MAXPERMISSION 32768 //This holds the maximum value for a permission. It is used in iteration, so keep it updated. +#define R_MAXPERMISSION 65536 //This holds the maximum value for a permission. It is used in iteration, so keep it updated. -#define R_HOST 65535 +#define R_HOST 131071 // Sum of all permissions to allow easy setting #define ADMIN_QUE(user,display) "[display]" #define ADMIN_FLW(user,display) "[display]" diff --git a/code/__DEFINES/clothing.dm b/code/__DEFINES/clothing.dm index c39ce0947de..1678ea69c8e 100644 --- a/code/__DEFINES/clothing.dm +++ b/code/__DEFINES/clothing.dm @@ -78,7 +78,7 @@ //flags for covering body parts #define GLASSESCOVERSEYES 1 -#define MASKCOVERSEYES 2 // get rid of some of the other retardation in these flags +#define MASKCOVERSEYES 2 // get rid of some of the other mess in these flags #define HEADCOVERSEYES 4 // feel free to realloc these numbers for other purposes #define MASKCOVERSMOUTH 8 // on other items, these are just for mask/head #define HEADCOVERSMOUTH 16 @@ -92,8 +92,6 @@ #define BLOCKHEADHAIR 4 // temporarily removes the user's hair overlay. Leaves facial hair. #define BLOCKHAIR 32768 // temporarily removes the user's hair, facial and otherwise. -#define ONESIZEFITSALL 1 // determines if something can be worn by a fatty or not. - //flags for muzzle speech blocking #define MUZZLE_MUTE_NONE 0 // Does not mute you. #define MUZZLE_MUTE_MUFFLE 1 // Muffles everything you say "MHHPHHMMM!!! diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 13f7777d386..2bb53c91ce4 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -99,3 +99,12 @@ #define COLOR_ASSEMBLY_LBLUE "#5D99BE" #define COLOR_ASSEMBLY_BLUE "#38559E" #define COLOR_ASSEMBLY_PURPLE "#6F6192" + +// Pipe colours +#define PIPE_COLOR_GREY "#ffffff" //yes white is grey +#define PIPE_COLOR_RED "#ff0000" +#define PIPE_COLOR_BLUE "#0000ff" +#define PIPE_COLOR_CYAN "#00ffff" +#define PIPE_COLOR_GREEN "#00ff00" +#define PIPE_COLOR_YELLOW "#ffcc00" +#define PIPE_COLOR_PURPLE "#5c1ec0" diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 956930aae70..2f98b6ee7b5 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -35,7 +35,6 @@ #define CANPUSH 8 #define PASSEMOTES 16 //Mob has a cortical borer or holders inside of it that need to see emotes. #define GOTTAGOFAST 32 -#define GOTTAGOFAST_METH 64 #define IGNORESLOWDOWN 128 #define GODMODE 4096 #define FAKEDEATH 8192 //Replaces stuff like changeling.changeling_fakedeath diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm deleted file mode 100644 index c9691c195b8..00000000000 --- a/code/__DEFINES/components.dm +++ /dev/null @@ -1,291 +0,0 @@ -#define SEND_SIGNAL(target, sigtype, arguments...) ( !target.comp_lookup || !target.comp_lookup[sigtype] ? NONE : target._SendSignal(sigtype, list(target, ##arguments)) ) - -#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) ) - -//shorthand -#define GET_COMPONENT_FROM(varname, path, target) var##path/##varname = ##target.GetComponent(##path) -#define GET_COMPONENT(varname, path) GET_COMPONENT_FROM(varname, path, src) - -#define COMPONENT_INCOMPATIBLE 1 - -// How multiple components of the exact same type are handled in the same datum - -#define COMPONENT_DUPE_HIGHLANDER 0 //old component is deleted (default) -#define COMPONENT_DUPE_ALLOWED 1 //duplicates allowed -#define COMPONENT_DUPE_UNIQUE 2 //new component is deleted -#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 //old component is given the initialization args of the new - -// All signals. Format: -// When the signal is called: (signal arguments) -// All signals send the source datum of the signal as the first argument - -// global signals -// These are signals which can be listened to by any component on any parent -// start global signals with "!", this used to be necessary but now it's just a formatting choice -#define COMSIG_GLOB_NEW_Z "!new_z" //from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args) -#define COMSIG_GLOB_VAR_EDIT "!var_edit" //called after a successful var edit somewhere in the world: (list/args) -#define COMSIG_GLOB_MOB_CREATED "!mob_created" //mob was created somewhere : (mob) -#define COMSIG_GLOB_MOB_DEATH "!mob_death" //mob died somewhere : (mob , gibbed) - -////////////////////////////////////////////////////////////////// - -// /datum signals -#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component) -#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component) -#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation -#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called -#define COMSIG_TOPIC "handle_topic" //generic topic handler (usr, href_list) - -// /atom signals -#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params) - #define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called -#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human) -#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob, result) -#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" //from base of atom/get_examine_name(): (/mob, list/overrides) - //Positions for overrides list - #define EXAMINE_POSITION_ARTICLE 1 - #define EXAMINE_POSITION_BEFORE 2 - //End positions - #define COMPONENT_EXNAME_CHANGED 1 -#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable/entering, /atom) -#define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc) -#define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc) - #define COMPONENT_ATOM_BLOCK_EXIT 1 -#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target) -#define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity) -#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume) -#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" //from base of atom/bullet_act(): (/obj/item/projectile, def_zone) -#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" //from base of atom/blob_act(): (/obj/structure/blob) -#define COMSIG_ATOM_ACID_ACT "atom_acid_act" //from base of atom/acid_act(): (acidpwr, acid_volume) -#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" //from base of atom/emag_act(): () -#define COMSIG_ATOM_RAD_ACT "atom_rad_act" //from base of atom/rad_act(intensity) -#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" //from base of atom/narsie_act(): () -#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" //from base of atom/ratvar_act(): () -#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode) -#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size) -#define COMSIG_ATOM_SET_LIGHT "atom_set_light" //from base of atom/set_light(): (l_range, l_power, l_color) -#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" //from base of atom/setDir(): (old_dir, new_dir) -#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" //from base of atom/handle_atom_del(): (atom/deleted) -#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" //from base of atom/has_gravity(): (turf/location, list/forced_gravities) -#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" //from proc/get_rad_contents(): () - #define COMPONENT_BLOCK_RADIATION 1 -#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam" //from base of datum/radiation_wave/radiate(): (strength) - #define COMPONENT_BLOCK_CONTAMINATION 1 -#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass" //from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width) - #define COMPONENT_RAD_WAVE_HANDLED 1 -#define COMSIG_ATOM_CANREACH "atom_can_reach" //from internal loop in atom/movable/proc/CanReach(): (list/next) - #define COMPONENT_BLOCK_REACH 1 -#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" //from base of atom/screwdriver_act(): (mob/living/user, obj/item/I) -///////////////// -#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost" //from base of atom/attack_ghost(): (mob/dead/observer/ghost) -#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand" //from base of atom/attack_hand(): (mob/user) -#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw" //from base of atom/attack_paw(): (mob/user) - #define COMPONENT_NO_ATTACK_HAND 1 //works on all 3. -///////////////// - -#define COMSIG_ENTER_AREA "enter_area" //from base of area/Entered(): (/area) -#define COMSIG_EXIT_AREA "exit_area" //from base of area/Exited(): (/area) - -#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params, mob/user) -#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob) -#define COMSIG_CLICK_CTRL "ctrl_click" //from base of atom/CtrlClickOn(): (/mob) -#define COMSIG_CLICK_ALT "alt_click" //from base of atom/AltClick(): (/mob) -#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" //from base of atom/CtrlShiftClick(/mob) -#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto" //from base of atom/MouseDrop(): (/atom/over, /mob/user) - #define COMPONENT_NO_MOUSEDROP 1 -#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto" //from base of atom/MouseDrop_T: (/atom/from, /mob/user) - -// /area signals -#define COMSIG_AREA_ENTERED "area_entered" //from base of area/Entered(): (atom/movable/M) -#define COMSIG_AREA_EXITED "area_exited" //from base of area/Exited(): (atom/movable/M) - -// /turf signals -#define COMSIG_TURF_CHANGE "turf_change" //from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps) -#define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity" //from base of atom/has_gravity(): (atom/asker, list/forced_gravities) - -// /atom/movable signals -#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir) -#define COMSIG_MOVABLE_CROSS "movable_cross" //from base of atom/movable/Cross(): (/atom/movable) -#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable) -#define COMSIG_CROSSED_MOVABLE "crossed_movable" //when we cross over something (calling Crossed() on that atom) -#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" //from base of atom/movable/Uncrossed(): (/atom/movable) -#define COMSIG_MOVABLE_UNCROSS "movable_uncross" //from base of atom/movable/Uncross(): (/atom/movable) - #define COMPONENT_MOVABLE_BLOCK_UNCROSS 1 -#define COMSIG_MOVABLE_BUMP "movable_bump" //from base of atom/movable/Bump(): (/atom) -#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum) -#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone" //from base of mob/living/hitby(): (mob/living/target, hit_zone) -#define COMSIG_MOVABLE_BUCKLE "buckle" //from base of atom/movable/buckle_mob(): (mob, force) -#define COMSIG_MOVABLE_UNBUCKLE "unbuckle" //from base of atom/movable/unbuckle_mob(): (mob, force) -#define COMSIG_MOVABLE_PRE_THROW "movable_pre_throw" //from base of atom/movable/throw_at(): (list/args) - #define COMPONENT_CANCEL_THROW 1 -#define COMSIG_MOVABLE_POST_THROW "movable_post_throw" //from base of atom/movable/throw_at(): (datum/thrownthing, spin) -#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit" //from base of atom/movable/onTransitZ(): (old_z, new_z) -#define COMSIG_MOVABLE_HEAR "movable_hear" //from base of atom/movable/Hear(): (message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode) -#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source) - -// /mob signals -#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed) -#define COMSIG_MOB_CLICKON "mob_clickon" //from base of mob/clickon(): (atom/A, params) - #define COMSIG_MOB_CANCEL_CLICKON 1 -#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj -#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (magic, holy, protection_sources) - #define COMPONENT_BLOCK_MAGIC 1 -#define COMSIG_MOB_HUD_CREATED "mob_hud_created" //from base of mob/create_mob_hud(): () -#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" //from base of -#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" //from base of /obj/item/attack(): (mob/M, mob/user) -#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters) -#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //from base of mob/RangedAttack(): (atom/A, params) -#define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target) -#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): () - -// /mob/living signals -#define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living) -#define COMSIG_LIVING_IGNITED "living_ignite" //from base of mob/living/IgniteMob() (/mob/living) -#define COMSIG_LIVING_EXTINGUISHED "living_extinguished" //from base of mob/living/ExtinguishMob() (/mob/living) -#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage) -#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: () - -//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! -#define COMSIG_LIVING_STATUS_STUN "living_stun" //from base of mob/living/Stun() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" //from base of mob/living/Knockdown() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze" //from base of mob/living/Paralyze() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize" //from base of mob/living/Immobilize() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious" //from base of mob/living/Unconscious() (amount, update, ignore) -#define COMSIG_LIVING_STATUS_SLEEP "living_sleeping" //from base of mob/living/Sleeping() (amount, update, ignore) - #define COMPONENT_NO_STUN 1 //For all of them - -// /mob/living/carbon signals -#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity)) - -// /mob/living/simple_animal/hostile signals -#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" - #define COMPONENT_HOSTILE_NO_ATTACK 1 - -// /obj signals -#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled) -#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value) -#define COMSIG_OBJ_UPDATE_ICON "obj_update_icon" //called in /obj/update_icon() - - -// /obj/item signals -#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user) -#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob) - #define COMPONENT_NO_INTERACT 1 -#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob) - #define COMPONENT_NO_ATTACK_OBJ 1 -#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" //from base of obj/item/pre_attack(): (atom/target, mob/user, params) - #define COMPONENT_NO_ATTACK 1 -#define COMSIG_ITEM_AFTERATTACK "item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, params) -#define COMSIG_ITEM_EQUIPPED "item_equip" //from base of obj/item/equipped(): (/mob/equipper, slot) -#define COMSIG_ITEM_DROPPED "item_drop" //from base of obj/item/dropped(): (mob/user) -#define COMSIG_ITEM_PICKUP "item_pickup" //from base of obj/item/pickup(): (/mob/taker) -#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) -#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user) -#define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args) - -// /obj/item/clothing signals -#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () - -// /obj/item/implant signals -#define COMSIG_IMPLANT_ACTIVATED "implant_activated" //from base of /obj/item/implant/proc/activate(): () -#define COMSIG_IMPLANT_IMPLANTING "implant_implanting" //from base of /obj/item/implant/proc/implant(): (list/args) - #define COMPONENT_STOP_IMPLANTING 1 -#define COMSIG_IMPLANT_OTHER "implant_other" //called on already installed implants when a new one is being added in /obj/item/implant/proc/implant(): (list/args, obj/item/implant/new_implant) - //#define COMPONENT_STOP_IMPLANTING 1 //The name makes sense for both - #define COMPONENT_DELETE_NEW_IMPLANT 2 - #define COMPONENT_DELETE_OLD_IMPLANT 4 -#define COMSIG_IMPLANT_EXISTING_UPLINK "implant_uplink_exists" //called on implants being implanted into someone with an uplink implant: (datum/component/uplink) - //This uses all return values of COMSIG_IMPLANT_OTHER - -// /obj/item/pda signals -#define COMSIG_PDA_CHANGE_RINGTONE "pda_change_ringtone" //called on pda when the user changes the ringtone: (mob/living/user, new_ringtone) - #define COMPONENT_STOP_RINGTONE_CHANGE 1 - -// /obj/item/radio signals -#define COMSIG_RADIO_NEW_FREQUENCY "radio_new_frequency" //called from base of /obj/item/radio/proc/set_frequency(): (list/args) - -// /obj/item/pen signals -#define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user) - - -// /mob/living/carbon/human signals -#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target) -#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker) -#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted) - -// /datum/species signals -#define COMSIG_SPECIES_GAIN "species_gain" //from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species) -#define COMSIG_SPECIES_LOSS "species_loss" //from datum/species/on_species_loss(): (datum/species/lost_species) - -/*******Component Specific Signals*******/ -//Janitor -#define COMSIG_TURF_IS_WET "check_turf_wet" //(): Returns bitflags of wet values. -#define COMSIG_TURF_MAKE_DRY "make_turf_try" //(max_strength, immediate, duration_decrease = INFINITY): Returns bool. -#define COMSIG_COMPONENT_CLEAN_ACT "clean_act" //called on an object to clean it of cleanables. Usualy with soap: (num/strength) - -//Food -#define COMSIG_FOOD_EATEN "food_eaten" //from base of obj/item/reagent_containers/food/snacks/attack(): (mob/living/eater, mob/feeder) - -//Mood -#define COMSIG_ADD_MOOD_EVENT "add_mood" //Called when you send a mood event from anywhere in the code. -#define COMSIG_CLEAR_MOOD_EVENT "clear_mood" //Called when you clear a mood event from anywhere in the code. - -//NTnet -#define COMSIG_COMPONENT_NTNET_RECEIVE "ntnet_receive" //called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata)) - -//Nanites -#define COMSIG_HAS_NANITES "has_nanites" //() returns TRUE if nanites are found -#define COMSIG_NANITE_GET_PROGRAMS "nanite_get_programs" //(list/nanite_programs) - makes the input list a copy the nanites' program list -#define COMSIG_NANITE_SET_VOLUME "nanite_set_volume" //(amount) Sets current nanite volume to the given amount -#define COMSIG_NANITE_ADJUST_VOLUME "nanite_adjust" //(amount) Adjusts nanite volume by the given amount -#define COMSIG_NANITE_SET_MAX_VOLUME "nanite_set_max_volume" //(amount) Sets maximum nanite volume to the given amount -#define COMSIG_NANITE_SET_CLOUD "nanite_set_cloud" //(amount(0-100)) Sets cloud ID to the given amount -#define COMSIG_NANITE_SET_SAFETY "nanite_set_safety" //(amount) Sets safety threshold to the given amount -#define COMSIG_NANITE_SET_REGEN "nanite_set_regen" //(amount) Sets regeneration rate to the given amount -#define COMSIG_NANITE_SIGNAL "nanite_signal" //(code(1-9999)) Called when sending a nanite signal to a mob. -#define COMSIG_NANITE_SCAN "nanite_scan" //(mob/user, full_scan) - sends to chat a scan of the nanites to the user, returns TRUE if nanites are detected -#define COMSIG_NANITE_UI_DATA "nanite_ui_data" //(list/data, scan_level) - adds nanite data to the given data list - made for ui_data procs -#define COMSIG_NANITE_ADD_PROGRAM "nanite_add_program" //(datum/nanite_program/new_program, datum/nanite_program/source_program) Called when adding a program to a nanite component - #define COMPONENT_PROGRAM_INSTALLED 1 //Installation successful - #define COMPONENT_PROGRAM_NOT_INSTALLED 2 //Installation failed, but there are still nanites -#define COMSIG_NANITE_SYNC "nanite_sync" //(datum/component/nanites, full_overwrite, copy_activation) Called to sync the target's nanites to a given nanite component - -// /datum/component/storage signals -#define COMSIG_CONTAINS_STORAGE "is_storage" //() - returns bool. -#define COMSIG_TRY_STORAGE_INSERT "storage_try_insert" //(obj/item/inserting, mob/user, silent, force) - returns bool -#define COMSIG_TRY_STORAGE_SHOW "storage_show_to" //(mob/show_to, force) - returns bool. -#define COMSIG_TRY_STORAGE_HIDE_FROM "storage_hide_from" //(mob/hide_from) - returns bool -#define COMSIG_TRY_STORAGE_HIDE_ALL "storage_hide_all" //returns bool -#define COMSIG_TRY_STORAGE_SET_LOCKSTATE "storage_lock_set_state" //(newstate) -#define COMSIG_IS_STORAGE_LOCKED "storage_get_lockstate" //() - returns bool. MUST CHECK IF STORAGE IS THERE FIRST! -#define COMSIG_TRY_STORAGE_TAKE_TYPE "storage_take_type" //(type, atom/destination, amount = INFINITY, check_adjacent, force, mob/user, list/inserted) - returns bool - type can be a list of types. -#define COMSIG_TRY_STORAGE_FILL_TYPE "storage_fill_type" //(type, amount = INFINITY, force = FALSE) //don't fuck this up. Force will ignore max_items, and amount is normally clamped to max_items. -#define COMSIG_TRY_STORAGE_TAKE "storage_take_obj" //(obj, new_loc, force = FALSE) - returns bool -#define COMSIG_TRY_STORAGE_QUICK_EMPTY "storage_quick_empty" //(loc) - returns bool - if loc is null it will dump at parent location. -#define COMSIG_TRY_STORAGE_RETURN_INVENTORY "storage_return_inventory" //(list/list_to_inject_results_into, recursively_search_inside_storages = TRUE) -#define COMSIG_TRY_STORAGE_CAN_INSERT "storage_can_equip" //(obj/item/insertion_candidate, mob/user, silent) - returns bool - -// /datum/action signals -#define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action) - #define COMPONENT_ACTION_BLOCK_TRIGGER 1 - -/*******Non-Signal Component Related Defines*******/ - -//Redirection component init flags -#define REDIRECT_TRANSFER_WITH_TURF 1 - -//Arch -#define ARCH_PROB "probability" //Probability for each item -#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount - -//Ouch my toes! -#define CALTROP_BYPASS_SHOES 1 -#define CALTROP_IGNORE_WALKERS 2 - -//Xenobio hotkeys -#define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" //from slime CtrlClickOn(): (/mob) -#define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" //from slime AltClickOn(): (/mob) -#define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift" //from slime ShiftClickOn(): (/mob) -#define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift" //from turf ShiftClickOn(): (/mob) -#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" //from turf AltClickOn(): (/mob) -#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" //from monkey CtrlClickOn(): (/mob) diff --git a/code/__DEFINES/criminal_status.dm b/code/__DEFINES/criminal_status.dm new file mode 100644 index 00000000000..75c33909fc2 --- /dev/null +++ b/code/__DEFINES/criminal_status.dm @@ -0,0 +1,10 @@ +//criminal status defines +#define SEC_RECORD_STATUS_NONE "None" +#define SEC_RECORD_STATUS_ARREST "*Arrest*" +#define SEC_RECORD_STATUS_EXECUTE "*Execute*" +#define SEC_RECORD_STATUS_INCARCERATED "Incarcerated" +#define SEC_RECORD_STATUS_RELEASED "Released" +#define SEC_RECORD_STATUS_PAROLLED "Parolled" +#define SEC_RECORD_STATUS_DEMOTE "Demote" +#define SEC_RECORD_STATUS_SEARCH "Search" +#define SEC_RECORD_STATUS_MONITOR "Monitor" diff --git a/code/__DEFINES/dcs/flags.dm b/code/__DEFINES/dcs/flags.dm new file mode 100644 index 00000000000..128c9f19387 --- /dev/null +++ b/code/__DEFINES/dcs/flags.dm @@ -0,0 +1,41 @@ +/// Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. +/// `parent` must not be modified if this is to be returned. +/// This will be noted in the runtime logs +#define COMPONENT_INCOMPATIBLE 1 +/// Returned in PostTransfer to prevent transfer, similar to `COMPONENT_INCOMPATIBLE` +#define COMPONENT_NOTRANSFER 2 + +/// Return value to cancel attaching +#define ELEMENT_INCOMPATIBLE 1 + +// /datum/element flags +/// Causes the detach proc to be called when the host object is being deleted +#define ELEMENT_DETACH (1 << 0) +/** + * Only elements created with the same arguments given after `id_arg_index` share an element instance + * The arguments are the same when the text and number values are the same and all other values have the same ref + */ +#define ELEMENT_BESPOKE (1 << 1) + +// How multiple components of the exact same type are handled in the same datum +/// old component is deleted (default) +#define COMPONENT_DUPE_HIGHLANDER 0 +/// duplicates allowed +#define COMPONENT_DUPE_ALLOWED 1 +/// new component is deleted +#define COMPONENT_DUPE_UNIQUE 2 +/// old component is given the initialization args of the new +#define COMPONENT_DUPE_UNIQUE_PASSARGS 4 +/// each component of the same type is consulted as to whether the duplicate should be allowed +#define COMPONENT_DUPE_SELECTIVE 5 + +//Redirection component init flags +#define REDIRECT_TRANSFER_WITH_TURF 1 + +//Arch +#define ARCH_PROB "probability" //Probability for each item +#define ARCH_MAXDROP "max_drop_amount" //each item's max drop amount + +//Ouch my toes! +#define CALTROP_BYPASS_SHOES 1 +#define CALTROP_IGNORE_WALKERS 2 diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm new file mode 100644 index 00000000000..144e94f1fe0 --- /dev/null +++ b/code/__DEFINES/dcs/helpers.dm @@ -0,0 +1,15 @@ +/// Used to trigger signals and call procs registered for that signal +/// The datum hosting the signal is automaticaly added as the first argument +/// Returns a bitfield gathered from all registered procs +/// Arguments given here are packaged in a list and given to _SendSignal +#define SEND_SIGNAL(target, sigtype, arguments...) ( !target.comp_lookup || !target.comp_lookup[sigtype] ? NONE : target._SendSignal(sigtype, list(target, ##arguments)) ) + +#define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) ) + +/// A wrapper for _AddElement that allows us to pretend we're using normal named arguments +#define AddElement(arguments...) _AddElement(list(##arguments)) +/// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments +#define RemoveElement(arguments...) _RemoveElement(list(##arguments)) + +/// A wrapper for _AddComponent that allows us to pretend we're using normal named arguments +#define AddComponent(arguments...) _AddComponent(list(##arguments)) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm new file mode 100644 index 00000000000..10aa1718dda --- /dev/null +++ b/code/__DEFINES/dcs/signals.dm @@ -0,0 +1,728 @@ +// All signals. Format: +// When the signal is called: (signal arguments) +// All signals send the source datum of the signal as the first argument + +// global signals +// These are signals which can be listened to by any component on any parent +// start global signals with "!", this used to be necessary but now it's just a formatting choice + +///from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args) +#define COMSIG_GLOB_NEW_Z "!new_z" +/// called after a successful var edit somewhere in the world: (list/args) +#define COMSIG_GLOB_VAR_EDIT "!var_edit" +/// called after an explosion happened : (epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range) +#define COMSIG_GLOB_EXPLOSION "!explosion" +/// mob was created somewhere : (mob) +#define COMSIG_GLOB_MOB_CREATED "!mob_created" +/// mob died somewhere : (mob , gibbed) +#define COMSIG_GLOB_MOB_DEATH "!mob_death" +/// global living say plug - use sparingly: (mob/speaker , message) +#define COMSIG_GLOB_LIVING_SAY_SPECIAL "!say_special" +/// called by datum/cinematic/play() : (datum/cinematic/new_cinematic) +#define COMSIG_GLOB_PLAY_CINEMATIC "!play_cinematic" + #define COMPONENT_GLOB_BLOCK_CINEMATIC (1<<0) +/// ingame button pressed (/obj/machinery/button/button) +#define COMSIG_GLOB_BUTTON_PRESSED "!button_pressed" + +/// signals from globally accessible objects + +///from SSsun when the sun changes position : (azimuth) +#define COMSIG_SUN_MOVED "sun_moved" + +////////////////////////////////////////////////////////////////// + +// /datum signals +/// when a component is added to a datum: (/datum/component) +#define COMSIG_COMPONENT_ADDED "component_added" +/// before a component is removed from a datum because of RemoveComponent: (/datum/component) +#define COMSIG_COMPONENT_REMOVING "component_removing" +/// before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation +#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" +/// just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called +#define COMSIG_PARENT_QDELETING "parent_qdeleting" +/// generic topic handler (usr, href_list) +#define COMSIG_TOPIC "handle_topic" + +/// fires on the target datum when an element is attached to it (/datum/element) +#define COMSIG_ELEMENT_ATTACH "element_attach" +/// fires on the target datum when an element is attached to it (/datum/element) +#define COMSIG_ELEMENT_DETACH "element_detach" + +// /atom signals +///from base of atom/proc/Initialize(): sent any time a new atom is created +#define COMSIG_ATOM_CREATED "atom_created" +//from SSatoms InitAtom - Only if the atom was not deleted or failed initialization +#define COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE "atom_init_success" +///from base of atom/attackby(): (/obj/item, /mob/living, params) +#define COMSIG_PARENT_ATTACKBY "atom_attackby" +///Return this in response if you don't want afterattack to be called + #define COMPONENT_NO_AFTERATTACK (1<<0) +///from base of atom/attack_hulk(): (/mob/living/carbon/human) +#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" +///from base of atom/animal_attack(): (/mob/user) +#define COMSIG_ATOM_ATTACK_ANIMAL "attack_animal" +///from base of atom/examine(): (/mob) +#define COMSIG_PARENT_EXAMINE "atom_examine" +///from base of atom/get_examine_name(): (/mob, list/overrides) +#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" + //Positions for overrides list + #define EXAMINE_POSITION_ARTICLE (1<<0) + #define EXAMINE_POSITION_BEFORE (1<<1) + //End positions + #define COMPONENT_EXNAME_CHANGED (1<<0) +///from base of atom/update_icon(): () +#define COMSIG_ATOM_UPDATE_ICON "atom_update_icon" + #define COMSIG_ATOM_NO_UPDATE_ICON_STATE (1<<0) + #define COMSIG_ATOM_NO_UPDATE_OVERLAYS (1<<1) +///from base of atom/update_overlays(): (list/new_overlays) +#define COMSIG_ATOM_UPDATE_OVERLAYS "atom_update_overlays" +///from base of atom/update_icon(): (signalOut, did_anything) +#define COMSIG_ATOM_UPDATED_ICON "atom_updated_icon" +///from base of atom/Entered(): (atom/movable/entering, /atom) +#define COMSIG_ATOM_ENTERED "atom_entered" +///from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc) +#define COMSIG_ATOM_EXIT "atom_exit" + #define COMPONENT_ATOM_BLOCK_EXIT (1<<0) +///from base of atom/Exited(): (atom/movable/exiting, atom/newloc) +#define COMSIG_ATOM_EXITED "atom_exited" +///from base of atom/Bumped(): (/atom/movable) +#define COMSIG_ATOM_BUMPED "atom_bumped" +///from base of atom/ex_act(): (severity, target) +#define COMSIG_ATOM_EX_ACT "atom_ex_act" +///from base of atom/emp_act(): (severity) +#define COMSIG_ATOM_EMP_ACT "atom_emp_act" +///from base of atom/fire_act(): (exposed_temperature, exposed_volume) +#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" +///from base of atom/bullet_act(): (/obj/projectile, def_zone) +#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" +///from base of atom/blob_act(): (/obj/structure/blob) +#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" +///from base of atom/acid_act(): (acidpwr, acid_volume) +#define COMSIG_ATOM_ACID_ACT "atom_acid_act" +///from base of atom/emag_act(): (/mob/user) +#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" +///from base of atom/rad_act(intensity) +#define COMSIG_ATOM_RAD_ACT "atom_rad_act" +///from base of atom/narsie_act(): () +#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" +///from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode) +#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" +///from base of atom/singularity_pull(): (S, current_size) +#define COMSIG_ATOM_SING_PULL "atom_sing_pull" +///from obj/machinery/bsa/full/proc/fire(): () +#define COMSIG_ATOM_BSA_BEAM "atom_bsa_beam_pass" + #define COMSIG_ATOM_BLOCKS_BSA_BEAM (1<<0) +///from base of atom/set_light(): (l_range, l_power, l_color) +#define COMSIG_ATOM_SET_LIGHT "atom_set_light" +///from base of atom/setDir(): (old_dir, new_dir) +#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" +///from base of atom/handle_atom_del(): (atom/deleted) +#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" +///from base of atom/has_gravity(): (turf/location, list/forced_gravities) +#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" +///from proc/get_rad_contents(): () +#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" + #define COMPONENT_BLOCK_RADIATION (1<<0) +///from base of datum/radiation_wave/radiate(): (strength) +#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam" + #define COMPONENT_BLOCK_CONTAMINATION (1<<0) +///from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width) +#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass" + #define COMPONENT_RAD_WAVE_HANDLED (1<<0) +///from internal loop in atom/movable/proc/CanReach(): (list/next) +#define COMSIG_ATOM_CANREACH "atom_can_reach" + #define COMPONENT_BLOCK_REACH (1<<0) +///from base of atom/screwdriver_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" +///from base of atom/wrench_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_WRENCH_ACT "atom_wrench_act" +///from base of atom/multitool_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_MULTITOOL_ACT "atom_multitool_act" +///from base of atom/welder_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_WELDER_ACT "atom_welder_act" +///from base of atom/wirecutter_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_WIRECUTTER_ACT "atom_wirecutter_act" +///from base of atom/crowbar_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_CROWBAR_ACT "atom_crowbar_act" +///from base of atom/analyser_act(): (mob/living/user, obj/item/I) +#define COMSIG_ATOM_ANALYSER_ACT "atom_analyser_act" + #define COMPONENT_BLOCK_TOOL_ATTACK (1<<0) +///called when teleporting into a protected turf: (channel, turf/origin) +#define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport" + #define COMPONENT_BLOCK_TELEPORT (1<<0) +///called when an atom is added to the hearers on get_hearers_in_view(): (list/processing_list, list/hearers) +#define COMSIG_ATOM_HEARER_IN_VIEW "atom_hearer_in_view" +///called when an atom starts orbiting another atom: (atom) +#define COMSIG_ATOM_ORBIT_BEGIN "atom_orbit_begin" +///called when an atom stops orbiting another atom: (atom) +#define COMSIG_ATOM_ORBIT_STOP "atom_orbit_stop" +///////////////// +///from base of atom/attack_ghost(): (mob/dead/observer/ghost) +#define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost" +///from base of atom/attack_hand(): (mob/user) +#define COMSIG_ATOM_ATTACK_HAND "atom_attack_hand" +///from base of atom/attack_paw(): (mob/user) +#define COMSIG_ATOM_ATTACK_PAW "atom_attack_paw" + #define COMPONENT_NO_ATTACK_HAND (1<<0) //works on all 3. +//This signal return value bitflags can be found in __DEFINES/misc.dm + +///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels) +#define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact" +///called on a movable (NOT living) when someone starts pulling it (atom/movable/puller, state, force) +#define COMSIG_ATOM_START_PULL "movable_start_pull" +///called on /living when someone starts pulling it (atom/movable/puller, state, force) +#define COMSIG_LIVING_START_PULL "living_start_pull" + +///////////////// + +///from base of area/Entered(): (/area) +#define COMSIG_ENTER_AREA "enter_area" +///from base of area/Exited(): (/area) +#define COMSIG_EXIT_AREA "exit_area" +///from base of atom/Click(): (location, control, params, mob/user) +#define COMSIG_CLICK "atom_click" +///from base of atom/ShiftClick(): (/mob) +#define COMSIG_CLICK_SHIFT "shift_click" + #define COMPONENT_ALLOW_EXAMINATE (1<<0) //Allows the user to examinate regardless of client.eye. +///from base of atom/CtrlClickOn(): (/mob) +#define COMSIG_CLICK_CTRL "ctrl_click" +///from base of atom/AltClick(): (/mob) +#define COMSIG_CLICK_ALT "alt_click" +///from base of atom/CtrlShiftClick(/mob) +#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" +///from base of atom/MouseDrop(): (/atom/over, /mob/user) +#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto" + #define COMPONENT_NO_MOUSEDROP (1<<0) +///from base of atom/MouseDrop_T: (/atom/from, /mob/user) +#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto" + +// /area signals + +///from base of area/Entered(): (atom/movable/M) +#define COMSIG_AREA_ENTERED "area_entered" +///from base of area/Exited(): (atom/movable/M) +#define COMSIG_AREA_EXITED "area_exited" + +// /turf signals + +///from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps) +#define COMSIG_TURF_CHANGE "turf_change" +///from base of atom/has_gravity(): (atom/asker, list/forced_gravities) +#define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity" +///from base of turf/New(): (turf/source, direction) +#define COMSIG_TURF_MULTIZ_NEW "turf_multiz_new" + +// /atom/movable signals + +///from base of atom/movable/Moved(): (/atom) +#define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move" + #define COMPONENT_MOVABLE_BLOCK_PRE_MOVE (1<<0) +///from base of atom/movable/Moved(): (/atom, dir) +#define COMSIG_MOVABLE_MOVED "movable_moved" +///from base of atom/movable/Cross(): (/atom/movable) +#define COMSIG_MOVABLE_CROSS "movable_cross" +///from base of atom/movable/Crossed(): (/atom/movable) +#define COMSIG_MOVABLE_CROSSED "movable_crossed" +///when we cross over something (calling Crossed() on that atom) +#define COMSIG_CROSSED_MOVABLE "crossed_movable" +///from base of atom/movable/Uncross(): (/atom/movable) +#define COMSIG_MOVABLE_UNCROSS "movable_uncross" + #define COMPONENT_MOVABLE_BLOCK_UNCROSS (1<<0) +///from base of atom/movable/Uncrossed(): (/atom/movable) +#define COMSIG_MOVABLE_UNCROSSED "movable_uncrossed" +///from base of atom/movable/Bump(): (/atom) +#define COMSIG_MOVABLE_BUMP "movable_bump" +///from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum) +#define COMSIG_MOVABLE_IMPACT "movable_impact" + #define COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH (1<<0) //if true, flip if the impact will push what it hits + #define COMPONENT_MOVABLE_IMPACT_NEVERMIND (1<<1) //return true if you destroyed whatever it was you're impacting and there won't be anything for hitby() to run on +///from base of mob/living/hitby(): (mob/living/target, hit_zone) +#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone" +///from base of atom/movable/buckle_mob(): (mob, force) +#define COMSIG_MOVABLE_BUCKLE "buckle" +///from base of atom/movable/unbuckle_mob(): (mob, force) +#define COMSIG_MOVABLE_UNBUCKLE "unbuckle" +///from base of atom/movable/throw_at(): (list/args) +#define COMSIG_MOVABLE_PRE_THROW "movable_pre_throw" + #define COMPONENT_CANCEL_THROW (1<<0) +///from base of atom/movable/throw_at(): (datum/thrownthing, spin) +#define COMSIG_MOVABLE_POST_THROW "movable_post_throw" +///from base of atom/movable/onTransitZ(): (old_z, new_z) +#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit" +///called when the movable is placed in an unaccessible area, used for stationloving: () +#define COMSIG_MOVABLE_SECLUDED_LOCATION "movable_secluded" +///from base of atom/movable/Hear(): (proc args list(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)) +#define COMSIG_MOVABLE_HEAR "movable_hear" + #define HEARING_MESSAGE 1 + #define HEARING_SPEAKER 2 +// #define HEARING_LANGUAGE 3 + #define HEARING_RAW_MESSAGE 4 + /* #define HEARING_RADIO_FREQ 5 + #define HEARING_SPANS 6 + #define HEARING_MESSAGE_MODE 7 */ + +///called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source) +#define COMSIG_MOVABLE_DISPOSING "movable_disposing" + +// /mob signals + +///from base of /mob/Login(): () +#define COMSIG_MOB_LOGIN "mob_login" +///from base of /mob/Logout(): () +#define COMSIG_MOB_LOGOUT "mob_logout" +///from base of mob/death(): (gibbed) +#define COMSIG_MOB_DEATH "mob_death" +///from base of mob/set_stat(): (new_stat) +#define COMSIG_MOB_STATCHANGE "mob_statchange" +///from base of mob/clickon(): (atom/A, params) +#define COMSIG_MOB_CLICKON "mob_clickon" +///from base of mob/MiddleClickOn(): (atom/A) +#define COMSIG_MOB_MIDDLECLICKON "mob_middleclickon" +///from base of mob/AltClickOn(): (atom/A) +#define COMSIG_MOB_ALTCLICKON "mob_altclickon" + #define COMSIG_MOB_CANCEL_CLICKON (1<<0) + +///from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj +#define COMSIG_MOB_ALLOWED "mob_allowed" +///from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources) +#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" + #define COMPONENT_BLOCK_MAGIC (1<<0) +///from base of mob/create_mob_hud(): () +#define COMSIG_MOB_HUD_CREATED "mob_hud_created" +///from base of atom/attack_hand(): (mob/user) +#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" +///from base of /obj/item/attack(): (mob/M, mob/user) +#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" + #define COMPONENT_ITEM_NO_ATTACK (1<<0) +///from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone) +#define COMSIG_MOB_APPLY_DAMGE "mob_apply_damage" +///from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters) +#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" +///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, proxiumity_flag, click_parameters) +#define COMSIG_MOB_ITEM_ATTACK_QDELETED "mob_item_attack_qdeleted" +///from base of mob/RangedAttack(): (atom/A, params) +#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" +///from base of /mob/throw_item(): (atom/target) +#define COMSIG_MOB_THROW "mob_throw" +///from base of /mob/verb/examinate(): (atom/target) +#define COMSIG_MOB_EXAMINATE "mob_examinate" +///from base of /mob/update_sight(): () +#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" +////from /mob/living/say(): () +#define COMSIG_MOB_SAY "mob_say" + #define COMPONENT_UPPERCASE_SPEECH (1<<0) + // used to access COMSIG_MOB_SAY argslist + #define SPEECH_MESSAGE 1 + // #define SPEECH_BUBBLE_TYPE 2 + #define SPEECH_SPANS 3 + /* #define SPEECH_SANITIZE 4 + #define SPEECH_LANGUAGE 5 + #define SPEECH_IGNORE_SPAM 6 + #define SPEECH_FORCED 7 */ + +///from /mob/say_dead(): (mob/speaker, message) +#define COMSIG_MOB_DEADSAY "mob_deadsay" + #define MOB_DEADSAY_SIGNAL_INTERCEPT (1<<0) +///from /mob/living/emote(): () +#define COMSIG_MOB_EMOTE "mob_emote" +///from base of mob/swap_hand(): (obj/item) +#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands" + #define COMPONENT_BLOCK_SWAP (1<<0) + +// /mob/living signals + +///from base of mob/living/resist() (/mob/living) +#define COMSIG_LIVING_RESIST "living_resist" +///from base of mob/living/IgniteMob() (/mob/living) +#define COMSIG_LIVING_IGNITED "living_ignite" +///from base of mob/living/ExtinguishMob() (/mob/living) +#define COMSIG_LIVING_EXTINGUISHED "living_extinguished" +///from base of mob/living/electrocute_act(): (shock_damage, source, siemens_coeff, flags) +#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" +///sent when items with siemen coeff. of 0 block a shock: (power_source, source, siemens_coeff, dist_check) +#define COMSIG_LIVING_SHOCK_PREVENTED "living_shock_prevented" +///sent by stuff like stunbatons and tasers: () +#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" +///from base of mob/living/revive() (full_heal, admin_revive) +#define COMSIG_LIVING_REVIVE "living_revive" +///from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs) +#define COMSIG_LIVING_REGENERATE_LIMBS "living_regen_limbs" +///from base of /obj/item/bodypart/proc/attach_limb(): (new_limb, special) allows you to fail limb attachment +#define COMSIG_LIVING_ATTACH_LIMB "living_attach_limb" + #define COMPONENT_NO_ATTACH (1<<0) +///sent from borg recharge stations: (amount, repairs) +#define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge" +///sent when a mob/login() finishes: (client) +#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" +///sent from borg mobs to itself, for tools to catch an upcoming destroy() due to safe decon (rather than detonation) +#define COMSIG_BORG_SAFE_DECONSTRUCT "borg_safe_decon" + +//ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! + +///from base of mob/living/Stun() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_STUN "living_stun" +///from base of mob/living/Knockdown() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" +///from base of mob/living/Paralyze() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze" +///from base of mob/living/Immobilize() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize" +///from base of mob/living/Unconscious() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious" +///from base of mob/living/Sleeping() (amount, update, ignore) +#define COMSIG_LIVING_STATUS_SLEEP "living_sleeping" + #define COMPONENT_NO_STUN (1<<0) //For all of them +///from base of /mob/living/can_track(): (mob/user) +#define COMSIG_LIVING_CAN_TRACK "mob_cantrack" + #define COMPONENT_CANT_TRACK (1<<0) + +// /mob/living/carbon signals + +///from base of mob/living/carbon/soundbang_act(): (list(intensity)) +#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" +///from /item/organ/proc/Insert() (/obj/item/organ/) +#define COMSIG_CARBON_GAIN_ORGAN "carbon_gain_organ" +///from /item/organ/proc/Remove() (/obj/item/organ/) +#define COMSIG_CARBON_LOSE_ORGAN "carbon_lose_organ" +///from /mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop, silent) +#define COMSIG_CARBON_EQUIP_HAT "carbon_equip_hat" +///from /mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop, silent) +#define COMSIG_CARBON_UNEQUIP_HAT "carbon_unequip_hat" +///defined twice, in carbon and human's topics, fired when interacting with a valid embedded_object to pull it out (mob/living/carbon/target, /obj/item, /obj/item/bodypart/L) +#define COMSIG_CARBON_EMBED_RIP "item_embed_start_rip" +///called when removing a given item from a mob, from mob/living/carbon/remove_embedded_object(mob/living/carbon/target, /obj/item) +#define COMSIG_CARBON_EMBED_REMOVAL "item_embed_remove_safe" + +// /mob/living/simple_animal/hostile signals +#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" + #define COMPONENT_HOSTILE_NO_ATTACK (1<<0) + +// /obj signals + +///from base of obj/deconstruct(): (disassembled) +#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" +///called in /obj/structure/setAnchored(): (value) +#define COMSIG_OBJ_SETANCHORED "obj_setanchored" +///from base of code/game/machinery +#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench" +///from base of /turf/proc/levelupdate(). (intact) true to hide and false to unhide +#define COMSIG_OBJ_HIDE "obj_hide" +///called in /obj/update_icon() +#define COMSIG_OBJ_UPDATE_ICON "obj_update_icon" + +// /obj/machinery signals + +///from /obj/machinery/obj_break(damage_flag): (damage_flag) +#define COMSIG_MACHINERY_BROKEN "machinery_broken" +///from base power_change() when power is lost +#define COMSIG_MACHINERY_POWER_LOST "machinery_power_lost" +///from base power_change() when power is restored +#define COMSIG_MACHINERY_POWER_RESTORED "machinery_power_restored" + +// /obj/item signals + +///from base of obj/item/attack(): (/mob/living/target, /mob/living/user) +#define COMSIG_ITEM_ATTACK "item_attack" +///from base of obj/item/attack_self(): (/mob) +#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" + #define COMPONENT_NO_INTERACT (1<<0) +///from base of obj/item/attack_obj(): (/obj, /mob) +#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" + #define COMPONENT_NO_ATTACK_OBJ (1<<0) +///from base of obj/item/pre_attack(): (atom/target, mob/user, params) +#define COMSIG_ITEM_PRE_ATTACK "item_pre_attack" + #define COMPONENT_NO_ATTACK (1<<0) +///from base of obj/item/afterattack(): (atom/target, mob/user, params) +#define COMSIG_ITEM_AFTERATTACK "item_afterattack" +///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, params) +#define COMSIG_ITEM_ATTACK_QDELETED "item_attack_qdeleted" +///from base of obj/item/equipped(): (/mob/equipper, slot) +#define COMSIG_ITEM_EQUIPPED "item_equip" +///from base of obj/item/dropped(): (mob/user) +#define COMSIG_ITEM_DROPPED "item_drop" +///from base of obj/item/pickup(): (/mob/taker) +#define COMSIG_ITEM_PICKUP "item_pickup" +///from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) +#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" +///return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user) +#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" +///called before marking an object for retrieval, checked in /obj/effect/proc_holder/spell/targeted/summonitem/cast() : (mob/user) +#define COMSIG_ITEM_MARK_RETRIEVAL "item_mark_retrieval" + #define COMPONENT_BLOCK_MARK_RETRIEVAL (1<<0) +///from base of obj/item/hit_reaction(): (list/args) +#define COMSIG_ITEM_HIT_REACT "item_hit_react" +///called on item when crossed by something (): (/atom/movable, mob/living/crossed) +#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" +///called on item when microwaved (): (obj/machinery/microwave/M) +#define COMSIG_ITEM_MICROWAVE_ACT "microwave_act" +///from base of item/sharpener/attackby(): (amount, max) +#define COMSIG_ITEM_SHARPEN_ACT "sharpen_act" + #define COMPONENT_BLOCK_SHARPEN_APPLIED (1<<0) + #define COMPONENT_BLOCK_SHARPEN_BLOCKED (1<<1) + #define COMPONENT_BLOCK_SHARPEN_ALREADY (1<<2) + #define COMPONENT_BLOCK_SHARPEN_MAXED (1<<3) +///from base of [/obj/item/proc/tool_check_callback]: (mob/living/user) +#define COMSIG_TOOL_IN_USE "tool_in_use" +///from base of [/obj/item/proc/tool_start_check]: (mob/living/user) +#define COMSIG_TOOL_START_USE "tool_start_use" +///from [/obj/item/proc/disableEmbedding]: +#define COMSIG_ITEM_DISABLE_EMBED "item_disable_embed" +///from [/obj/effect/mine/proc/triggermine]: +#define COMSIG_MINE_TRIGGERED "minegoboom" + +// /obj/item signals for economy +///called when an item is sold by the exports subsystem +#define COMSIG_ITEM_SOLD "item_sold" +///called when a wrapped up structure is opened by hand +#define COMSIG_STRUCTURE_UNWRAPPED "structure_unwrapped" +#define COMSIG_ITEM_UNWRAPPED "item_unwrapped" +///called when a wrapped up item is opened by hand + #define COMSIG_ITEM_SPLIT_VALUE (1<<0) +///called when getting the item's exact ratio for cargo's profit. +#define COMSIG_ITEM_SPLIT_PROFIT "item_split_profits" +///called when getting the item's exact ratio for cargo's profit, without selling the item. +#define COMSIG_ITEM_SPLIT_PROFIT_DRY "item_split_profits_dry" + +// /obj/item/clothing signals + +///from base of obj/item/clothing/shoes/proc/step_action(): () +#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" +///from base of /obj/item/clothing/suit/space/proc/toggle_spacesuit(): (obj/item/clothing/suit/space/suit) +#define COMSIG_SUIT_SPACE_TOGGLE "suit_space_toggle" + +// /obj/item/implant signals +///from base of /obj/item/implant/proc/activate(): () +#define COMSIG_IMPLANT_ACTIVATED "implant_activated" +///from base of /obj/item/implant/proc/implant(): (list/args) +#define COMSIG_IMPLANT_IMPLANTING "implant_implanting" + #define COMPONENT_STOP_IMPLANTING (1<<0) +///called on already installed implants when a new one is being added in /obj/item/implant/proc/implant(): (list/args, obj/item/implant/new_implant) +#define COMSIG_IMPLANT_OTHER "implant_other" + //#define COMPONENT_STOP_IMPLANTING (1<<0) //The name makes sense for both + #define COMPONENT_DELETE_NEW_IMPLANT (1<<1) + #define COMPONENT_DELETE_OLD_IMPLANT (1<<2) +///called on implants being implanted into someone with an uplink implant: (datum/component/uplink) +#define COMSIG_IMPLANT_EXISTING_UPLINK "implant_uplink_exists" + //This uses all return values of COMSIG_IMPLANT_OTHER + +// /obj/item/pda signals + +///called on pda when the user changes the ringtone: (mob/living/user, new_ringtone) +#define COMSIG_PDA_CHANGE_RINGTONE "pda_change_ringtone" + #define COMPONENT_STOP_RINGTONE_CHANGE (1<<0) +#define COMSIG_PDA_CHECK_DETONATE "pda_check_detonate" + #define COMPONENT_PDA_NO_DETONATE (1<<0) + +// /obj/item/radio signals + +///called from base of /obj/item/radio/proc/set_frequency(): (list/args) +#define COMSIG_RADIO_NEW_FREQUENCY "radio_new_frequency" + +// /obj/item/pen signals + +///called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user) +#define COMSIG_PEN_ROTATED "pen_rotated" + +// /obj/item/gun signals + +///called in /obj/item/gun/process_fire (user, target, params, zone_override) +#define COMSIG_MOB_FIRED_GUN "mob_fired_gun" + +// /obj/item/grenade signals + +///called in /obj/item/gun/process_fire (user, target, params, zone_override) +#define COMSIG_GRENADE_PRIME "grenade_prime" +///called in /obj/item/gun/process_fire (user, target, params, zone_override) +#define COMSIG_GRENADE_ARMED "grenade_armed" + +// /obj/projectile signals (sent to the firer) + +///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle) +#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" +///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle) +#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" +///from base of /obj/projectile/proc/fire(): (obj/projectile, atom/original_target) +#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" +///from the base of /obj/projectile/proc/fire(): () +#define COMSIG_PROJECTILE_FIRE "projectile_fire" +///sent to targets during the process_hit proc of projectiles +#define COMSIG_PROJECTILE_PREHIT "com_proj_prehit" +///sent to targets during the process_hit proc of projectiles +#define COMSIG_PROJECTILE_RANGE_OUT "projectile_range_out" +///sent when trying to force an embed (mainly for projectiles, only used in the embed element) +#define COMSIG_EMBED_TRY_FORCE "item_try_embed" + +///sent to targets during the process_hit proc of projectiles +#define COMSIG_PELLET_CLOUD_INIT "pellet_cloud_init" + +// /obj/mecha signals + +///sent from mecha action buttons to the mecha they're linked to +#define COMSIG_MECHA_ACTION_ACTIVATE "mecha_action_activate" + +// /mob/living/carbon/human signals + +///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity) +#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack" +///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity) +#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" +///from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker) +#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" +///Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted) +#define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" +///Whenever EquipRanked is called, called after job is set +#define COMSIG_JOB_RECEIVED "job_received" + +// /datum/species signals + +///from datum/species/on_species_gain(): (datum/species/new_species, datum/species/old_species) +#define COMSIG_SPECIES_GAIN "species_gain" +///from datum/species/on_species_loss(): (datum/species/lost_species) +#define COMSIG_SPECIES_LOSS "species_loss" + +// /datum/song signals + +///sent to the instrument when a song starts playing +#define COMSIG_SONG_START "song_start" +///sent to the instrument when a song stops playing +#define COMSIG_SONG_END "song_end" + +/*******Component Specific Signals*******/ +//Janitor + +///(): Returns bitflags of wet values. +#define COMSIG_TURF_IS_WET "check_turf_wet" +///(max_strength, immediate, duration_decrease = INFINITY): Returns bool. +#define COMSIG_TURF_MAKE_DRY "make_turf_try" +///called on an object to clean it of cleanables. Usualy with soap: (num/strength) +#define COMSIG_COMPONENT_CLEAN_ACT "clean_act" + +//Creamed + +///called when you wash your face at a sink: (num/strength) +#define COMSIG_COMPONENT_CLEAN_FACE_ACT "clean_face_act" + +//Food + +///from base of obj/item/reagent_containers/food/snacks/attack(): (mob/living/eater, mob/feeder) +#define COMSIG_FOOD_EATEN "food_eaten" + +//Gibs + +///from base of /obj/effect/decal/cleanable/blood/gibs/streak(): (list/directions, list/diseases) +#define COMSIG_GIBS_STREAK "gibs_streak" + +//Mood + +///called when you send a mood event from anywhere in the code. +#define COMSIG_ADD_MOOD_EVENT "add_mood" +///Mood event that only RnD members listen for +#define COMSIG_ADD_MOOD_EVENT_RND "RND_add_mood" +///called when you clear a mood event from anywhere in the code. +#define COMSIG_CLEAR_MOOD_EVENT "clear_mood" + +//NTnet + +///called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata)) +#define COMSIG_COMPONENT_NTNET_RECEIVE "ntnet_receive" + +//Nanites + +///() returns TRUE if nanites are found +#define COMSIG_HAS_NANITES "has_nanites" +///() returns TRUE if nanites have stealth +#define COMSIG_NANITE_IS_STEALTHY "nanite_is_stealthy" +///() deletes the nanite component +#define COMSIG_NANITE_DELETE "nanite_delete" +///(list/nanite_programs) - makes the input list a copy the nanites' program list +#define COMSIG_NANITE_GET_PROGRAMS "nanite_get_programs" +///(amount) Returns nanite amount +#define COMSIG_NANITE_GET_VOLUME "nanite_get_volume" +///(amount) Sets current nanite volume to the given amount +#define COMSIG_NANITE_SET_VOLUME "nanite_set_volume" +///(amount) Adjusts nanite volume by the given amount +#define COMSIG_NANITE_ADJUST_VOLUME "nanite_adjust" +///(amount) Sets maximum nanite volume to the given amount +#define COMSIG_NANITE_SET_MAX_VOLUME "nanite_set_max_volume" +///(amount(0-100)) Sets cloud ID to the given amount +#define COMSIG_NANITE_SET_CLOUD "nanite_set_cloud" +///(method) Modify cloud sync status. Method can be toggle, enable or disable +#define COMSIG_NANITE_SET_CLOUD_SYNC "nanite_set_cloud_sync" +///(amount) Sets safety threshold to the given amount +#define COMSIG_NANITE_SET_SAFETY "nanite_set_safety" +///(amount) Sets regeneration rate to the given amount +#define COMSIG_NANITE_SET_REGEN "nanite_set_regen" +///(code(1-9999)) Called when sending a nanite signal to a mob. +#define COMSIG_NANITE_SIGNAL "nanite_signal" +///(comm_code(1-9999), comm_message) Called when sending a nanite comm signal to a mob. +#define COMSIG_NANITE_COMM_SIGNAL "nanite_comm_signal" +///(mob/user, full_scan) - sends to chat a scan of the nanites to the user, returns TRUE if nanites are detected +#define COMSIG_NANITE_SCAN "nanite_scan" +///(list/data, scan_level) - adds nanite data to the given data list - made for ui_data procs +#define COMSIG_NANITE_UI_DATA "nanite_ui_data" +///(datum/nanite_program/new_program, datum/nanite_program/source_program) Called when adding a program to a nanite component +#define COMSIG_NANITE_ADD_PROGRAM "nanite_add_program" + ///Installation successful + #define COMPONENT_PROGRAM_INSTALLED (1<<0) + ///Installation failed, but there are still nanites + #define COMPONENT_PROGRAM_NOT_INSTALLED (1<<1) +///(datum/component/nanites, full_overwrite, copy_activation) Called to sync the target's nanites to a given nanite component +#define COMSIG_NANITE_SYNC "nanite_sync" + +// /datum/component/storage signals + +///() - returns bool. +#define COMSIG_CONTAINS_STORAGE "is_storage" +///(obj/item/inserting, mob/user, silent, force) - returns bool +#define COMSIG_TRY_STORAGE_INSERT "storage_try_insert" +///(mob/show_to, force) - returns bool. +#define COMSIG_TRY_STORAGE_SHOW "storage_show_to" +///(mob/hide_from) - returns bool +#define COMSIG_TRY_STORAGE_HIDE_FROM "storage_hide_from" +///returns bool +#define COMSIG_TRY_STORAGE_HIDE_ALL "storage_hide_all" +///(newstate) +#define COMSIG_TRY_STORAGE_SET_LOCKSTATE "storage_lock_set_state" +///() - returns bool. MUST CHECK IF STORAGE IS THERE FIRST! +#define COMSIG_IS_STORAGE_LOCKED "storage_get_lockstate" +///(type, atom/destination, amount = INFINITY, check_adjacent, force, mob/user, list/inserted) - returns bool - type can be a list of types. +#define COMSIG_TRY_STORAGE_TAKE_TYPE "storage_take_type" +///(type, amount = INFINITY, force = FALSE). Force will ignore max_items, and amount is normally clamped to max_items. +#define COMSIG_TRY_STORAGE_FILL_TYPE "storage_fill_type" +///(obj, new_loc, force = FALSE) - returns bool +#define COMSIG_TRY_STORAGE_TAKE "storage_take_obj" +///(loc) - returns bool - if loc is null it will dump at parent location. +#define COMSIG_TRY_STORAGE_QUICK_EMPTY "storage_quick_empty" +///(list/list_to_inject_results_into, recursively_search_inside_storages = TRUE) +#define COMSIG_TRY_STORAGE_RETURN_INVENTORY "storage_return_inventory" +///(obj/item/insertion_candidate, mob/user, silent) - returns bool +#define COMSIG_TRY_STORAGE_CAN_INSERT "storage_can_equip" + +// /datum/component/two_handed signals + +///from base of datum/component/two_handed/proc/wield(mob/living/carbon/user): (/mob/user) +#define COMSIG_TWOHANDED_WIELD "twohanded_wield" + #define COMPONENT_TWOHANDED_BLOCK_WIELD (1<<0) +///from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user) +#define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield" + +// /datum/action signals + +///from base of datum/action/proc/Trigger(): (datum/action) +#define COMSIG_ACTION_TRIGGER "action_trigger" + #define COMPONENT_ACTION_BLOCK_TRIGGER (1<<0) + +//Xenobio hotkeys + +///from slime CtrlClickOn(): (/mob) +#define COMSIG_XENO_SLIME_CLICK_CTRL "xeno_slime_click_ctrl" +///from slime AltClickOn(): (/mob) +#define COMSIG_XENO_SLIME_CLICK_ALT "xeno_slime_click_alt" +///from slime ShiftClickOn(): (/mob) +#define COMSIG_XENO_SLIME_CLICK_SHIFT "xeno_slime_click_shift" +///from turf ShiftClickOn(): (/mob) +#define COMSIG_XENO_TURF_CLICK_SHIFT "xeno_turf_click_shift" +///from turf AltClickOn(): (/mob) +#define COMSIG_XENO_TURF_CLICK_CTRL "xeno_turf_click_alt" +///from monkey CtrlClickOn(): (/mob) +#define COMSIG_XENO_MONKEY_CLICK_CTRL "xeno_monkey_click_ctrl" diff --git a/code/__DEFINES/dna.dm b/code/__DEFINES/dna.dm new file mode 100644 index 00000000000..7984c1a6dde --- /dev/null +++ b/code/__DEFINES/dna.dm @@ -0,0 +1,57 @@ +// Defines for all genetics/DNA related stuff + +// What each index means: +#define DNA_OFF_LOWERBOUND 1 // changed as lists start at 1 not 0 +#define DNA_OFF_UPPERBOUND 2 +#define DNA_ON_LOWERBOUND 3 +#define DNA_ON_UPPERBOUND 4 + +// Define block bounds (off-low,off-high,on-low,on-high) +// Used in setupgame.dm +#define DNA_DEFAULT_BOUNDS list(1,2049,2050,4095) +#define DNA_HARDER_BOUNDS list(1,3049,3050,4095) +#define DNA_HARD_BOUNDS list(1,3490,3500,4095) + +// UI Indices (can change to mutblock style, if desired) +#define DNA_UI_HAIR_R 1 +#define DNA_UI_HAIR_G 2 +#define DNA_UI_HAIR_B 3 +#define DNA_UI_HAIR2_R 4 +#define DNA_UI_HAIR2_G 5 +#define DNA_UI_HAIR2_B 6 +#define DNA_UI_BEARD_R 7 +#define DNA_UI_BEARD_G 8 +#define DNA_UI_BEARD_B 9 +#define DNA_UI_BEARD2_R 10 +#define DNA_UI_BEARD2_G 11 +#define DNA_UI_BEARD2_B 12 +#define DNA_UI_SKIN_TONE 13 +#define DNA_UI_SKIN_R 14 +#define DNA_UI_SKIN_G 15 +#define DNA_UI_SKIN_B 16 +#define DNA_UI_HACC_R 17 +#define DNA_UI_HACC_G 18 +#define DNA_UI_HACC_B 19 +#define DNA_UI_HEAD_MARK_R 20 +#define DNA_UI_HEAD_MARK_G 21 +#define DNA_UI_HEAD_MARK_B 22 +#define DNA_UI_BODY_MARK_R 23 +#define DNA_UI_BODY_MARK_G 24 +#define DNA_UI_BODY_MARK_B 25 +#define DNA_UI_TAIL_MARK_R 26 +#define DNA_UI_TAIL_MARK_G 27 +#define DNA_UI_TAIL_MARK_B 28 +#define DNA_UI_EYES_R 29 +#define DNA_UI_EYES_G 30 +#define DNA_UI_EYES_B 31 +#define DNA_UI_GENDER 32 +#define DNA_UI_BEARD_STYLE 33 +#define DNA_UI_HAIR_STYLE 34 +/*#define DNA_UI_BACC_STYLE 23*/ +#define DNA_UI_HACC_STYLE 35 +#define DNA_UI_HEAD_MARK_STYLE 36 +#define DNA_UI_BODY_MARK_STYLE 37 +#define DNA_UI_TAIL_MARK_STYLE 38 +#define DNA_UI_LENGTH 38 // Update this when you add something, or you WILL break shit. + +#define DNA_SE_LENGTH 55 // Was STRUCDNASIZE, size 27. 15 new blocks added = 42, plus room to grow. diff --git a/code/__DEFINES/genetics.dm b/code/__DEFINES/genetics.dm index c465ab2d514..58571e8b1ca 100644 --- a/code/__DEFINES/genetics.dm +++ b/code/__DEFINES/genetics.dm @@ -24,78 +24,61 @@ /////////////////////////////////////// // MUTATIONS /////////////////////////////////////// + // Generic mutations: -#define TK 1 -#define COLDRES 2 -#define XRAY 3 -#define HULK 4 -#define CLUMSY 5 -#define FAT 6 -#define HUSK 7 -#define NOCLONE 8 - -// Extra powers: -#define LASER 9 // harm intent - click anywhere to shoot lasers from eyes - -//species mutation -#define WINGDINGS 10 // Ayy lmao - -//2spooky -#define SKELETON 29 -#define PLANT 30 - -// Other Mutations: -#define BREATHLESS 100 // no breathing -#define REMOTE_VIEW 101 // remote viewing -#define REGEN 102 // health regen -#define RUN 103 // no slowdown -#define REMOTE_TALK 104 // remote talking -#define MORPH 105 // changing appearance -#define HEATRES 106 // heat resistance -#define HALLUCINATE 107 // hallucinations -#define FINGERPRINTS 108 // no fingerprints -#define NO_SHOCK 109 // insulated hands -#define DWARF 110 // table climbing - -// Goon muts -#define OBESITY 200 // Decreased metabolism -// 201 undefined -#define STRONG 202 // (Nothing) -#define SOBER 203 // Increased alcohol metabolism -#define PSY_RESIST 204 // Block remoteview -// 205 undefined -#define EMPATH 206 //Read minds -#define COMIC 207 //Comic Sans - -// /vg/ muts -#define LOUD 208 // CAUSES INTENSE YELLING -#define DIZZY 210 // Trippy. - -#define LISP 300 -#define RADIOACTIVE 301 -#define CHAV 302 -#define SWEDISH 303 -#define SCRAMBLED 304 -#define HORNS 305 -#define IMMOLATE 306 -#define CLOAK 307 -#define CHAMELEON 308 -#define CRYO 309 -#define EATER 310 - -#define JUMPY 400 -#define POLYMORPH 401 - +#define TK "telekenesis" +#define COLDRES "cold_resistance" +#define XRAY "xray" +#define HULK "hulk" +#define CLUMSY "clumsy" +#define FAT "fat" +#define HUSK "husk" +#define NOCLONE "noclone" +#define LASER "eyelaser" // harm intent - click anywhere to shoot lasers from eyes +#define WINGDINGS "wingdings" // Ayy lmao +#define SKELETON "skeleton" +#define BREATHLESS "breathless" // no breathing +#define REMOTE_VIEW "remove_view" // remote viewing +#define REGEN "regeneration" // health regen +#define RUN "increased_run" // no slowdown +#define REMOTE_TALK "remote_talk" // remote talking +#define MORPH "morph" // changing appearance +#define HEATRES "heat_resistance" // heat resistance +#define HALLUCINATE "hallucinate" // hallucinations +#define FINGERPRINTS "no_prints" // no fingerprints +#define NO_SHOCK "no_shock" // insulated hands +#define DWARF "dwarf" // table climbing +#define OBESITY "obesity" // Decreased metabolism +#define STRONG "strong" // (Nothing) +#define SOBER "sober" // Increased alcohol metabolism +#define PSY_RESIST "psy_resist" // Block remoteview +#define EMPATH "empathy" //Read minds +#define COMIC "comic_sans" //Comic Sans +#define LOUD "loudness" // CAUSES INTENSE YELLING +#define DIZZY "dizzy" // Trippy. +#define LISP "lisp" +#define RADIOACTIVE "radioactive" +#define CHAV "chav" +#define SWEDISH "swedish" +#define SCRAMBLED "scrambled" +#define HORNS "horns" +#define IMMOLATE "immolate" +#define CLOAK "cloak" +#define CHAMELEON "chameleon" +#define CRYO "cryokinesis" +#define EATER "matter_eater" +#define JUMPY "jumpy" +#define POLYMORPH "polymorph" //disabilities -#define NEARSIGHTED 1 -#define EPILEPSY 2 -#define COUGHING 4 -#define TOURETTES 8 -#define NERVOUS 16 -#define BLIND 32 -#define COLOURBLIND 64 -#define MUTE 128 -#define DEAF 256 +#define NEARSIGHTED "nearsighted" +#define EPILEPSY "epilepsy" +#define COUGHING "coughing" +#define TOURETTES "tourettes" +#define NERVOUS "nervous" +#define BLINDNESS "blind" +#define COLOURBLIND "colorblind" +#define MUTE "mute" +#define DEAF "deaf" //Nutrition levels for humans. No idea where else to put it #define NUTRITION_LEVEL_FAT 600 @@ -104,6 +87,7 @@ #define NUTRITION_LEVEL_FED 350 #define NUTRITION_LEVEL_HUNGRY 250 #define NUTRITION_LEVEL_STARVING 150 +#define NUTRITION_LEVEL_HYPOGLYCEMIA 100 #define NUTRITION_LEVEL_CURSED 0 //Used as an upper limit for species that continuously gain nutriment @@ -151,7 +135,6 @@ #define NO_SCAN "no_scan" #define NO_PAIN "no_pain" #define IS_PLANT "is_plant" -#define CAN_BE_FAT "can_be_fat" #define NO_INTORGANS "no_internal_organs" #define RADIMMUNE "rad_immunity" #define NOGUNS "no_guns" diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index cec707b8196..23ac017f1ec 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -5,6 +5,3 @@ #define WEIGHT_CLASS_BULKY 4 //Items that can be weilded or equipped but not stored in an inventory, ex: Defibrillator, Backpack, Space Suits #define WEIGHT_CLASS_HUGE 5 //Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons #define WEIGHT_CLASS_GIGANTIC 6 //Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - -#define TV_TRIP "trip" -#define TV_SLIP "slip" diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 33ce299c540..671897b612d 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -28,13 +28,13 @@ #define is_pen(W) (istype(W, /obj/item/pen)) -var/list/static/global/pointed_types = typecacheof(list( +GLOBAL_LIST_INIT(pointed_types, typecacheof(list( /obj/item/pen, /obj/item/screwdriver, /obj/item/reagent_containers/syringe, - /obj/item/kitchen/utensil/fork)) + /obj/item/kitchen/utensil/fork))) -#define is_pointed(W) (is_type_in_typecache(W, pointed_types)) +#define is_pointed(W) (is_type_in_typecache(W, GLOB.pointed_types)) GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list( /obj/item/stack/sheet/glass, diff --git a/code/__DEFINES/job.dm b/code/__DEFINES/job.dm index d72628e2cb7..349d1b246be 100644 --- a/code/__DEFINES/job.dm +++ b/code/__DEFINES/job.dm @@ -51,7 +51,7 @@ #define JOB_CLOWN (1<<11) #define JOB_MIME (1<<12) #define JOB_CIVILIAN (1<<13) - +#define JOB_EXPLORER (1<<14) #define JOBCAT_KARMA (1<<3) diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index 01dbc2f1c2b..34528090e86 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -90,3 +90,27 @@ #define FLASH_LIGHT_DURATION 2 #define FLASH_LIGHT_POWER 3 #define FLASH_LIGHT_RANGE 3.8 + +/// Returns the red part of a #RRGGBB hex sequence as number +#define GETREDPART(hexa) hex2num(copytext(hexa, 2, 4)) + +/// Returns the green part of a #RRGGBB hex sequence as number +#define GETGREENPART(hexa) hex2num(copytext(hexa, 4, 6)) + +/// Returns the blue part of a #RRGGBB hex sequence as number +#define GETBLUEPART(hexa) hex2num(copytext(hexa, 6, 8)) + +/// Parse the hexadecimal color into lumcounts of each perspective. +#define PARSE_LIGHT_COLOR(source) \ +do { \ + if (source.light_color) { \ + var/__light_color = source.light_color; \ + source.lum_r = GETREDPART(__light_color) / 255; \ + source.lum_g = GETGREENPART(__light_color) / 255; \ + source.lum_b = GETBLUEPART(__light_color) / 255; \ + } else { \ + source.lum_r = 1; \ + source.lum_g = 1; \ + source.lum_b = 1; \ + }; \ +} while (FALSE) diff --git a/code/__DEFINES/logs.dm b/code/__DEFINES/logs.dm new file mode 100644 index 00000000000..25d1fac7323 --- /dev/null +++ b/code/__DEFINES/logs.dm @@ -0,0 +1,6 @@ +#define ATTACK_LOG "Attack" +#define DEFENSE_LOG "Defense" +#define CONVERSION_LOG "Conversion" +#define SAY_LOG "Say" +#define EMOTE_LOG "Emote" +#define MISC_LOG "Misc" diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 346664e0758..cf27ec09143 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -122,10 +122,10 @@ ) #define FOR_DVIEW(type, range, center, invis_flags) \ - dview_mob.loc = center; \ - dview_mob.see_invisible = invis_flags; \ - for(type in view(range, dview_mob)) -#define END_FOR_DVIEW dview_mob.loc = null + GLOB.dview_mob.loc = center; \ + GLOB.dview_mob.see_invisible = invis_flags; \ + for(type in view(range, GLOB.dview_mob)) +#define END_FOR_DVIEW GLOB.dview_mob.loc = null //Turf locational stuff #define get_turf(A) (get_step(A, 0)) @@ -319,7 +319,7 @@ #define INVESTIGATE_BOMB "bombs" // The SQL version required by this version of the code -#define SQL_VERSION 11 +#define SQL_VERSION 12 // Vending machine stuff #define CAT_NORMAL 1 @@ -345,7 +345,7 @@ #define MOUSE_OPACITY_OPAQUE 2 // Defib stats -#define DEFIB_TIME_LIMIT 120 +#define DEFIB_TIME_LIMIT 300 #define DEFIB_TIME_LOSS 60 //different types of atom colorations diff --git a/code/__DEFINES/radio.dm b/code/__DEFINES/radio.dm index e0c71836c72..ec65a37642f 100644 --- a/code/__DEFINES/radio.dm +++ b/code/__DEFINES/radio.dm @@ -58,3 +58,10 @@ #define RADIO_MEDBOT "12" #define RADIO_MAGNETS "radio_magnet" #define RADIO_LOGIC "radio_logic" + +// Signal types +#define SIGNALTYPE_NORMAL 0 +#define SIGNALTYPE_INTERCOM 1 // Will only broadcast to intercoms +#define SIGNALTYPE_INTERCOM_SBR 2 // Will only broadcast to intercoms and station-bounced radios +#define SIGNALTYPE_AINOTRACK 4 // AI can't track down this person. Useful for imitation broadcasts where you can't find the actual mob + diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 2b9e2c56b4d..8021fa4452d 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -48,7 +48,7 @@ //Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. //The gamemode specific ones are just so the gamemodes can query whether a player is old enough //(in game days played) to play that role -var/global/list/special_roles = list( +GLOBAL_LIST_INIT(special_roles, list( ROLE_ABDUCTOR = /datum/game_mode/abduction, // Abductor ROLE_BLOB = /datum/game_mode/blob, // Blob ROLE_CHANGELING = /datum/game_mode/changeling, // Changeling @@ -72,10 +72,10 @@ var/global/list/special_roles = list( ROLE_VAMPIRE = /datum/game_mode/vampire, // Vampire ROLE_RAIDER = /datum/game_mode/heist, // Vox raider ROLE_ALIEN, // Xenomorph - ROLE_WIZARD = /datum/game_mode/wizard, // Wizard + ROLE_WIZARD = /datum/game_mode/wizard // Wizard // UNUSED/BROKEN ANTAGS // ROLE_HOG_GOD = /datum/game_mode/hand_of_god, // ROLE_HOG_CULTIST = /datum/game_mode/hand_of_god, // ROLE_MONKEY = /datum/game_mode/monkey, Sooner or later these are going to get ported -// ROLE_GANG = /datum/game_mode/gang, -) +// ROLE_GANG = /datum/game_mode/gang +)) diff --git a/code/__DEFINES/rolebans.dm b/code/__DEFINES/rolebans.dm index d6e54abf14a..ad6f1324afa 100644 --- a/code/__DEFINES/rolebans.dm +++ b/code/__DEFINES/rolebans.dm @@ -1,5 +1,5 @@ // Bannable antag roles -var/global/list/antag_roles = list( +GLOBAL_LIST_INIT(antag_roles, list( ROLE_TRAITOR, ROLE_OPERATIVE, ROLE_CHANGELING, @@ -18,14 +18,14 @@ var/global/list/antag_roles = list( ROLE_GUARDIAN, ROLE_MORPH, ROLE_GSPIDER, -) +)) // Bannable other roles -var/global/list/other_roles = list( +GLOBAL_LIST_INIT(other_roles, list( ROLE_SENTIENT, ROLE_NYMPH, ROLE_ERT, ROLE_GHOST, "AntagHUD", "Records" -) +)) diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 300d3a41fc0..b1773ba10d5 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -66,6 +66,7 @@ #define INIT_ORDER_TIMER 1 #define INIT_ORDER_DEFAULT 0 #define INIT_ORDER_AIR -1 +#define INIT_ORDER_SUN -2 #define INIT_ORDER_MINIMAP -3 #define INIT_ORDER_ASSETS -4 #define INIT_ORDER_ICON_SMOOTHING -5 diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 7a91c3bf9bc..f5d582f5e42 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -5,7 +5,7 @@ // will get logs that are one big line if the system is Linux and they are using notepad. This solves it by adding CR to every line ending // in the logs. ascii character 13 = CR -/var/global/log_end = world.system_type == UNIX ? ascii2text(13) : "" +GLOBAL_VAR_INIT(log_end, (world.system_type == UNIX ? ascii2text(13) : "")) #define DIRECT_OUTPUT(A, B) A << B #define SEND_IMAGE(target, image) DIRECT_OUTPUT(target, image) @@ -30,13 +30,13 @@ #endif /proc/log_admin(text) - admin_log.Add(text) + GLOB.admin_log.Add(text) if(config.log_admin) - WRITE_LOG(GLOB.world_game_log, "ADMIN: [text][log_end]") + WRITE_LOG(GLOB.world_game_log, "ADMIN: [text][GLOB.log_end]") /proc/log_debug(text) if(config.log_debug) - WRITE_LOG(GLOB.world_game_log, "DEBUG: [text][log_end]") + WRITE_LOG(GLOB.world_game_log, "DEBUG: [text][GLOB.log_end]") for(var/client/C in GLOB.admins) if(check_rights(R_DEBUG, 0, C.mob) && (C.prefs.toggles & CHAT_DEBUGLOGS)) @@ -44,88 +44,88 @@ /proc/log_game(text) if(config.log_game) - WRITE_LOG(GLOB.world_game_log, "GAME: [text][log_end]") + WRITE_LOG(GLOB.world_game_log, "GAME: [text][GLOB.log_end]") /proc/log_vote(text) if(config.log_vote) - WRITE_LOG(GLOB.world_game_log, "VOTE: [text][log_end]") + WRITE_LOG(GLOB.world_game_log, "VOTE: [text][GLOB.log_end]") /proc/log_access_in(client/new_client) if(config.log_access) var/message = "[key_name(new_client)] - IP:[new_client.address] - CID:[new_client.computer_id] - BYOND v[new_client.byond_version]" - WRITE_LOG(GLOB.world_game_log, "ACCESS IN: [message][log_end]") + WRITE_LOG(GLOB.world_game_log, "ACCESS IN: [message][GLOB.log_end]") /proc/log_access_out(mob/last_mob) if(config.log_access) var/message = "[key_name(last_mob)] - IP:[last_mob.lastKnownIP] - CID:[last_mob.computer_id] - BYOND Logged Out" - WRITE_LOG(GLOB.world_game_log, "ACCESS OUT: [message][log_end]") + WRITE_LOG(GLOB.world_game_log, "ACCESS OUT: [message][GLOB.log_end]") /proc/log_say(text, mob/speaker) if(config.log_say) - WRITE_LOG(GLOB.world_game_log, "SAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "SAY: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_whisper(text, mob/speaker) if(config.log_whisper) - WRITE_LOG(GLOB.world_game_log, "WHISPER: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "WHISPER: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_ooc(text, client/user) if(config.log_ooc) - WRITE_LOG(GLOB.world_game_log, "OOC: [user.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "OOC: [user.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_aooc(text, client/user) if(config.log_ooc) - WRITE_LOG(GLOB.world_game_log, "AOOC: [user.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "AOOC: [user.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_looc(text, client/user) if(config.log_ooc) - WRITE_LOG(GLOB.world_game_log, "LOOC: [user.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "LOOC: [user.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_emote(text, mob/speaker) if(config.log_emote) - WRITE_LOG(GLOB.world_game_log, "EMOTE: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "EMOTE: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_attack(attacker, defender, message) if(config.log_attack) - WRITE_LOG(GLOB.world_game_log, "ATTACK: [attacker] against [defender]: [message][log_end]") //Seperate attack logs? Why? + WRITE_LOG(GLOB.world_game_log, "ATTACK: [attacker] against [defender]: [message][GLOB.log_end]") //Seperate attack logs? Why? /proc/log_adminsay(text, mob/speaker) if(config.log_adminchat) - WRITE_LOG(GLOB.world_game_log, "ADMINSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "ADMINSAY: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_qdel(text) WRITE_LOG(GLOB.world_qdel_log, "QDEL: [text]") /proc/log_mentorsay(text, mob/speaker) if(config.log_adminchat) - WRITE_LOG(GLOB.world_game_log, "MENTORSAY: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "MENTORSAY: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_ghostsay(text, mob/speaker) if(config.log_say) - WRITE_LOG(GLOB.world_game_log, "DEADCHAT: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "DEADCHAT: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_ghostemote(text, mob/speaker) if(config.log_emote) - WRITE_LOG(GLOB.world_game_log, "DEADEMOTE: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "DEADEMOTE: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_adminwarn(text) if(config.log_adminwarn) - WRITE_LOG(GLOB.world_game_log, "ADMINWARN: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "ADMINWARN: [html_decode(text)][GLOB.log_end]") /proc/log_pda(text, mob/speaker) if(config.log_pda) - WRITE_LOG(GLOB.world_game_log, "PDA: [speaker.simple_info_line()]: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "PDA: [speaker.simple_info_line()]: [html_decode(text)][GLOB.log_end]") /proc/log_chat(text, mob/speaker) if(config.log_pda) - WRITE_LOG(GLOB.world_game_log, "CHAT: [speaker.simple_info_line()] [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "CHAT: [speaker.simple_info_line()] [html_decode(text)][GLOB.log_end]") /proc/log_misc(text) - WRITE_LOG(GLOB.world_game_log, "MISC: [text][log_end]") + WRITE_LOG(GLOB.world_game_log, "MISC: [text][GLOB.log_end]") /proc/log_world(text) SEND_TEXT(world.log, text) if(config && config.log_world_output) - WRITE_LOG(GLOB.world_game_log, "WORLD: [html_decode(text)][log_end]") + WRITE_LOG(GLOB.world_game_log, "WORLD: [html_decode(text)][GLOB.log_end]") /proc/log_runtime_txt(text) // different from /tg/'s log_runtime because our error handler has a log_runtime proc already that does other stuff WRITE_LOG(GLOB.world_runtime_log, text) diff --git a/code/__HELPERS/_string_lists.dm b/code/__HELPERS/_string_lists.dm index 36aa2f9b6fa..e2f0c6081e7 100644 --- a/code/__HELPERS/_string_lists.dm +++ b/code/__HELPERS/_string_lists.dm @@ -2,15 +2,15 @@ #define pick_list_replacements(FILE, KEY) (strings_replacement(FILE, KEY)) #define json_load(FILE) (json_decode(file2text(FILE))) -var/global/list/string_cache -var/global/list/string_filename_current_key +GLOBAL_LIST_EMPTY(string_cache) +GLOBAL_LIST_EMPTY(string_filename_current_key) /proc/strings_replacement(filename, key) load_strings_file(filename) - if((filename in string_cache) && (key in string_cache[filename])) - var/response = pick(string_cache[filename][key]) + if((filename in GLOB.string_cache) && (key in GLOB.string_cache[filename])) + var/response = pick(GLOB.string_cache[filename][key]) var/regex/r = regex("@pick\\((\\D+?)\\)", "g") response = r.Replace(response, /proc/strings_subkey_lookup) return response @@ -19,23 +19,23 @@ var/global/list/string_filename_current_key /proc/strings(filename as text, key as text) load_strings_file(filename) - if((filename in string_cache) && (key in string_cache[filename])) - return string_cache[filename][key] + if((filename in GLOB.string_cache) && (key in GLOB.string_cache[filename])) + return GLOB.string_cache[filename][key] else CRASH("strings list not found: strings/[filename], index=[key]") /proc/strings_subkey_lookup(match, group1) - return pick_list(string_filename_current_key, group1) + return pick_list(GLOB.string_filename_current_key, group1) /proc/load_strings_file(filename) - string_filename_current_key = filename - if(filename in string_cache) + GLOB.string_filename_current_key = filename + if(filename in GLOB.string_cache) return //no work to do - if(!string_cache) - string_cache = new + if(!GLOB.string_cache) + GLOB.string_cache = new if(fexists("strings/[filename]")) - string_cache[filename] = json_load("strings/[filename]") + GLOB.string_cache[filename] = json_load("strings/[filename]") else CRASH("file not found: strings/[filename]") diff --git a/code/__HELPERS/files.dm b/code/__HELPERS/files.dm index c96357299c2..0a58ed035f7 100644 --- a/code/__HELPERS/files.dm +++ b/code/__HELPERS/files.dm @@ -18,6 +18,8 @@ src << browse_rsc(file) /client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list(".txt",".log",".htm")) + // wow why was this ever a parameter + root = "data/logs/" var/path = root for(var/i=0, i 0) to_chat(src, "Error: file_spam_check(): Spam. Please wait [round(time_to_wait/10)] seconds.") return 1 - fileaccess_timer = world.time + FTPDELAY + GLOB.fileaccess_timer = world.time + FTPDELAY return 0 #undef FTPDELAY diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index f61b6452f22..366b8b3bcd9 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -1,4 +1,5 @@ /proc/get_area(atom/A) + RETURN_TYPE(/area) if(isarea(A)) return A var/turf/T = get_turf(A) @@ -120,7 +121,7 @@ -//var/debug_mob = 0 +//GLOBAL_VAR_INIT(debug_mob, 0) // Will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents. // It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects, @@ -128,7 +129,7 @@ /proc/recursive_mob_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_radio = 1) - //debug_mob += O.contents.len + //GLOB.debug_mob += O.contents.len if(!recursion_limit) return L for(var/atom/A in O.contents) @@ -273,7 +274,7 @@ /proc/try_move_adjacent(atom/movable/AM) var/turf/T = get_turf(AM) - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if(AM.Move(get_step(T, direction))) break @@ -407,7 +408,7 @@ /proc/alone_in_area(var/area/the_area, var/mob/must_be_alone, var/check_type = /mob/living/carbon) var/area/our_area = get_area(the_area) - for(var/C in GLOB.living_mob_list) + for(var/C in GLOB.alive_mob_list) if(!istype(C, check_type)) continue if(C == must_be_alone) @@ -416,16 +417,6 @@ return 0 return 1 - -/proc/GetRedPart(const/hexa) - return hex2num(copytext(hexa, 2, 4)) - -/proc/GetGreenPart(const/hexa) - return hex2num(copytext(hexa, 4, 6)) - -/proc/GetBluePart(const/hexa) - return hex2num(copytext(hexa, 6, 8)) - /proc/lavaland_equipment_pressure_check(turf/T) . = FALSE if(!istype(T)) @@ -437,13 +428,6 @@ if(pressure <= LAVALAND_EQUIPMENT_EFFECT_PRESSURE) . = TRUE -/proc/GetHexColors(const/hexa) - return list( - GetRedPart(hexa), - GetGreenPart(hexa), - GetBluePart(hexa), - ) - /proc/MinutesToTicks(var/minutes as num) return minutes * 60 * 10 diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm index acf202f0eee..dc256a93478 100644 --- a/code/__HELPERS/icon_smoothing.dm +++ b/code/__HELPERS/icon_smoothing.dm @@ -66,7 +66,7 @@ if(AM.can_be_unanchored && !AM.anchored) return 0 - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) AM = find_type_in_direction(A, direction) if(AM == NULLTURF_BORDER) if((A.smooth & SMOOTH_BORDER)) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index a434dd75577..4e11dbf4140 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -15,7 +15,7 @@ CHANGING ICONS Several new procs have been added to the /icon datum to simplify working with icons. To use them, remember you first need to setup an /icon var like so: -var/icon/my_icon = new('iconfile.dmi') + var/icon/my_icon = new('iconfile.dmi') icon/ChangeOpacity(amount = 1) A very common operation in DM is to try to make an icon more or less transparent. Making an icon more @@ -570,6 +570,18 @@ world /proc/BlendRGBasHSV(rgb1, rgb2, amount) return HSVtoRGB(RGBtoHSV(rgb1), RGBtoHSV(rgb2), amount) +//Returns the perceived brightness of a color. +//https://en.wikipedia.org/wiki/Relative_luminance +//https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color +/proc/getLuminance(color) + var/list/RGB = ReadRGB(color) + var/R = RGB[1] + var/G = RGB[2] + var/B = RGB[2] + + var/Y = (0.2126 * R) + (0.7152 * G) + (0.0722 * B) + return Clamp((Y * 0.01), 0, 1) //Returns the brightness of a color in decimal percentage format. Can multiply light_power by this to receive 100% brightness or a lower brightness. Not a higher brightness. + /proc/HueToAngle(hue) // normalize hsv in case anything is screwy if(hue < 0 || hue >= 1536) hue %= 1536 diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index d3deb81d458..76d422e3d82 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -77,13 +77,13 @@ //68% chance that the number is within 1stddev //95% chance that the number is within 2stddev //98% chance that the number is within 3stddev...etc -var/gaussian_next +GLOBAL_VAR(gaussian_next) #define ACCURACY 10000 /proc/gaussian(mean, stddev) var/R1;var/R2;var/working - if(gaussian_next != null) - R1 = gaussian_next - gaussian_next = null + if(GLOB.gaussian_next != null) + R1 = GLOB.gaussian_next + GLOB.gaussian_next = null else do R1 = rand(-ACCURACY,ACCURACY)/ACCURACY @@ -92,7 +92,7 @@ var/gaussian_next while(working >= 1 || working==0) working = sqrt(-2 * log(working) / working) R1 *= working - gaussian_next = R2 * working + GLOB.gaussian_next = R2 * working return (mean + stddev * R1) #undef ACCURACY diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 2dc3057ce19..f437c409088 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -59,7 +59,7 @@ proc/random_hair_style(var/gender, species = "Human", var/datum/robolimb/robohea continue if(species == "Machine") //If the user is a species who can have a robotic head... if(!robohead) - robohead = all_robolimbs["Morpheus Cyberkinetics"] + robohead = GLOB.all_robolimbs["Morpheus Cyberkinetics"] if((species in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_hairstyles += hairstyle //Give them their hairstyles if they do. else @@ -88,7 +88,7 @@ proc/random_facial_hair_style(var/gender, species = "Human", var/datum/robolimb/ continue if(species == "Machine") //If the user is a species who can have a robotic head... if(!robohead) - robohead = all_robolimbs["Morpheus Cyberkinetics"] + robohead = GLOB.all_robolimbs["Morpheus Cyberkinetics"] if((species in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a facial hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_facial_hairstyles += facialhairstyle //Give them their facial hairstyles if they do. else @@ -142,7 +142,7 @@ proc/random_marking_style(var/location = "body", species = "Human", var/datum/ro var/datum/sprite_accessory/body_markings/head/M = GLOB.marking_styles_list[S.name] if(species == "Machine")//If the user is a species that can have a robotic head... if(!robohead) - robohead = all_robolimbs["Morpheus Cyberkinetics"] + robohead = GLOB.all_robolimbs["Morpheus Cyberkinetics"] if(!(S.models_allowed && (robohead.company in S.models_allowed))) //Make sure they don't get markings incompatible with their head. continue else if(alt_head && alt_head != "None") //If the user's got an alt head, validate markings for that head. @@ -161,8 +161,8 @@ proc/random_marking_style(var/location = "body", species = "Human", var/datum/ro proc/random_body_accessory(species = "Vulpkanin") var/body_accessory = null var/list/valid_body_accessories = list() - for(var/B in body_accessory_by_name) - var/datum/body_accessory/A = body_accessory_by_name[B] + for(var/B in GLOB.body_accessory_by_name) + var/datum/body_accessory/A = GLOB.body_accessory_by_name[B] if(!istype(A)) valid_body_accessories += "None" //The only null entry should be the "None" option. continue @@ -244,24 +244,30 @@ proc/age2agedescription(age) var/their_rank = target_records.fields["rank"] switch(criminal_status) if("arrest") - status = "*Arrest*" + status = SEC_RECORD_STATUS_ARREST if("none") - status = "None" + status = SEC_RECORD_STATUS_NONE if("execute") if((ACCESS_MAGISTRATE in authcard_access) || (ACCESS_ARMORY in authcard_access)) - status = "*Execute*" + status = SEC_RECORD_STATUS_EXECUTE message_admins("[ADMIN_FULLMONTY(usr)] authorized EXECUTION for [their_rank] [their_name], with comment: [comment]") else return 0 + if("search") + status = SEC_RECORD_STATUS_SEARCH + if("monitor") + status = SEC_RECORD_STATUS_MONITOR + if ("demote") + status = SEC_RECORD_STATUS_DEMOTE if("incarcerated") - status = "Incarcerated" + status = SEC_RECORD_STATUS_INCARCERATED if("parolled") - status = "Parolled" + status = SEC_RECORD_STATUS_PAROLLED if("released") - status = "Released" + status = SEC_RECORD_STATUS_RELEASED target_records.fields["criminal"] = status log_admin("[key_name_admin(user)] set secstatus of [their_rank] [their_name] to [status], comment: [comment]") - target_records.fields["comments"] += "Set to [status] by [user.name] ([user_rank]) on [current_date_string] [station_time_timestamp()], comment: [comment]" + target_records.fields["comments"] += "Set to [status] by [user.name] ([user_rank]) on [GLOB.current_date_string] [station_time_timestamp()], comment: [comment]" update_all_mob_security_hud() return 1 @@ -274,32 +280,41 @@ Proc for attack log creation, because really why not This is always put in the attack log. */ -/proc/add_attack_logs(mob/user, mob/target, what_done, custom_level) +/proc/add_attack_logs(atom/user, target, what_done, custom_level) if(islist(target)) // Multi-victim adding var/list/targets = target - for(var/mob/M in targets) - add_attack_logs(user, M, what_done, custom_level) + for(var/t in targets) + add_attack_logs(user, t, what_done, custom_level) return var/user_str = key_name_log(user) + COORD(user) - var/target_str = key_name_log(target) + COORD(target) - - if(istype(user)) - user.create_attack_log("Attacked [target_str]: [what_done]") - if(istype(target)) - target.create_attack_log("Attacked by [user_str]: [what_done]") + var/target_str + if(isatom(target)) + var/atom/AT = target + target_str = key_name_log(AT) + COORD(AT) + else + target_str = target + var/mob/MU = user + var/mob/MT = target + if(istype(MU)) + MU.create_log(ATTACK_LOG, what_done, target, get_turf(user)) + MU.create_attack_log("Attacked [target_str]: [what_done]") + if(istype(MT)) + MT.create_log(DEFENSE_LOG, what_done, user, get_turf(MT)) + MT.create_attack_log("Attacked by [user_str]: [what_done]") log_attack(user_str, target_str, what_done) var/loglevel = ATKLOG_MOST if(!isnull(custom_level)) loglevel = custom_level - else if(istype(target)) - if(istype(user) && !user.ckey && !target.ckey) // Attacks between NPCs are only shown to admins with ATKLOG_ALL - loglevel = ATKLOG_ALL - else if(!user.ckey || !target.ckey || (user.ckey == target.ckey)) // Player v NPC combat is de-prioritized. Also no self-harm, nobody cares - loglevel = ATKLOG_ALMOSTALL + else if(istype(MT)) + if(istype(MU)) + if(!MU.ckey && !MT.ckey) // Attacks between NPCs are only shown to admins with ATKLOG_ALL + loglevel = ATKLOG_ALL + else if(!MU.ckey || !MT.ckey || (MU.ckey == MT.ckey)) // Player v NPC combat is de-prioritized. Also no self-harm, nobody cares + loglevel = ATKLOG_ALMOSTALL else - var/area/A = get_area(target) + var/area/A = get_area(MT) if(A && A.hide_attacklogs) loglevel = ATKLOG_ALMOSTALL if(isLivingSSD(target)) // Attacks on SSDs are shown to admins with any log level except ATKLOG_NONE. Overrides custom level @@ -307,7 +322,7 @@ This is always put in the attack log. msg_admin_attack("[key_name_admin(user)] vs [key_name_admin(target)]: [what_done]", loglevel) -/proc/do_mob(var/mob/user, var/mob/target, var/time = 30, var/uninterruptible = 0, progress = 1, datum/callback/extra_checks = null) +/proc/do_mob(mob/user, mob/target, time = 30, uninterruptible = 0, progress = 1, list/extra_checks = list()) if(!user || !target) return 0 var/user_loc = user.loc @@ -340,30 +355,41 @@ This is always put in the attack log. drifting = 0 user_loc = user.loc - if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_hand() != holding || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke())) + if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_hand() != holding || user.incapacitated() || user.lying || check_for_true_callbacks(extra_checks)) . = 0 break if(progress) qdel(progbar) -/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, datum/callback/extra_checks = null) +/* Use this proc when you want to have code under it execute after a delay, and ensure certain conditions are met during that delay... + * Such as the user not being interrupted via getting stunned or by moving off the tile they're currently on. + * + * Example usage: + * + * if(do_after(user, 50, target = sometarget, extra_checks = list(callback_check1, callback_check2))) + * do_stuff() + * + * This will create progress bar that lasts for 5 seconds. If the user doesn't move or otherwise do something that would cause the checks to fail in those 5 seconds, do_stuff() would execute. + * The Proc returns TRUE upon success (the progress bar reached the end), or FALSE upon failure (the user moved or some other check failed) + */ +/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1, list/extra_checks = list(), use_default_checks = TRUE) if(!user) - return 0 + return FALSE var/atom/Tloc = null if(target) Tloc = target.loc var/atom/Uloc = user.loc - var/drifting = 0 + var/drifting = FALSE if(!user.Process_Spacemove(0) && user.inertia_dir) - drifting = 1 + drifting = TRUE var/holding = user.get_active_hand() - var/holdingnull = 1 //User's hand started out empty, check for an empty hand + var/holdingnull = TRUE //User's hand started out empty, check for an empty hand if(holding) - holdingnull = 0 //Users hand started holding something, check to see if it's still holding that + holdingnull = FALSE //Users hand started holding something, check to see if it's still holding that var/datum/progressbar/progbar if(progress) @@ -371,22 +397,29 @@ This is always put in the attack log. var/endtime = world.time + delay var/starttime = world.time - . = 1 + . = TRUE + + // By default, checks for weakness and stunned get added to the extra_checks list. + // Setting `use_default_checks` to FALSE means that you don't want the do_after to check for these statuses, or that you will be supplying your own checks. + if(use_default_checks) + extra_checks += CALLBACK(user, /mob.proc/IsWeakened) + extra_checks += CALLBACK(user, /mob.proc/IsStunned) + while(world.time < endtime) sleep(1) if(progress) progbar.update(world.time - starttime) if(drifting && !user.inertia_dir) - drifting = 0 + drifting = FALSE Uloc = user.loc - if(!user || user.stat || user.IsWeakened() || user.stunned || (!drifting && user.loc != Uloc)|| (extra_checks && !extra_checks.Invoke())) - . = 0 + if(!user || user.stat || (!drifting && user.loc != Uloc) || check_for_true_callbacks(extra_checks)) + . = FALSE break if(Tloc && (!target || Tloc != target.loc)) - . = 0 + . = FALSE break if(needhand) @@ -394,14 +427,21 @@ This is always put in the attack log. //i.e the hand is used to pull some item/tool out of the construction if(!holdingnull) if(!holding) - . = 0 + . = FALSE break if(user.get_active_hand() != holding) - . = 0 + . = FALSE break if(progress) qdel(progbar) +// Upon any of the callbacks in the list returning TRUE, the proc will return TRUE. +/proc/check_for_true_callbacks(list/extra_checks) + for(var/datum/callback/CB in extra_checks) + if(CB.Invoke()) + return TRUE + return FALSE + #define DOAFTERONCE_MAGIC "Magic~~" GLOBAL_LIST_INIT(do_after_once_tracker, list()) /proc/do_after_once(mob/user, delay, needhand = 1, atom/target = null, progress = 1, attempt_cancel_message = "Attempt cancelled.") @@ -414,14 +454,14 @@ GLOBAL_LIST_INIT(do_after_once_tracker, list()) to_chat(user, "[attempt_cancel_message]") return FALSE GLOB.do_after_once_tracker[cache_key] = TRUE - . = do_after(user, delay, needhand, target, progress, extra_checks = CALLBACK(GLOBAL_PROC, .proc/do_after_once_checks, cache_key)) + . = do_after(user, delay, needhand, target, progress, extra_checks = list(CALLBACK(GLOBAL_PROC, .proc/do_after_once_checks, cache_key))) GLOB.do_after_once_tracker[cache_key] = FALSE /proc/do_after_once_checks(cache_key) if(GLOB.do_after_once_tracker[cache_key] && GLOB.do_after_once_tracker[cache_key] == DOAFTERONCE_MAGIC) GLOB.do_after_once_tracker[cache_key] = FALSE - return FALSE - return TRUE + return TRUE + return FALSE /proc/is_species(A, species_datum) . = FALSE diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 2125326852e..29e0f9b52b9 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -1,7 +1,7 @@ -var/church_name = null +GLOBAL_VAR(church_name) /proc/church_name() - if(church_name) - return church_name + if(GLOB.church_name) + return GLOB.church_name var/name = "" @@ -15,14 +15,14 @@ var/church_name = null return name -var/command_name = null +GLOBAL_VAR(command_name) /proc/command_name() - return using_map.dock_name + return GLOB.using_map.dock_name -var/religion_name = null +GLOBAL_VAR(religion_name) /proc/religion_name() - if(religion_name) - return religion_name + if(GLOB.religion_name) + return GLOB.religion_name var/name = "" @@ -32,10 +32,10 @@ var/religion_name = null return capitalize(name) /proc/system_name() - return using_map.starsys_name + return GLOB.using_map.starsys_name /proc/station_name() - return using_map.station_name + return GLOB.using_map.station_name /proc/new_station_name() var/random = rand(1,5) @@ -80,10 +80,10 @@ var/religion_name = null new_station_name += pick("13","XIII","Thirteen") return new_station_name -var/syndicate_name = null +GLOBAL_VAR(syndicate_name) /proc/syndicate_name() - if(syndicate_name) - return syndicate_name + if(GLOB.syndicate_name) + return GLOB.syndicate_name var/name = "" @@ -107,7 +107,7 @@ var/syndicate_name = null name += pick("-", "*", "") name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Gen", "Star", "Dyne", "Code", "Hive") - syndicate_name = name + GLOB.syndicate_name = name return name @@ -142,10 +142,10 @@ GLOBAL_VAR(syndicate_code_response) //Code response for traitors. var/safety[] = list(1,2,3)//Tells the proc which options to remove later on. var/nouns[] = list("love","hate","anger","peace","pride","sympathy","bravery","loyalty","honesty","integrity","compassion","charity","success","courage","deceit","skill","beauty","brilliance","pain","misery","beliefs","dreams","justice","truth","faith","liberty","knowledge","thought","information","culture","trust","dedication","progress","education","hospitality","leisure","trouble","friendships", "relaxation") var/drinks[] = list("vodka and tonic","gin fizz","bahama mama","manhattan","black Russian","whiskey soda","long island tea","margarita","Irish coffee"," manly dwarf","Irish cream","doctor's delight","Beepksy Smash","tequila sunrise","brave bull","gargle blaster","bloody mary","whiskey cola","white Russian","vodka martini","martini","Cuba libre","kahlua","vodka","wine","moonshine") - var/locations[] = teleportlocs.len ? teleportlocs : drinks//if null, defaults to drinks instead. + var/locations[] = GLOB.teleportlocs.len ? GLOB.teleportlocs : drinks//if null, defaults to drinks instead. var/names[] = list() - for(var/datum/data/record/t in data_core.general)//Picks from crew manifest. + for(var/datum/data/record/t in GLOB.data_core.general)//Picks from crew manifest. names += t.fields["name"] var/maxwords = words//Extra var to check for duplicates. diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 289bbbae717..ecbebf813df 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -19,7 +19,7 @@ return null if(!istext(t)) t = "[t]" // Just quietly assume any non-texts are supposed to be text - var/sqltext = dbcon.Quote(t); + var/sqltext = GLOB.dbcon.Quote(t); return copytext(sqltext, 2, length(sqltext));//Quote() adds quotes around input, we already do that /proc/format_table_name(table as text) @@ -207,7 +207,7 @@ proc/checkhtml(var/t) tag = copytext(t,start, p) p++ tag = copytext(t,start+1, p) - if(!(tag in paper_tag_whitelist)) //if it's unkown tag, disarming it + if(!(tag in GLOB.paper_tag_whitelist)) //if it's unkown tag, disarming it t = copytext(t,1,start-1) + "<" + copytext(t,start+1) p = findtext(t,"<",p) return t diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm index d13bf08c58b..340d7a3b134 100644 --- a/code/__HELPERS/time.dm +++ b/code/__HELPERS/time.dm @@ -50,10 +50,24 @@ return "[date_portion]T[time_portion]" /proc/gameTimestamp(format = "hh:mm:ss", wtime=null) - if(!wtime) + if(wtime == null) wtime = world.time return time2text(wtime - GLOB.timezoneOffset, format) +// max hh:mm:ss supported +/proc/timeStampToNum(timestamp) + var/list/splits = text2numlist(timestamp, ":") + . = 0 + var/split_len = length(splits) + for(var/i = 1 to length(splits)) + switch(split_len - i) + if(2) + . += splits[i] HOURS + if(1) + . += splits[i] MINUTES + if(0) + . += splits[i] SECONDS + /* This is used for displaying the "station time" equivelent of a world.time value Calling it with no args will give you the current time, but you can specify a world.time-based value as an argument - You can use this, for example, to do "This will expire at [station_time_at(world.time + 500)]" to display a "station time" expiration date diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm index 467b07a0ddf..352a6fa3680 100644 --- a/code/__HELPERS/traits.dm +++ b/code/__HELPERS/traits.dm @@ -62,7 +62,10 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai //mob traits #define TRAIT_PACIFISM "pacifism" -#define TRAIT_WATERBREATH "waterbreathing" +#define TRAIT_WATERBREATH "waterbreathing" +#define TRAIT_BLOODCRAWL "bloodcrawl" +#define TRAIT_BLOODCRAWL_EAT "bloodcrawl_eat" +#define TRAIT_JESTER "jester" // common trait sources #define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 661d09f0412..bf44f6a4bc9 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -167,7 +167,7 @@ return SOUTH if(225.6 to 315.5) return WEST - + //returns the north-zero clockwise angle in degrees, given a direction /proc/dir2angle(var/D) @@ -212,6 +212,7 @@ if(rights & R_PROCCALL) . += "[seperator]+PROCCALL" if(rights & R_MOD) . += "[seperator]+MODERATOR" if(rights & R_MENTOR) . += "[seperator]+MENTOR" + if(rights & R_VIEWRUNTIMES) . += "[seperator]+VIEWRUNTIMES" return . /proc/ui_style2icon(ui_style) diff --git a/code/__HELPERS/unique_ids.dm b/code/__HELPERS/unique_ids.dm index a66de0b5a88..549f5c71016 100644 --- a/code/__HELPERS/unique_ids.dm +++ b/code/__HELPERS/unique_ids.dm @@ -14,7 +14,7 @@ // var/myUID = mydatum.UID() // var/datum/D = locateUID(myUID) -var/global/next_unique_datum_id = 1 +GLOBAL_VAR_INIT(next_unique_datum_id, 1) // /client/var/tmp/unique_datum_id = null @@ -22,7 +22,7 @@ var/global/next_unique_datum_id = 1 if(!unique_datum_id) var/tag_backup = tag tag = null // Grab the raw ref, not the tag - unique_datum_id = "\ref[src]_[next_unique_datum_id++]" + unique_datum_id = "\ref[src]_[GLOB.next_unique_datum_id++]" tag = tag_backup return unique_datum_id diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 45283498ebd..80852f25c3f 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -320,7 +320,7 @@ Turf and target are seperate in case you want to teleport some distance from a t //When a borg is activated, it can choose which AI it wants to be slaved to /proc/active_ais() . = list() - for(var/mob/living/silicon/ai/A in GLOB.living_mob_list) + for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list) if(A.stat == DEAD) continue if(A.control_disabled == 1) @@ -1129,9 +1129,9 @@ proc/get_mob_with_client_list() //For objects that should embed, but make no sense being is_sharp or is_pointed() //e.g: rods -var/list/can_embed_types = typecacheof(list( +GLOBAL_LIST_INIT(can_embed_types, typecacheof(list( /obj/item/stack/rods, - /obj/item/pipe)) + /obj/item/pipe))) /proc/can_embed(obj/item/W) if(is_sharp(W)) @@ -1139,7 +1139,7 @@ var/list/can_embed_types = typecacheof(list( if(is_pointed(W)) return 1 - if(is_type_in_typecache(W, can_embed_types)) + if(is_type_in_typecache(W, GLOB.can_embed_types)) return 1 /proc/is_hot(obj/item/W as obj) @@ -1221,18 +1221,18 @@ var/list/can_embed_types = typecacheof(list( /* Checks if that loc and dir has a item on the wall */ -var/list/static/global/wall_items = typecacheof(list(/obj/machinery/power/apc, /obj/machinery/alarm, +GLOBAL_LIST_INIT(wall_items, typecacheof(list(/obj/machinery/power/apc, /obj/machinery/alarm, /obj/item/radio/intercom, /obj/structure/extinguisher_cabinet, /obj/structure/reagent_dispensers/peppertank, /obj/machinery/status_display, /obj/machinery/requests_console, /obj/machinery/light_switch, /obj/structure/sign, /obj/machinery/newscaster, /obj/machinery/firealarm, /obj/structure/noticeboard, /obj/machinery/door_control, /obj/machinery/computer/security/telescreen, /obj/machinery/embedded_controller/radio/airlock, /obj/item/storage/secure/safe, /obj/machinery/door_timer, /obj/machinery/flasher, /obj/machinery/keycard_auth, /obj/structure/mirror, /obj/structure/closet/fireaxecabinet, /obj/machinery/computer/security/telescreen/entertainment, - /obj/structure/sign)) + /obj/structure/sign))) /proc/gotwallitem(loc, dir) for(var/obj/O in loc) - if(is_type_in_typecache(O, wall_items)) + if(is_type_in_typecache(O, GLOB.wall_items)) //Direction works sometimes if(O.dir == dir) return 1 @@ -1254,7 +1254,7 @@ var/list/static/global/wall_items = typecacheof(list(/obj/machinery/power/apc, / //Some stuff is placed directly on the wallturf (signs) for(var/obj/O in get_step(loc, dir)) - if(is_type_in_typecache(O, wall_items)) + if(is_type_in_typecache(O, GLOB.wall_items)) if(abs(O.pixel_x) <= 10 && abs(O.pixel_y) <= 10) return 1 return 0 @@ -1381,7 +1381,7 @@ atom/proc/GetTypeInAllContents(typepath) var/initial_chance = chance while(steps > 0) if(prob(chance)) - step(AM, pick(alldirs)) + step(AM, pick(GLOB.alldirs)) chance = max(chance - (initial_chance / steps), 0) steps-- @@ -1415,19 +1415,19 @@ atom/proc/GetTypeInAllContents(typepath) return locate(dest_x,dest_y,dest_z) -var/mob/dview/dview_mob = new +GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) //Version of view() which ignores darkness, because BYOND doesn't have it. /proc/dview(var/range = world.view, var/center, var/invis_flags = 0) if(!center) return - dview_mob.loc = center + GLOB.dview_mob.loc = center - dview_mob.see_invisible = invis_flags + GLOB.dview_mob.see_invisible = invis_flags - . = view(range, dview_mob) - dview_mob.loc = null + . = view(range, GLOB.dview_mob) + GLOB.dview_mob.loc = null /mob/dview invisibility = 101 @@ -1813,7 +1813,6 @@ var/mob/dview/dview_mob = new /obj/machinery/portable_atmospherics/canister = "CANISTER", /obj/machinery/portable_atmospherics = "PORT_ATMOS", /obj/machinery/power = "POWER", - /obj/machinery/telecomms = "TCOMMS", /obj/machinery = "MACHINERY", /obj/mecha = "MECHA", /obj/structure/closet/crate = "CRATE", @@ -1895,8 +1894,15 @@ var/mob/dview/dview_mob = new #undef DELTA_CALC -// This proc gets a list of all "points of interest" (poi's) that can be used by admins to track valuable mobs or atoms (such as the nuke disk). -/proc/getpois(mobs_only=0,skip_mindless=0) +/* + * This proc gets a list of all "points of interest" (poi's) that can be used by admins to track valuable mobs or atoms (such as the nuke disk). + * @param mobs_only if set to TRUE it won't include locations to the returned list + * @param skip_mindless if set to TRUE it will skip mindless mobs + * @param force_include_bots if set to TRUE it will include bots even if skip_mindless is set to TRUE + * @param force_include_cameras if set to TRUE it will include camera eyes even if skip_mindless is set to TRUE + * @return returns a list with the found points of interest +*/ +/proc/getpois(mobs_only = FALSE, skip_mindless = FALSE, force_include_bots = FALSE, force_include_cameras = FALSE) var/list/mobs = sortmobs() var/list/names = list() var/list/pois = list() @@ -1904,7 +1910,7 @@ var/mob/dview/dview_mob = new for(var/mob/M in mobs) if(skip_mindless && (!M.mind && !M.ckey)) - if(!isbot(M) && !istype(M, /mob/camera/)) + if(!(force_include_bots && isbot(M)) && !(force_include_cameras && istype(M, /mob/camera))) continue if(M.client && M.client.holder && M.client.holder.fakekey) //stealthmins continue @@ -2032,3 +2038,7 @@ var/mob/dview/dview_mob = new tX = Clamp(origin.x + text2num(tX) - round(actual_view[1] / 2) - 1, 1, world.maxx) tY = Clamp(origin.y + text2num(tY) - round(actual_view[2] / 2) - 1, 1, world.maxy) return locate(tX, tY, tZ) + +/proc/CallAsync(datum/source, proctype, list/arguments) + set waitfor = FALSE + return call(source, proctype)(arglist(arguments)) diff --git a/code/_compile_options.dm b/code/_compile_options.dm index bd7e6484bdf..536ea01cc96 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -28,4 +28,4 @@ This may require updating to a beta release. #endif // Macros that must exist before world.dm -#define to_chat to_chat_filename=__FILE__;to_chat_line=__LINE__;to_chat_src=src;__to_chat +// #define to_chat to_chat_filename=__FILE__;to_chat_line=__LINE__;to_chat_src=src;__to_chat diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index ee3f6a73a92..ea2cf1290fd 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -1,45 +1,44 @@ -var/datum/configuration/config = null +GLOBAL_REAL(config, /datum/configuration) -var/host = null -var/join_motd = null +GLOBAL_VAR(host) +GLOBAL_VAR(join_motd) GLOBAL_VAR(join_tos) -var/game_version = "ParaCode" -var/changelog_hash = md5('html/changelog.html') //used to check if the CL changed -var/game_year = (text2num(time2text(world.realtime, "YYYY")) + 544) +GLOBAL_VAR_INIT(game_version, "ParaCode") +GLOBAL_VAR_INIT(game_year, (text2num(time2text(world.realtime, "YYYY")) + 544)) -var/aliens_allowed = 1 -var/traitor_scaling = 1 -//var/goonsay_allowed = 0 -var/dna_ident = 1 -var/abandon_allowed = 0 -var/enter_allowed = 1 -var/guests_allowed = 1 -var/shuttle_frozen = 0 -var/shuttle_left = 0 -var/tinted_weldhelh = 1 -var/mouse_respawn_time = 5 //Amount of time that must pass between a player dying as a mouse and repawning as a mouse. In minutes. - -// Command to run if shutting down (SHUTDOWN_ON_REBOOT) instead of rebooting -// It's defined here as a global because this is a hilariously bad thing to have on the easily-edited config datum -var/global/shutdown_shell_command - -// Also global to prevent easy edits -var/global/python_path = "" //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix +GLOBAL_VAR_INIT(aliens_allowed, 1) +GLOBAL_VAR_INIT(traitor_scaling, 1) +//GLOBAL_VAR_INIT(goonsay_allowed, 0) +GLOBAL_VAR_INIT(dna_ident, 1) +GLOBAL_VAR_INIT(abandon_allowed, 0) +GLOBAL_VAR_INIT(enter_allowed, 1) +GLOBAL_VAR_INIT(guests_allowed, 1) +GLOBAL_VAR_INIT(shuttle_frozen, 0) +GLOBAL_VAR_INIT(shuttle_left, 0) +GLOBAL_VAR_INIT(tinted_weldhelh, 1) +GLOBAL_VAR_INIT(mouse_respawn_time, 5) //Amount of time that must pass between a player dying as a mouse and repawning as a mouse. In minutes. // Debug is used exactly once (in living.dm) but is commented out in a lot of places. It is not set anywhere and only checked. // Debug2 is used in conjunction with a lot of admin verbs and therefore is actually legit. -var/Debug = 0 // global debug switch -var/Debug2 = 1 // enables detailed job debug file in secrets +GLOBAL_VAR_INIT(debug, 0) // global debug switch +GLOBAL_VAR_INIT(debug2, 1) // enables detailed job debug file in secrets //This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage -var/MAX_EX_DEVASTATION_RANGE = 3 -var/MAX_EX_HEAVY_RANGE = 7 -var/MAX_EX_LIGHT_RANGE = 14 -var/MAX_EX_FLASH_RANGE = 14 -var/MAX_EX_FLAME_RANGE = 14 +GLOBAL_VAR_INIT(max_ex_devastation_range, 3) +GLOBAL_VAR_INIT(max_ex_heavy_range, 7) +GLOBAL_VAR_INIT(max_ex_light_range, 14) +GLOBAL_VAR_INIT(max_ex_flash_range, 14) +GLOBAL_VAR_INIT(max_ex_flame_range, 14) //Random event stuff, apparently used -var/eventchance = 10 //% per 5 mins -var/event = 0 -var/hadevent = 0 -var/blobevent = 0 +GLOBAL_VAR_INIT(eventchance, 10) //% per 5 mins +GLOBAL_VAR_INIT(event, 0) +GLOBAL_VAR_INIT(hadevent, 0) +GLOBAL_VAR_INIT(blobevent, 0) + +// These vars are protected because changing them could pose a security risk, though they are fine to be read since they are just system paths +GLOBAL_VAR(shutdown_shell_command) // Command to run if shutting down (SHUTDOWN_ON_REBOOT) instead of rebooting +GLOBAL_PROTECT(shutdown_shell_command) + +GLOBAL_VAR(python_path) //Path to the python executable. Defaults to "python" on windows and "/usr/bin/env python2" on unix +GLOBAL_PROTECT(python_path) diff --git a/code/_globalvars/database.dm b/code/_globalvars/database.dm deleted file mode 100644 index 5c5b4e93f6a..00000000000 --- a/code/_globalvars/database.dm +++ /dev/null @@ -1,11 +0,0 @@ -// MySQL configuration -var/sqladdress = "localhost" -var/sqlport = "3306" -var/sqlfdbkdb = "test" -var/sqlfdbklogin = "root" -var/sqlfdbkpass = "" -var/sqlfdbktableprefix = "erro_" //backwords compatibility with downstream server hosts - -//Database connections -//A connection is established on world creation. Ideally, the connection dies when the server restarts (After feedback logging.). -var/DBConnection/dbcon = new() //Feedback database (New database) diff --git a/code/_globalvars/game_modes.dm b/code/_globalvars/game_modes.dm index 3f8ec321470..3088270579c 100644 --- a/code/_globalvars/game_modes.dm +++ b/code/_globalvars/game_modes.dm @@ -1,10 +1,11 @@ -var/master_mode = "extended"//"extended" -var/secret_force_mode = "secret" // if this is anything but "secret", the secret rotation will forceably choose this mode -var/wavesecret = 0 // meteor mode, delays wave progression, terrible name -var/datum/station_state/start_state = null // Used in round-end report +GLOBAL_VAR_INIT(master_mode, "extended") //"extended" +GLOBAL_VAR_INIT(secret_force_mode, "secret") // if this is anything but "secret", the secret rotation will forceably choose this mode -var/custom_event_msg = null -var/custom_event_admin_msg = null +GLOBAL_VAR_INIT(wavesecret, 0) // meteor mode, delays wave progression, terrible name +GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report. Dont ask why it inits as null -var/list/summon_spots = list() +GLOBAL_VAR(custom_event_msg) +GLOBAL_VAR(custom_event_admin_msg) + +GLOBAL_LIST_EMPTY(summon_spots) diff --git a/code/_globalvars/genetics.dm b/code/_globalvars/genetics.dm index 6a4a118f866..1119ac364cc 100644 --- a/code/_globalvars/genetics.dm +++ b/code/_globalvars/genetics.dm @@ -1,68 +1,68 @@ /////////// -var/BLINDBLOCK = 0 -var/COLOURBLINDBLOCK = 0 -var/DEAFBLOCK = 0 -var/HULKBLOCK = 0 -var/TELEBLOCK = 0 -var/FIREBLOCK = 0 -var/XRAYBLOCK = 0 -var/CLUMSYBLOCK = 0 -var/FAKEBLOCK = 0 -var/COUGHBLOCK = 0 -var/GLASSESBLOCK = 0 -var/EPILEPSYBLOCK = 0 -var/TWITCHBLOCK = 0 -var/NERVOUSBLOCK = 0 -var/WINGDINGSBLOCK = 0 -var/MONKEYBLOCK = 50 // Monkey block will always be the DNA_SE_LENGTH +GLOBAL_VAR_INIT(blindblock, 0) +GLOBAL_VAR_INIT(colourblindblock, 0) +GLOBAL_VAR_INIT(deafblock, 0) +GLOBAL_VAR_INIT(hulkblock, 0) +GLOBAL_VAR_INIT(teleblock, 0) +GLOBAL_VAR_INIT(fireblock, 0) +GLOBAL_VAR_INIT(xrayblock, 0) +GLOBAL_VAR_INIT(clumsyblock, 0) +GLOBAL_VAR_INIT(fakeblock, 0) +GLOBAL_VAR_INIT(coughblock, 0) +GLOBAL_VAR_INIT(glassesblock, 0) +GLOBAL_VAR_INIT(epilepsyblock, 0) +GLOBAL_VAR_INIT(twitchblock, 0) +GLOBAL_VAR_INIT(nervousblock, 0) +GLOBAL_VAR_INIT(wingdingsblock, 0) +GLOBAL_VAR_INIT(monkeyblock, DNA_SE_LENGTH) // Monkey block will always be the DNA_SE_LENGTH -var/BLOCKADD = 0 -var/DIFFMUT = 0 +GLOBAL_VAR_INIT(blockadd, 0) +GLOBAL_VAR_INIT(diffmut, 0) -var/BREATHLESSBLOCK = 0 -var/REMOTEVIEWBLOCK = 0 -var/REGENERATEBLOCK = 0 -var/INCREASERUNBLOCK = 0 -var/REMOTETALKBLOCK = 0 -var/MORPHBLOCK = 0 -var/COLDBLOCK = 0 -var/HALLUCINATIONBLOCK = 0 -var/NOPRINTSBLOCK = 0 -var/SHOCKIMMUNITYBLOCK = 0 -var/SMALLSIZEBLOCK = 0 +GLOBAL_VAR_INIT(breathlessblock, 0) +GLOBAL_VAR_INIT(remoteviewblock, 0) +GLOBAL_VAR_INIT(regenerateblock, 0) +GLOBAL_VAR_INIT(increaserunblock, 0) +GLOBAL_VAR_INIT(remotetalkblock, 0) +GLOBAL_VAR_INIT(morphblock, 0) +GLOBAL_VAR_INIT(coldblock, 0) +GLOBAL_VAR_INIT(hallucinationblock, 0) +GLOBAL_VAR_INIT(noprintsblock, 0) +GLOBAL_VAR_INIT(shockimmunityblock, 0) +GLOBAL_VAR_INIT(smallsizeblock, 0) /////////////////////////////// // Goon Stuff /////////////////////////////// // Disabilities -var/LISPBLOCK = 0 -var/MUTEBLOCK = 0 -var/RADBLOCK = 0 -var/FATBLOCK = 0 -var/CHAVBLOCK = 0 -var/SWEDEBLOCK = 0 -var/SCRAMBLEBLOCK = 0 -var/STRONGBLOCK = 0 -var/HORNSBLOCK = 0 -var/COMICBLOCK = 0 +GLOBAL_VAR_INIT(lispblock, 0) +GLOBAL_VAR_INIT(muteblock, 0) +GLOBAL_VAR_INIT(radblock, 0) +GLOBAL_VAR_INIT(fatblock, 0) +GLOBAL_VAR_INIT(chavblock, 0) +GLOBAL_VAR_INIT(swedeblock, 0) +GLOBAL_VAR_INIT(scrambleblock, 0) +GLOBAL_VAR_INIT(strongblock, 0) +GLOBAL_VAR_INIT(hornsblock, 0) +GLOBAL_VAR_INIT(comicblock, 0) // Powers -var/SOBERBLOCK = 0 -var/PSYRESISTBLOCK = 0 -var/SHADOWBLOCK = 0 -var/CHAMELEONBLOCK = 0 -var/CRYOBLOCK = 0 -var/EATBLOCK = 0 -var/JUMPBLOCK = 0 -var/EMPATHBLOCK = 0 -var/IMMOLATEBLOCK = 0 -var/POLYMORPHBLOCK = 0 +GLOBAL_VAR_INIT(soberblock, 0) +GLOBAL_VAR_INIT(psyresistblock, 0) +GLOBAL_VAR_INIT(shadowblock, 0) +GLOBAL_VAR_INIT(chameleonblock, 0) +GLOBAL_VAR_INIT(cryoblock, 0) +GLOBAL_VAR_INIT(eatblock, 0) +GLOBAL_VAR_INIT(jumpblock, 0) +GLOBAL_VAR_INIT(empathblock, 0) +GLOBAL_VAR_INIT(immolateblock, 0) +GLOBAL_VAR_INIT(polymorphblock, 0) /////////////////////////////// // /vg/ Mutations /////////////////////////////// -var/LOUDBLOCK = 0 -var/DIZZYBLOCK = 0 +GLOBAL_VAR_INIT(loudblock, 0) +GLOBAL_VAR_INIT(dizzyblock, 0) -var/list/reg_dna = list( ) //this appears to be a list of UE == real_name correlations -var/list/global_mutations = list() // list of hidden mutation things +GLOBAL_LIST_EMPTY(reg_dna) +GLOBAL_LIST_EMPTY(global_mutations) diff --git a/code/_globalvars/lists/devil.dm b/code/_globalvars/lists/devil.dm index 2c941069fe4..54528709573 100644 --- a/code/_globalvars/lists/devil.dm +++ b/code/_globalvars/lists/devil.dm @@ -1,8 +1,8 @@ //what could possibly go wrong -var/list/devil_machines = typecacheof(/obj/item/circuitboard, TRUE) - list( +GLOBAL_LIST_INIT(devil_machines, typecacheof(/obj/item/circuitboard, TRUE) - list( /obj/item/circuitboard/shuttle, /obj/item/circuitboard/swfdoor, /obj/item/circuitboard/olddoor, /obj/item/circuitboard/computer, /obj/item/circuitboard/machine - ) +)) diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index b6fcae25061..2caa158757c 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -3,30 +3,31 @@ GLOBAL_LIST_EMPTY(all_species) GLOBAL_LIST_EMPTY(all_languages) GLOBAL_LIST_EMPTY(language_keys) // Table of say codes for all languages GLOBAL_LIST_EMPTY(all_superheroes) -GLOBAL_LIST_INIT(whitelisted_species, list()) +GLOBAL_LIST_EMPTY(whitelisted_species) -GLOBAL_LIST_INIT(clients, list()) //list of all clients -GLOBAL_LIST_INIT(admins, list()) //list of all clients whom are admins -GLOBAL_LIST_INIT(deadmins, list()) //list of all clients who have used the de-admin verb. -GLOBAL_LIST_INIT(directory, list()) //list of all ckeys with associated client -GLOBAL_LIST_INIT(stealthminID, list()) //reference list with IDs that store ckeys, for stealthmins +GLOBAL_LIST_EMPTY(clients) //list of all clients +GLOBAL_LIST_EMPTY(admins) //list of all clients whom are admins +GLOBAL_LIST_EMPTY(deadmins) //list of all clients who have used the de-admin verb. +GLOBAL_LIST_EMPTY(directory) //list of all ckeys with associated client +GLOBAL_LIST_EMPTY(stealthminID) //reference list with IDs that store ckeys, for stealthmins //Since it didn't really belong in any other category, I'm putting this here //This is for procs to replace all the goddamn 'in world's that are chilling around the code -GLOBAL_LIST_INIT(player_list, list()) //List of all mobs **with clients attached**. Excludes /mob/new_player -GLOBAL_LIST_INIT(mob_list, list()) //List of all mobs, including clientless -GLOBAL_LIST_INIT(silicon_mob_list, list()) //List of all silicon mobs, including clientless -GLOBAL_LIST_INIT(spirits, list()) //List of all the spirits, including Masks -GLOBAL_LIST_INIT(living_mob_list, list()) //List of all alive mobs, including clientless. Excludes /mob/new_player -GLOBAL_LIST_INIT(dead_mob_list, list()) //List of all dead mobs, including clientless. Excludes /mob/new_player -GLOBAL_LIST_INIT(respawnable_list, list()) //List of all mobs, dead or in mindless creatures that still be respawned. -GLOBAL_LIST_INIT(non_respawnable_keys, list()) //List of ckeys that are excluded from respawning for remainder of round. +GLOBAL_LIST_EMPTY(player_list) //List of all mobs **with clients attached**. Excludes /mob/new_player +GLOBAL_LIST_EMPTY(mob_list) //List of all mobs, including clientless +GLOBAL_LIST_EMPTY(silicon_mob_list) //List of all silicon mobs, including clientless +GLOBAL_LIST_EMPTY(mob_living_list) //all instances of /mob/living and subtypes +GLOBAL_LIST_EMPTY(spirits) //List of all the spirits, including Masks +GLOBAL_LIST_EMPTY(alive_mob_list) //List of all alive mobs, including clientless. Excludes /mob/new_player +GLOBAL_LIST_EMPTY(dead_mob_list) //List of all dead mobs, including clientless. Excludes /mob/new_player +GLOBAL_LIST_EMPTY(respawnable_list) //List of all mobs, dead or in mindless creatures that still be respawned. +GLOBAL_LIST_EMPTY(non_respawnable_keys) //List of ckeys that are excluded from respawning for remainder of round. GLOBAL_LIST_INIT(simple_animals, list(list(), list(), list(), list())) //One for each AI_* status define, List of all simple animals, including clientless -GLOBAL_LIST_INIT(bots_list, list()) //List of all bots(beepsky, medibots,etc) +GLOBAL_LIST_EMPTY(bots_list) //List of all bots(beepsky, medibots,etc) -GLOBAL_LIST_INIT(med_hud_users, list()) -GLOBAL_LIST_INIT(sec_hud_users, list()) -GLOBAL_LIST_INIT(antag_hud_users, list()) -GLOBAL_LIST_INIT(surgeries_list, list()) -GLOBAL_LIST_INIT(hear_radio_list, list()) //Mobs that hear the radio even if there's no client +GLOBAL_LIST_EMPTY(med_hud_users) +GLOBAL_LIST_EMPTY(sec_hud_users) +GLOBAL_LIST_EMPTY(antag_hud_users) +GLOBAL_LIST_EMPTY(surgeries_list) +GLOBAL_LIST_EMPTY(hear_radio_list) //Mobs that hear the radio even if there's no client diff --git a/code/_globalvars/lists/reagents.dm b/code/_globalvars/lists/reagents.dm index 20620d60800..abd878ff936 100644 --- a/code/_globalvars/lists/reagents.dm +++ b/code/_globalvars/lists/reagents.dm @@ -64,3 +64,5 @@ GLOBAL_LIST_INIT(safe_chem_list, list("antihol", "charcoal", "epinephrine", "ins "omnizine", "stimulants", "synaptizine", "potass_iodide", "oculine", "mannitol", "styptic_powder", "spaceacillin", "salglu_solution", "sal_acid", "cryoxadone", "blood", "synthflesh", "hydrocodone", "mitocholide", "rezadone")) + +GLOBAL_LIST_INIT(safe_chem_applicator_list, list("silver_sulfadiazine", "styptic_powder", "synthflesh")) diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index 10c7d74c752..0ea513708a1 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -1,3 +1,4 @@ +// Everything in this file should be protected GLOBAL_VAR(log_directory) GLOBAL_PROTECT(log_directory) GLOBAL_VAR(world_game_log) @@ -15,14 +16,20 @@ GLOBAL_PROTECT(world_asset_log) GLOBAL_VAR(runtime_summary_log) GLOBAL_PROTECT(runtime_summary_log) -var/list/jobMax = list() -var/list/admin_log = list ( ) -var/list/lastsignalers = list( ) //keeps last 100 signals here in format: "[src] used \ref[src] @ location [src.loc]: [freq]/[code]" -var/list/lawchanges = list( ) //Stores who uploaded laws to which silicon-based lifeform, and what the law was +GLOBAL_LIST_EMPTY(jobMax) +GLOBAL_PROTECT(jobMax) +GLOBAL_LIST_EMPTY(admin_log) +GLOBAL_PROTECT(admin_log) +GLOBAL_LIST_EMPTY(lastsignalers) +GLOBAL_PROTECT(lastsignalers) +GLOBAL_LIST_EMPTY(lawchanges) +GLOBAL_PROTECT(lawchanges) -var/list/combatlog = list() -var/list/IClog = list() -var/list/OOClog = list() -var/list/adminlog = list() +GLOBAL_LIST_EMPTY(combatlog) +GLOBAL_PROTECT(combatlog) +GLOBAL_LIST_EMPTY(IClog) +GLOBAL_PROTECT(IClog) +GLOBAL_LIST_EMPTY(OOClog) +GLOBAL_PROTECT(OOClog) -var/list/investigate_log_subjects = list("notes", "watchlist", "hrefs") +GLOBAL_LIST_INIT(investigate_log_subjects, list("notes", "watchlist", "hrefs")) diff --git a/code/_globalvars/mapping.dm b/code/_globalvars/mapping.dm index 9c54212cbb7..ca1c899e301 100644 --- a/code/_globalvars/mapping.dm +++ b/code/_globalvars/mapping.dm @@ -3,12 +3,14 @@ #define Z_SOUTH 3 #define Z_WEST 4 -var/list/cardinal = list( NORTH, SOUTH, EAST, WEST ) -var/list/alldirs = list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) -var/list/diagonals = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST) +GLOBAL_LIST_INIT(cardinal, list( NORTH, SOUTH, EAST, WEST )) +GLOBAL_LIST_INIT(alldirs, list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) +GLOBAL_LIST_INIT(diagonals, list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)) -var/global/list/global_map = null - //list/global_map = list(list(1,5),list(4,3))//an array of map Z levels. +// This must exist early on or shit breaks bad +GLOBAL_DATUM_INIT(using_map, /datum/map, new USING_MAP_DATUM) + +GLOBAL_LIST(global_map) // This is the array of zlevels | list(list(1,5),list(4,3)) | becomes a 2D array of zlevels //Resulting sector map looks like //|_1_|_4_| //|_5_|_3_| @@ -18,38 +20,37 @@ var/global/list/global_map = null //3 - AI satellite //5 - empty space -var/list/wizardstart = list() -var/list/newplayer_start = list() -var/list/latejoin = list() -var/list/latejoin_gateway = list() -var/list/latejoin_cryo = list() -var/list/latejoin_cyborg = list() -var/list/prisonwarp = list() //prisoners go to these -var/list/xeno_spawn = list()//Aliens spawn at these. -var/list/ertdirector = list() -var/list/emergencyresponseteamspawn = list() -var/list/tdome1 = list() -var/list/tdome2 = list() -var/list/team_alpha = list() -var/list/team_bravo = list() -var/list/tdomeobserve = list() -var/list/tdomeadmin = list() -var/list/aroomwarp = list() -var/list/prisonsecuritywarp = list() //prison security goes to these -var/list/prisonwarped = list() //list of players already warped -var/list/blobstart = list() -var/list/ninjastart = list() -var/list/carplist = list() //list of all carp-spawn landmarks -var/list/syndicateofficer = list() +GLOBAL_LIST_EMPTY(wizardstart) +GLOBAL_LIST_EMPTY(newplayer_start) +GLOBAL_LIST_EMPTY(latejoin) +GLOBAL_LIST_EMPTY(latejoin_gateway) +GLOBAL_LIST_EMPTY(latejoin_cryo) +GLOBAL_LIST_EMPTY(latejoin_cyborg) +GLOBAL_LIST_EMPTY(prisonwarp) //prisoners go to these +GLOBAL_LIST_EMPTY(xeno_spawn)//Aliens spawn at these. +GLOBAL_LIST_EMPTY(ertdirector) +GLOBAL_LIST_EMPTY(emergencyresponseteamspawn) +GLOBAL_LIST_EMPTY(tdome1) +GLOBAL_LIST_EMPTY(tdome2) +GLOBAL_LIST_EMPTY(team_alpha) +GLOBAL_LIST_EMPTY(team_bravo) +GLOBAL_LIST_EMPTY(tdomeobserve) +GLOBAL_LIST_EMPTY(tdomeadmin) +GLOBAL_LIST_EMPTY(aroomwarp) +GLOBAL_LIST_EMPTY(prisonsecuritywarp) //prison security goes to these +GLOBAL_LIST_EMPTY(prisonwarped) //list of players already warped +GLOBAL_LIST_EMPTY(blobstart) +GLOBAL_LIST_EMPTY(ninjastart) +GLOBAL_LIST_EMPTY(carplist) //list of all carp-spawn landmarks +GLOBAL_LIST_EMPTY(syndicateofficer) //away missions -var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to +GLOBAL_LIST_EMPTY(awaydestinations) //a list of landmarks that the warpgate can take you to //List of preloaded templates -var/list/datum/map_template/map_templates = list() - -var/list/datum/map_template/ruins_templates = list() -var/list/datum/map_template/space_ruins_templates = list() -var/list/datum/map_template/lava_ruins_templates = list() -var/list/datum/map_template/shelter_templates = list() -var/list/datum/map_template/shuttle_templates = list() +GLOBAL_LIST_EMPTY(map_templates) +GLOBAL_LIST_EMPTY(ruins_templates) +GLOBAL_LIST_EMPTY(space_ruins_templates) +GLOBAL_LIST_EMPTY(lava_ruins_templates) +GLOBAL_LIST_EMPTY(shelter_templates) +GLOBAL_LIST_EMPTY(shuttle_templates) diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index 04db7233401..32d6370f3d0 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -1,93 +1,103 @@ -var/global/obj/effect/overlay/plmaster = null -var/global/obj/effect/overlay/slmaster = null +GLOBAL_DATUM(plmaster, /obj/effect/overlay) +GLOBAL_DATUM(slmaster, /obj/effect/overlay) GLOBAL_VAR_INIT(CELLRATE, 0.002) // conversion ratio between a watt-tick and kilojoule GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second) // Announcer intercom, because too much stuff creates an intercom for one message then hard del()s it. -var/global/obj/item/radio/intercom/global_announcer = create_global_announcer() -var/global/obj/item/radio/intercom/command/command_announcer = create_command_announcer() +GLOBAL_DATUM_INIT(global_announcer, /obj/item/radio/intercom, create_global_announcer()) +GLOBAL_DATUM_INIT(command_announcer, /obj/item/radio/intercom/command, create_command_announcer()) + // Load order issues means this can't be new'd until other code runs // This is probably not the way I should be doing this, but I don't know how to do it right! proc/create_global_announcer() spawn(0) - global_announcer = new(null) + GLOB.global_announcer = new(null) return proc/create_command_announcer() spawn(0) - command_announcer = new(null) + GLOB.command_announcer = new(null) return -var/list/paper_tag_whitelist = list("center","p","div","span","h1","h2","h3","h4","h5","h6","hr","pre", \ +GLOBAL_LIST_INIT(paper_tag_whitelist, list("center","p","div","span","h1","h2","h3","h4","h5","h6","hr","pre", \ "big","small","font","i","u","b","s","sub","sup","tt","br","hr","ol","ul","li","caption","col", \ - "table","td","th","tr") -var/list/paper_blacklist = list("java","onblur","onchange","onclick","ondblclick","onfocus","onkeydown", \ + "table","td","th","tr")) +GLOBAL_LIST_INIT(paper_blacklist, list("java","onblur","onchange","onclick","ondblclick","onfocus","onkeydown", \ "onkeypress","onkeyup","onload","onmousedown","onmousemove","onmouseout","onmouseover", \ - "onmouseup","onreset","onselect","onsubmit","onunload") + "onmouseup","onreset","onselect","onsubmit","onunload")) //Reverse of dir -var/list/reverse_dir = list(2, 1, 3, 8, 10, 9, 11, 4, 6, 5, 7, 12, 14, 13, 15, 32, 34, 33, 35, 40, 42, 41, 43, 36, 38, 37, 39, 44, 46, 45, 47, 16, 18, 17, 19, 24, 26, 25, 27, 20, 22, 21, 23, 28, 30, 29, 31, 48, 50, 49, 51, 56, 58, 57, 59, 52, 54, 53, 55, 60, 62, 61, 63) -var/gravity_is_on = 1 //basically unused, just one admin verb.. +GLOBAL_LIST_INIT(reverse_dir, list(2, 1, 3, 8, 10, 9, 11, 4, 6, 5, 7, 12, 14, 13, 15, 32, 34, 33, 35, 40, 42, 41, 43, 36, 38, 37, 39, 44, 46, 45, 47, 16, 18, 17, 19, 24, 26, 25, 27, 20, 22, 21, 23, 28, 30, 29, 31, 48, 50, 49, 51, 56, 58, 57, 59, 52, 54, 53, 55, 60, 62, 61, 63)) +GLOBAL_VAR_INIT(gravity_is_on, 1) //basically unused, just one admin verb.. // Recall time limit: 2 hours -var/recall_time_limit=72000 //apparently used for the comm console +GLOBAL_VAR_INIT(recall_time_limit, 72000) //apparently used for the comm console //////SCORE STUFF //Goonstyle scoreboard -var/score_crewscore = 0 // this is the overall var/score for the whole round -var/score_stuffshipped = 0 // how many useful items have cargo shipped out? -var/score_stuffharvested = 0 // how many harvests have hydroponics done? -var/score_oremined = 0 // obvious -var/score_researchdone = 0 -var/score_eventsendured = 0 // how many random events did the station survive? -var/score_powerloss = 0 // how many APCs have poor charge? -var/score_escapees = 0 // how many people got out alive? -var/score_deadcrew = 0 // dead bodies on the station, oh no -var/score_mess = 0 // how much poo, puke, gibs, etc went uncleaned -var/score_meals = 0 -var/score_disease = 0 // how many rampant, uncured diseases are on board the station -var/score_deadcommand = 0 // used during rev, how many command staff perished -var/score_arrested = 0 // how many traitors/revs/whatever are alive in the brig -var/score_traitorswon = 0 // how many traitors were successful? -var/score_allarrested = 0 // did the crew catch all the enemies alive? -var/score_opkilled = 0 // used during nuke mode, how many operatives died? -var/score_disc = 0 // is the disc safe and secure? -var/score_nuked = 0 // was the station blown into little bits? -var/score_nuked_penalty = 0 //penalty for getting blown to bits +GLOBAL_VAR_INIT(score_crewscore, 0) // this is the overall var/score for the whole round +GLOBAL_VAR_INIT(score_stuffshipped, 0) // how many useful items have cargo shipped out? +GLOBAL_VAR_INIT(score_stuffharvested, 0) // how many harvests have hydroponics done? +GLOBAL_VAR_INIT(score_oremined, 0) // obvious +GLOBAL_VAR_INIT(score_researchdone, 0) +GLOBAL_VAR_INIT(score_eventsendured, 0) // how many random events did the station survive? +GLOBAL_VAR_INIT(score_powerloss, 0) // how many APCs have poor charge? +GLOBAL_VAR_INIT(score_escapees, 0) // how many people got out alive? +GLOBAL_VAR_INIT(score_deadcrew, 0) // dead bodies on the station, oh no +GLOBAL_VAR_INIT(score_mess, 0) // how much poo, puke, gibs, etc went uncleaned +GLOBAL_VAR_INIT(score_meals, 0) +GLOBAL_VAR_INIT(score_disease, 0) // how many rampant, uncured diseases are on board the station +GLOBAL_VAR_INIT(score_deadcommand, 0) // used during rev, how many command staff perished +GLOBAL_VAR_INIT(score_arrested, 0) // how many traitors/revs/whatever are alive in the brig +GLOBAL_VAR_INIT(score_traitorswon, 0) // how many traitors were successful? +GLOBAL_VAR_INIT(score_allarrested, 0) // did the crew catch all the enemies alive? +GLOBAL_VAR_INIT(score_opkilled, 0) // used during nuke mode, how many operatives died? +GLOBAL_VAR_INIT(score_disc, 0) // is the disc safe and secure? +GLOBAL_VAR_INIT(score_nuked, 0) // was the station blown into little bits? +GLOBAL_VAR_INIT(score_nuked_penalty, 0) //penalty for getting blown to bits // these ones are mainly for the stat panel -var/score_powerbonus = 0 // if all APCs on the station are running optimally, big bonus -var/score_messbonus = 0 // if there are no messes on the station anywhere, huge bonus -var/score_deadaipenalty = 0 // is the AI dead? if so, big penalty -var/score_foodeaten = 0 // nom nom nom -var/score_clownabuse = 0 // how many times a clown was punched, struck or otherwise maligned -var/score_richestname = null // this is all stuff to show who was the richest alive on the shuttle -var/score_richestjob = null // kinda pointless if you dont have a money system i guess -var/score_richestcash = 0 -var/score_richestkey = null -var/score_dmgestname = null // who had the most damage on the shuttle (but was still alive) -var/score_dmgestjob = null -var/score_dmgestdamage = 0 -var/score_dmgestkey = null +GLOBAL_VAR_INIT(score_powerbonus, 0) // if all APCs on the station are running optimally, big bonus +GLOBAL_VAR_INIT(score_messbonus, 0) // if there are no messes on the station anywhere, huge bonus +GLOBAL_VAR_INIT(score_deadaipenalty, 0) // is the AI dead? if so, big penalty +GLOBAL_VAR_INIT(score_foodeaten, 0) // nom nom nom +GLOBAL_VAR_INIT(score_clownabuse, 0) // how many times a clown was punched, struck or otherwise maligned +GLOBAL_VAR(score_richestname) // this is all stuff to show who was the richest alive on the shuttle +GLOBAL_VAR(score_richestjob) // kinda pointless if you dont have a money system i guess +GLOBAL_VAR_INIT(score_richestcash, 0) +GLOBAL_VAR(score_richestkey) +GLOBAL_VAR(score_dmgestname) // who had the most damage on the shuttle (but was still alive) +GLOBAL_VAR(score_dmgestjob) +GLOBAL_VAR_INIT(score_dmgestdamage, 0) +GLOBAL_VAR(score_dmgestkey) -var/TAB = "    " +#define TAB "    " GLOBAL_VAR_INIT(timezoneOffset, 0) // The difference betwen midnight (of the host computer) and 0 world.ticks. // For FTP requests. (i.e. downloading runtime logs.) // However it'd be ok to use for accessing attack logs and such too, which are even laggier. -var/fileaccess_timer = 0 +GLOBAL_VAR_INIT(fileaccess_timer, 0) GLOBAL_VAR_INIT(gametime_offset, 432000) // 12:00 in seconds //printers shutdown if too much shit printed -var/copier_items_printed = 0 -var/copier_max_items = 300 -var/copier_items_printed_logged = FALSE +GLOBAL_VAR_INIT(copier_items_printed, 0) +GLOBAL_VAR_INIT(copier_max_items, 300) +GLOBAL_VAR_INIT(copier_items_printed_logged, FALSE) GLOBAL_VAR(map_name) // Self explanatory -var/global/datum/datacore/data_core = null // Station datacore, manifest, etc +GLOBAL_DATUM(data_core, /datum/datacore) // Station datacore, manifest, etc GLOBAL_VAR_INIT(panic_bunker_enabled, FALSE) // Is the panic bunker enabled + +//Database connections +//A connection is established on world creation. Ideally, the connection dies when the server restarts (After feedback logging.). +// This is a protected datum which means its read only. I hope the reason for protecting this is obvious +GLOBAL_DATUM_INIT(dbcon, /DBConnection, new) //Feedback database (New database) +GLOBAL_PROTECT(dbcon) + +GLOBAL_LIST_EMPTY(ability_verbs) // Create-level abilities +GLOBAL_LIST_INIT(pipe_colors, list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE)) diff --git a/code/_globalvars/sensitive.dm b/code/_globalvars/sensitive.dm new file mode 100644 index 00000000000..b1e6751c4dd --- /dev/null +++ b/code/_globalvars/sensitive.dm @@ -0,0 +1,12 @@ +// All global vars in this file require a different handler as we dont want their data to be exposed, not even to admins with permission to view globals +// They write as native BYOND globals, which means they cant be edited at all, and also use a format +// Please only throw absolutely crucial do-not-view shit in here please. -aa07 + +// MySQL configuration +GLOBAL_REAL_VAR(sqladdress) = "localhost" +GLOBAL_REAL_VAR(sqlport) = "3306" +GLOBAL_REAL_VAR(sqlfdbkdb) = "test" +GLOBAL_REAL_VAR(sqlfdbklogin) = "root" +GLOBAL_REAL_VAR(sqlfdbkpass) = "" +GLOBAL_REAL_VAR(sqlfdbktableprefix) = "erro_" + diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 9e0d45643be..ccc31e5c501 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -5,7 +5,10 @@ */ GLOBAL_LIST_INIT(traits_by_type, list( /mob = list( - "TRAIT_PACIFISM" = TRAIT_PACIFISM + "TRAIT_PACIFISM" = TRAIT_PACIFISM, + "TRAIT_WATERBREATH" = TRAIT_WATERBREATH, + "BLOODCRAWL" = TRAIT_BLOODCRAWL, + "BLOODCRAWL_EAT" = TRAIT_BLOODCRAWL_EAT ))) /// value -> trait name, generated on use from trait_by_type global diff --git a/code/_globalvars/unused.dm b/code/_globalvars/unused.dm deleted file mode 100644 index 6e2075559b8..00000000000 --- a/code/_globalvars/unused.dm +++ /dev/null @@ -1 +0,0 @@ -var/going = 1.0 diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 7c2214e2287..fbb04d4c021 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -42,7 +42,7 @@ if(control_disabled || stat) return - + var/turf/pixel_turf = isturf(A) ? A : get_turf_pixel(A) if(isnull(pixel_turf)) return @@ -57,7 +57,7 @@ var/turf_visible if(pixel_turf) - turf_visible = cameranet.checkTurfVis(pixel_turf) + turf_visible = GLOB.cameranet.checkTurfVis(pixel_turf) if(!turf_visible) if(istype(loc, /obj/item/aicard) && (pixel_turf in view(client.view, loc))) turf_visible = TRUE @@ -228,4 +228,4 @@ // /mob/living/silicon/ai/TurfAdjacent(var/turf/T) - return (cameranet && cameranet.checkTurfVis(T)) + return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(T)) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 6bfd72413de..d840f64bb4a 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -134,9 +134,9 @@ if(W == A) W.attack_self(src) if(hand) - update_inv_l_hand(0) + update_inv_l_hand() else - update_inv_r_hand(0) + update_inv_r_hand() return // operate three levels deep here (item in backpack in src; item in box in backpack in src, not any deeper) @@ -258,28 +258,34 @@ Makes the mob face the direction of the clicked thing */ /mob/proc/MiddleShiftClickOn(atom/A) + return + +/mob/living/MiddleShiftClickOn(atom/A) if(incapacitated()) return var/face_dir = get_cardinal_dir(src, A) - if(forced_look == face_dir) + if(!face_dir || forced_look == face_dir || A == src) forced_look = null - to_chat(src, "You are no longer facing any direction.") + to_chat(src, "Cancelled direction lock.") return forced_look = face_dir - to_chat(src, "You are now facing [dir2text(forced_look)].") + to_chat(src, "You are now facing [dir2text(forced_look)]. To cancel this, shift-middleclick yourself.") /* Middle shift-control-click Makes the mob constantly face the object (until it's out of sight) */ /mob/proc/MiddleShiftControlClickOn(atom/A) + return + +/mob/living/MiddleShiftControlClickOn(atom/A) var/face_uid = A.UID() - if(forced_look == face_uid) + if(forced_look == face_uid || A == src) forced_look = null - to_chat(src, "You are no longer facing [A].") + to_chat(src, "Cancelled direction lock.") return forced_look = face_uid - to_chat(src, "You are now facing [A].") + to_chat(src, "You are now facing [A]. To cancel this, shift-middleclick yourself.") // In case of use break glass /* diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm index f03d436bcaf..8f243dfcdc1 100644 --- a/code/_onclick/hud/other_mobs.dm +++ b/code/_onclick/hud/other_mobs.dm @@ -3,6 +3,10 @@ /datum/hud/simple_animal/New(mob/user) ..() + + mymob.healths = new /obj/screen/healths() + infodisplay += mymob.healths + var/obj/screen/using using = new /obj/screen/act_intent/simple_animal() using.icon_state = mymob.a_intent diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index c0f5cfd5f3b..1423720f8f6 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -371,15 +371,15 @@ return 1 if(istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech return 1 - + if(hud?.mymob && slot_id) var/obj/item/inv_item = hud.mymob.get_item_by_slot(slot_id) if(inv_item) return inv_item.Click(location, control, params) if(usr.attack_ui(slot_id)) - usr.update_inv_l_hand(0) - usr.update_inv_r_hand(0) + usr.update_inv_l_hand() + usr.update_inv_r_hand() return 1 /obj/screen/inventory/hand diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index d2a91da4020..e27002cf118 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -58,7 +58,7 @@ else return 1 var/obj/item/organ/external/O = M.get_organ(user.zone_selected) - if((is_sharp(src) || (isscrewdriver(src) && O.is_robotic())) && user.a_intent == INTENT_HELP) + if((is_sharp(src) || (isscrewdriver(src) && O?.is_robotic())) && user.a_intent == INTENT_HELP) if(!attempt_initiate_surgery(src, M, user)) return FALSE else diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 3f5785e44ab..2f4811de380 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -502,7 +502,7 @@ config.guest_jobban = 1 if("guest_ban") - guests_allowed = 0 + GLOB.guests_allowed = 0 if("panic_bunker_threshold") config.panic_bunker_threshold = text2num(value) @@ -618,12 +618,12 @@ if("python_path") if(value) - python_path = value + GLOB.python_path = value else if(world.system_type == UNIX) - python_path = "/usr/bin/env python2" + GLOB.python_path = "/usr/bin/env python2" else //probably windows, if not this should work anyway - python_path = "pythonw" + GLOB.python_path = "pythonw" if("assistant_limit") config.assistantlimit = 1 @@ -716,7 +716,7 @@ config.shutdown_on_reboot = 1 if("shutdown_shell_command") - shutdown_shell_command = value + GLOB.shutdown_shell_command = value if("disable_karma") config.disable_karma = 1 @@ -789,11 +789,11 @@ if(BombCap > 128) BombCap = 128 - MAX_EX_DEVASTATION_RANGE = round(BombCap/4) - MAX_EX_HEAVY_RANGE = round(BombCap/2) - MAX_EX_LIGHT_RANGE = BombCap - MAX_EX_FLASH_RANGE = BombCap - MAX_EX_FLAME_RANGE = BombCap + GLOB.max_ex_devastation_range = round(BombCap/4) + GLOB.max_ex_heavy_range = round(BombCap/2) + GLOB.max_ex_light_range = BombCap + GLOB.max_ex_flash_range = BombCap + GLOB.max_ex_flame_range = BombCap if("default_laws") config.default_laws = text2num(value) if("randomize_shift_time") @@ -856,7 +856,7 @@ log_config("WARNING: DB_CONFIG DEFINITION MISMATCH!") spawn(60) if(SSticker.current_state == GAME_STATE_PREGAME) - going = 0 + SSticker.ticker_going = FALSE spawn(600) to_chat(world, "DB_CONFIG MISMATCH, ROUND START DELAYED.
Please check database version for recent upstream changes!
") diff --git a/code/controllers/master.dm b/code/controllers/master.dm index f64e566e097..fea79c2f7a5 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -62,10 +62,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/static/current_ticklimit = TICK_LIMIT_RUNNING /datum/controller/master/New() - //temporary file used to record errors with loading config, moved to log directory once logging is set up - GLOB.config_error_log = GLOB.world_game_log = GLOB.world_runtime_log = "data/logs/config_error.log" - load_configuration() - // Highlander-style: there can only be one! Kill off the old and replace it with the new. if(!random_seed) random_seed = rand(1, 1e9) @@ -73,6 +69,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new var/list/_subsystems = list() subsystems = _subsystems + // Highlander-style: there can only be one! Kill off the old and replace it with the new. if(Master != src) if(istype(Master)) Recover() @@ -146,7 +143,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new msg = "The [BadBoy.name] subsystem was the last to fire for 2 controller restarts. It will be recovered now and disabled if it happens again." FireHim = TRUE if(3) - msg = "The [BadBoy.name] subsystem seems to be destabilizing the MC and will be offlined." + msg = "The [BadBoy.name] subsystem seems to be destabilizing the MC and will be offlined. The following implications are now in effect: [BadBoy.offline_implications]" BadBoy.flags |= SS_NO_FIRE if(msg) to_chat(GLOB.admins, "[msg]") diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index b8996f2cf89..68ee4bfeace 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -1,7 +1,7 @@ /datum/controller/subsystem // Metadata; you should define these. - name = "fire coderbus" //name of the subsystem + name = "fire codertrain" //name of the subsystem var/init_order = INIT_ORDER_DEFAULT //order of initialization. Higher numbers are initialized first, lower numbers later. Use defines in __DEFINES/subsystems.dm for easy understanding of order. var/wait = 20 //time to wait (in deciseconds) between each call to fire(). Must be a positive integer. var/priority = FIRE_PRIORITY_DEFAULT //When mutiple subsystems need to run in the same tick, higher priority subsystems will run first and be given a higher share of the tick before MC_TICK_CHECK triggers a sleep @@ -35,6 +35,8 @@ var/static/list/failure_strikes //How many times we suspect a subsystem type has crashed the MC, 3 strikes and you're out! + var/offline_implications = "None" // What are the implications of this SS being offlined? + //Do not override ///datum/controller/subsystem/New() @@ -179,7 +181,7 @@ var/title = name if(can_fire) - title = "\[[state_letter()]][title]" + title = "[state_colour()]\[[state_letter()]][title]" stat(title, statclick.update(msg)) @@ -196,6 +198,18 @@ if(SS_IDLE) . = " " +/datum/controller/subsystem/proc/state_colour() + switch(state) + if(SS_RUNNING) // If its actively processing, colour it green + . = "" + if(SS_QUEUED) // If its in the running queue, but delayed, colour it orange + . = "" + if(SS_PAUSED, SS_PAUSING) // If its being paused due to lag, colour it red + . = "" + if(SS_SLEEPING) // If fire() slept, colour it blue + . = "" + if(SS_IDLE) // Leave it default if the SS is idle + . = "" //could be used to postpone a costly subsystem for (default one) var/cycles, cycles //for instance, during cpu intensive operations like explosions /datum/controller/subsystem/proc/postpone(cycles = 1) diff --git a/code/controllers/subsystem/acid.dm b/code/controllers/subsystem/acid.dm index 40063b00a87..119d82113d7 100644 --- a/code/controllers/subsystem/acid.dm +++ b/code/controllers/subsystem/acid.dm @@ -3,6 +3,7 @@ SUBSYSTEM_DEF(acid) priority = FIRE_PRIORITY_ACID flags = SS_NO_INIT|SS_BACKGROUND runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + offline_implications = "Objects will no longer react to acid. No immediate action is needed." var/list/currentrun = list() var/list/processing = list() diff --git a/code/controllers/subsystem/afk.dm b/code/controllers/subsystem/afk.dm index 6ab1d67a816..037b9a2bd0a 100644 --- a/code/controllers/subsystem/afk.dm +++ b/code/controllers/subsystem/afk.dm @@ -1,63 +1,76 @@ -#define AFK_WARNED 1 -#define AFK_CRYOD 2 +#define AFK_WARNED 1 +#define AFK_CRYOD 2 +#define AFK_ADMINS_WARNED 3 SUBSYSTEM_DEF(afk) name = "AFK Watcher" wait = 300 flags = SS_BACKGROUND + offline_implications = "Players will no longer be marked as AFK. No immediate action is needed." var/list/afk_players = list() // Associative list. ckey as key and AFK state as value + var/list/non_cryo_antags /datum/controller/subsystem/afk/Initialize() - if(config.warn_afk_minimum <= 0 || config.auto_cryo_afk <= 0 || config.auto_despawn_afk <= 0) - flags |= SS_NO_FIRE + if(config.warn_afk_minimum <= 0 || config.auto_cryo_afk <= 0 || config.auto_despawn_afk <= 0) + flags |= SS_NO_FIRE + else + non_cryo_antags = list(SPECIAL_ROLE_ABDUCTOR_AGENT, SPECIAL_ROLE_ABDUCTOR_SCIENTIST, \ + SPECIAL_ROLE_SHADOWLING, SPECIAL_ROLE_WIZARD, SPECIAL_ROLE_WIZARD_APPRENTICE, SPECIAL_ROLE_NUKEOPS) + return ..() /datum/controller/subsystem/afk/fire() var/list/toRemove = list() - for(var/mob/living/carbon/human/H in GLOB.living_mob_list) - if(!H.ckey) // Useless non ckey creatures + for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) + if(!H?.ckey) // Useless non ckey creatures continue - - var/turf/T + + var/turf/T // Only players and players with the AFK watch enabled - // No dead, unconcious, restrained, people without jobs, people on other Z levels than the station or antags + // No dead, unconcious, restrained, people without jobs or people on other Z levels than the station if(!H.client || !H.client.prefs.afk_watch || !H.mind || \ - H.stat || H.restrained() || !H.job || H.mind.special_role || \ - !is_station_level((T = get_turf(H)).z)) // Assign the turf as last. Small optimization - if(afk_players[H.ckey]) + H.stat || H.restrained() || !H.job || !is_station_level((T = get_turf(H)).z)) // Assign the turf as last. Small optimization + if(afk_players[H.ckey]) toRemove += H.ckey continue - + var/mins_afk = round(H.client.inactivity / 600) if(mins_afk < config.warn_afk_minimum) if(afk_players[H.ckey]) toRemove += H.ckey continue - + if(!afk_players[H.ckey]) afk_players[H.ckey] = AFK_WARNED warn(H, "You are AFK for [mins_afk] minutes. You will be cryod after [config.auto_cryo_afk] total minutes and fully despawned after [config.auto_despawn_afk] total minutes. Please move or click in game if you want to avoid being despawned.") - else + else var/area/A = T.loc // Turfs loc is the area if(afk_players[H.ckey] == AFK_WARNED) if(mins_afk >= config.auto_cryo_afk && A.can_get_auto_cryod) if(A.fast_despawn) toRemove += H.ckey warn(H, "You are have been despawned after being AFK for [mins_afk] minutes. You have been despawned instantly due to you being in a secure area.") - msg_admins(H, mins_afk, T, "forcefully despawned", "AFK in a fast despawn area") + log_afk_action(H, mins_afk, T, "despawned", "AFK in a fast despawn area") force_cryo_human(H) - else if(cryo_ssd(H)) - afk_players[H.ckey] = AFK_CRYOD - msg_admins(H, mins_afk, T, "put into cryostorage") - warn(H, "You are AFK for [mins_afk] minutes and have been moved to cryostorage. After being AFK for [config.auto_despawn_afk] total minutes you will be fully despawned. Please eject yourself (right click, eject) out of the cryostorage if you want to avoid being despawned.") - - else if(mins_afk >= config.auto_despawn_afk) - var/obj/machinery/cryopod/P = H.loc - msg_admins(H, mins_afk, T, "forcefully despawned") + else + if(!(H.mind.special_role in non_cryo_antags)) + if(cryo_ssd(H)) + H.create_log(MISC_LOG, "Put into cryostorage by the AFK subsystem") + afk_players[H.ckey] = AFK_CRYOD + log_afk_action(H, mins_afk, T, "put into cryostorage") + warn(H, "You are AFK for [mins_afk] minutes and have been moved to cryostorage. \ + After being AFK for another [config.auto_despawn_afk] minutes you will be fully despawned. \ + Please eject yourself (right click, eject) out of the cryostorage if you want to avoid being despawned.") + else + message_admins("[key_name_admin(H)] at ([get_area(T).name] [ADMIN_JMP(T)]) is AFK for [mins_afk] and can't be automatically cryod due to it's antag status: ([H.mind.special_role]).") + afk_players[H.ckey] = AFK_ADMINS_WARNED + + else if(afk_players[H.ckey] != AFK_ADMINS_WARNED && mins_afk >= config.auto_despawn_afk) + log_afk_action(H, mins_afk, T, "despawned") warn(H, "You are have been despawned after being AFK for [mins_afk] minutes.") toRemove += H.ckey - P.despawn_occupant() - + force_cryo_human(H) + removeFromWatchList(toRemove) /datum/controller/subsystem/afk/proc/warn(mob/living/carbon/human/H, text) @@ -66,9 +79,8 @@ SUBSYSTEM_DEF(afk) if(H.client) window_flash(H.client) -/datum/controller/subsystem/afk/proc/msg_admins(mob/living/carbon/human/H, mins_afk, turf/location, action, info) +/datum/controller/subsystem/afk/proc/log_afk_action(mob/living/carbon/human/H, mins_afk, turf/location, action, info) log_admin("[key_name(H)] has been [action] by the AFK Watcher subsystem after being AFK for [mins_afk] minutes.[info ? " Extra info:" + info : ""]") - message_admins("[key_name_admin(H)] at ([get_area(location).name] [ADMIN_JMP(location)]) has been [action] by the AFK Watcher subsystem after being AFK for [mins_afk] minutes.[info ? " Extra info:" + info : ""]") /datum/controller/subsystem/afk/proc/removeFromWatchList(list/toRemove) for(var/C in toRemove) @@ -79,3 +91,4 @@ SUBSYSTEM_DEF(afk) #undef AFK_WARNED #undef AFK_CRYOD +#undef AFK_ADMINS_WARNED diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 04141f6c3ab..80ce66d13ec 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -14,6 +14,7 @@ SUBSYSTEM_DEF(air) wait = 5 flags = SS_BACKGROUND runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + offline_implications = "Turfs will no longer process atmos, and all atmospheric machines (including cryotubes) will no longer function. Shuttle call recommended." var/cost_turfs = 0 var/cost_groups = 0 var/cost_highpressure = 0 @@ -275,7 +276,7 @@ SUBSYSTEM_DEF(air) if(blockchanges && T.excited_group) T.excited_group.garbage_collect() else - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if(!(T.atmos_adjacent_turfs & direction)) continue var/turf/simulated/S = get_step(T, direction) @@ -360,21 +361,21 @@ SUBSYSTEM_DEF(air) return count /datum/controller/subsystem/air/proc/setup_overlays() - plmaster = new /obj/effect/overlay() - plmaster.icon = 'icons/effects/tile_effects.dmi' - plmaster.icon_state = "plasma" - plmaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT - plmaster.anchored = TRUE // should only appear in vis_contents, but to be safe - plmaster.layer = FLY_LAYER - plmaster.appearance_flags = TILE_BOUND + GLOB.plmaster = new /obj/effect/overlay() + GLOB.plmaster.icon = 'icons/effects/tile_effects.dmi' + GLOB.plmaster.icon_state = "plasma" + GLOB.plmaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + GLOB.plmaster.anchored = TRUE // should only appear in vis_contents, but to be safe + GLOB.plmaster.layer = FLY_LAYER + GLOB.plmaster.appearance_flags = TILE_BOUND - slmaster = new /obj/effect/overlay() - slmaster.icon = 'icons/effects/tile_effects.dmi' - slmaster.icon_state = "sleeping_agent" - slmaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT - slmaster.anchored = TRUE // should only appear in vis_contents, but to be safe - slmaster.layer = FLY_LAYER - slmaster.appearance_flags = TILE_BOUND + GLOB.slmaster = new /obj/effect/overlay() + GLOB.slmaster.icon = 'icons/effects/tile_effects.dmi' + GLOB.slmaster.icon_state = "sleeping_agent" + GLOB.slmaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + GLOB.slmaster.anchored = TRUE // should only appear in vis_contents, but to be safe + GLOB.slmaster.layer = FLY_LAYER + GLOB.slmaster.appearance_flags = TILE_BOUND #undef SSAIR_PIPENETS #undef SSAIR_ATMOSMACHINERY diff --git a/code/controllers/subsystem/alarm.dm b/code/controllers/subsystem/alarm.dm index bac32a449de..289adf6de40 100644 --- a/code/controllers/subsystem/alarm.dm +++ b/code/controllers/subsystem/alarm.dm @@ -1,6 +1,7 @@ SUBSYSTEM_DEF(alarms) name = "Alarms" init_order = INIT_ORDER_ALARMS // 2 + offline_implications = "Alarms (Power, camera, fire, etc) will no longer be checked. No immediate action is needed." var/datum/alarm_handler/atmosphere/atmosphere_alarm = new() var/datum/alarm_handler/burglar/burglar_alarm = new() var/datum/alarm_handler/camera/camera_alarm = new() diff --git a/code/controllers/subsystem/changelog.dm b/code/controllers/subsystem/changelog.dm new file mode 100644 index 00000000000..98188599abd --- /dev/null +++ b/code/controllers/subsystem/changelog.dm @@ -0,0 +1,263 @@ +/* + Subsystem core for ParadiseSS13 changelogs + Author: AffectedArc07 + + Basically this SS extracts changelogs from the past 30 days from the database, and cleanly formats them into HTML that the players can see + It only runs the extraction on initialize to ensure that the changelog doesnt change mid round, and to reduce the amount of DB calls that need to be done + The changelog entries are generated from the PHP scripts in tools/githubChangelogProcessor.php + + This SS also handles the checking of player CL dates and informing them if it has changed + +*/ + +SUBSYSTEM_DEF(changelog) + name = "Changelog" + flags = SS_NO_FIRE + var/current_cl_timestamp = "0" // Timestamp is seconds since UNIX epoch (1st January 1970). ITs also a string because BYOND doesnt like big numbers. + var/ss_ready = FALSE // Is the SS ready? We dont want to run procs if we have not generated yet + var/list/startup_clients_button = list() // Clients who connected before initialization who need their button color updating + var/list/startup_clients_open = list() // Clients who connected before initialization who need the CL opening + var/changelogHTML = "" // HTML that the changelog will use to display + +/datum/controller/subsystem/changelog/Initialize() + // This entire subsystem relies on SQL being here. + if(!GLOB.dbcon.IsConnected()) + return ..() + + var/DBQuery/latest_cl_date = GLOB.dbcon.NewQuery("SELECT UNIX_TIMESTAMP(date_merged) AS ut FROM [format_table_name("changelog")] ORDER BY date_merged DESC LIMIT 1") + if(!latest_cl_date.Execute()) + var/err = latest_cl_date.ErrorMsg() + log_game("SQL ERROR during SSchangelog initialization L24. Error: \[[err]\]\n") + message_admins("SQL ERROR during SSchangelog initialization L24. Error: \[[err]\]\n") + // Abort if we cant do this + return ..() + + while(latest_cl_date.NextRow()) + current_cl_timestamp = latest_cl_date.item[1] + + if(!GenerateChangelogHTML()) // if this failed to generate + to_chat(world, "WARNING: Changelog failed to generate. Please inform a coder/server dev") + return ..() + + ss_ready = TRUE + // Now we can alert anyone who wanted to check the changelog + for(var/x in startup_clients_button) + var/client/C = x + UpdatePlayerChangelogButton(C) + + // Now we can alert anyone who wanted to check the changelog + for(var/client/C in startup_clients_open) + OpenChangelog(C) + + return ..() + + +/datum/controller/subsystem/changelog/proc/UpdatePlayerChangelogDate(client/C) + if(!ss_ready) + return // Only return here, we dont have to worry about a queue list because this will be called from ShowChangelog() + // Technically this is only for the date but we can also do the UI button at the same time + var/datum/preferences/P = GLOB.preferences_datums[C.ckey] + if(P.toggles & UI_DARKMODE) + winset(C, "rpane.changelog", "background-color=#40628a;font-color=#ffffff;font-style=none") + else + winset(C, "rpane.changelog", "background-color=none;font-style=none") + C.prefs.lastchangelog = current_cl_timestamp + var/DBQuery/updatePlayerCLTime = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastchangelog='[sanitizeSQL(current_cl_timestamp)]' WHERE ckey='[C.ckey]'") + if(!updatePlayerCLTime.Execute()) + var/err = updatePlayerCLTime.ErrorMsg() + log_game("SQL ERROR during lastchangelog updating. Error: \[[err]\]\n") + message_admins("SQL ERROR during lastchangelog updating. Error: \[[err]\]\n") + to_chat(C, "Couldn't update your last seen changelog, please try again later.") + return FALSE + return TRUE + +/datum/controller/subsystem/changelog/proc/UpdatePlayerChangelogButton(client/C) + // If SQL aint even enabled, just set the button to default style + if(!GLOB.dbcon.IsConnected()) + if(C.prefs.toggles & UI_DARKMODE) + winset(C, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF") + else + winset(C, "rpane.changelog", "background-color=none;text-color=#000000") + return + + // If SQL is enabled but we aint ready, queue them up, and use the default style + if(!ss_ready) + startup_clients_button |= C + if(C.prefs.toggles & UI_DARKMODE) + winset(C, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF") + else + winset(C, "rpane.changelog", "background-color=none;text-color=#000000") + return + + // Sanity check to ensure clients still exist (If a client DCs mid startup this would runtime) + if(C && C.prefs) + // If we are ready, process the button style + if(C.prefs.lastchangelog != current_cl_timestamp) + winset(C, "rpane.changelog", "background-color=#bb7700;text-color=#FFFFFF;font-style=bold") + to_chat(C, "Changelog has changed since your last visit.") + else + if(C.prefs.toggles & UI_DARKMODE) + winset(C, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF") + else + winset(C, "rpane.changelog", "background-color=none;text-color=#000000") + + +/datum/controller/subsystem/changelog/proc/OpenChangelog(client/C) + // If SQL isnt enabled, dont even queue them, just tell them it wont work + if(!GLOB.dbcon.IsConnected()) + to_chat(C, "This server is not running with an SQL backend. Changelog is unavailable.") + return + + // If SQL is enabled but we aint ready, queue them up + if(!ss_ready) + startup_clients_open |= C + to_chat(C, "The changelog system is still initializing. The changelog will open for you once it has initialized.") + return + + UpdatePlayerChangelogDate(C) + UpdatePlayerChangelogButton(C) + + var/datum/browser/cl_popup = new(C.mob, "changelog", "Changelog", 700, 800) + cl_popup.set_content(changelogHTML) + cl_popup.open() + +/client/verb/changes() + set name = "Changelog" + set desc = "View the changelog." + set category = "OOC" + // Just invoke the actual CL thing + SSchangelog.OpenChangelog(src) + +// Helper to turn CL types into a fontawesome icon instead of an image +// The colors are #28a745 for green, #fd7e14 for orange, and #dc3545 for red. +// These colours are from bootstrap and look good with black and white +/datum/controller/subsystem/changelog/proc/Text2Icon(text) + switch(text) + if("FIX") + return "" // Fixes are white because while they are good, they have no negative coutnerpart + if("WIP") + return "" // WIP stuff is orange because new code is good but its not done yet + if("TWEAK") + return "" // Tweaks are white because they could be good or bad, and theres no specific add or remove + if("SOUNDADD") + return "" // Sound additions are green because its something new + if("SOUNDDEL") + return "" // Sound removals are red because something has been removed + if("CODEADD") + return "" // Code additions are green because its something new + if("CODEDEL") + return "" // Code removals are red becuase someting has been removed + if("IMAGEADD") + return "" // Image additions are green because something has been added + if("IMAGEDEL") + return "" // Image removals are red because something has been removed + if("SPELLCHECK") + return "" // Spellcheck is white because theres no dedicated negative to it, so theres no red for it to collate with + if("EXPERIMENT") + return "" // Experimental stuff is orange because while its a new feature, its unstable + else // Just incase the DB somehow breaks + return "" // Same here + +// This proc is the star of the show +/datum/controller/subsystem/changelog/proc/GenerateChangelogHTML() + // Modify the code below to modify the header of the changelog + var/changelog_header = {" + + ParadiseSS13 Changelog + +
+

Paradise Station Changelog

+

Forum - Wiki - GitHub

+
+ "} + + var/list/prs_to_process = list() + // Grab all from last 30 days + var/DBQuery/pr_list_query = GLOB.dbcon.NewQuery("SELECT DISTINCT pr_number FROM changelog WHERE date_merged BETWEEN NOW() - INTERVAL 30 DAY AND NOW() ORDER BY date_merged DESC") + if(!pr_list_query.Execute()) + var/err = pr_list_query.ErrorMsg() + log_game("SQL ERROR during CL generation L143. Error: \[[err]\]\n") + message_admins("SQL ERROR during CL generation L143. Error: \[[err]\]\n") + return FALSE + + while(pr_list_query.NextRow()) + prs_to_process += text2num(pr_list_query.item[1]) + + // Load in the header + changelogHTML += changelog_header + + // Make blocks for all the PRs + for(var/pr_number in prs_to_process) + // Initial declarations + var/pr_block = "" // HTML for the changelog section + var/author = "" // Author of the PR + var/merge_date = "" // Timestamp of when the PR was merged + + // Now we gather the data from the DB + // Also we probably dont need to sanitize the PR number but you never know + var/DBQuery/pr_meta = GLOB.dbcon.NewQuery("SELECT author,DATE(date_merged) AS date FROM changelog WHERE pr_number = [sanitizeSQL(pr_number)] LIMIT 1") + if(!pr_meta.Execute()) + var/err = pr_meta.ErrorMsg() + log_game("SQL ERROR during CL generation L190. Error: \[[err]\]\n") + message_admins("SQL ERROR during CL generation L190. Error: \[[err]\]\n") + return FALSE + + while(pr_meta.NextRow()) + author = pr_meta.item[1] + merge_date = pr_meta.item[2] + + // Now for each actual entry + var/DBQuery/db_entries = GLOB.dbcon.NewQuery("SELECT cl_type, cl_entry FROM changelog WHERE pr_number = [sanitizeSQL(pr_number)]") + if(!db_entries.Execute()) + var/err = db_entries.ErrorMsg() + log_game("SQL ERROR during CL generation L204. Error: \[[err]\]\n") + message_admins("SQL ERROR during CL generation L204. Error: \[[err]\]\n") + return FALSE + + + // Now we make a changelog block + pr_block += "
" + // If the github URL in the config has a trailing slash, it doesnt matter here, thankfully github accepts having a double slash: https://github.com/org/repo//pull/1 + pr_block += "

#[pr_number] by [author] (Merged on [merge_date])" + + while(db_entries.NextRow()) + pr_block += "

[Text2Icon(db_entries.item[1])] [db_entries.item[2]]

" + + pr_block += "

" + + changelogHTML += pr_block + + // Make sure we return TRUE so we know it worked + return TRUE + + +// Topic handler so that PRs and forums and stuff open in another window +/datum/controller/subsystem/changelog/Topic(href, href_list) + // Handler to open pages in your browser instead of inside the CL window + // Yes usr.client is gross here but src is the subsystem + // Takes the page to open as an argument + if(href_list["openPage"]) + switch(href_list["openPage"]) + if("forum") + usr.client.forum() + if("wiki") + // Wiki needs snowflake because it has no cancel button + if(config.wikiurl) + if(alert("This will open the wiki in your browser. Are you sure?",,"Yes","No")=="No") + return + usr.client.wiki("") // Blank arg is important here + else + to_chat(usr, "The Wiki URL is not set in the server configuration. Please inform the server host.") + + if("github") + usr.client.github() + // Takes a PR number as argument + if(href_list["openPR"]) + if(config.githuburl) + if(alert("This will open PR #[href_list["openPR"]] in your browser. Are you sure?",,"Yes","No")=="No") + return + var/url = "[config.githuburl]/pull/[href_list["openPR"]]" + usr << link(url) + else + to_chat(usr, "The GitHub URL is not set in the server configuration. PRs cannot be opened from changelog view. Please inform the server host.") + diff --git a/code/controllers/subsystem/chat.dm b/code/controllers/subsystem/chat.dm index dbe38634e6a..4eb468a0952 100644 --- a/code/controllers/subsystem/chat.dm +++ b/code/controllers/subsystem/chat.dm @@ -4,6 +4,7 @@ SUBSYSTEM_DEF(chat) wait = 1 priority = FIRE_PRIORITY_CHAT init_order = INIT_ORDER_CHAT + offline_implications = "Chat messages will no longer be cleanly queued. No immediate action is needed." var/list/payload = list() diff --git a/code/controllers/subsystem/dcs.dm b/code/controllers/subsystem/dcs.dm new file mode 100644 index 00000000000..09dea24071f --- /dev/null +++ b/code/controllers/subsystem/dcs.dm @@ -0,0 +1,53 @@ +PROCESSING_SUBSYSTEM_DEF(dcs) + name = "Datum Component System" + flags = SS_NO_INIT + + var/list/elements_by_type = list() + +/datum/controller/subsystem/processing/dcs/Recover() + comp_lookup = SSdcs.comp_lookup + +/datum/controller/subsystem/processing/dcs/proc/GetElement(list/arguments) + var/datum/element/eletype = arguments[1] + var/element_id = eletype + + if(!ispath(eletype, /datum/element)) + CRASH("Attempted to instantiate [eletype] as a /datum/element") + + if(initial(eletype.element_flags) & ELEMENT_BESPOKE) + element_id = GetIdFromArguments(arguments) + + . = elements_by_type[element_id] + if(.) + return + . = elements_by_type[element_id] = new eletype + +/**** + * Generates an id for bespoke elements when given the argument list + * Generating the id here is a bit complex because we need to support named arguments + * Named arguments can appear in any order and we need them to appear after ordered arguments + * We assume that no one will pass in a named argument with a value of null + **/ +/datum/controller/subsystem/processing/dcs/proc/GetIdFromArguments(list/arguments) + var/datum/element/eletype = arguments[1] + var/list/fullid = list("[eletype]") + var/list/named_arguments = list() + for(var/i in initial(eletype.id_arg_index) to length(arguments)) + var/key = arguments[i] + var/value + if(istext(key)) + value = arguments[key] + if(!(istext(key) || isnum(key))) + key = "\ref[key]" + key = "[key]" // Key is stringified so numbers dont break things + if(!isnull(value)) + if(!(istext(value) || isnum(value))) + value = "\ref[value]" + named_arguments["[key]"] = value + else + fullid += "[key]" + + if(length(named_arguments)) + named_arguments = sortList(named_arguments) + fullid += named_arguments + return list2params(fullid) diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm index 0465f47e152..ad77904bac7 100644 --- a/code/controllers/subsystem/events.dm +++ b/code/controllers/subsystem/events.dm @@ -2,6 +2,7 @@ SUBSYSTEM_DEF(events) name = "Events" init_order = INIT_ORDER_EVENTS runlevels = RUNLEVEL_GAME + offline_implications = "Random events will no longer happen. No immediate action is needed." // Report events at the end of the rouund var/report_at_round_end = 0 @@ -36,7 +37,7 @@ SUBSYSTEM_DEF(events) E.process() for(var/i = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR) - var/list/datum/event_container/EC = event_containers[i] + var/datum/event_container/EC = event_containers[i] EC.process() /datum/controller/subsystem/events/proc/event_complete(var/datum/event/E) @@ -65,7 +66,7 @@ SUBSYSTEM_DEF(events) log_debug("Event '[EM.name]' has completed at [station_time_timestamp()].") /datum/controller/subsystem/events/proc/delay_events(var/severity, var/delay) - var/list/datum/event_container/EC = event_containers[severity] + var/datum/event_container/EC = event_containers[severity] EC.next_event_time += delay /datum/controller/subsystem/events/proc/Interact(var/mob/living/user) @@ -104,7 +105,7 @@ SUBSYSTEM_DEF(events) html += "Back
" html += "Time till start: [round(event_time / 600, 0.1)]
" html += "
" - html += "

Available [severity_to_string[selected_event_container.severity]] Events (queued & running events will not be displayed)

" + html += "

Available [GLOB.severity_to_string[selected_event_container.severity]] Events (queued & running events will not be displayed)

" html += "" html += "Name Weight MinWeight MaxWeight OneShot Enabled CurrWeight Remove" for(var/datum/event_meta/EM in selected_event_container.available_events) @@ -145,7 +146,7 @@ SUBSYSTEM_DEF(events) var/datum/event_container/EC = event_containers[severity] var/next_event_at = max(0, EC.next_event_time - world.time) html += "" - html += "[severity_to_string[severity]]" + html += "[GLOB.severity_to_string[severity]]" html += "[station_time_timestamp("hh:mm:ss", max(EC.next_event_time, world.time))]" html += "[round(next_event_at / 600, 0.1)]" html += "" @@ -172,7 +173,7 @@ SUBSYSTEM_DEF(events) var/datum/event_container/EC = event_containers[severity] var/datum/event_meta/EM = EC.next_event html += "" - html += "[severity_to_string[severity]]" + html += "[GLOB.severity_to_string[severity]]" html += "[EM ? EM.name : "Random"]" html += "View" html += "Clear" @@ -193,7 +194,7 @@ SUBSYSTEM_DEF(events) var/ends_in = max(0, round((ends_at - world.time) / 600, 0.1)) var/no_end = E.noAutoEnd html += "" - html += "[severity_to_string[EM.severity]]" + html += "[GLOB.severity_to_string[EM.severity]]" html += "[EM.name]" html += "[no_end ? "N/A" : station_time_timestamp("hh:mm:ss", ends_at)]" html += "[no_end ? "N/A" : ends_in]" @@ -216,33 +217,33 @@ SUBSYSTEM_DEF(events) var/datum/event_container/EC = locate(href_list["event"]) var/decrease = (60 * RaiseToPower(10, text2num(href_list["dec_timer"]))) EC.next_event_time -= decrease - admin_log_and_message_admins("decreased timer for [severity_to_string[EC.severity]] events by [decrease/600] minute(s).") + admin_log_and_message_admins("decreased timer for [GLOB.severity_to_string[EC.severity]] events by [decrease/600] minute(s).") else if(href_list["inc_timer"]) var/datum/event_container/EC = locate(href_list["event"]) var/increase = (60 * RaiseToPower(10, text2num(href_list["inc_timer"]))) EC.next_event_time += increase - admin_log_and_message_admins("increased timer for [severity_to_string[EC.severity]] events by [increase/600] minute(s).") + admin_log_and_message_admins("increased timer for [GLOB.severity_to_string[EC.severity]] events by [increase/600] minute(s).") else if(href_list["select_event"]) var/datum/event_container/EC = locate(href_list["select_event"]) var/datum/event_meta/EM = EC.SelectEvent() if(EM) - admin_log_and_message_admins("has queued the [severity_to_string[EC.severity]] event '[EM.name]'.") + admin_log_and_message_admins("has queued the [GLOB.severity_to_string[EC.severity]] event '[EM.name]'.") else if(href_list["pause"]) var/datum/event_container/EC = locate(href_list["pause"]) EC.delayed = !EC.delayed - admin_log_and_message_admins("has [EC.delayed ? "paused" : "resumed"] countdown for [severity_to_string[EC.severity]] events.") + admin_log_and_message_admins("has [EC.delayed ? "paused" : "resumed"] countdown for [GLOB.severity_to_string[EC.severity]] events.") else if(href_list["interval"]) var/delay = input("Enter delay modifier. A value less than one means events fire more often, higher than one less often.", "Set Interval Modifier") as num|null if(delay && delay > 0) var/datum/event_container/EC = locate(href_list["interval"]) EC.delay_modifier = delay - admin_log_and_message_admins("has set the interval modifier for [severity_to_string[EC.severity]] events to [EC.delay_modifier].") + admin_log_and_message_admins("has set the interval modifier for [GLOB.severity_to_string[EC.severity]] events to [EC.delay_modifier].") else if(href_list["stop"]) if(alert("Stopping an event may have unintended side-effects. Continue?","Stopping Event!","Yes","No") != "Yes") return var/datum/event/E = locate(href_list["stop"]) var/datum/event_meta/EM = E.event_meta - admin_log_and_message_admins("has stopped the [severity_to_string[EM.severity]] event '[EM.name]'.") + admin_log_and_message_admins("has stopped the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.") E.kill() else if(href_list["view_events"]) selected_event_container = locate(href_list["view_events"]) @@ -264,23 +265,23 @@ SUBSYSTEM_DEF(events) var/datum/event_meta/EM = locate(href_list["set_weight"]) EM.weight = weight if(EM != new_event) - admin_log_and_message_admins("has changed the weight of the [severity_to_string[EM.severity]] event '[EM.name]' to [EM.weight].") + admin_log_and_message_admins("has changed the weight of the [GLOB.severity_to_string[EM.severity]] event '[EM.name]' to [EM.weight].") else if(href_list["toggle_oneshot"]) var/datum/event_meta/EM = locate(href_list["toggle_oneshot"]) EM.one_shot = !EM.one_shot if(EM != new_event) - admin_log_and_message_admins("has [EM.one_shot ? "set" : "unset"] the oneshot flag for the [severity_to_string[EM.severity]] event '[EM.name]'.") + admin_log_and_message_admins("has [EM.one_shot ? "set" : "unset"] the oneshot flag for the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.") else if(href_list["toggle_enabled"]) var/datum/event_meta/EM = locate(href_list["toggle_enabled"]) EM.enabled = !EM.enabled - admin_log_and_message_admins("has [EM.enabled ? "enabled" : "disabled"] the [severity_to_string[EM.severity]] event '[EM.name]'.") + admin_log_and_message_admins("has [EM.enabled ? "enabled" : "disabled"] the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.") else if(href_list["remove"]) if(alert("This will remove the event from rotation. Continue?","Removing Event!","Yes","No") != "Yes") return var/datum/event_meta/EM = locate(href_list["remove"]) var/datum/event_container/EC = locate(href_list["EC"]) EC.available_events -= EM - admin_log_and_message_admins("has removed the [severity_to_string[EM.severity]] event '[EM.name]'.") + admin_log_and_message_admins("has removed the [GLOB.severity_to_string[EM.severity]] event '[EM.name]'.") else if(href_list["add"]) if(!new_event.name || !new_event.event_type) return @@ -288,12 +289,12 @@ SUBSYSTEM_DEF(events) return new_event.severity = selected_event_container.severity selected_event_container.available_events += new_event - admin_log_and_message_admins("has added \a [severity_to_string[new_event.severity]] event '[new_event.name]' of type [new_event.event_type] with weight [new_event.weight].") + admin_log_and_message_admins("has added \a [GLOB.severity_to_string[new_event.severity]] event '[new_event.name]' of type [new_event.event_type] with weight [new_event.weight].") new_event = new else if(href_list["clear"]) var/datum/event_container/EC = locate(href_list["clear"]) if(EC.next_event) - admin_log_and_message_admins("has dequeued the [severity_to_string[EC.severity]] event '[EC.next_event.name]'.") + admin_log_and_message_admins("has dequeued the [GLOB.severity_to_string[EC.severity]] event '[EC.next_event.name]'.") EC.next_event = null Interact(usr) diff --git a/code/controllers/subsystem/fires.dm b/code/controllers/subsystem/fires.dm index aafc5ed48d5..dc419fffeb5 100644 --- a/code/controllers/subsystem/fires.dm +++ b/code/controllers/subsystem/fires.dm @@ -3,6 +3,7 @@ SUBSYSTEM_DEF(fires) priority = FIRE_PRIOTITY_BURNING flags = SS_NO_INIT|SS_BACKGROUND runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + offline_implications = "Objects will no longer react to fires. No immediate action is needed." var/list/currentrun = list() var/list/processing = list() diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 4bc3965e6cf..cbf17d05fbf 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -5,6 +5,7 @@ SUBSYSTEM_DEF(garbage) flags = SS_POST_FIRE_TIMING|SS_BACKGROUND|SS_NO_INIT runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY init_order = INIT_ORDER_GARBAGE + offline_implications = "Garbage collection is no longer functional, and objects will not be qdel'd. Immediate server restart recommended." var/list/collection_timeout = list(0, 2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level diff --git a/code/controllers/subsystem/icon_smooth.dm b/code/controllers/subsystem/icon_smooth.dm index 531b6af2e78..289505a153c 100644 --- a/code/controllers/subsystem/icon_smooth.dm +++ b/code/controllers/subsystem/icon_smooth.dm @@ -4,6 +4,7 @@ SUBSYSTEM_DEF(icon_smooth) wait = 1 priority = FIRE_PRIOTITY_SMOOTHING flags = SS_TICKER + offline_implications = "Objects will no longer smooth together properly. No immediate action is needed." var/list/smooth_queue = list() diff --git a/code/controllers/subsystem/idlenpcpool.dm b/code/controllers/subsystem/idlenpcpool.dm index 42df941e10f..d61b90f1239 100644 --- a/code/controllers/subsystem/idlenpcpool.dm +++ b/code/controllers/subsystem/idlenpcpool.dm @@ -4,6 +4,7 @@ SUBSYSTEM_DEF(idlenpcpool) priority = FIRE_PRIORITY_IDLE_NPC wait = 60 runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + offline_implications = "Idle simple animals will no longer process. Shuttle call recommended." var/list/currentrun = list() var/static/list/idle_mobs_by_zlevel[][] @@ -39,4 +40,4 @@ SUBSYSTEM_DEF(idlenpcpool) if(SA.stat != DEAD) SA.consider_wakeup() if(MC_TICK_CHECK) - return + return diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm index f379deec72b..9dd6fce1554 100644 --- a/code/controllers/subsystem/input.dm +++ b/code/controllers/subsystem/input.dm @@ -5,6 +5,7 @@ SUBSYSTEM_DEF(input) flags = SS_TICKER priority = FIRE_PRIORITY_INPUT runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY + offline_implications = "Player input will no longer be recognised. Immediate server restart recommended." var/list/macro_sets var/list/movement_keys @@ -24,7 +25,7 @@ SUBSYSTEM_DEF(input) // This is for when macro sets are eventualy datumized /datum/controller/subsystem/input/proc/setup_default_macro_sets() var/list/static/default_macro_sets - + if(default_macro_sets) macro_sets = default_macro_sets return diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm index 29efa85b8a0..ef89317d0f5 100644 --- a/code/controllers/subsystem/jobs.dm +++ b/code/controllers/subsystem/jobs.dm @@ -3,6 +3,7 @@ SUBSYSTEM_DEF(jobs) init_order = INIT_ORDER_JOBS // 12 wait = 3000 // 5 minutes (Deciseconds) runlevels = RUNLEVEL_GAME + offline_implications = "Job playtime hours will no longer be logged. No immediate action is needed." //List of all jobs var/list/occupations = list() @@ -10,7 +11,7 @@ SUBSYSTEM_DEF(jobs) var/list/type_occupations = list() //Dict of all jobs, keys are types var/list/prioritized_jobs = list() // List of jobs set to priority by HoP/Captain var/list/id_change_records = list() // List of all job transfer records - var/list/id_change_counter = 1 + var/id_change_counter = 1 //Players who need jobs var/list/unassigned = list() //Debug info @@ -39,8 +40,6 @@ SUBSYSTEM_DEF(jobs) var/datum/job/job = new J() if(!job) continue - if(!job.faction in faction) - continue occupations += job name_occupations[job.title] = job type_occupations[J] = job @@ -49,7 +48,7 @@ SUBSYSTEM_DEF(jobs) /datum/controller/subsystem/jobs/proc/Debug(var/text) - if(!Debug2) + if(!GLOB.debug2) return 0 job_debug.Add(text) return 1 @@ -138,7 +137,7 @@ SUBSYSTEM_DEF(jobs) if(flag && !(flag in player.client.prefs.be_special)) Debug("FOC flag failed, Player: [player], Flag: [flag], ") continue - if(player.mind && job.title in player.mind.restricted_roles) + if(player.mind && (job.title in player.mind.restricted_roles)) Debug("FOC incompatbile with antagonist role, Player: [player]") continue if(player.client.prefs.GetJobDepartment(job, level) & job.flag) @@ -155,10 +154,10 @@ SUBSYSTEM_DEF(jobs) if(istype(job, GetJob("Civilian"))) // We don't want to give him assistant, that's boring! continue - if(job.title in command_positions) //If you want a command position, select it! + if(job.title in GLOB.command_positions) //If you want a command position, select it! continue - if(job.title in whitelisted_positions) // No random whitelisted job, sorry! + if(job.title in GLOB.whitelisted_positions) // No random whitelisted job, sorry! continue if(job.admin_only) // No admin positions either. @@ -180,7 +179,7 @@ SUBSYSTEM_DEF(jobs) Debug("GRJ player has disability rendering them ineligible for job, Player: [player]") continue - if(player.mind && job.title in player.mind.restricted_roles) + if(player.mind && (job.title in player.mind.restricted_roles)) Debug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]") continue @@ -203,7 +202,7 @@ SUBSYSTEM_DEF(jobs) ///This proc is called before the level loop of DivideOccupations() and will try to select a head, ignoring ALL non-head preferences for every level until it locates a head or runs out of levels to check /datum/controller/subsystem/jobs/proc/FillHeadPosition() for(var/level = 1 to 3) - for(var/command_position in command_positions) + for(var/command_position in GLOB.command_positions) var/datum/job/job = GetJob(command_position) if(!job) continue @@ -231,7 +230,7 @@ SUBSYSTEM_DEF(jobs) ///This proc is called at the start of the level loop of DivideOccupations() and will cause head jobs to be checked before any other jobs of the same level /datum/controller/subsystem/jobs/proc/CheckHeadPositions(var/level) - for(var/command_position in command_positions) + for(var/command_position in GLOB.command_positions) var/datum/job/job = GetJob(command_position) if(!job) continue @@ -357,7 +356,7 @@ SUBSYSTEM_DEF(jobs) Debug("DO player has disability rendering them ineligible for job, Player: [player], Job:[job.title]") continue - if(player.mind && job.title in player.mind.restricted_roles) + if(player.mind && (job.title in player.mind.restricted_roles)) Debug("DO incompatible with antagonist role, Player: [player], Job:[job.title]") continue @@ -498,13 +497,14 @@ SUBSYSTEM_DEF(jobs) job.after_spawn(H) //Gives glasses to the vision impaired - if(H.disabilities & DISABILITY_FLAG_NEARSIGHTED) + if(NEARSIGHTED in H.mutations) var/equipped = H.equip_to_slot_or_del(new /obj/item/clothing/glasses/regular(H), slot_glasses) if(equipped != 1) var/obj/item/clothing/glasses/G = H.glasses if(istype(G) && !G.prescription) - G.prescription = 1 + G.prescription = TRUE G.name = "prescription [G.name]" + H.update_nearsighted_effects() return H @@ -600,7 +600,7 @@ SUBSYSTEM_DEF(jobs) // If they're head, give them the account info for their department if(job && job.head_position) remembered_info = "" - var/datum/money_account/department_account = department_accounts[job.department] + var/datum/money_account/department_account = GLOB.department_accounts[job.department] if(department_account) remembered_info += "Your department's account number is: #[department_account.account_number]
" @@ -622,7 +622,9 @@ SUBSYSTEM_DEF(jobs) if(tgtcard.assignment && tgtcard.assignment == job.title) jobs_to_formats[job.title] = "disabled" // the job they already have is pre-selected else if(!job.would_accept_job_transfer_from_player(M)) - jobs_to_formats[job.title] = "linkDiscourage" // karma jobs they don't have available are discouraged + jobs_to_formats[job.title] = "linkDiscourage" // jobs which are karma-locked and not unlocked for this player are discouraged + else if((job.title in GLOB.command_positions) && istype(M) && M.client && job.available_in_playtime(M.client)) + jobs_to_formats[job.title] = "linkDiscourage" // command jobs which are playtime-locked and not unlocked for this player are discouraged else if(job.total_positions && !job.current_positions && job.title != "Civilian") jobs_to_formats[job.title] = "linkEncourage" // jobs with nobody doing them at all are encouraged else if(job.total_positions >= 0 && job.current_positions >= job.total_positions) @@ -638,7 +640,7 @@ SUBSYSTEM_DEF(jobs) var/datum/job/oldjobdatum = SSjobs.GetJob(oldtitle) var/datum/job/newjobdatum = SSjobs.GetJob(newtitle) if(istype(oldjobdatum) && oldjobdatum.current_positions > 0 && istype(newjobdatum)) - if(!(oldjobdatum.title in command_positions) && !(newjobdatum.title in command_positions)) + if(!(oldjobdatum.title in GLOB.command_positions) && !(newjobdatum.title in GLOB.command_positions)) oldjobdatum.current_positions-- newjobdatum.current_positions++ diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index 7441d855f22..3fc92a3346a 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -7,6 +7,7 @@ SUBSYSTEM_DEF(lighting) wait = 2 init_order = INIT_ORDER_LIGHTING flags = SS_TICKER + offline_implications = "Lighting will no longer update. Shuttle call recommended." /datum/controller/subsystem/lighting/stat_entry() ..("L:[GLOB.lighting_update_lights.len]|C:[GLOB.lighting_update_corners.len]|O:[GLOB.lighting_update_objects.len]") diff --git a/code/controllers/subsystem/machinery.dm b/code/controllers/subsystem/machinery.dm index 9a73c1dbabb..7e78e2b9df1 100644 --- a/code/controllers/subsystem/machinery.dm +++ b/code/controllers/subsystem/machinery.dm @@ -6,6 +6,7 @@ SUBSYSTEM_DEF(machines) name = "Machines" init_order = INIT_ORDER_MACHINES flags = SS_KEEP_TIMING + offline_implications = "Machinery will no longer process. Shuttle call recommended." var/list/processing = list() var/list/currentrun = list() diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index af741423526..67e2b5c5e88 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -13,24 +13,109 @@ SUBSYSTEM_DEF(mapping) if(!config.disable_space_ruins) var/timer = start_watch() log_startup_progress("Creating random space levels...") - seedRuins(list(level_name_to_num(EMPTY_AREA)), rand(0, 3), /area/space, space_ruins_templates) + seedRuins(list(level_name_to_num(EMPTY_AREA)), rand(0, 3), /area/space, GLOB.space_ruins_templates) log_startup_progress("Loaded random space levels in [stop_watch(timer)]s.") // load in extra levels of space ruins var/num_extra_space = rand(config.extra_space_ruin_levels_min, config.extra_space_ruin_levels_max) for(var/i = 1, i <= num_extra_space, i++) - var/zlev = space_manager.add_new_zlevel("[EMPTY_AREA] #[i]", linkage = CROSSLINKED, traits = list(REACHABLE)) - seedRuins(list(zlev), rand(0, 3), /area/space, space_ruins_templates) + var/zlev = GLOB.space_manager.add_new_zlevel("[EMPTY_AREA] #[i]", linkage = CROSSLINKED, traits = list(REACHABLE)) + seedRuins(list(zlev), rand(0, 3), /area/space, GLOB.space_ruins_templates) // Setup the Z-level linkage - space_manager.do_transition_setup() + GLOB.space_manager.do_transition_setup() // Spawn Lavaland ruins and rivers. - seedRuins(list(level_name_to_num(MINING)), config.lavaland_budget, /area/lavaland/surface/outdoors/unexplored, lava_ruins_templates) + seedRuins(list(level_name_to_num(MINING)), config.lavaland_budget, /area/lavaland/surface/outdoors/unexplored, GLOB.lava_ruins_templates) spawn_rivers(list(level_name_to_num(MINING))) return ..() + +/datum/controller/subsystem/mapping/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins) + if(!z_levels || !z_levels.len) + WARNING("No Z levels provided - Not generating ruins") + return + + for(var/zl in z_levels) + var/turf/T = locate(1, 1, zl) + if(!T) + WARNING("Z level [zl] does not exist - Not generating ruins") + return + + var/list/ruins = potentialRuins.Copy() + + var/list/forced_ruins = list() //These go first on the z level associated (same random one by default) + var/list/ruins_availible = list() //we can try these in the current pass + var/forced_z //If set we won't pick z level and use this one instead. + + //Set up the starting ruin list + for(var/key in ruins) + var/datum/map_template/ruin/R = ruins[key] + if(R.cost > budget) //Why would you do that + continue + if(R.always_place) + forced_ruins[R] = -1 + if(R.unpickable) + continue + ruins_availible[R] = R.placement_weight + + while(budget > 0 && (ruins_availible.len || forced_ruins.len)) + var/datum/map_template/ruin/current_pick + var/forced = FALSE + if(forced_ruins.len) //We have something we need to load right now, so just pick it + for(var/ruin in forced_ruins) + current_pick = ruin + if(forced_ruins[ruin] > 0) //Load into designated z + forced_z = forced_ruins[ruin] + forced = TRUE + break + else //Otherwise just pick random one + current_pick = pickweight(ruins_availible) + + var/placement_tries = PLACEMENT_TRIES + var/failed_to_place = TRUE + var/z_placed = 0 + while(placement_tries > 0) + placement_tries-- + z_placed = pick(z_levels) + if(!current_pick.try_to_place(forced_z ? forced_z : z_placed,whitelist)) + continue + else + failed_to_place = FALSE + break + + //That's done remove from priority even if it failed + if(forced) + //TODO : handle forced ruins with multiple variants + forced_ruins -= current_pick + forced = FALSE + + if(failed_to_place) + for(var/datum/map_template/ruin/R in ruins_availible) + if(R.id == current_pick.id) + ruins_availible -= R + log_world("Failed to place [current_pick.name] ruin.") + else + budget -= current_pick.cost + if(!current_pick.allow_duplicates) + for(var/datum/map_template/ruin/R in ruins_availible) + if(R.id == current_pick.id) + ruins_availible -= R + if(current_pick.never_spawn_with) + for(var/blacklisted_type in current_pick.never_spawn_with) + for(var/possible_exclusion in ruins_availible) + if(istype(possible_exclusion,blacklisted_type)) + ruins_availible -= possible_exclusion + forced_z = 0 + + //Update the availible list + for(var/datum/map_template/ruin/R in ruins_availible) + if(R.cost > budget) + ruins_availible -= R + + log_world("Ruin loader finished with [budget] left to spend.") + /datum/controller/subsystem/mapping/Recover() flags |= SS_NO_INIT diff --git a/code/controllers/subsystem/mobs.dm b/code/controllers/subsystem/mobs.dm index c21b8f0760a..9445dd2717a 100644 --- a/code/controllers/subsystem/mobs.dm +++ b/code/controllers/subsystem/mobs.dm @@ -3,6 +3,7 @@ SUBSYSTEM_DEF(mobs) priority = FIRE_PRIORITY_MOBS flags = SS_KEEP_TIMING runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + offline_implications = "Mobs will no longer process. Immediate server restart recommended." var/list/currentrun = list() var/static/list/clients_by_zlevel[][] @@ -10,7 +11,7 @@ SUBSYSTEM_DEF(mobs) var/static/list/cubemonkeys = list() /datum/controller/subsystem/mobs/stat_entry() - ..("P:[GLOB.mob_list.len]") + ..("P:[GLOB.mob_living_list.len]") /datum/controller/subsystem/mobs/Initialize(start_timeofday) clients_by_zlevel = new /list(world.maxz,0) @@ -20,17 +21,17 @@ SUBSYSTEM_DEF(mobs) /datum/controller/subsystem/mobs/fire(resumed = 0) var/seconds = wait * 0.1 if(!resumed) - src.currentrun = GLOB.mob_list.Copy() + src.currentrun = GLOB.mob_living_list.Copy() //cache for sanic speed (lists are references anyways) var/list/currentrun = src.currentrun var/times_fired = src.times_fired while(currentrun.len) - var/mob/M = currentrun[currentrun.len] + var/mob/living/L = currentrun[currentrun.len] currentrun.len-- - if(M) - M.Life(seconds, times_fired) + if(L) + L.Life(seconds, times_fired) else - GLOB.mob_list.Remove(M) + GLOB.mob_living_list.Remove(L) if(MC_TICK_CHECK) return diff --git a/code/controllers/subsystem/nano_mob_hunter.dm b/code/controllers/subsystem/nano_mob_hunter.dm index a634f091013..9094bf9fe2b 100644 --- a/code/controllers/subsystem/nano_mob_hunter.dm +++ b/code/controllers/subsystem/nano_mob_hunter.dm @@ -2,6 +2,7 @@ SUBSYSTEM_DEF(mob_hunt) name = "Nano-Mob Hunter GO Server" init_order = INIT_ORDER_NANOMOB priority = FIRE_PRIORITY_NANOMOB // Low priority, no need for MC_TICK_CHECK due to extremely low performance impact. + offline_implications = "Nano-Mob Hunter will no longer spawn mobs. No immediate action is needed." var/max_normal_spawns = 15 //change this to adjust the number of normal spawns that can exist at one time. trapped spawns (from traitors) don't count towards this var/list/normal_spawns = list() var/max_trap_spawns = 15 //change this to adjust the number of trap spawns that can exist at one time. traps spawned beyond this point clear the oldest traps diff --git a/code/controllers/subsystem/nanoui.dm b/code/controllers/subsystem/nanoui.dm index c8cbbc62013..ef1b6ee03fe 100644 --- a/code/controllers/subsystem/nanoui.dm +++ b/code/controllers/subsystem/nanoui.dm @@ -4,6 +4,7 @@ SUBSYSTEM_DEF(nanoui) flags = SS_NO_INIT priority = FIRE_PRIORITY_NANOUI runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT + offline_implications = "All NanoUIs will no longer process. Shuttle call recommended." var/list/currentrun = list() var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key. diff --git a/code/controllers/subsystem/nightshift.dm b/code/controllers/subsystem/nightshift.dm index 4ebe1dceb0e..deffcb6bddf 100644 --- a/code/controllers/subsystem/nightshift.dm +++ b/code/controllers/subsystem/nightshift.dm @@ -4,6 +4,7 @@ SUBSYSTEM_DEF(nightshift) priority = FIRE_PRIORITY_NIGHTSHIFT wait = 600 flags = SS_NO_TICK_CHECK + offline_implications = "The game will no longer shift between day and night lighting. No immediate action is needed." var/nightshift_active = FALSE var/nightshift_start_time = 702000 //7:30 PM, station time @@ -25,12 +26,12 @@ SUBSYSTEM_DEF(nightshift) check_nightshift() /datum/controller/subsystem/nightshift/proc/announce(message) - priority_announcement.Announce(message, new_sound = 'sound/misc/notice2.ogg', new_title = "Automated Lighting System Announcement") + GLOB.priority_announcement.Announce(message, new_sound = 'sound/misc/notice2.ogg', new_title = "Automated Lighting System Announcement") /datum/controller/subsystem/nightshift/proc/check_nightshift(check_canfire=FALSE) if(check_canfire && !can_fire) return - var/emergency = security_level >= SEC_LEVEL_RED + var/emergency = GLOB.security_level >= SEC_LEVEL_RED var/announcing = TRUE var/time = station_time() var/night_time = (time < nightshift_end_time) || (time > nightshift_start_time) @@ -41,7 +42,7 @@ SUBSYSTEM_DEF(nightshift) if(!emergency) announce("Restoring night lighting configuration to normal operation.") else - announce("Disabling night lighting: Station is in a state of emergency.") + announce("Disabling night lighting: Station is in a state of emergency.") if(emergency) night_time = FALSE if(nightshift_active != night_time) diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm index 5eaca5d19c4..79541c199a4 100644 --- a/code/controllers/subsystem/npcpool.dm +++ b/code/controllers/subsystem/npcpool.dm @@ -3,6 +3,7 @@ SUBSYSTEM_DEF(npcpool) flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND priority = FIRE_PRIORITY_NPC runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + offline_implications = "Simple animals will no longer process. Shuttle call recommended." var/list/currentrun = list() diff --git a/code/controllers/subsystem/overlays.dm b/code/controllers/subsystem/overlays.dm index c35f1adee65..95b9e925b5d 100644 --- a/code/controllers/subsystem/overlays.dm +++ b/code/controllers/subsystem/overlays.dm @@ -4,6 +4,7 @@ SUBSYSTEM_DEF(overlays) wait = 1 priority = FIRE_PRIORITY_OVERLAYS init_order = INIT_ORDER_OVERLAY + offline_implications = "Overlays may look strange. No immediate action is needed." var/list/queue var/list/stats diff --git a/code/controllers/subsystem/parallax.dm b/code/controllers/subsystem/parallax.dm index 039b6d2b008..9135f62b03f 100644 --- a/code/controllers/subsystem/parallax.dm +++ b/code/controllers/subsystem/parallax.dm @@ -4,6 +4,7 @@ SUBSYSTEM_DEF(parallax) flags = SS_POST_FIRE_TIMING | SS_BACKGROUND priority = FIRE_PRIORITY_PARALLAX runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT + offline_implications = "Space parallax will no longer move around. No immediate action is needed." var/list/currentrun var/planet_x_offset = 128 var/planet_y_offset = 128 diff --git a/code/controllers/subsystem/radio.dm b/code/controllers/subsystem/radio.dm index 49b30062786..5a49070bf89 100644 --- a/code/controllers/subsystem/radio.dm +++ b/code/controllers/subsystem/radio.dm @@ -54,7 +54,7 @@ SUBSYSTEM_DEF(radio) // If the above switch somehow failed. And it needs the SSradio. part otherwise it fails to compile if(frequency in DEPT_FREQS) return "deptradio" - + // If its none of the others return "radio" diff --git a/code/controllers/subsystem/shuttles.dm b/code/controllers/subsystem/shuttles.dm index da3d91c1de1..247d71d05b8 100644 --- a/code/controllers/subsystem/shuttles.dm +++ b/code/controllers/subsystem/shuttles.dm @@ -6,6 +6,7 @@ SUBSYSTEM_DEF(shuttle) init_order = INIT_ORDER_SHUTTLE flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK runlevels = RUNLEVEL_SETUP | RUNLEVEL_GAME + offline_implications = "Shuttles will no longer function and cargo will not generate points. Immediate server restart recommended." var/list/mobile = list() var/list/stationary = list() var/list/transit = list() @@ -223,11 +224,12 @@ SUBSYSTEM_DEF(shuttle) return 0 //dock successful -/datum/controller/subsystem/shuttle/proc/moveShuttle(shuttleId, dockId, timed) +/datum/controller/subsystem/shuttle/proc/moveShuttle(shuttleId, dockId, timed, mob/user) var/obj/docking_port/mobile/M = getShuttle(shuttleId) var/obj/docking_port/stationary/D = getDock(dockId) if(!M) return 1 + M.last_caller = user // Save the caller of the shuttle for later logging if(timed) if(M.request(D)) return 2 diff --git a/code/controllers/subsystem/spacedrift.dm b/code/controllers/subsystem/spacedrift.dm index fcc62a2fa50..d9c46f9c9d7 100644 --- a/code/controllers/subsystem/spacedrift.dm +++ b/code/controllers/subsystem/spacedrift.dm @@ -4,6 +4,7 @@ SUBSYSTEM_DEF(spacedrift) wait = 5 flags = SS_NO_INIT|SS_KEEP_TIMING runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + offline_implications = "Mobs will no longer respect a lack of gravity. No immediate action is needed." var/list/currentrun = list() var/list/processing = list() diff --git a/code/controllers/subsystem/statistics.dm b/code/controllers/subsystem/statistics.dm new file mode 100644 index 00000000000..3a0bf7e51e2 --- /dev/null +++ b/code/controllers/subsystem/statistics.dm @@ -0,0 +1,28 @@ +SUBSYSTEM_DEF(statistics) + name = "Statistics" + wait = 6000 // 10 minute delay between fires + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME // Only count time actually ingame to avoid logging pre-round dips + offline_implications = "Player count and admin count statistics will no longer be logged to the database. No immediate action is needed." + + +/datum/controller/subsystem/statistics/Initialize(start_timeofday) + if(!config.sql_enabled) + flags |= SS_NO_FIRE // Disable firing if SQL is disabled + return ..() + +/datum/controller/subsystem/statistics/fire(resumed = 0) + sql_poll_players() + +/datum/controller/subsystem/statistics/proc/sql_poll_players() + if(!config.sql_enabled) + return + var/playercount = GLOB.clients.len + var/admincount = GLOB.admins.len + if(!GLOB.dbcon.IsConnected()) + log_game("SQL ERROR during player polling. Failed to connect.") + else + var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") + var/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, admincount, time) VALUES ([playercount], [admincount], '[sqltime]')") + if(!query.Execute()) + var/err = query.ErrorMsg() + log_game("SQL ERROR during playercount polling. Error: \[[err]\]\n") diff --git a/code/controllers/subsystem/sun.dm b/code/controllers/subsystem/sun.dm index 6cfb52f2d25..3f8e15df05a 100644 --- a/code/controllers/subsystem/sun.dm +++ b/code/controllers/subsystem/sun.dm @@ -1,19 +1,29 @@ SUBSYSTEM_DEF(sun) name = "Sun" wait = 600 - flags = SS_NO_TICK_CHECK|SS_NO_INIT + flags = SS_NO_TICK_CHECK + init_order = INIT_ORDER_SUN + offline_implications = "Solar panels will no longer rotate. No immediate action is needed." var/angle var/dx var/dy var/rate var/list/solars = list() -/datum/controller/subsystem/sun/PreInit() +/datum/controller/subsystem/sun/Initialize(start_timeofday) + // Lets work out an angle for the "sun" to rotate around the station angle = rand (0,360) // the station position to the sun is randomised at round start rate = rand(50,200)/100 // 50% - 200% of standard rotation if(prob(50)) // same chance to rotate clockwise than counter-clockwise rate = -rate + // Solar consoles need to load after machines init, so this handles that + for(var/obj/machinery/power/solar_control/SC in solars) + SC.setup() + + return ..() + + /datum/controller/subsystem/sun/stat_entry(msg) ..("P:[solars.len]") diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index 74dbf4c4d93..04ddf40f442 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -7,6 +7,7 @@ SUBSYSTEM_DEF(throwing) wait = 1 flags = SS_NO_INIT|SS_KEEP_TIMING|SS_TICKER runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME + offline_implications = "Thrown objects may not react properly. Shuttle call recommended." var/list/currentrun var/list/processing = list() diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 6366eba7613..228f1a7c528 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -5,6 +5,7 @@ SUBSYSTEM_DEF(ticker) priority = FIRE_PRIORITY_TICKER flags = SS_KEEP_TIMING runlevels = RUNLEVEL_LOBBY | RUNLEVEL_SETUP | RUNLEVEL_GAME + offline_implications = "The game is no longer aware of when the round ends. Immediate server restart recommended." var/round_start_time = 0 var/const/restart_timeout = 600 @@ -23,17 +24,15 @@ SUBSYSTEM_DEF(ticker) var/Bible_deity_name var/datum/cult_info/cultdat = null //here instead of cult for adminbus purposes var/random_players = 0 // if set to nonzero, ALL players who latejoin or declare-ready join will have random appearances/genders - var/list/syndicate_coalition = list() // list of traitor-compatible factions - var/list/factions = list() // list of all factions - var/list/availablefactions = list() // list of factions with openings var/tipped = FALSE //Did we broadcast the tip of the day yet? var/selected_tip // What will be the tip of the day? var/pregame_timeleft // This is used for calculations var/delay_end = 0 //if set to nonzero, the round will not restart on it's own var/triai = 0//Global holder for Triumvirate - var/initialtpass = 0 //holder for inital autotransfer vote timer + var/next_autotransfer = 0 //holder for inital autotransfer vote timer var/obj/screen/cinematic = null //used for station explosion cinematic - var/round_end_announced = 0 // Spam Prevention. Announce round end only once.\ + var/round_end_announced = 0 // Spam Prevention. Announce round end only once. + var/ticker_going = TRUE // This used to be in the unused globals, but it turns out its actually used in a load of places. Its now a ticker var because its related to round stuff, -aa /datum/controller/subsystem/ticker/Initialize() login_music = pick(\ @@ -42,10 +41,9 @@ SUBSYSTEM_DEF(ticker) 'sound/music/title1.ogg',\ 'sound/music/title2.ogg',\ 'sound/music/title3.ogg',) - // Map name - if(using_map && using_map.name) - GLOB.map_name = "[using_map.name]" + if(GLOB.using_map && GLOB.using_map.name) + GLOB.map_name = "[GLOB.using_map.name]" else GLOB.map_name = "Unknown" @@ -68,12 +66,12 @@ SUBSYSTEM_DEF(ticker) current_state = GAME_STATE_PREGAME fire() // TG says this is a good idea if(GAME_STATE_PREGAME) - if(!going) + if(!SSticker.ticker_going) // This has to be referenced like this, and I dont know why. If you dont put SSticker. it will break return // This is so we dont have sleeps in controllers, because that is a bad, bad thing if(!delay_end) - pregame_timeleft = max(0,round_start_time - world.time) // Normal lobby countdown when roundstart was not delayed + pregame_timeleft = max(0,round_start_time - world.time) // Normal lobby countdown when roundstart was not delayed else pregame_timeleft = max(0,pregame_timeleft - 20) // If roundstart was delayed, we should resume the countdown where it left off @@ -92,12 +90,17 @@ SUBSYSTEM_DEF(ticker) delay_end = 0 // reset this in case round start was delayed mode.process() mode.process_job_tasks() + + if(world.time > next_autotransfer) + SSvote.autotransfer() + next_autotransfer = world.time + config.vote_autotransfer_interval + var/game_finished = SSshuttle.emergency.mode >= SHUTTLE_ENDGAME || mode.station_was_nuked if(config.continuous_rounds) mode.check_finished() // some modes contain var-changing code in here, so call even if we don't uses result else game_finished |= mode.check_finished() - if(game_finished) + if(game_finished || force_ending) current_state = GAME_STATE_FINISHED if(GAME_STATE_FINISHED) current_state = GAME_STATE_FINISHED @@ -113,36 +116,23 @@ SUBSYSTEM_DEF(ticker) else world.Reboot("Round ended.", "end_proper", "proper completion") - -/datum/controller/subsystem/ticker/proc/votetimer() - var/timerbuffer = 0 - if(initialtpass == 0) - timerbuffer = config.vote_autotransfer_initial - else - timerbuffer = config.vote_autotransfer_interval - spawn(timerbuffer) - SSvote.autotransfer() - initialtpass = 1 - votetimer() - - /datum/controller/subsystem/ticker/proc/setup() cultdat = setupcult() //Create and announce mode - if(master_mode=="secret") + if(GLOB.master_mode=="secret") src.hide_mode = 1 var/list/datum/game_mode/runnable_modes - if((master_mode=="random") || (master_mode=="secret")) + if((GLOB.master_mode=="random") || (GLOB.master_mode=="secret")) runnable_modes = config.get_runnable_modes() if(runnable_modes.len==0) current_state = GAME_STATE_PREGAME Master.SetRunLevel(RUNLEVEL_LOBBY) to_chat(world, "Unable to choose playable game mode. Reverting to pre-game lobby.") return 0 - if(secret_force_mode != "secret") - var/datum/game_mode/M = config.pick_mode(secret_force_mode) + if(GLOB.secret_force_mode != "secret") + var/datum/game_mode/M = config.pick_mode(GLOB.secret_force_mode) if(M.can_start()) - src.mode = config.pick_mode(secret_force_mode) + src.mode = config.pick_mode(GLOB.secret_force_mode) SSjobs.ResetOccupations() if(!src.mode) src.mode = pickweight(runnable_modes) @@ -150,7 +140,7 @@ SUBSYSTEM_DEF(ticker) var/mtype = src.mode.type src.mode = new mtype else - src.mode = config.pick_mode(master_mode) + src.mode = config.pick_mode(GLOB.master_mode) if(!src.mode.can_start()) to_chat(world, "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby.") mode = null @@ -167,7 +157,7 @@ SUBSYSTEM_DEF(ticker) if(!can_continue) qdel(mode) current_state = GAME_STATE_PREGAME - to_chat(world, "Error setting up [master_mode]. Reverting to pre-game lobby.") + to_chat(world, "Error setting up [GLOB.master_mode]. Reverting to pre-game lobby.") SSjobs.ResetOccupations() Master.SetRunLevel(RUNLEVEL_LOBBY) return 0 @@ -186,7 +176,7 @@ SUBSYSTEM_DEF(ticker) populate_spawn_points() collect_minds() equip_characters() - data_core.manifest() + GLOB.data_core.manifest() current_state = GAME_STATE_PLAYING Master.SetRunLevel(RUNLEVEL_GAME) @@ -194,7 +184,6 @@ SUBSYSTEM_DEF(ticker) //here to initialize the random events nicely at round start setup_economy() - setupfactions() //shuttle_controller.setup_shuttle_docks() @@ -284,11 +273,8 @@ SUBSYSTEM_DEF(ticker) auto_toggle_ooc(0) // Turn it off round_start_time = world.time - if(config.sql_enabled) - spawn(3000) - statistic_cycle() // Polls population totals regularly and stores them in an SQL DB - - votetimer() + // Sets the auto shuttle vote to happen after the config duration + next_autotransfer = world.time + config.vote_autotransfer_initial for(var/mob/new_player/N in GLOB.mob_list) if(N.client) @@ -309,15 +295,12 @@ SUBSYSTEM_DEF(ticker) cinematic.mouse_opacity = MOUSE_OPACITY_TRANSPARENT cinematic.screen_loc = "1,0" - var/obj/structure/bed/temp_buckle = new(src) if(station_missed) for(var/mob/M in GLOB.mob_list) - M.buckled = temp_buckle //buckles the mob so it can't do anything if(M.client) M.client.screen += cinematic //show every client the cinematic else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived" for(var/mob/M in GLOB.mob_list) - M.buckled = temp_buckle if(M.stat != DEAD) var/turf/T = get_turf(M) if(T && is_station_level(T.z) && !istype(M.loc, /obj/structure/closet/secure_closet/freezer)) @@ -387,8 +370,6 @@ SUBSYSTEM_DEF(ticker) //Otherwise if its a verb it will continue on afterwards. spawn(300) QDEL_NULL(cinematic) //end the cinematic - if(temp_buckle) - qdel(temp_buckle) //release everybody @@ -442,18 +423,12 @@ SUBSYSTEM_DEF(ticker) if(m) to_chat(world, "Tip of the round: [html_encode(m)]") -/datum/controller/subsystem/ticker/proc/getfactionbyname(var/name) - for(var/datum/faction/F in factions) - if(F.name == name) - return F - - /datum/controller/subsystem/ticker/proc/declare_completion() - nologevent = 1 //end of round murder and shenanigans are legal; there's no need to jam up attack logs past this point. + GLOB.nologevent = 1 //end of round murder and shenanigans are legal; there's no need to jam up attack logs past this point. //Round statistics report var/datum/station_state/end_state = new /datum/station_state() end_state.count() - var/station_integrity = min(round( 100.0 * start_state.score(end_state), 0.1), 100.0) + var/station_integrity = min(round( 100.0 * GLOB.start_state.score(end_state), 0.1), 100.0) to_chat(world, "
[TAB]Shift Duration: [round(ROUND_TIME / 36000)]:[add_zero("[ROUND_TIME / 600 % 60]", 2)]:[ROUND_TIME / 100 % 6][ROUND_TIME / 100 % 10]") to_chat(world, "
[TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]") @@ -518,8 +493,13 @@ SUBSYSTEM_DEF(ticker) //Ask the event manager to print round end information SSevents.RoundEnd() + //make big obvious note in game logs that round ended + log_game("///////////////////////////////////////////////////////") + log_game("///////////////////// ROUND ENDED /////////////////////") + log_game("///////////////////////////////////////////////////////") + // Add AntagHUD to everyone, see who was really evil the whole time! - for(var/datum/atom_hud/antag/H in huds) + for(var/datum/atom_hud/antag/H in GLOB.huds) for(var/m in GLOB.player_list) var/mob/M = m H.add_hud_to(M) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 1caa3d7819a..7bb6a496274 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -9,6 +9,7 @@ SUBSYSTEM_DEF(timer) init_order = INIT_ORDER_TIMER flags = SS_TICKER|SS_NO_INIT + offline_implications = "The game will no longer process timers. Immediate server restart recommended." var/list/second_queue = list() //awe, yes, you've had first queue, but what about second queue? var/list/hashes = list() diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 4cb49e8a3f1..b0110258da7 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -3,6 +3,7 @@ SUBSYSTEM_DEF(vote) wait = 10 flags = SS_KEEP_TIMING|SS_NO_INIT runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT + offline_implications = "Votes (Endround shuttle) will no longer function. Shuttle call recommended." var/initiator = null var/started_time = null @@ -90,10 +91,10 @@ SUBSYSTEM_DEF(vote) if(choices["Continue Playing"] >= greatest_votes) greatest_votes = choices["Continue Playing"] else if(mode == "gamemode") - if(master_mode in choices) - choices[master_mode] += non_voters - if(choices[master_mode] >= greatest_votes) - greatest_votes = choices[master_mode] + if(GLOB.master_mode in choices) + choices[GLOB.master_mode] += non_voters + if(choices[GLOB.master_mode] >= greatest_votes) + greatest_votes = choices[GLOB.master_mode] else if(mode == "crew_transfer") var/factor = 0.5 switch(world.time / (10 * 60)) // minutes @@ -164,14 +165,14 @@ SUBSYSTEM_DEF(vote) if(. == "Restart Round") restart = 1 if("gamemode") - if(master_mode != .) + if(GLOB.master_mode != .) world.save_mode(.) if(SSticker && SSticker.mode) restart = 1 else - master_mode = . - if(!going) - going = 1 + GLOB.master_mode = . + if(!SSticker.ticker_going) + SSticker.ticker_going = TRUE to_chat(world, "The round will start soon.") if("crew_transfer") if(. == "Initiate Crew Transfer") @@ -253,8 +254,8 @@ SUBSYSTEM_DEF(vote) world << sound('sound/ambience/alarm4.ogg') if("custom") world << sound('sound/ambience/alarm4.ogg') - if(mode == "gamemode" && going) - going = 0 + if(mode == "gamemode" && SSticker.ticker_going) + SSticker.ticker_going = FALSE to_chat(world, "Round start has been delayed.") if(mode == "crew_transfer" && config.ooc_allowed) auto_muted = 1 diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm index ac2f0c59313..bf405444110 100644 --- a/code/controllers/subsystem/weather.dm +++ b/code/controllers/subsystem/weather.dm @@ -9,6 +9,7 @@ SUBSYSTEM_DEF(weather) flags = SS_BACKGROUND wait = 10 runlevels = RUNLEVEL_GAME + offline_implications = "Ash storms will no longer trigger. No immediate action is needed." var/list/processing = list() var/list/eligible_zlevels = list() var/list/next_hit_by_zlevel = list() //Used by barometers to know when the next storm is coming @@ -19,7 +20,7 @@ SUBSYSTEM_DEF(weather) var/datum/weather/W = V if(W.aesthetic || W.stage != MAIN_STAGE) continue - for(var/i in GLOB.living_mob_list) + for(var/i in GLOB.mob_living_list) var/mob/living/L = i if(W.can_weather_act(L)) W.weather_act(L) diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index c67e53184a1..3eaed85c303 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -53,10 +53,10 @@ debug_variables(config) feedback_add_details("admin_verb","DConf") if("pAI") - debug_variables(paiController) + debug_variables(GLOB.paiController) feedback_add_details("admin_verb","DpAI") if("Cameras") - debug_variables(cameranet) + debug_variables(GLOB.cameranet) feedback_add_details("admin_verb","DCameras") if("Garbage") debug_variables(SSgarbage) @@ -92,7 +92,7 @@ debug_variables(SSweather) feedback_add_details("admin_verb","DWeather") if("Space") - debug_variables(space_manager) + debug_variables(GLOB.space_manager) feedback_add_details("admin_verb","DSpace") if("Mob Hunt Server") debug_variables(SSmob_hunt) diff --git a/code/datums/action.dm b/code/datums/action.dm index b7af84e9ddf..c1802da47c1 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -339,7 +339,7 @@ /datum/action/item_action/remove_tape/Trigger(attack_self = FALSE) if(..()) - GET_COMPONENT_FROM(DT, /datum/component/ducttape, target) + var/datum/component/ducttape/DT = target.GetComponent(/datum/component/ducttape) DT.remove_tape(target, usr) /datum/action/item_action/toggle_jetpack diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 0a14b0e9476..8e1a9d8bcce 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -62,15 +62,15 @@ if(sorted_laws.len) return - for(var/ion_law in ion_laws) - sorted_laws += ion_law - - for(var/evil_law in devil_laws) - sorted_laws += evil_law - if(zeroth_law) sorted_laws += zeroth_law + for(var/ion_law in ion_laws) + sorted_laws += ion_law + + for(var/evil_law in devil_laws) + sorted_laws += evil_law + var/index = 1 for(var/datum/ai_law/inherent_law in inherent_laws) inherent_law.index = index++ @@ -133,12 +133,12 @@ for(var/datum/ai_law/AL in devil_laws) if(AL.law == law) return - + var/new_law = new/datum/ai_law/sixsixsix(law) devil_laws += new_law if(state_devil.len < devil_laws.len) state_devil += 1 - + sorted_laws.Cut() /datum/ai_laws/proc/add_ion_law(var/law) @@ -209,9 +209,9 @@ /datum/ai_law/ion/delete_law(var/datum/ai_laws/laws) laws.internal_delete_law(laws.ion_laws, laws.state_ion, src) - + /datum/ai_law/sixsixsix/delete_law(var/datum/ai_laws/laws) - laws.internal_delete_law(laws.devil_laws, laws.state_devil, src) + laws.internal_delete_law(laws.devil_laws, laws.state_devil, src) /datum/ai_law/inherent/delete_law(var/datum/ai_laws/laws) laws.internal_delete_law(laws.inherent_laws, laws.state_inherent, src) diff --git a/code/datums/cache/air_alarm.dm b/code/datums/cache/air_alarm.dm index 662b0958d5c..2edc0792a34 100644 --- a/code/datums/cache/air_alarm.dm +++ b/code/datums/cache/air_alarm.dm @@ -1,4 +1,4 @@ -var/global/datum/repository/air_alarm/air_alarm_repository = new() +GLOBAL_DATUM_INIT(air_alarm_repository, /datum/repository/air_alarm, new()) /datum/repository/air_alarm/proc/air_alarm_data(var/list/monitored_alarms, var/refresh = 0, var/obj/machinery/alarm/passed_alarm) var/alarms[0] @@ -11,13 +11,13 @@ var/global/datum/repository/air_alarm/air_alarm_repository = new() if(!refresh) return cache_entry.data - if(SSticker && SSticker.current_state < GAME_STATE_PLAYING && istype(passed_alarm)) // Generating the list for the first time as the game hasn't started - no need to run through the machines list everything every time + if(SSticker && SSticker.current_state < GAME_STATE_PLAYING && istype(passed_alarm)) // Generating the list for the first time as the game hasn't started - no need to run through the machines list everything every time alarms = cache_entry.data // Don't deleate the list if(is_station_contact(passed_alarm.z) && passed_alarm.remote_control) // Still need sanity checks - alarms[++alarms.len] = passed_alarm.get_nano_data_console() + alarms[++alarms.len] = passed_alarm.get_nano_data_console() else for(var/obj/machinery/alarm/alarm in (monitored_alarms ? monitored_alarms : GLOB.air_alarms)) // Generating the whole list again is a bad habit but I can't be bothered to fix it right now - if(!monitored_alarms && !is_station_contact(alarm.z)) + if(!monitored_alarms && !is_station_contact(alarm.z)) continue if(!alarm.remote_control) continue diff --git a/code/datums/cache/apc.dm b/code/datums/cache/apc.dm index 524a8793415..318fd654fe3 100644 --- a/code/datums/cache/apc.dm +++ b/code/datums/cache/apc.dm @@ -1,4 +1,4 @@ -var/global/datum/repository/apc/apc_repository = new() +GLOBAL_DATUM_INIT(apc_repository, /datum/repository/apc, new()) /datum/repository/apc/proc/apc_data(datum/powernet/powernet) var/apcData[0] diff --git a/code/datums/cache/crew.dm b/code/datums/cache/crew.dm index b30b5c57889..21ec5ebcc79 100644 --- a/code/datums/cache/crew.dm +++ b/code/datums/cache/crew.dm @@ -1,4 +1,4 @@ -var/global/datum/repository/crew/crew_repository = new() +GLOBAL_DATUM_INIT(crew_repository, /datum/repository/crew, new()) /datum/repository/crew/New() cache_data = list() diff --git a/code/datums/cache/powermonitor.dm b/code/datums/cache/powermonitor.dm index 29394195edf..606dd500eda 100644 --- a/code/datums/cache/powermonitor.dm +++ b/code/datums/cache/powermonitor.dm @@ -1,8 +1,8 @@ -var/global/datum/repository/powermonitor/powermonitor_repository = new() +GLOBAL_DATUM_INIT(powermonitor_repository, /datum/repository/powermonitor, new()) /datum/repository/powermonitor/proc/powermonitor_data(var/refresh = 0) var/pMonData[0] - + var/datum/cache_entry/cache_entry = cache_data if(!cache_entry) cache_entry = new/datum/cache_entry @@ -10,15 +10,15 @@ var/global/datum/repository/powermonitor/powermonitor_repository = new() if(!refresh) return cache_entry.data - + for(var/obj/machinery/computer/monitor/pMon in GLOB.power_monitors) if( !(pMon.stat & (NOPOWER|BROKEN)) && !pMon.is_secret_monitor ) pMonData[++pMonData.len] = list ("Name" = pMon.name, "ref" = "\ref[pMon]") cache_entry.timestamp = world.time //+ 30 SECONDS - cache_entry.data = pMonData + cache_entry.data = pMonData return pMonData - + /datum/repository/powermonitor/proc/update_cache() return powermonitor_data(refresh = 1) - + diff --git a/code/datums/components/README.md b/code/datums/components/README.md index 9d06a255dd7..03f7d3a5875 100644 --- a/code/datums/components/README.md +++ b/code/datums/components/README.md @@ -2,134 +2,8 @@ ## Concept -Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SEND_SIGNAL` call. Now every component that want's to can also know about this happening. +Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SendSignal()` call. Now every component that want's to can also know about this happening. -### In the code +See [this thread](https://tgstation13.org/phpBB/viewtopic.php?f=5&t=22674) for an introduction to the system as a whole. -#### Slippery things - -At the time of this writing, every object that is slippery overrides atom/Crossed does some checks, then slips the mob. Instead of all those Crossed overrides they could add a slippery component to all these objects. And have the checks in one proc that is run by the Crossed event - -#### Powercells - -A lot of objects have powercells. The `get_cell()` proc was added to give generic access to the cell var if it had one. This is just a specific use case of `GetComponent()` - -#### Radios - -The radio object as it is should not exist, given that more things use the _concept_ of radios rather than the object itself. The actual function of the radio can exist in a component which all the things that use it (Request consoles, actual radios, the SM shard) can add to themselves. - -#### Standos - -Stands have a lot of procs which mimic mob procs. Rather than inserting hooks for all these procs in overrides, the same can be accomplished with signals - -## API - -### Defines - -1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned. This will be noted in the runtime logs - -### Vars - -1. `/datum/var/list/datum_components` (private) - * Lazy associated list of type -> component/list of components. -1. `/datum/var/list/comp_lookup` (private) - * Lazy associated list of signal -> registree/list of registrees -1. `/datum/var/list/signal_procs` (private) - * Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum receives that signal -1. `/datum/var/signal_enabled` (protected, boolean) - * If the datum is signal enabled. If not, it will not react to signals - * `FALSE` by default, set to `TRUE` when a signal is registered -1. `/datum/component/var/dupe_mode` (protected, enum) - * How duplicate component types are handled when added to the datum. - * `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it - * `COMPONENT_DUPE_ALLOWED`: The components will be treated as separate, `GetComponent()` will return the first added - * `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it - * `COMPONENT_DUPE_UNIQUE_PASSARGS`: New component will never exist and instead its initialization arguments will be passed on to the old component. -1. `/datum/component/var/dupe_type` (protected, type) - * Definition of a duplicate component type - * `null` means exact match on `type` (default) - * Any other type means that and all subtypes -1. `/datum/component/var/datum/parent` (protected, read-only) - * The datum this component belongs to - * Never `null` in child procs -1. `report_signal_origin` (protected, boolean) - * If `TRUE`, will invoke the callback when signalled with the signal type as the first argument. - * `FALSE` by default. - -### Procs - -1. `/datum/proc/GetComponent(component_type(type)) -> datum/component?` (public, final) - * Returns a reference to a component of component_type if it exists in the datum, null otherwise -1. `/datum/proc/GetComponents(component_type(type)) -> list` (public, final) - * Returns a list of references to all components of component_type that exist in the datum -1. `/datum/proc/GetExactComponent(component_type(type)) -> datum/component?` (public, final) - * Returns a reference to a component whose type MATCHES component_type if that component exists in the datum, null otherwise -1. `GET_COMPONENT(varname, component_type)` OR `GET_COMPONENT_FROM(varname, component_type, src)` - * Shorthand for `var/component_type/varname = src.GetComponent(component_type)` -1. `SEND_SIGNAL(target, sigtype, ...)` (public, final) - * Use to send signals to target datum - * Extra arguments are to be specified in the signal definition - * Returns a bitflag with signal specific information assembled from all activated components - * Arguments are packaged in a list and handed off to _SendSignal() -1. `/datum/proc/AddComponent(component_type(type), ...) -> datum/component` (public, final) - * Creates an instance of `component_type` in the datum and passes `...` to its `Initialize()` call - * Sends the `COMSIG_COMPONENT_ADDED` signal to the datum - * All components a datum owns are deleted with the datum - * Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set - * If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it - * Properly handles duplicate situations based on the `dupe_mode` var -1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final) - * Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead -1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async) - * Called on a component's `parent` after a signal received causes it to activate. `src` is the parameter - * Will only be called if a component's callback returns `TRUE` -1. `/datum/proc/TakeComponent(datum/component/C)` (public, final) - * Properly transfers ownership of a component from one datum to another - * Signals `COMSIG_COMPONENT_REMOVING` on the parent - * Called on the datum you want to own the component with another datum's component -1. `/datum/proc/_SendSignal(signal, list/arguments)` (private, final) - * Handles most of the actual signaling procedure - * Will runtime if used on datums with an empty component list -1. `/datum/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) - * If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments - * Makes the datum listen for the specified `signal` on it's `parent` datum. - * When that signal is received `proc_ref` will be called on the component, along with associated arguments - * Example proc ref: `.proc/OnEvent` - * If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this - * These callbacks run asyncronously - * Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it -1. `/datum/component/New(datum/parent, ...)` (private, final) - * Runs internal setup for the component - * Extra arguments are passed to `Initialize()` -1. `/datum/component/Initialize(...)` (abstract, no-sleep) - * Called by `New()` with the same argments excluding `parent` - * Component does not exist in `parent`'s `datum_components` list yet, although `parent` is set and may be used - * Signals will not be received while this function is running - * Component may be deleted after this function completes without being attached - * Do not call `qdel(src)` from this function -1. `/datum/component/Destroy(force(bool), silent(bool))` (virtual, no-sleep) - * Sends the `COMSIG_COMPONENT_REMOVING` signal to the parent datum if the `parent` isn't being qdeleted - * Properly removes the component from `parent` and cleans up references - * Setting `force` makes it not check for and remove the component from the parent - * Setting `silent` deletes the component without sending a `COMSIG_COMPONENT_REMOVING` signal -1. `/datum/component/proc/InheritComponent(datum/component/C, i_am_original(boolean))` (abstract, no-sleep) - * Called on a component when a component of the same type was added to the same parent - * See `/datum/component/var/dupe_mode` - * `C`'s type will always be the same of the called component -1. `/datum/component/proc/AfterComponentActivated()` (abstract, async) - * Called on a component that was activated after it's `parent`'s `ComponentActivated()` is called -1. `/datum/component/proc/OnTransfer(datum/new_parent)` (abstract, no-sleep) - * Called before `new_parent` is assigned to `parent` in `TakeComponent()` - * Allows the component to react to ownership transfers -1. `/datum/component/proc/_RemoveFromParent()` (private, final) - * Clears `parent` and removes the component from it's component list -1. `/datum/component/proc/_JoinParent` (private, final) - * Tries to add the component to it's `parent`s `datum_components` list -1. `/datum/component/proc/RegisterWithParent` (abstract, no-sleep) - * Used to register the signals that should be on the `parent` object - * Use this if you plan on the component transfering between parents -1. `/datum/component/proc/UnregisterFromParent` (abstract, no-sleep) - * Counterpart to `RegisterWithParent()` - * Used to unregister the signals that should only be on the `parent` object - -### See/Define signals and their arguments in __DEFINES\components.dm +### See/Define signals and their arguments in [__DEFINES\dcs\signals.dm](../../__DEFINES/dcs/signals.dm) diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index e733ca78d2b..f895b8d81b1 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -1,21 +1,87 @@ +/** + * # Component + * + * The component datum + * + * A component should be a single standalone unit + * of functionality, that works by receiving signals from it's parent + * object to provide some single functionality (i.e a slippery component) + * that makes the object it's attached to cause people to slip over. + * Useful when you want shared behaviour independent of type inheritance + */ /datum/component + /** + * Defines how duplicate existing components are handled when added to a datum + * + * See [COMPONENT_DUPE_*][COMPONENT_DUPE_ALLOWED] definitions for available options + */ var/dupe_mode = COMPONENT_DUPE_HIGHLANDER + + /** + * The type to check for duplication + * + * `null` means exact match on `type` (default) + * + * Any other type means that and all subtypes + */ var/dupe_type + + /// The datum this components belongs to var/datum/parent - //only set to true if you are able to properly transfer this component - //At a minimum RegisterWithParent and UnregisterFromParent should be used - //Make sure you also implement PostTransfer for any post transfer handling + + /** + * Only set to true if you are able to properly transfer this component + * + * At a minimum [RegisterWithParent][/datum/component/proc/RegisterWithParent] and [UnregisterFromParent][/datum/component/proc/UnregisterFromParent] should be used + * + * Make sure you also implement [PostTransfer][/datum/component/proc/PostTransfer] for any post transfer handling + */ var/can_transfer = FALSE -/datum/component/New(datum/P, ...) - parent = P - var/list/arguments = args.Copy(2) +/** + * Create a new component. + * + * Additional arguments are passed to [Initialize()][/datum/component/proc/Initialize] + * + * Arguments: + * * datum/P the parent datum this component reacts to signals from + */ +/datum/component/New(list/raw_args) + parent = raw_args[1] + var/list/arguments = raw_args.Copy(2) if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE) + stack_trace("Incompatible [type] assigned to a [parent.type]! args: [json_encode(arguments)]") qdel(src, TRUE, TRUE) - CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]") + return - _JoinParent(P) + _JoinParent(parent) +/** + * Called during component creation with the same arguments as in new excluding parent. + * + * Do not call `qdel(src)` from this function, `return COMPONENT_INCOMPATIBLE` instead + */ +/datum/component/proc/Initialize(...) + return + +/** + * Properly removes the component from `parent` and cleans up references + * + * Arguments: + * * force - makes it not check for and remove the component from the parent + * * silent - deletes the component without sending a [COMSIG_COMPONENT_REMOVING] signal + */ +/datum/component/Destroy(force=FALSE, silent=FALSE) + if(!force && parent) + _RemoveFromParent() + if(!silent) + SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src) + parent = null + return ..() + +/** + * Internal proc to handle behaviour of components when joining a parent + */ /datum/component/proc/_JoinParent() var/datum/P = parent //lazy init the parent's dc list @@ -51,21 +117,9 @@ RegisterWithParent() -// If you want/expect to be moving the component around between parents, use this to register on the parent for signals -/datum/component/proc/RegisterWithParent() - return - -/datum/component/proc/Initialize(...) - return - -/datum/component/Destroy(force=FALSE, silent=FALSE) - if(!force && parent) - _RemoveFromParent() - if(!silent) - SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src) - parent = null - return ..() - +/** + * Internal proc to handle behaviour when being removed from a parent + */ /datum/component/proc/_RemoveFromParent() var/datum/P = parent var/list/dc = P.datum_components @@ -84,10 +138,41 @@ UnregisterFromParent() +/** + * Register the component with the parent object + * + * Use this proc to register with your parent object + * + * Overridable proc that's called when added to a new parent + */ +/datum/component/proc/RegisterWithParent() + return + +/** + * Unregister from our parent object + * + * Use this proc to unregister from your parent object + * + * Overridable proc that's called when removed from a parent + * * + */ /datum/component/proc/UnregisterFromParent() return -/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE) +/** + * Register to listen for a signal from the passed in target + * + * This sets up a listening relationship such that when the target object emits a signal + * the source datum this proc is called upon, will recieve a callback to the given proctype + * Return values from procs registered must be a bitfield + * + * Arguments: + * * datum/target The target to listen for signals from + * * sig_type_or_types Either a string signal name, or a list of signal names (strings) + * * proctype The proc to call back when the signal is emitted + * * override If a previous registration exists you must explicitly set this + */ +/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proctype, override = FALSE) if(QDELETED(src) || QDELETED(target)) return @@ -100,15 +185,12 @@ if(!lookup) target.comp_lookup = lookup = list() - if(!istype(proc_or_callback, /datum/callback)) //if it wasnt a callback before, it is now - proc_or_callback = CALLBACK(src, proc_or_callback) - var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types) for(var/sig_type in sig_types) if(!override && procs[target][sig_type]) stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning") - procs[target][sig_type] = proc_or_callback + procs[target][sig_type] = proctype if(!lookup[sig_type]) // Nothing has registered here yet lookup[sig_type] = src @@ -122,6 +204,17 @@ signal_enabled = TRUE +/** + * Stop listening to a given signal from target + * + * Breaks the relationship between target and source datum, removing the callback when the signal fires + * + * Doesn't care if a registration exists or not + * + * Arguments: + * * datum/target Datum to stop listening to signals from + * * sig_typeor_types Signal string key or list of signal keys to stop listening to specifically + */ /datum/proc/UnregisterSignal(datum/target, sig_type_or_types) var/list/lookup = target.comp_lookup if(!signal_procs || !signal_procs[target] || !lookup) @@ -129,6 +222,8 @@ if(!islist(sig_type_or_types)) sig_type_or_types = list(sig_type_or_types) for(var/sig in sig_type_or_types) + if(!signal_procs[target][sig]) + continue switch(length(lookup[sig])) if(2) lookup[sig] = (lookup[sig]-src)[1] @@ -151,41 +246,96 @@ if(!signal_procs[target].len) signal_procs -= target +/** + * Called on a component when a component of the same type was added to the same parent + * + * See [/datum/component/var/dupe_mode] + * + * `C`'s type will always be the same of the called component + */ /datum/component/proc/InheritComponent(datum/component/C, i_am_original) return + +/** + * Called on a component when a component of the same type was added to the same parent with [COMPONENT_DUPE_SELECTIVE] + * + * See [/datum/component/var/dupe_mode] + * + * `C`'s type will always be the same of the called component + * + * return TRUE if you are absorbing the component, otherwise FALSE if you are fine having it exist as a duplicate component + */ +/datum/component/proc/CheckDupeComponent(datum/component/C, ...) + return + + +/** + * Callback Just before this component is transferred + * + * Use this to do any special cleanup you might need to do before being deregged from an object + */ /datum/component/proc/PreTransfer() return +/** + * Callback Just after a component is transferred + * + * Use this to do any special setup you need to do after being moved to a new object + * + * Do not call `qdel(src)` from this function, `return COMPONENT_INCOMPATIBLE` instead + */ /datum/component/proc/PostTransfer() return COMPONENT_INCOMPATIBLE //Do not support transfer by default as you must properly support it +/** + * Internal proc to create a list of our type and all parent types + */ /datum/component/proc/_GetInverseTypeList(our_type = type) //we can do this one simple trick var/current_type = parent_type . = list(our_type, current_type) //and since most components are root level + 1, this won't even have to run - while(current_type != /datum/component) + while (current_type != /datum/component) current_type = type2parent(current_type) . += current_type +/** + * Internal proc to handle most all of the signaling procedure + * + * Will runtime if used on datums with an empty component list + * + * Use the [SEND_SIGNAL] define instead + */ /datum/proc/_SendSignal(sigtype, list/arguments) var/target = comp_lookup[sigtype] if(!length(target)) var/datum/C = target if(!C.signal_enabled) return NONE - var/datum/callback/CB = C.signal_procs[src][sigtype] - return CB.InvokeAsync(arglist(arguments)) + var/proctype = C.signal_procs[src][sigtype] + return NONE | CallAsync(C, proctype, arguments) . = NONE for(var/I in target) var/datum/C = I if(!C.signal_enabled) continue - var/datum/callback/CB = C.signal_procs[src][sigtype] - . |= CB.InvokeAsync(arglist(arguments)) + var/proctype = C.signal_procs[src][sigtype] + . |= CallAsync(C, proctype, arguments) -/datum/proc/GetComponent(c_type) +// The type arg is casted so initial works, you shouldn't be passing a real instance into this +/** + * Return any component assigned to this datum of the given type + * + * This will throw an error if it's possible to have more than one component of that type on the parent + * + * Arguments: + * * datum/component/c_type The typepath of the component you want to get a reference to + */ +/datum/proc/GetComponent(datum/component/c_type) + RETURN_TYPE(c_type) + if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED || initial(c_type.dupe_mode) == COMPONENT_DUPE_SELECTIVE) + stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]") var/list/dc = datum_components if(!dc) return null @@ -193,7 +343,19 @@ if(length(.)) return .[1] -/datum/proc/GetExactComponent(c_type) +// The type arg is casted so initial works, you shouldn't be passing a real instance into this +/** + * Return any component assigned to this datum of the exact given type + * + * This will throw an error if it's possible to have more than one component of that type on the parent + * + * Arguments: + * * datum/component/c_type The typepath of the component you want to get a reference to + */ +/datum/proc/GetExactComponent(datum/component/c_type) + RETURN_TYPE(c_type) + if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED || initial(c_type.dupe_mode) == COMPONENT_DUPE_SELECTIVE) + stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]") var/list/dc = datum_components if(!dc) return null @@ -205,6 +367,12 @@ return C return null +/** + * Get all components of a given type that are attached to this datum + * + * Arguments: + * * c_type The component type path + */ /datum/proc/GetComponents(c_type) var/list/dc = datum_components if(!dc) @@ -213,7 +381,19 @@ if(!length(.)) return list(.) -/datum/proc/AddComponent(new_type, ...) +/** + * Creates an instance of `new_type` in the datum and attaches to it as parent + * + * Sends the [COMSIG_COMPONENT_ADDED] signal to the datum + * + * Returns the component that was created. Or the old component in a dupe situation where [COMPONENT_DUPE_UNIQUE] was set + * + * If this tries to add a component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it + * + * Properly handles duplicate situations based on the `dupe_mode` var + */ +/datum/proc/_AddComponent(list/raw_args) + var/new_type = raw_args[1] var/datum/component/nt = new_type var/dm = initial(nt.dupe_mode) var/dt = initial(nt.dupe_type) @@ -228,7 +408,7 @@ new_comp = nt nt = new_comp.type - args[1] = src + raw_args[1] = src if(dm != COMPONENT_DUPE_ALLOWED) if(!dt) @@ -239,37 +419,62 @@ switch(dm) if(COMPONENT_DUPE_UNIQUE) if(!new_comp) - new_comp = new nt(arglist(args)) + new_comp = new nt(raw_args) if(!QDELETED(new_comp)) old_comp.InheritComponent(new_comp, TRUE) QDEL_NULL(new_comp) if(COMPONENT_DUPE_HIGHLANDER) if(!new_comp) - new_comp = new nt(arglist(args)) + new_comp = new nt(raw_args) if(!QDELETED(new_comp)) new_comp.InheritComponent(old_comp, FALSE) QDEL_NULL(old_comp) if(COMPONENT_DUPE_UNIQUE_PASSARGS) if(!new_comp) - var/list/arguments = args.Copy(2) - old_comp.InheritComponent(null, TRUE, arguments) + var/list/arguments = raw_args.Copy(2) + arguments.Insert(1, null, TRUE) + old_comp.InheritComponent(arglist(arguments)) else old_comp.InheritComponent(new_comp, TRUE) + if(COMPONENT_DUPE_SELECTIVE) + var/list/arguments = raw_args.Copy() + arguments[1] = new_comp + var/make_new_component = TRUE + for(var/i in GetComponents(new_type)) + var/datum/component/C = i + if(C.CheckDupeComponent(arglist(arguments))) + make_new_component = FALSE + QDEL_NULL(new_comp) + break + if(!new_comp && make_new_component) + new_comp = new nt(raw_args) else if(!new_comp) - new_comp = new nt(arglist(args)) // There's a valid dupe mode but there's no old component, act like normal + new_comp = new nt(raw_args) // There's a valid dupe mode but there's no old component, act like normal else if(!new_comp) - new_comp = new nt(arglist(args)) // Dupes are allowed, act like normal + new_comp = new nt(raw_args) // Dupes are allowed, act like normal if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_comp) return new_comp return old_comp +/** + * Get existing component of type, or create it and return a reference to it + * + * Use this if the item needs to exist at the time of this call, but may not have been created before now + * + * Arguments: + * * component_type The typepath of the component to create or return + * * ... additional arguments to be passed when creating the component if it does not exist + */ /datum/proc/LoadComponent(component_type, ...) . = GetComponent(component_type) if(!.) - return AddComponent(arglist(args)) + return _AddComponent(args) +/** + * Removes the component from parent, ends up with a null parent + */ /datum/component/proc/RemoveComponent() if(!parent) return @@ -279,6 +484,14 @@ parent = null SEND_SIGNAL(old_parent, COMSIG_COMPONENT_REMOVING, src) +/** + * Transfer this component to another parent + * + * Component is taken from source datum + * + * Arguments: + * * datum/component/target Target datum to transfer to + */ /datum/proc/TakeComponent(datum/component/target) if(!target || target.parent == src) return @@ -295,6 +508,14 @@ if(target == AddComponent(target)) target._JoinParent() +/** + * Transfer all components to target + * + * All components from source datum are taken + * + * Arguments: + * * /datum/target the target to move the components to + */ /datum/proc/TransferComponents(datum/target) var/list/dc = datum_components if(!dc) @@ -309,5 +530,8 @@ if(C.can_transfer) target.TakeComponent(comps) +/** + * Return the object that is the host of any UI's that this component has + */ /datum/component/nano_host() return parent diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm index 6a0f686b13a..876cf0c0507 100644 --- a/code/datums/components/decal.dm +++ b/code/datums/components/decal.dm @@ -7,7 +7,7 @@ var/first_dir // This only stores the dir arg from init -/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255) +/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable = CLEAN_GOD, _color, _layer = TURF_LAYER, _description, _alpha = 255) if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha)) return COMPONENT_INCOMPATIBLE first_dir = _dir diff --git a/code/datums/components/edit_complainer.dm b/code/datums/components/edit_complainer.dm new file mode 100644 index 00000000000..35bb05ca791 --- /dev/null +++ b/code/datums/components/edit_complainer.dm @@ -0,0 +1,23 @@ +// This is just a bit of fun while making an example for global signal +/datum/component/edit_complainer + var/list/say_lines + +/datum/component/edit_complainer/Initialize(list/text) + if(!ismovableatom(parent)) + return COMPONENT_INCOMPATIBLE + + var/static/list/default_lines = list( + "CentComm's profligacy frays another thread.", + "Another tug at the weave.", + "Who knows when the stresses will finally shatter the form?", + "Even now a light shines through the cracks.", + "CentComm once more twists knowledge beyond its authority.", + "There is an uncertain air in the mansus.", + ) + say_lines = text || default_lines + + RegisterSignal(SSdcs, COMSIG_GLOB_VAR_EDIT, .proc/var_edit_react) + +/datum/component/edit_complainer/proc/var_edit_react(datum/source, list/arguments) + var/atom/movable/master = parent + master.atom_say(pick(say_lines)) diff --git a/code/datums/components/jestosterone.dm b/code/datums/components/jestosterone.dm deleted file mode 100644 index f37f1f03efb..00000000000 --- a/code/datums/components/jestosterone.dm +++ /dev/null @@ -1,5 +0,0 @@ -/datum/component/jestosterone - var/mind_type //Is the affected mob a clown / mime? - -/datum/component/jestosterone/Initialize(mind_type_arg) - mind_type = mind_type_arg diff --git a/code/datums/components/label.dm b/code/datums/components/label.dm new file mode 100644 index 00000000000..c6d0c595ebb --- /dev/null +++ b/code/datums/components/label.dm @@ -0,0 +1,87 @@ +/** + The label component. + + This component is used to manage labels applied by the hand labeler. + + Atoms can only have one instance of this component, and therefore only one label at a time. + This is to avoid having names like "Backpack (label1) (label2) (label3)". This is annoying and abnoxious to read. + + When a player clicks the atom with a hand labeler to apply a label, this component gets applied to it. + If the labeler is off, the component will be removed from it, and the label will be removed from its name. + */ +/datum/component/label + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + /// The name of the label the player is applying to the parent. + var/label_name + +/datum/component/label/Initialize(_label_name) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + label_name = _label_name + apply_label() + +/datum/component/label/RegisterWithParent() + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackby) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/Examine) + +/datum/component/label/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_PARENT_ATTACKBY, COMSIG_PARENT_EXAMINE)) + +/** + This proc will fire after the parent is hit by a hand labeler which is trying to apply another label. + Since the parent already has a label, it will remove the old one from the parent's name, and apply the new one. +*/ +/datum/component/label/InheritComponent(datum/component/label/new_comp , i_am_original, _label_name) + remove_label() + if(new_comp) + label_name = new_comp.label_name + else + label_name = _label_name + apply_label() + +/** + This proc will trigger when any object is used to attack the parent. + + If the attacking object is not a hand labeler, it will return. + If the attacking object is a hand labeler it will restore the name of the parent to what it was before this component was added to it, and the component will be deleted. + + Arguments: + * source: The parent. + * attacker: The object that is hitting the parent. + * user: The mob who is wielding the attacking object. +*/ +/datum/component/label/proc/OnAttackby(datum/source, obj/item/attacker, mob/user) + // If the attacking object is not a hand labeler or its mode is 1 (has a label ready to apply), return. + // The hand labeler should be off (mode is 0), in order to remove a label. + var/obj/item/hand_labeler/labeler = attacker + if(!istype(labeler) || labeler.mode) + return + + remove_label() + playsound(parent, 'sound/items/poster_ripped.ogg', 20, TRUE) + to_chat(user, "You remove the label from [parent].") + qdel(src) // Remove the component from the object. + +/** + This proc will trigger when someone examines the parent. + It will attach the text found in the body of the proc to the `examine_list` and display it to the player examining the parent. + + Arguments: + * source: The parent. + * user: The mob exmaining the parent. + * examine_list: The current list of text getting passed from the parent's normal examine() proc. +*/ +/datum/component/label/proc/Examine(datum/source, mob/user, list/examine_list) + examine_list += "It has a label with some words written on it. Use a hand labeler to remove it." + +/// Applies a label to the name of the parent in the format of: "parent_name (label)" +/datum/component/label/proc/apply_label() + var/atom/owner = parent + owner.name += " ([label_name])" + +/// Removes the label from the parent's name +/datum/component/label/proc/remove_label() + var/atom/owner = parent + owner.name = replacetext(owner.name, "([label_name])", "") // Remove the label text from the parent's name, wherever it's located. + owner.name = trim(owner.name) // Shave off any white space from the beginning or end of the parent's name. diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm new file mode 100644 index 00000000000..3e505eb0a8a --- /dev/null +++ b/code/datums/components/slippery.dm @@ -0,0 +1,56 @@ +/** + * # Slip Component + * + * This is a component that can be applied to any movable atom (mob or obj). + * + * While the atom has this component, any human mob that walks over it will have a chance to slip. + * Duration, tiles moved, and so on, depend on what variables are passed in when the component is added. + * + */ +/datum/component/slippery + /// Text that gets displayed in the slip proc, i.e. "user slips on [description]" + var/description + /// The amount of stun to apply after slip. + var/stun + /// The amount of weaken to apply after slip. + var/weaken + /// The chance that walking over the parent will slip you. + var/slip_chance + /// The amount of tiles someone will be moved after slip. + var/slip_tiles + /// TRUE If this slip can be avoided by walking. + var/walking_is_safe + /// TRUE if having no slip shoes makes you immune to this slip. + var/noslip_is_immune + /// The verb that players will see when someone slips on the parent. In the form of "You [slip_verb]ped on". + var/slip_verb + +/datum/component/slippery/Initialize(_description, _stun = 0, _weaken = 0, _slip_chance = 100, _slip_tiles = 0, _walking_is_safe = TRUE, _noslip_is_immune = TRUE, _slip_verb = "slip") + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + description = _description + stun = max(0, _stun) + weaken = max(0, _weaken) + slip_chance = max(0, _slip_chance) + slip_tiles = max(0, _slip_tiles) + walking_is_safe = _walking_is_safe + noslip_is_immune = _noslip_is_immune + slip_verb = _slip_verb + +/datum/component/slippery/RegisterWithParent() + RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED), .proc/Slip) + +/datum/component/slippery/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED)) + +/** + Called whenever the parent recieves either the `MOVABLE_CROSSED` signal or the `ATOM_ENTERED` signal. + + Calls the `victim`'s `slip()` proc with the component's variables as arguments. + Additionally calls the parent's `after_slip()` proc on the `victim`. +*/ +/datum/component/slippery/proc/Slip(datum/source, mob/living/carbon/human/victim) + if(istype(victim) && prob(slip_chance) && victim.slip(description, stun, weaken, slip_tiles, walking_is_safe, noslip_is_immune, slip_verb)) + var/atom/movable/owner = parent + owner.after_slip(victim) diff --git a/code/datums/components/waddling.dm b/code/datums/components/waddling.dm deleted file mode 100644 index a1f538e4dd7..00000000000 --- a/code/datums/components/waddling.dm +++ /dev/null @@ -1,15 +0,0 @@ -/datum/component/waddling - dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS - -/datum/component/waddling/Initialize() - if(!isliving(parent)) - return COMPONENT_INCOMPATIBLE - RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle) - -/datum/component/waddling/proc/Waddle() - var/mob/living/L = parent - if(L.incapacitated() || L.lying) - return - animate(L, pixel_z = 4, time = 0) - animate(pixel_z = 0, transform = turn(matrix(), pick(-12, 0, 12)), time=2) - animate(pixel_z = 0, transform = matrix(), time = 0) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index f908685cf09..7bfc79e4e71 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -1,5 +1,5 @@ /hook/startup/proc/createDatacore() - data_core = new /datum/datacore() + GLOB.data_core = new /datum/datacore() return 1 /datum/datacore @@ -34,7 +34,7 @@ "} var/even = 0 // sort mobs - for(var/datum/data/record/t in data_core.general) + for(var/datum/data/record/t in GLOB.data_core.general) var/name = t.fields["name"] var/rank = t.fields["rank"] var/real_rank = t.fields["real_rank"] @@ -48,28 +48,28 @@ else isactive[name] = t.fields["p_stat"] var/department = 0 - if(real_rank in command_positions) + if(real_rank in GLOB.command_positions) heads[name] = rank department = 1 - if(real_rank in security_positions) + if(real_rank in GLOB.security_positions) sec[name] = rank department = 1 - if(real_rank in engineering_positions) + if(real_rank in GLOB.engineering_positions) eng[name] = rank department = 1 - if(real_rank in medical_positions) + if(real_rank in GLOB.medical_positions) med[name] = rank department = 1 - if(real_rank in science_positions) + if(real_rank in GLOB.science_positions) sci[name] = rank department = 1 - if(real_rank in service_positions) + if(real_rank in GLOB.service_positions) ser[name] = rank department = 1 - if(real_rank in supply_positions) + if(real_rank in GLOB.supply_positions) sup[name] = rank department = 1 - if(real_rank in nonhuman_positions) + if(real_rank in GLOB.nonhuman_positions) bot[name] = rank department = 1 if(!department && !(name in heads)) @@ -133,10 +133,10 @@ we'll only update it when it changes. The PDA_Manifest global list is zeroed ou using /datum/datacore/proc/manifest_inject(), or manifest_insert() */ -var/global/list/PDA_Manifest = list() +GLOBAL_LIST_EMPTY(PDA_Manifest) /datum/datacore/proc/get_manifest_json() - if(PDA_Manifest.len) + if(GLOB.PDA_Manifest.len) return var/heads[0] var/sec[0] @@ -147,7 +147,7 @@ var/global/list/PDA_Manifest = list() var/sup[0] var/bot[0] var/misc[0] - for(var/datum/data/record/t in data_core.general) + for(var/datum/data/record/t in GLOB.data_core.general) var/name = sanitize(t.fields["name"]) var/rank = sanitize(t.fields["rank"]) var/real_rank = t.fields["real_rank"] @@ -155,50 +155,50 @@ var/global/list/PDA_Manifest = list() var/isactive = t.fields["p_stat"] var/department = 0 var/depthead = 0 // Department Heads will be placed at the top of their lists. - if(real_rank in command_positions) + if(real_rank in GLOB.command_positions) heads[++heads.len] = list("name" = name, "rank" = rank, "active" = isactive) department = 1 depthead = 1 if(rank == "Captain" && heads.len != 1) heads.Swap(1, heads.len) - if(real_rank in security_positions) + if(real_rank in GLOB.security_positions) sec[++sec.len] = list("name" = name, "rank" = rank, "active" = isactive) department = 1 if(depthead && sec.len != 1) sec.Swap(1, sec.len) - if(real_rank in engineering_positions) + if(real_rank in GLOB.engineering_positions) eng[++eng.len] = list("name" = name, "rank" = rank, "active" = isactive) department = 1 if(depthead && eng.len != 1) eng.Swap(1, eng.len) - if(real_rank in medical_positions) + if(real_rank in GLOB.medical_positions) med[++med.len] = list("name" = name, "rank" = rank, "active" = isactive) department = 1 if(depthead && med.len != 1) med.Swap(1, med.len) - if(real_rank in science_positions) + if(real_rank in GLOB.science_positions) sci[++sci.len] = list("name" = name, "rank" = rank, "active" = isactive) department = 1 if(depthead && sci.len != 1) sci.Swap(1, sci.len) - if(real_rank in service_positions) + if(real_rank in GLOB.service_positions) ser[++ser.len] = list("name" = name, "rank" = rank, "active" = isactive) department = 1 if(depthead && ser.len != 1) ser.Swap(1, ser.len) - if(real_rank in supply_positions) + if(real_rank in GLOB.supply_positions) sup[++sup.len] = list("name" = name, "rank" = rank, "active" = isactive) department = 1 if(depthead && sup.len != 1) sup.Swap(1, sup.len) - if(real_rank in nonhuman_positions) + if(real_rank in GLOB.nonhuman_positions) bot[++bot.len] = list("name" = name, "rank" = rank, "active" = isactive) department = 1 @@ -206,7 +206,7 @@ var/global/list/PDA_Manifest = list() misc[++misc.len] = list("name" = name, "rank" = rank, "active" = isactive) - PDA_Manifest = list(\ + GLOB.PDA_Manifest = list(\ "heads" = heads,\ "sec" = sec,\ "eng" = eng,\ @@ -226,12 +226,12 @@ var/global/list/PDA_Manifest = list() manifest_inject(H) /datum/datacore/proc/manifest_modify(name, assignment) - if(PDA_Manifest.len) - PDA_Manifest.Cut() + if(GLOB.PDA_Manifest.len) + GLOB.PDA_Manifest.Cut() var/datum/data/record/foundrecord var/real_title = assignment - for(var/datum/data/record/t in data_core.general) + for(var/datum/data/record/t in GLOB.data_core.general) if(t) if(t.fields["name"] == name) foundrecord = t @@ -250,10 +250,10 @@ var/global/list/PDA_Manifest = list() foundrecord.fields["rank"] = assignment foundrecord.fields["real_rank"] = real_title -var/record_id_num = 1001 +GLOBAL_VAR_INIT(record_id_num, 1001) /datum/datacore/proc/manifest_inject(mob/living/carbon/human/H) - if(PDA_Manifest.len) - PDA_Manifest.Cut() + if(GLOB.PDA_Manifest.len) + GLOB.PDA_Manifest.Cut() if(H.mind && (H.mind.assigned_role != H.mind.special_role)) var/assignment @@ -266,7 +266,7 @@ var/record_id_num = 1001 else assignment = "Unassigned" - var/id = num2hex(record_id_num++, 6) + var/id = num2hex(GLOB.record_id_num++, 6) //General Record @@ -624,7 +624,7 @@ var/record_id_num = 1001 clothes_s = new /icon('icons/mob/uniform.dmi', "syndicate_s") clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY) clothes_s.Blend(new /icon('icons/mob/hands.dmi', "swat_gl"), ICON_UNDERLAY) - else if(H.mind && H.mind.assigned_role in get_all_centcom_jobs()) + else if(H.mind && (H.mind.assigned_role in get_all_centcom_jobs())) clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s") clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY) else diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 00054349e36..6a183987a30 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -5,7 +5,7 @@ /// Status traits attached to this datum var/list/status_traits var/list/comp_lookup - var/list/signal_procs + var/list/list/datum/callback/signal_procs var/signal_enabled = FALSE var/datum_flags = NONE var/var_edited = FALSE //Warranty void if seal is broken diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 1defb9a6afa..b2b09003934 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -31,7 +31,7 @@ /datum/proc/vv_get_var(var_name) switch(var_name) - if("attack_log", "debug_log") + if("attack_log_old", "debug_log") return debug_variable(var_name, vars[var_name], 0, src, sanitize = FALSE) if("vars") return debug_variable(var_name, list(), 0, src) diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm index 63fa3af0605..81312cdfcc4 100644 --- a/code/datums/diseases/_MobProcs.dm +++ b/code/datums/diseases/_MobProcs.dm @@ -126,11 +126,19 @@ AddDisease(D) +/** + * Forces the mob to contract a virus. If the mob can have viruses. Ignores clothing and other protection + * Returns TRUE if it succeeds. False if it doesn't + * + * Arguments: + * * D - the disease the mob will try to contract + */ //Same as ContractDisease, except never overidden clothes checks /mob/proc/ForceContractDisease(datum/disease/D) if(!CanContractDisease(D)) - return 0 + return FALSE AddDisease(D) + return TRUE /mob/living/carbon/human/CanContractDisease(datum/disease/D) diff --git a/code/datums/diseases/_disease.dm b/code/datums/diseases/_disease.dm index 84dde0f22e0..6b7c2d89606 100644 --- a/code/datums/diseases/_disease.dm +++ b/code/datums/diseases/_disease.dm @@ -29,7 +29,7 @@ #define BIOHAZARD "BIOHAZARD THREAT!" -var/list/diseases = subtypesof(/datum/disease) +GLOBAL_LIST_INIT(diseases, subtypesof(/datum/disease)) /datum/disease diff --git a/code/datums/diseases/advance/advance.dm b/code/datums/diseases/advance/advance.dm index e0711d88e5f..9aeade59a1d 100644 --- a/code/datums/diseases/advance/advance.dm +++ b/code/datums/diseases/advance/advance.dm @@ -6,16 +6,15 @@ If you need help with creating new symptoms or expanding the advance disease, ask for Giacom on #coderbus. */ - -var/list/archive_diseases = list() +GLOBAL_LIST_EMPTY(archive_diseases) // The order goes from easy to cure to hard to cure. -var/list/advance_cures = list( +GLOBAL_LIST_INIT(advance_cures, list( "sodiumchloride", "sugar", "orangejuice", "spaceacillin", "salglu_solution", "ethanol", "teporone", "diphenhydramine", "lipolicide", "silver", "gold" - ) +)) /* @@ -132,7 +131,7 @@ var/list/advance_cures = list( // Generate symptoms. By default, we only choose non-deadly symptoms. var/list/possible_symptoms = list() - for(var/symp in list_symptoms) + for(var/symp in GLOB.list_symptoms) var/datum/symptom/S = new symp if(S.level >= level_min && S.level <= level_max) if(!HasSymptom(S)) @@ -158,13 +157,13 @@ var/list/advance_cures = list( AssignProperties(properties) id = null - if(!archive_diseases[GetDiseaseID()]) + if(!GLOB.archive_diseases[GetDiseaseID()]) if(new_name) AssignName() - archive_diseases[GetDiseaseID()] = src // So we don't infinite loop - archive_diseases[GetDiseaseID()] = new /datum/disease/advance(0, src, 1) + GLOB.archive_diseases[GetDiseaseID()] = src // So we don't infinite loop + GLOB.archive_diseases[GetDiseaseID()] = new /datum/disease/advance(0, src, 1) - var/datum/disease/advance/A = archive_diseases[GetDiseaseID()] + var/datum/disease/advance/A = GLOB.archive_diseases[GetDiseaseID()] AssignName(A.name) //Generate disease properties based on the effects. Returns an associated list. @@ -246,9 +245,9 @@ var/list/advance_cures = list( // Will generate a random cure, the less resistance the symptoms have, the harder the cure. /datum/disease/advance/proc/GenerateCure(list/properties = list()) if(properties && properties.len) - var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len) + var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, GLOB.advance_cures.len) // to_chat(world, "Res = [res]") - cures = list(advance_cures[res]) + cures = list(GLOB.advance_cures[res]) // Get the cure name from the cure_id var/datum/reagent/D = GLOB.chemical_reagents_list[cures[1]] @@ -371,7 +370,7 @@ var/list/advance_cures = list( var/list/symptoms = list() symptoms += "Done" - symptoms += list_symptoms.Copy() + symptoms += GLOB.list_symptoms.Copy() do if(user) var/symptom = input(user, "Choose a symptom to add ([i] remaining)", "Choose a Symptom") in symptoms @@ -397,7 +396,7 @@ var/list/advance_cures = list( for(var/datum/disease/advance/AD in GLOB.active_diseases) AD.Refresh() - for(var/mob/living/carbon/human/H in shuffle(GLOB.living_mob_list)) + for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list)) if(!is_station_level(H.z)) continue if(!H.HasDisease(D)) diff --git a/code/datums/diseases/advance/symptoms/deafness.dm b/code/datums/diseases/advance/symptoms/deafness.dm index 1a9bba6961e..a3111478b26 100644 --- a/code/datums/diseases/advance/symptoms/deafness.dm +++ b/code/datums/diseases/advance/symptoms/deafness.dm @@ -33,7 +33,7 @@ Bonus if(3, 4) to_chat(M, "[pick("You hear a ringing in your ear.", "Your ears pop.")]") if(5) - if(!(M.disabilities & DEAF)) + if(!(DEAF in M.mutations)) to_chat(M, "Your ears pop and begin ringing loudly!") M.BecomeDeaf() spawn(200) diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm index cf39d91a866..5759ab32de6 100644 --- a/code/datums/diseases/advance/symptoms/sensory.dm +++ b/code/datums/diseases/advance/symptoms/sensory.dm @@ -62,4 +62,4 @@ Bonus M.reagents.add_reagent("oculine", 20) else if(prob(SYMPTOM_ACTIVATION_PROB * 5)) - to_chat(M, "[pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.","Your ears feel great.","Your healing feels more acute.")]") + to_chat(M, "[pick("Your eyes feel great.","You feel like your eyes can focus more clearly.", "You don't feel the need to blink.","Your ears feel great.","Your hearing feels more acute.")]") diff --git a/code/datums/diseases/advance/symptoms/skin.dm b/code/datums/diseases/advance/symptoms/skin.dm index aa5a3494584..a3346dce800 100644 --- a/code/datums/diseases/advance/symptoms/skin.dm +++ b/code/datums/diseases/advance/symptoms/skin.dm @@ -35,7 +35,7 @@ BONUS switch(A.stage) if(5) H.s_tone = -85 - H.update_body(0) + H.update_body() else H.visible_message("[H] looks a bit pale...", "Your skin suddenly appears lighter...") @@ -79,7 +79,7 @@ BONUS switch(A.stage) if(5) H.s_tone = 85 - H.update_body(0) + H.update_body() else H.visible_message("[H] looks a bit dark...", "Your skin suddenly appears darker...") diff --git a/code/datums/diseases/advance/symptoms/symptoms.dm b/code/datums/diseases/advance/symptoms/symptoms.dm index f2c5beee400..8f72de7f599 100644 --- a/code/datums/diseases/advance/symptoms/symptoms.dm +++ b/code/datums/diseases/advance/symptoms/symptoms.dm @@ -1,6 +1,6 @@ // Symptoms are the effects that engineered advanced diseases do. -var/list/list_symptoms = subtypesof(/datum/symptom) +GLOBAL_LIST_INIT(list_symptoms, subtypesof(/datum/symptom)) /datum/symptom // Buffs/Debuffs the symptom has to the overall engineered disease. @@ -17,7 +17,7 @@ var/list/list_symptoms = subtypesof(/datum/symptom) var/id = "" /datum/symptom/New() - var/list/S = list_symptoms + var/list/S = GLOB.list_symptoms for(var/i = 1; i <= S.len; i++) if(type == S[i]) id = "[i]" diff --git a/code/datums/diseases/brainrot.dm b/code/datums/diseases/brainrot.dm index cacd229c429..02f36b532d7 100644 --- a/code/datums/diseases/brainrot.dm +++ b/code/datums/diseases/brainrot.dm @@ -30,7 +30,7 @@ affected_mob.emote("stare") if(prob(2)) affected_mob.emote("drool") - if(prob(10) && affected_mob.getBrainLoss()<=98)//shouldn't retard you to death now + if(prob(10) && affected_mob.getBrainLoss()<=98)//shouldn't brainpain you to death now affected_mob.adjustBrainLoss(2) if(prob(2)) to_chat(affected_mob, "Your try to remember something important...but can't.") @@ -40,7 +40,7 @@ affected_mob.emote("stare") if(prob(2)) affected_mob.emote("drool") - if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't retard you to death now + if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't brainpain you to death now affected_mob.adjustBrainLoss(3) if(prob(2)) to_chat(affected_mob, "Strange buzzing fills your head, removing all thoughts.") diff --git a/code/datums/diseases/critical.dm b/code/datums/diseases/critical.dm index e3ebc2cf905..3afb48ce534 100644 --- a/code/datums/diseases/critical.dm +++ b/code/datums/diseases/critical.dm @@ -6,12 +6,17 @@ if(prob(stage_prob)) stage = min(stage + 1, max_stages) + if(has_cure()) + cure() + return FALSE + return TRUE + +/datum/disease/critical/has_cure() for(var/C_id in cures) if(affected_mob.reagents.has_reagent(C_id)) if(prob(cure_chance)) - cure() - return FALSE - return TRUE + return TRUE + return FALSE /datum/disease/critical/shock name = "Shock" @@ -31,7 +36,7 @@ /datum/disease/critical/shock/stage_act() if(..()) - if(affected_mob.health >= 25) + if(affected_mob.health >= 25 && affected_mob.nutrition >= NUTRITION_LEVEL_HYPOGLYCEMIA) to_chat(affected_mob, "You feel better.") cure() return @@ -134,3 +139,64 @@ if(prob(5) && ishuman(affected_mob)) var/mob/living/carbon/human/H = affected_mob H.set_heartattack(TRUE) + +/datum/disease/critical/hypoglycemia + name = "Hypoglycemia" + form = "Medical Emergency" + max_stages = 3 + spread_flags = SPECIAL + spread_text = "The patient has low blood sugar." + cure_text = "Eating or administration of vitamins or nutrients" + viable_mobtypes = list(/mob/living/carbon/human) + stage_prob = 1 + severity = DANGEROUS + disease_flags = CURABLE + bypasses_immunity = TRUE + virus_heal_resistant = TRUE + +/datum/disease/critical/hypoglycemia/has_cure() + if(ishuman(affected_mob)) + var/mob/living/carbon/human/H = affected_mob + if(NO_HUNGER in H.dna.species.species_traits) + return TRUE + if(ismachine(H)) + return TRUE + return ..() + +/datum/disease/critical/hypoglycemia/stage_act() + if(..()) + if(affected_mob.nutrition > NUTRITION_LEVEL_HYPOGLYCEMIA) + to_chat(affected_mob, "You feel a lot better!") + cure() + return + switch(stage) + if(1) + if(prob(4)) + to_chat(affected_mob, "You feel hungry!") + if(prob(2)) + to_chat(affected_mob, "You have a headache!") + if(prob(2)) + to_chat(affected_mob, "You feel [pick("anxious", "depressed")]!") + if(2) + if(prob(4)) + to_chat(affected_mob, "You feel like everything is wrong with your life!") + if(prob(5)) + affected_mob.Slowed(rand(4, 16)) + to_chat(affected_mob, "You feel [pick("tired", "exhausted", "sluggish")].") + if(prob(5)) + affected_mob.Weaken(6) + affected_mob.Stuttering(10) + to_chat(affected_mob, "You feel [pick("numb", "confused", "dizzy", "lightheaded")].") + affected_mob.emote("collapse") + if(3) + if(prob(8)) + var/datum/disease/D = new /datum/disease/critical/shock + affected_mob.ForceContractDisease(D) + if(prob(12)) + affected_mob.Weaken(6) + affected_mob.Stuttering(10) + to_chat(affected_mob, "You feel [pick("numb", "confused", "dizzy", "lightheaded")].") + affected_mob.emote("collapse") + if(prob(12)) + to_chat(affected_mob, "You feel [pick("tired", "exhausted", "sluggish")].") + affected_mob.Slowed(rand(4, 16)) diff --git a/code/datums/diseases/wizarditis.dm b/code/datums/diseases/wizarditis.dm index 158324e72f1..bb85f62199a 100644 --- a/code/datums/diseases/wizarditis.dm +++ b/code/datums/diseases/wizarditis.dm @@ -9,7 +9,7 @@ viable_mobtypes = list(/mob/living/carbon/human) disease_flags = CAN_CARRY|CAN_RESIST|CURABLE permeability_mod = 0.75 - desc = "Some speculate, that this virus is the cause of Wizard Federation existance. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition." + desc = "Some speculate, that this virus is the cause of Wizard Federation existance. Subjects affected show the signs of dementia, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition." severity = HARMFUL required_organs = list(/obj/item/organ/external/head) diff --git a/code/datums/elements/_element.dm b/code/datums/elements/_element.dm new file mode 100644 index 00000000000..46a295f90be --- /dev/null +++ b/code/datums/elements/_element.dm @@ -0,0 +1,55 @@ +/** + * A holder for simple behaviour that can be attached to many different types + * + * Only one element of each type is instanced during game init. + * Otherwise acts basically like a lightweight component. + */ +/datum/element + /// Option flags for element behaviour + var/element_flags = NONE + /** + * The index of the first attach argument to consider for duplicate elements + * + * Is only used when flags contains [ELEMENT_BESPOKE] + * + * This is infinity so you must explicitly set this + */ + var/id_arg_index = INFINITY + +/// Activates the functionality defined by the element on the given target datum +/datum/element/proc/Attach(datum/target) + SHOULD_CALL_PARENT(1) + if(type == /datum/element) + return ELEMENT_INCOMPATIBLE + SEND_SIGNAL(target, COMSIG_ELEMENT_ATTACH, src) + if(element_flags & ELEMENT_DETACH) + RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach, override = TRUE) + +/// Deactivates the functionality defines by the element on the given datum +/datum/element/proc/Detach(datum/source, force) + SEND_SIGNAL(source, COMSIG_ELEMENT_DETACH, src) + SHOULD_CALL_PARENT(1) + UnregisterSignal(source, COMSIG_PARENT_QDELETING) + +/datum/element/Destroy(force) + if(!force) + return QDEL_HINT_LETMELIVE + SSdcs.elements_by_type -= type + return ..() + +//DATUM PROCS + +/// Finds the singleton for the element type given and attaches it to src +/datum/proc/_AddElement(list/arguments) + var/datum/element/ele = SSdcs.GetElement(arguments) + arguments[1] = src + if(ele.Attach(arglist(arguments)) == ELEMENT_INCOMPATIBLE) + CRASH("Incompatible [arguments[1]] assigned to a [type]! args: [json_encode(args)]") + +/** + * Finds the singleton for the element type given and detaches it from src + * You only need additional arguments beyond the type if you're using [ELEMENT_BESPOKE] + */ +/datum/proc/_RemoveElement(list/arguments) + var/datum/element/ele = SSdcs.GetElement(arguments) + ele.Detach(src) diff --git a/code/datums/elements/waddling.dm b/code/datums/elements/waddling.dm new file mode 100644 index 00000000000..6abe75b3923 --- /dev/null +++ b/code/datums/elements/waddling.dm @@ -0,0 +1,25 @@ +/datum/element/waddling + +/datum/element/waddling/Attach(datum/target) + . = ..() + if(!ismovableatom(target)) + return ELEMENT_INCOMPATIBLE + if(isliving(target)) + RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/LivingWaddle) + else + RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/Waddle) + +/datum/element/waddling/Detach(datum/source, force) + . = ..() + UnregisterSignal(source, COMSIG_MOVABLE_MOVED) + +/datum/element/waddling/proc/LivingWaddle(mob/living/target) + if(target.incapacitated() || target.lying) + return + Waddle(target) + +/datum/element/waddling/proc/Waddle(atom/movable/target) + animate(target, pixel_z = 4, time = 0) + var/prev_trans = matrix(target.transform) + animate(pixel_z = 0, transform = turn(target.transform, pick(-12, 0, 12)), time = 2) + animate(pixel_z = 0, transform = prev_trans, time = 0) diff --git a/code/datums/gas_mixture.dm b/code/datums/gas_mixture.dm index 35cc970aa67..63b70b512ee 100644 --- a/code/datums/gas_mixture.dm +++ b/code/datums/gas_mixture.dm @@ -645,7 +645,7 @@ What are the archived variables for? ((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen))) return 0 if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \ - ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) + ((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (carbon_dioxide > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide))) return 0 if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \ ((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins))) diff --git a/code/datums/helper_datums/global_iterator.dm b/code/datums/helper_datums/global_iterator.dm deleted file mode 100644 index 214045941b5..00000000000 --- a/code/datums/helper_datums/global_iterator.dm +++ /dev/null @@ -1,152 +0,0 @@ -/* -README: - -The global_iterator datum is supposed to provide a simple and robust way to -create some constantly "looping" processes with ability to stop and restart them at will. -Generally, the only thing you want to play with (meaning, redefine) is the process() proc. -It must contain all the things you want done. - -Control functions: - new - used to create datum. First argument (optional) - var list(to use in process() proc) as list, - second (optional) - autostart control. - If autostart == TRUE, the loop will be started immediately after datum creation. - - start(list/arguments) - starts the loop. Takes arguments(optional) as a list, which is then used - by process() proc. Returns null if datum already active, 1 if loop started succesfully and 0 if there's - an error in supplied arguments (not list or empty list). - - stop() - stops the loop. Returns null if datum is already inactive and 1 on success. - - set_delay(new_delay) - sets the delay between iterations. Pretty selfexplanatory. - Returns 0 on error(new_delay is not numerical), 1 otherwise. - - set_process_args(list/arguments) - passes the supplied arguments to the process() proc. - - active() - Returns 1 if datum is active, 0 otherwise. - - toggle() - toggles datum state. Returns new datum state (see active()). - -Misc functions: - - get_last_exec_time() - Returns the time of last iteration. - - get_last_exec_time_as_text() - Returns the time of last iteration as text - - -Control vars: - - delay - delay between iterations - - check_for_null - if equals TRUE, on each iteration the supplied arguments will be checked for nulls. - If some varible equals null (and null only), the loop is stopped. - Usefull, if some var unexpectedly becomes null - due to object deletion, for example. - Of course, you can also check the variables inside process() proc to prevent runtime errors. - -Data storage vars: - - result - stores the value returned by process() proc -*/ - -/datum/global_iterator - var/control_switch = 0 - var/delay = 10 - var/list/arg_list = new - var/last_exec = null - var/check_for_null = 1 - var/forbid_garbage = 0 - var/result - var/state = 0 - -/datum/global_iterator/New(list/arguments=null,autostart=1) - delay = delay>0?(delay):1 - if(forbid_garbage) //prevents garbage collection with tag != null - tag = "\ref[src]" - set_process_args(arguments) - if(autostart) - start() - return - -/datum/global_iterator/proc/main() - state = 1 - while(src && control_switch) - last_exec = world.timeofday - if(check_for_null && has_null_args()) - stop() - return 0 - result = process(arglist(arg_list)) - for(var/sleep_time=delay;sleep_time>0;sleep_time--) //uhh, this is ugly. But I see no other way to terminate sleeping proc. Such disgrace. - if(!control_switch) - return 0 - sleep(1) - return 0 - -/datum/global_iterator/proc/start(list/arguments=null) - if(active()) - return - if(arguments) - if(!set_process_args(arguments)) - return 0 - if(!state_check()) //the main loop is sleeping, wait for it to terminate. - return - control_switch = 1 - spawn() - state = main() - return 1 - -/datum/global_iterator/proc/stop() - if(!active()) - return - control_switch = 0 - spawn(-1) //report termination error but don't wait for state_check(). - state_check() - return 1 - -/datum/global_iterator/proc/state_check() - var/lag = 0 - while(state) - sleep(1) - if(++lag>10) - CRASH("The global_iterator loop \ref[src] failed to terminate in designated timeframe. This may be caused by server lagging.") - return 1 - -/datum/global_iterator/process() - return - -/datum/global_iterator/proc/active() - return control_switch - -/datum/global_iterator/proc/has_null_args() - if(null in arg_list) - return 1 - return 0 - - -/datum/global_iterator/proc/set_delay(new_delay) - if(isnum(new_delay)) - delay = max(1, round(new_delay)) - return 1 - else - return 0 - -/datum/global_iterator/proc/get_last_exec_time() - return (last_exec||0) - -/datum/global_iterator/proc/get_last_exec_time_as_text() - return (time2text(last_exec)||"Wasn't executed yet") - -/datum/global_iterator/proc/set_process_args(list/arguments) - if(arguments && istype(arguments, /list) && arguments.len) - arg_list = arguments - return 1 - else -// to_chat(world, "Invalid arguments supplied for [src.type], ref = \ref[src]") - return 0 - -/datum/global_iterator/proc/toggle_null_checks() - check_for_null = !check_for_null - return check_for_null - -/datum/global_iterator/proc/toggle() - if(!stop()) - start() - return active() diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm index 8a1e7576e7a..a54707842db 100644 --- a/code/datums/helper_datums/map_template.dm +++ b/code/datums/helper_datums/map_template.dm @@ -17,7 +17,7 @@ name = rename /datum/map_template/proc/preload_size(path) - var/bounds = maploader.load_map(file(path), 1, 1, 1, cropMap = 0, measureOnly = 1) + var/bounds = GLOB.maploader.load_map(file(path), 1, 1, 1, cropMap = 0, measureOnly = 1) if(bounds) width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1 height = bounds[MAP_MAXY] @@ -48,8 +48,8 @@ // This system will metaphorically snap in half (not postpone init everywhere) // if given a multi-z template // it might need to be adapted for that when that time comes - space_manager.add_dirt(placement.z) - var/list/bounds = maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1) + GLOB.space_manager.add_dirt(placement.z) + var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, cropMap = 1) if(!bounds) return 0 if(bot_left == null || top_right == null) @@ -58,7 +58,7 @@ if(ST_bot_left == null || ST_top_right == null) log_runtime(EXCEPTION("One of the smoothing corners is bust"), src) - space_manager.remove_dirt(placement.z) + GLOB.space_manager.remove_dirt(placement.z) late_setup_level( block(bot_left, top_right), block(ST_bot_left, ST_top_right)) @@ -108,7 +108,7 @@ for(var/map in flist(path)) if(cmptext(copytext(map, length(map) - 3), ".dmm")) var/datum/map_template/T = new(path = "[path][map]", rename = "[map]") - map_templates[T.name] = T + GLOB.map_templates[T.name] = T if(!config.disable_space_ruins) // so we don't unnecessarily clutter start-up preloadRuinTemplates() @@ -134,13 +134,13 @@ if(banned.Find(R.mappath)) continue - map_templates[R.name] = R - ruins_templates[R.name] = R + GLOB.map_templates[R.name] = R + GLOB.ruins_templates[R.name] = R if(istype(R, /datum/map_template/ruin/lavaland)) - lava_ruins_templates[R.name] = R + GLOB.lava_ruins_templates[R.name] = R if(istype(R, /datum/map_template/ruin/space)) - space_ruins_templates[R.name] = R + GLOB.space_ruins_templates[R.name] = R /proc/preloadShelterTemplates() for(var/item in subtypesof(/datum/map_template/shelter)) @@ -149,8 +149,8 @@ continue var/datum/map_template/shelter/S = new shelter_type() - shelter_templates[S.shelter_id] = S - map_templates[S.shelter_id] = S + GLOB.shelter_templates[S.shelter_id] = S + GLOB.map_templates[S.shelter_id] = S /proc/preloadShuttleTemplates() for(var/item in subtypesof(/datum/map_template/shuttle)) @@ -160,5 +160,5 @@ var/datum/map_template/shuttle/S = new shuttle_type() - shuttle_templates[S.shuttle_id] = S - map_templates[S.shuttle_id] = S + GLOB.shuttle_templates[S.shuttle_id] = S + GLOB.map_templates[S.shuttle_id] = S diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index b8684072c3f..369c01cce42 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -148,7 +148,6 @@ eye.eye_user = user eye.name = "Camera Eye ([user.name])" user.remote_control = eye - user.remote_view = 1 user.reset_perspective(eye) eye.setLoc(get_turf(H)) diff --git a/code/datums/hud.dm b/code/datums/hud.dm index f204465d7d6..50152c4873d 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -1,8 +1,8 @@ /* HUD DATUMS */ -var/global/list/all_huds = list() +GLOBAL_LIST_EMPTY(all_huds) ///GLOBAL HUD LIST -var/datum/atom_hud/huds = list( \ +GLOBAL_LIST_INIT(huds, list( \ DATA_HUD_SECURITY_BASIC = new/datum/atom_hud/data/human/security/basic(), \ DATA_HUD_SECURITY_ADVANCED = new/datum/atom_hud/data/human/security/advanced(), \ DATA_HUD_MEDICAL_BASIC = new/datum/atom_hud/data/human/medical/basic(), \ @@ -24,7 +24,7 @@ var/datum/atom_hud/huds = list( \ ANTAG_HUD_DEVIL = new/datum/atom_hud/antag/hidden(),\ ANTAG_HUD_EVENTMISC = new/datum/atom_hud/antag/hidden(),\ ANTAG_HUD_BLOB = new/datum/atom_hud/antag/hidden()\ - ) +)) /datum/atom_hud var/list/atom/hudatoms = list() //list of all atoms which display this hud @@ -33,14 +33,14 @@ var/datum/atom_hud/huds = list( \ /datum/atom_hud/New() - all_huds += src + GLOB.all_huds += src /datum/atom_hud/Destroy() for(var/v in hudusers) remove_hud_from(v) for(var/v in hudatoms) remove_from_hud(v) - all_huds -= src + GLOB.all_huds -= src return ..() /datum/atom_hud/proc/remove_hud_from(mob/M) @@ -99,7 +99,7 @@ var/datum/atom_hud/huds = list( \ serv_huds += serv.thrallhud - for(var/datum/atom_hud/hud in (all_huds|serv_huds))//|gang_huds)) + for(var/datum/atom_hud/hud in (GLOB.all_huds|serv_huds))//|gang_huds)) if(src in hud.hudusers) hud.add_hud_to(src) diff --git a/code/datums/log_record.dm b/code/datums/log_record.dm new file mode 100644 index 00000000000..9b7d52b5390 --- /dev/null +++ b/code/datums/log_record.dm @@ -0,0 +1,37 @@ +/datum/log_record + var/log_type // Type of log + var/raw_time // When did this happen? + var/what // What happened + var/who // Who did it + var/target // Who/what was targeted (can be a string) + var/turf/where // Where did it happen + +/datum/log_record/New(_log_type, _who, _what, _target, _where, _raw_time) + log_type = _log_type + + who = get_subject_text(_who) + what = _what + target = get_subject_text(_target) + if(!_where) + _where = get_turf(_who) + where = _where + if(!_raw_time) + _raw_time = world.time + raw_time = _raw_time + +/datum/log_record/proc/get_subject_text(subject) + if(ismob(subject) || isclient(subject) || istype(subject, /datum/mind)) + return key_name_admin(subject) + if(isatom(subject)) + var/atom/A = subject + return A.name + if(istype(subject, /datum)) + var/datum/D = subject + return D.type + return subject + +/proc/compare_log_record(datum/log_record/A, datum/log_record/B) + var/time_diff = A.raw_time - B.raw_time + if(!time_diff) // Same time + return cmp_text_asc(A.log_type, B.log_type) + return time_diff diff --git a/code/datums/log_viewer.dm b/code/datums/log_viewer.dm new file mode 100644 index 00000000000..67eb3d21d86 --- /dev/null +++ b/code/datums/log_viewer.dm @@ -0,0 +1,235 @@ +#define ALL_LOGS list(ATTACK_LOG, DEFENSE_LOG, CONVERSION_LOG, SAY_LOG, EMOTE_LOG, MISC_LOG) + +/datum/log_viewer + var/time_from = 0 + var/time_to = 4 HOURS // 4 Hours should be enough. INFINITY would screw the UI up + var/list/selected_mobs = list() // The mobs in question + var/list/selected_log_types = list() // The log types being searched for + + var/list/log_records = list() // Found and sorted records + +/datum/log_viewer/proc/clear_all() + selected_mobs.Cut() + selected_log_types.Cut() + time_from = initial(time_from) + time_to = initial(time_to) + log_records.Cut() + return + +/datum/log_viewer/proc/search() + log_records.Cut() // Empty the old results + var/list/invalid_mobs = list() + for(var/i in selected_mobs) + var/mob/M = i + if(!M || QDELETED(M)) + invalid_mobs |= M + continue + for(var/log_type in selected_log_types) + var/list/logs = M.logs[log_type] + var/len_logs = length(logs) + if(len_logs) + var/start_index = get_earliest_log_index(logs) + if(!start_index) // No log found that matches the starting time criteria + continue + var/end_index = get_latest_log_index(logs) + if(!end_index) // No log found that matches the end time criteria + continue + log_records.Add(logs.Copy(start_index, end_index + 1)) + + if(invalid_mobs.len) + to_chat(usr, "The search criteria contained invalid mobs. They have been removed from the criteria.") + for(var/i in invalid_mobs) + selected_mobs -= i // Cleanup + + log_records = sortTim(log_records, /proc/compare_log_record) + +/** Binary search like implementation to find the earliest log + * Returns the index of the earliest log using the time_from value for the given list of logs. + * It will return 0 if no log after time_from is found +*/ +/datum/log_viewer/proc/get_earliest_log_index(list/logs) + if(!time_from) + return 1 + var/start = 1 + var/end = length(logs) + var/mid + do + mid = round_down((end + start) / 2) + var/datum/log_record/L = logs[mid] + if(L.raw_time >= time_from) + end = mid + else + start = mid + while(end - start > 1) + var/datum/log_record/L = logs[end] + if(L.raw_time >= time_from) // Check if there is atleast one valid log + return end + return 0 + +/** Binary search like implementation to find the latest log + * Returns the index of the latest log using the time_to value (1 second is added to prevent rounding weirdness) for the given list of logs. + * It will return 0 if no log before time_to + 10 is found +*/ +/datum/log_viewer/proc/get_latest_log_index(list/logs) + if(world.time < time_to) + return length(logs) + + var/end = length(logs) + var/start = 1 + var/mid + var/max_time = time_to + 10 + do + mid = round((end + start) / 2 + 0.5) + var/datum/log_record/L = logs[mid] + if(L.raw_time >= max_time) + end = mid + else + start = mid + while(end - start > 1) + var/datum/log_record/L = logs[start] + if(L.raw_time < max_time) // Check if there is atleast one valid log + return start + return 0 + +/datum/log_viewer/proc/add_mob(mob/user, mob/M) + if(!M || !user) + return + selected_mobs |= M + + show_ui(user) + +/datum/log_viewer/proc/show_ui(mob/user) + var/all_log_types = ALL_LOGS + var/trStyleTop = "border-top:2px solid; border-bottom:2px solid; padding-top: 5px; padding-bottom: 5px;" + var/trStyle = "border-top:1px solid; border-bottom:1px solid; padding-top: 5px; padding-bottom: 5px;" + var/dat + dat += "" + dat += "
" + dat += "Time Search Range: [gameTimestamp(wtime = time_from)]" + dat += " To: [gameTimestamp(wtime = time_to)]" + dat += "
" + + dat += "Mobs being used:" + for(var/i in selected_mobs) + var/mob/M = i + if(QDELETED(M)) + selected_mobs -= i + continue + dat += "[M.name]" + dat += "Add Mob" + dat += "Clear All Mobs" + dat += "
" + + dat += "Log Types:" + for(var/i in all_log_types) + var/log_type = i + var/enabled = (log_type in selected_log_types) + var/text + var/style + if(enabled) + text = "[log_type]" + style = "background: [get_logtype_color(i)]" + else + text = log_type + + dat += "[text]" + + dat += "
" + dat += "Clear All Settings" + dat += "Search" + dat += "
" + + // Search results + var/tdStyleTime = "width:80px; text-align:center;" + var/tdStyleType = "width:80px; text-align:center;" + var/tdStyleWho = "width:300px; text-align:center;" + var/tdStyleWhere = "width:150px; text-align:center;" + dat += "
" + dat += "" + dat += "" + for(var/i in log_records) + var/datum/log_record/L = i + var/time = gameTimestamp(wtime = L.raw_time - 9.99) // The time rounds up for some reason. Will result in weird filtering results + + dat +="\ + \ + " + + dat += "
WhenTypeWhoWhatTargetWhere
[time][L.log_type][L.who][L.what][L.target][ADMIN_COORDJMP(L.where)]
" + dat += "
" + + var/datum/browser/popup = new(user, "Log viewer", "Log viewer", 1400, 600) + popup.set_content(dat) + popup.open() + +/datum/log_viewer/Topic(href, href_list) + if(href_list["start_time"]) + var/input = input(usr, "hh:mm:ss", "Start time", "00:00:00") as text|null + if(!input) + return + var/res = timeStampToNum(input) + if(res < 0) + to_chat(usr, "'[input]' is an invalid input value.") + return + time_from = res + show_ui(usr) + return + if(href_list["end_time"]) + var/input = input(usr, "hh:mm:ss", "End time", "04:00:00") as text|null + if(!input) + return + var/res = timeStampToNum(input) + if(res < 0) + to_chat(usr, "'[input]' is an invalid input value.") + return + time_to = res + + show_ui(usr) + return + if(href_list["search"]) + search(usr) + show_ui(usr) + return + if(href_list["clear_all"]) + clear_all(usr) + show_ui(usr) + return + if(href_list["clear_mobs"]) + selected_mobs.Cut() + show_ui(usr) + return + if(href_list["add_mob"]) + var/list/mobs = getpois(TRUE, TRUE) + var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a mob: ", mobs) + A.on_close(CALLBACK(src, .proc/add_mob, usr)) + return + if(href_list["remove_mob"]) + var/mob/M = locate(href_list["remove_mob"]) + if(M) + selected_mobs -= M + show_ui(usr) + return + if(href_list["toggle_log_type"]) + var/log_type = href_list["toggle_log_type"] + if(log_type in selected_log_types) + selected_log_types -= log_type + else + selected_log_types += log_type + show_ui(usr) + return + +/datum/log_viewer/proc/get_logtype_color(log_type) + switch(log_type) + if(ATTACK_LOG) + return "darkred" + if(DEFENSE_LOG) + return "chocolate" + if(CONVERSION_LOG) + return "indigo" + if(SAY_LOG) + return "teal" + if(EMOTE_LOG) + return "deepskyblue" + if(MISC_LOG) + return "gray" + return "slategray" diff --git a/code/datums/mind.dm b/code/datums/mind.dm index db2420a1bf8..7d3a73abf24 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -49,23 +49,19 @@ var/miming = 0 // Mime's vow of silence var/list/antag_datums var/speech_span // What span any body this mind has talks in. - var/datum/faction/faction //associated faction var/datum/changeling/changeling //changeling holder var/linglink var/datum/vampire/vampire //vampire holder var/datum/abductor/abductor //abductor holder - var/datum/devilinfo/devilinfo //devil holder var/antag_hud_icon_state = null //this mind's ANTAG_HUD should have this icon_state var/datum/atom_hud/antag/antag_hud = null //this mind's antag HUD var/datum/mindslaves/som //stands for slave or master...hush.. var/datum/devilinfo/devilinfo //Information about the devil, if any. - var/damnation_type = 0 - var/datum/mind/soulOwner //who owns the soul. Under normal circumstances, this will point to src + var/damnation_type = 0 + var/datum/mind/soulOwner //who owns the soul. Under normal circumstances, this will point to src var/hasSoul = TRUE - var/rev_cooldown = 0 - var/isholy = FALSE // is this person a chaplain or admin role allowed to use bibles var/isblessed = FALSE // is this person blessed by a chaplain? var/num_blessed = 0 // for prayers @@ -105,6 +101,14 @@ current.mind = null leave_all_huds() //leave all the huds in the old body, so it won't get huds if somebody else enters it + for(var/log_type in current.logs) // Copy the old logs + var/list/logs = current.logs[log_type] + if(new_character.logs[log_type]) + new_character.logs[log_type] += logs.Copy() // Append the old ones + new_character.logs[log_type] = sortTim(new_character.logs[log_type], /proc/compare_log_record) // Sort them on time + else + new_character.logs[log_type] = logs.Copy() // Just copy them + SSnanoui.user_transferred(current, new_character) if(new_character.mind) //remove any mind currently in our new body's mind variable @@ -539,7 +543,7 @@ var/mob/def_target = null var/objective_list[] = list(/datum/objective/assassinate, /datum/objective/protect, /datum/objective/debrain) if(objective&&(objective.type in objective_list) && objective:target) - def_target = objective:target.current + def_target = objective.target.current possible_targets = sortAtom(possible_targets) possible_targets += "Free objective" @@ -845,11 +849,11 @@ to_chat(current, "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [SSticker.cultdat.entity_title2] above all else. Bring It back.") log_admin("[key_name(usr)] has culted [key_name(current)]") message_admins("[key_name_admin(usr)] has culted [key_name_admin(current)]") - if(!summon_spots.len) - while(summon_spots.len < SUMMON_POSSIBILITIES) - var/area/summon = pick(return_sorted_areas() - summon_spots) + if(!GLOB.summon_spots.len) + while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES) + var/area/summon = pick(return_sorted_areas() - GLOB.summon_spots) if(summon && is_station_level(summon.z) && summon.valid_territory) - summon_spots += summon + GLOB.summon_spots += summon if("tome") var/mob/living/carbon/human/H = current if(istype(H)) @@ -902,7 +906,7 @@ log_admin("[key_name(usr)] has wizarded [key_name(current)]") message_admins("[key_name_admin(usr)] has wizarded [key_name_admin(current)]") if("lair") - current.forceMove(pick(wizardstart)) + current.forceMove(pick(GLOB.wizardstart)) log_admin("[key_name(usr)] has moved [key_name(current)] to the wizard's lair") message_admins("[key_name_admin(usr)] has moved [key_name_admin(current)] to the wizard's lair") if("dressup") @@ -1165,7 +1169,7 @@ remove_antag_datum(/datum/antagonist/traitor) log_admin("[key_name(usr)] has de-traitored [key_name(current)]") message_admins("[key_name_admin(usr)] has de-traitored [key_name_admin(current)]") - + if("traitor") if(!(has_antag_datum(/datum/antagonist/traitor))) var/datum/antagonist/traitor/T = new() @@ -1487,11 +1491,11 @@ special_role = SPECIAL_ROLE_WIZARD assigned_role = SPECIAL_ROLE_WIZARD //ticker.mode.learn_basic_spells(current) - if(!wizardstart.len) - current.loc = pick(latejoin) + if(!GLOB.wizardstart.len) + current.loc = pick(GLOB.latejoin) to_chat(current, "HOT INSERTION, GO GO GO") else - current.loc = pick(wizardstart) + current.loc = pick(GLOB.wizardstart) SSticker.mode.equip_wizard(current) for(var/obj/item/spellbook/S in current.contents) @@ -1659,7 +1663,7 @@ SSticker.mode.implanter[missionary.mind] = implanters SSticker.mode.traitors += src - + var/datum/objective/protect/zealot_objective = new zealot_objective.target = missionary.mind zealot_objective.owner = src @@ -1684,7 +1688,7 @@ if(H.w_uniform) jumpsuit = H.w_uniform jumpsuit.color = team_color - H.update_inv_w_uniform(0,0) + H.update_inv_w_uniform() add_attack_logs(missionary, current, "Converted to a zealot for [convert_duration/600] minutes") addtimer(CALLBACK(src, .proc/remove_zealot, jumpsuit), convert_duration) //deconverts after the timer expires @@ -1701,7 +1705,7 @@ jumpsuit.color = initial(jumpsuit.color) //reset the jumpsuit no matter where our mind is if(ishuman(current)) //but only try updating us if we are still a human type since it is a human proc var/mob/living/carbon/human/H = current - H.update_inv_w_uniform(0,0) + H.update_inv_w_uniform() to_chat(current, "You seem to have forgotten the events of the past 10 minutes or so, and your head aches a bit as if someone beat it savagely with a stick.") to_chat(current, "This means you don't remember who you were working for or what you were doing.") diff --git a/code/datums/mixed.dm b/code/datums/mixed.dm index 05fb0a99649..a5ff38a26b0 100644 --- a/code/datums/mixed.dm +++ b/code/datums/mixed.dm @@ -22,14 +22,14 @@ var/list/fields = list( ) /datum/data/record/Destroy() - if(src in data_core.medical) - data_core.medical -= src - if(src in data_core.security) - data_core.security -= src - if(src in data_core.general) - data_core.general -= src - if(src in data_core.locked) - data_core.locked -= src + if(src in GLOB.data_core.medical) + GLOB.data_core.medical -= src + if(src in GLOB.data_core.security) + GLOB.data_core.security -= src + if(src in GLOB.data_core.general) + GLOB.data_core.general -= src + if(src in GLOB.data_core.locked) + GLOB.data_core.locked -= src return ..() /datum/data/text diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm index 0887290a6f4..4d870e1296c 100644 --- a/code/datums/mutable_appearance.dm +++ b/code/datums/mutable_appearance.dm @@ -22,5 +22,4 @@ /mutable_appearance/clean/New() . = ..() alpha = 255 - opacity = 1 transform = null diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm index db5cca6e9ec..416c4f9c02d 100644 --- a/code/datums/outfits/outfit.dm +++ b/code/datums/outfits/outfit.dm @@ -1,5 +1,5 @@ /datum/outfit - var/name = "Naked" + var/name = "SOMEBODY FORGOT TO SET A NAME, NOTIFY A CODER" var/collect_not_del = FALSE var/uniform = null @@ -33,6 +33,9 @@ var/can_be_admin_equipped = TRUE // Set to FALSE if your outfit requires runtime parameters +/datum/outfit/naked + name = "Naked" + /datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE) //to be overriden for customization depending on client prefs,species etc return diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm index d2c19f61bfa..14bc959fbb1 100644 --- a/code/datums/outfits/outfit_admin.dm +++ b/code/datums/outfits/outfit_admin.dm @@ -541,7 +541,7 @@ P.attack_self(H) // activate them, display musical notes effect /datum/outfit/admin/soviet - + name = "Soviet Generic" gloves = /obj/item/clothing/gloves/combat uniform = /obj/item/clothing/under/soviet back = /obj/item/storage/backpack/satchel @@ -709,7 +709,8 @@ pda = /obj/item/pda backpack_contents = list( /obj/item/storage/box/survival = 1, - /obj/item/hand_labeler = 1 + /obj/item/hand_labeler = 1, + /obj/item/hand_labeler_refill = 1 ) /datum/outfit/admin/sol_trader/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) @@ -771,6 +772,7 @@ apply_to_card(I, H, get_all_accesses(), "Space Explorer") /datum/outfit/admin/hardsuit + name = "Hardsuit Generic" back = /obj/item/tank/jetpack/oxygen mask = /obj/item/clothing/mask/breath shoes = /obj/item/clothing/shoes/magboots @@ -823,6 +825,7 @@ /datum/outfit/admin/tournament + name = "Tournament Generic" suit = /obj/item/clothing/suit/armor/vest shoes = /obj/item/clothing/shoes/black head = /obj/item/clothing/head/helmet/thunderdome @@ -1048,8 +1051,8 @@ to_chat(H, "You have gained the ability to shapeshift into lesser hellhound form. This is a combat form with different abilities, tough but not invincible. It can regenerate itself over time by resting.") H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/raise_vampires) to_chat(H, "You have gained the ability to Raise Vampires. This extremely powerful AOE ability affects all humans near you. Vampires/thralls are healed. Corpses are raised as vampires. Others are stunned, then brain damaged, then killed.") - H.dna.SetSEState(JUMPBLOCK, 1) - genemutcheck(H, JUMPBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.jumpblock, 1) + genemutcheck(H, GLOB.jumpblock, null, MUTCHK_FORCED) H.update_mutations() H.gene_stability = 100 @@ -1100,7 +1103,7 @@ l_hand = null backpack_contents = list( /obj/item/storage/box/engineer = 1, - /obj/item/clothing/suit/space/hardsuit/shielded/wizard = 1, + /obj/item/clothing/suit/space/hardsuit/shielded/wizard/arch = 1, /obj/item/clothing/shoes/magboots = 1, /obj/item/kitchen/knife/ritual = 1, /obj/item/clothing/suit/wizrobe/red = 1, diff --git a/code/datums/outfits/plasmamen.dm b/code/datums/outfits/plasmamen.dm index 376bf2af90c..94206c0ae3a 100644 --- a/code/datums/outfits/plasmamen.dm +++ b/code/datums/outfits/plasmamen.dm @@ -176,3 +176,9 @@ head = /obj/item/clothing/head/helmet/space/plasmaman/blueshield uniform = /obj/item/clothing/under/plasmaman/blueshield + +/datum/outfit/plasmaman/wizard + name = "Wizard Plasmaman" + + head = /obj/item/clothing/head/helmet/space/plasmaman/wizard + uniform = /obj/item/clothing/under/plasmaman/wizard diff --git a/code/datums/periodic_news.dm b/code/datums/periodic_news.dm index 9a09ec4a7ec..d0d1f01ebf3 100644 --- a/code/datums/periodic_news.dm +++ b/code/datums/periodic_news.dm @@ -2,136 +2,125 @@ // Uses BYOND's type system to put everything into a nice format /datum/news_announcement - var - round_time // time of the round at which this should be announced, in seconds - message // body of the message - author = "Nanotrasen Editor" - channel_name = "Nyx Daily" - can_be_redacted = 0 - message_type = "Story" - revolution_inciting_event + var/round_time // time of the round at which this should be announced, in seconds + var/message // body of the message + var/author = "Nanotrasen Editor" + var/channel_name = "Nyx Daily" + var/can_be_redacted = FALSE + var/message_type = "Story" - paycuts_suspicion - round_time = 60*10 - message = {"Reports have leaked that Nanotrasen Inc. is planning to put paycuts into - effect on many of its Research Stations in Tau Ceti. Apparently these research - stations haven't been able to yield the expected revenue, and thus adjustments - have to be made."} - author = "Unauthorized" +/datum/news_announcement/revolution_inciting_event/paycuts_suspicion + round_time = 60*10 + message = {"Reports have leaked that Nanotrasen Inc. is planning to put paycuts into + effect on many of its Research Stations in Tau Ceti. Apparently these research + stations haven't been able to yield the expected revenue, and thus adjustments + have to be made."} + author = "Unauthorized" - paycuts_confirmation - round_time = 60*40 - message = {"Earlier rumours about paycuts on Research Stations in the Tau Ceti system have - been confirmed. Shockingly, however, the cuts will only affect lower tier - personnel. Heads of Staff will, according to our sources, not be affected."} - author = "Unauthorized" +/datum/news_announcement/revolution_inciting_event/paycuts_confirmation + round_time = 60*40 + message = {"Earlier rumours about paycuts on Research Stations in the Tau Ceti system have + been confirmed. Shockingly, however, the cuts will only affect lower tier + personnel. Heads of Staff will, according to our sources, not be affected."} + author = "Unauthorized" - human_experiments - round_time = 60*90 - message = {"Unbelievable reports about human experimentation have reached our ears. According - to a refugee from one of the Tau Ceti Research Stations, their station, in order - to increase revenue, has refactored several of their facilities to perform experiments - on live humans, including virology research, genetic manipulation, and \"feeding them - to the slimes to see what happens\". Allegedly, these test subjects were neither - humanified monkeys nor volunteers, but rather unqualified staff that were forced into - the experiments, and reported to have died in a \"work accident\" by Nanotrasen Inc."} - author = "Unauthorized" +/datum/news_announcement/revolution_inciting_event/human_experiments + round_time = 60*90 + message = {"Unbelievable reports about human experimentation have reached our ears. According + to a refugee from one of the Tau Ceti Research Stations, their station, in order + to increase revenue, has refactored several of their facilities to perform experiments + on live humans, including virology research, genetic manipulation, and \"feeding them + to the slimes to see what happens\". Allegedly, these test subjects were neither + humanified monkeys nor volunteers, but rather unqualified staff that were forced into + the experiments, and reported to have died in a \"work accident\" by Nanotrasen Inc."} + author = "Unauthorized" - bluespace_research +/datum/news_announcement/bluespace_research/announcement + round_time = 60*20 + message = {"The new field of research trying to explain several interesting spacetime oddities, + also known as \"Bluespace Research\", has reached new heights. Of the several + hundred space stations now orbiting in Tau Ceti, fifteen are now specially equipped + to experiment with and research Bluespace effects. Rumours have it some of these + stations even sport functional \"travel gates\" that can instantly move a whole research + team to an alternate reality."} - announcement - round_time = 60*20 - message = {"The new field of research trying to explain several interesting spacetime oddities, - also known as \"Bluespace Research\", has reached new heights. Of the several - hundred space stations now orbiting in Tau Ceti, fifteen are now specially equipped - to experiment with and research Bluespace effects. Rumours have it some of these - stations even sport functional \"travel gates\" that can instantly move a whole research - team to an alternate reality."} +/datum/news_announcement/random_junk/cheesy_honkers + author = "Assistant Editor Carl Ritz" + channel_name = "The Gibson Gazette" + message = {"Do cheesy honkers increase risk of having a miscarriage? Several health administrations + say so!"} + round_time = 60 * 15 - random_junk +/datum/news_announcement/random_junk/net_block + author = "Assistant Editor Carl Ritz" + channel_name = "The Gibson Gazette" + message = {"Several corporations banding together to block access to 'wetskrell.nt', site administrators + claiming violation of net laws."} + round_time = 60 * 50 - cheesy_honkers - author = "Assistant Editor Carl Ritz" - channel_name = "The Gibson Gazette" - message = {"Do cheesy honkers increase risk of having a miscarriage? Several health administrations - say so!"} - round_time = 60 * 15 +/datum/news_announcement/random_junk/found_ssd + channel_name = "Nyx Daily" + author = "Doctor Eric Hanfield" - net_block - author = "Assistant Editor Carl Ritz" - channel_name = "The Gibson Gazette" - message = {"Several corporations banding together to block access to 'wetskrell.nt', site administrators - claiming violation of net laws."} - round_time = 60 * 50 + message = {"Several people have been found unconscious at their terminals. It is thought that it was due + to a lack of sleep or of simply migraines from staring at the screen too long. Camera footage + reveals that many of them were playing games instead of working and their pay has been docked + accordingly."} + round_time = 60 * 90 - found_ssd - channel_name = "Nyx Daily" - author = "Doctor Eric Hanfield" +/datum/news_announcement/lotus_tree/explosions + channel_name = "Nyx Daily" + author = "Reporter Leland H. Howards" - message = {"Several people have been found unconscious at their terminals. It is thought that it was due - to a lack of sleep or of simply migraines from staring at the screen too long. Camera footage - reveals that many of them were playing games instead of working and their pay has been docked - accordingly."} - round_time = 60 * 90 + message = {"The newly-christened civillian transport Lotus Tree suffered two very large explosions near the + bridge today, and there are unconfirmed reports that the death toll has passed 50. The cause of + the explosions remain unknown, but there is speculation that it might have something to do with + the recent change of regulation in the Moore-Lee Corporation, a major funder of the ship, when M-L + announced that they were officially acknowledging inter-species marriage and providing couples + with marriage tax-benefits."} + round_time = 60 * 30 - lotus_tree +/datum/news_announcement/food_riots/breaking_news + channel_name = "Nyx Daily" + author = "Reporter Ro'kii Ar-Raqis" - explosions - channel_name = "Nyx Daily" - author = "Reporter Leland H. Howards" + message = {"Breaking news: Food riots have broken out throughout the Refuge asteroid colony in the Tenebrae + Lupus system. This comes only hours after Nanotrasen officials announced they will no longer trade with the + colony, citing the increased presence of \"hostile factions\" on the colony has made trade too dangerous to + continue. Nanotrasen officials have not given any details about said factions. More on that at the top of + the hour."} + round_time = 60 * 10 - message = {"The newly-christened civillian transport Lotus Tree suffered two very large explosions near the - bridge today, and there are unconfirmed reports that the death toll has passed 50. The cause of - the explosions remain unknown, but there is speculation that it might have something to do with - the recent change of regulation in the Moore-Lee Corporation, a major funder of the ship, when M-L - announced that they were officially acknowledging inter-species marriage and providing couples - with marriage tax-benefits."} - round_time = 60 * 30 +/datum/news_announcement/food_riots/more + channel_name = "Nyx Daily" + author = "Reporter Ro'kii Ar-Raqis" - food_riots + message = {"More on the Refuge food riots: The Refuge Council has condemned Nanotrasen's withdrawal from + the colony, claiming \"there has been no increase in anti-Nanotrasen activity\", and \"\[the only] reason + Nanotrasen withdrew was because the \[Tenebrae Lupus] system's Plasma deposits have been completely mined out. + We have little to trade with them now\". Nanotrasen officials have denied these allegations, calling them + \"further proof\" of the colony's anti-Nanotrasen stance. Meanwhile, Refuge Security has been unable to quell + the riots. More on this at 6."} + round_time = 60 * 60 +GLOBAL_LIST_INIT(newscaster_standard_feeds, list(/datum/news_announcement/bluespace_research, /datum/news_announcement/lotus_tree, /datum/news_announcement/random_junk, /datum/news_announcement/food_riots)) - breaking_news - channel_name = "Nyx Daily" - author = "Reporter Ro'kii Ar-Raqis" - - message = {"Breaking news: Food riots have broken out throughout the Refuge asteroid colony in the Tenebrae - Lupus system. This comes only hours after Nanotrasen officials announced they will no longer trade with the - colony, citing the increased presence of \"hostile factions\" on the colony has made trade too dangerous to - continue. Nanotrasen officials have not given any details about said factions. More on that at the top of - the hour."} - round_time = 60 * 10 - - more - channel_name = "Nyx Daily" - author = "Reporter Ro'kii Ar-Raqis" - - message = {"More on the Refuge food riots: The Refuge Council has condemned Nanotrasen's withdrawal from - the colony, claiming \"there has been no increase in anti-Nanotrasen activity\", and \"\[the only] reason - Nanotrasen withdrew was because the \[Tenebrae Lupus] system's Plasma deposits have been completely mined out. - We have little to trade with them now\". Nanotrasen officials have denied these allegations, calling them - \"further proof\" of the colony's anti-Nanotrasen stance. Meanwhile, Refuge Security has been unable to quell - the riots. More on this at 6."} - round_time = 60 * 60 - - -var/global/list/newscaster_standard_feeds = list(/datum/news_announcement/bluespace_research, /datum/news_announcement/lotus_tree, /datum/news_announcement/random_junk, /datum/news_announcement/food_riots) - -proc/process_newscaster() +/proc/process_newscaster() check_for_newscaster_updates(SSticker.mode.newscaster_announcements) -var/global/tmp/announced_news_types = list() -proc/check_for_newscaster_updates(type) +GLOBAL_LIST_EMPTY(announced_news_types) + +/proc/check_for_newscaster_updates(type) for(var/subtype in subtypesof(type)) var/datum/news_announcement/news = new subtype() - if(news.round_time * 10 <= world.time && !(subtype in announced_news_types)) - announced_news_types += subtype + if(news.round_time * 10 <= world.time && !(subtype in GLOB.announced_news_types)) + GLOB.announced_news_types += subtype announce_newscaster_news(news) -proc/announce_newscaster_news(datum/news_announcement/news) +/proc/announce_newscaster_news(datum/news_announcement/news) var/datum/feed_channel/sendto - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == news.channel_name) sendto = FC break @@ -142,7 +131,7 @@ proc/announce_newscaster_news(datum/news_announcement/news) sendto.author = news.author sendto.locked = 1 sendto.is_admin_channel = 1 - news_network.network_channels += sendto + GLOB.news_network.network_channels += sendto var/datum/feed_message/newMsg = new /datum/feed_message newMsg.author = news.author ? news.author : sendto.author @@ -152,5 +141,5 @@ proc/announce_newscaster_news(datum/news_announcement/news) sendto.messages += newMsg - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters) NEWSCASTER.newsAlert(news.channel_name) diff --git a/code/datums/radio.dm b/code/datums/radio.dm index b748a9f9229..efeebc7c973 100644 --- a/code/datums/radio.dm +++ b/code/datums/radio.dm @@ -1,7 +1,7 @@ /datum/radio_frequency var/frequency as num - var/list/list/obj/devices = list() + var/list/obj/devices = list() /datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, var/filter = null as text|null, var/range = null as num|null) var/turf/start_point @@ -108,7 +108,7 @@ . = "Domestic Animal" else . = "Unidentifiable" - + //callback used by objects to react to incoming radio signals /obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param) return null diff --git a/code/datums/spawners_menu.dm b/code/datums/spawners_menu.dm index 5cc76721377..a651edbc79c 100644 --- a/code/datums/spawners_menu.dm +++ b/code/datums/spawners_menu.dm @@ -6,7 +6,7 @@ qdel(src) owner = new_owner -/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = FALSE, datum/topic_state/state = ghost_state, datum/nanoui/master_ui = null) +/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = FALSE, datum/topic_state/state = GLOB.ghost_state, datum/nanoui/master_ui = null) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "spawners_menu.tmpl", "Spawners Menu", 700, 600, master_ui, state = state) diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 7f1541248d9..6b114971258 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -13,7 +13,7 @@ /obj/effect/proc_holder/singularity_pull() return -var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin verb for now +GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) /obj/effect/proc_holder/proc/InterceptClickOn(mob/living/user, params, atom/A) if(user.ranged_ability != src) @@ -241,7 +241,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin before_cast(targets) invocation() if(user && user.ckey) - user.create_attack_log("[key_name(user)] cast the spell [name].") + add_attack_logs(user, targets, "cast the spell [name]", ATKLOG_ALL) spawn(0) if(charge_type == "recharge" && recharge) start_recharge() diff --git a/code/datums/spells/area_teleport.dm b/code/datums/spells/area_teleport.dm index fbde291ae98..0d24a984014 100644 --- a/code/datums/spells/area_teleport.dm +++ b/code/datums/spells/area_teleport.dm @@ -25,14 +25,14 @@ var/A = null if(!randomise_selection) - A = input("Area to teleport to", "Teleport", A) as null|anything in teleportlocs + A = input("Area to teleport to", "Teleport", A) as null|anything in GLOB.teleportlocs else - A = pick(teleportlocs) + A = pick(GLOB.teleportlocs) if(!A) return - var/area/thearea = teleportlocs[A] + var/area/thearea = GLOB.teleportlocs[A] if(thearea.tele_proof && !istype(thearea, /area/wizard_station)) to_chat(usr, "A mysterious force disrupts your arcane spell matrix, and you remain where you are.") @@ -79,6 +79,8 @@ target.forceMove(pick(L)) playsound(get_turf(user), sound2, 50,1) + user.update_action_buttons_icon() //Update action buttons as some spells might now be castable + return /obj/effect/proc_holder/spell/targeted/area_teleport/invocation(area/chosenarea = null) diff --git a/code/datums/spells/banana_touch.dm b/code/datums/spells/banana_touch.dm index cbfa158531e..e8b7f27b0da 100644 --- a/code/datums/spells/banana_touch.dm +++ b/code/datums/spells/banana_touch.dm @@ -55,10 +55,10 @@ equip_to_slot_if_possible(new /obj/item/clothing/under/rank/clown/nodrop, slot_w_uniform, TRUE, TRUE) equip_to_slot_if_possible(new /obj/item/clothing/shoes/clown_shoes/nodrop, slot_shoes, TRUE, TRUE) equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/clown_hat/nodrop, slot_wear_mask, TRUE, TRUE) - dna.SetSEState(CLUMSYBLOCK, TRUE, TRUE) - dna.SetSEState(COMICBLOCK, TRUE, TRUE) - genemutcheck(src, CLUMSYBLOCK, null, MUTCHK_FORCED) - genemutcheck(src, COMICBLOCK, null, MUTCHK_FORCED) + dna.SetSEState(GLOB.clumsyblock, TRUE, TRUE) + dna.SetSEState(GLOB.comicblock, TRUE, TRUE) + genemutcheck(src, GLOB.clumsyblock, null, MUTCHK_FORCED) + genemutcheck(src, GLOB.comicblock, null, MUTCHK_FORCED) if(!(iswizard(src) || (mind && mind.special_role == SPECIAL_ROLE_WIZARD_APPRENTICE))) //Mutations are permanent on non-wizards. Can still be removed by genetics fuckery but not mutadone. - dna.default_blocks.Add(CLUMSYBLOCK) - dna.default_blocks.Add(COMICBLOCK) + dna.default_blocks.Add(GLOB.clumsyblock) + dna.default_blocks.Add(GLOB.comicblock) diff --git a/code/datums/spells/cluwne.dm b/code/datums/spells/cluwne.dm index 58a33e31a44..19a12055fef 100644 --- a/code/datums/spells/cluwne.dm +++ b/code/datums/spells/cluwne.dm @@ -27,8 +27,8 @@ var/obj/item/organ/internal/honktumor/cursed/tumor = new tumor.insert(src) mutations.Add(NERVOUS) - dna.SetSEState(NERVOUSBLOCK, 1, 1) - genemutcheck(src, NERVOUSBLOCK, null, MUTCHK_FORCED) + dna.SetSEState(GLOB.nervousblock, 1, 1) + genemutcheck(src, GLOB.nervousblock, null, MUTCHK_FORCED) rename_character(real_name, "cluwne") unEquip(w_uniform, 1) @@ -36,10 +36,10 @@ unEquip(gloves, 1) if(!istype(wear_mask, /obj/item/clothing/mask/cursedclown)) //Infinite loops otherwise unEquip(wear_mask, 1) - equip_to_slot_if_possible(new /obj/item/clothing/under/cursedclown, slot_w_uniform, 1, 1, 1) - equip_to_slot_if_possible(new /obj/item/clothing/gloves/cursedclown, slot_gloves, 1, 1, 1) - equip_to_slot_if_possible(new /obj/item/clothing/mask/cursedclown, slot_wear_mask, 1, 1, 1) - equip_to_slot_if_possible(new /obj/item/clothing/shoes/cursedclown, slot_shoes, 1, 1, 1) + equip_to_slot_if_possible(new /obj/item/clothing/under/cursedclown, slot_w_uniform, TRUE, TRUE) + equip_to_slot_if_possible(new /obj/item/clothing/gloves/cursedclown, slot_gloves, TRUE, TRUE) + equip_to_slot_if_possible(new /obj/item/clothing/mask/cursedclown, slot_wear_mask, TRUE, TRUE) + equip_to_slot_if_possible(new /obj/item/clothing/shoes/cursedclown, slot_shoes, TRUE, TRUE) /mob/living/carbon/human/proc/makeAntiCluwne() to_chat(src, "You don't feel very funny.") @@ -56,14 +56,14 @@ tumor.remove(src) else mutations.Remove(CLUMSY) - mutations.Remove(COMICBLOCK) - dna.SetSEState(CLUMSYBLOCK,0) - dna.SetSEState(COMICBLOCK,0) - genemutcheck(src, CLUMSYBLOCK, null, MUTCHK_FORCED) - genemutcheck(src, COMICBLOCK, null, MUTCHK_FORCED) + mutations.Remove(GLOB.comicblock) + dna.SetSEState(GLOB.clumsyblock,0) + dna.SetSEState(GLOB.comicblock,0) + genemutcheck(src, GLOB.clumsyblock, null, MUTCHK_FORCED) + genemutcheck(src, GLOB.comicblock, null, MUTCHK_FORCED) mutations.Remove(NERVOUS) - dna.SetSEState(NERVOUSBLOCK, 0) - genemutcheck(src, NERVOUSBLOCK, null, MUTCHK_FORCED) + dna.SetSEState(GLOB.nervousblock, 0) + genemutcheck(src, GLOB.nervousblock, null, MUTCHK_FORCED) var/obj/item/clothing/under/U = w_uniform unEquip(w_uniform, 1) @@ -83,5 +83,5 @@ unEquip(gloves, 1) qdel(G) - equip_to_slot_if_possible(new /obj/item/clothing/under/lawyer/black, slot_w_uniform, 1, 1, 1) - equip_to_slot_if_possible(new /obj/item/clothing/shoes/black, slot_shoes, 1, 1, 1) + equip_to_slot_if_possible(new /obj/item/clothing/under/lawyer/black, slot_w_uniform, TRUE, TRUE) + equip_to_slot_if_possible(new /obj/item/clothing/shoes/black, slot_shoes, TRUE, TRUE) diff --git a/code/datums/spells/devil.dm b/code/datums/spells/devil.dm index 12e2a44a8c1..27b2fcb8851 100644 --- a/code/datums/spells/devil.dm +++ b/code/datums/spells/devil.dm @@ -142,7 +142,6 @@ return 0 fakefire() forceMove(get_turf(src)) - reset_perspective() visible_message("[src] appears in a firey blaze!") playsound(get_turf(src), 'sound/misc/exit_blood.ogg', 100, 1, -1) spawn(15) diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm index 4f2c88b659d..f7d7a9bfb8d 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -56,7 +56,7 @@ qdel(holder) if(!QDELETED(target)) if(mobloc.density) - for(var/direction in alldirs) + for(var/direction in GLOB.alldirs) var/turf/T = get_step(mobloc, direction) if(T) if(target.Move(T)) diff --git a/code/datums/spells/genetic.dm b/code/datums/spells/genetic.dm index 3c2f997e461..d95c6212486 100644 --- a/code/datums/spells/genetic.dm +++ b/code/datums/spells/genetic.dm @@ -2,7 +2,6 @@ name = "Genetic" desc = "This spell inflicts a set of mutations and disabilities upon the target." - var/disabilities = 0 //bits var/list/mutations = list() //mutation strings var/duration = 100 //deciseconds /* @@ -20,16 +19,12 @@ for(var/mob/living/target in targets) for(var/x in mutations) target.mutations.Add(x) - /* if(x == HULK && ishuman(target)) - target:hulk_time=world.time + duration */ - target.disabilities |= disabilities target.update_mutations() //update target's mutation overlays var/mob/living/carbon/human/H = target if(ishuman(target)) H.update_body() spawn(duration) target.mutations.Remove(mutations) - target.disabilities &= ~disabilities target.update_mutations() if(ishuman(target)) H.update_body() diff --git a/code/datums/spells/horsemask.dm b/code/datums/spells/horsemask.dm index 2c000a0d232..0140fbdf951 100644 --- a/code/datums/spells/horsemask.dm +++ b/code/datums/spells/horsemask.dm @@ -43,6 +43,6 @@ "Your face burns up, and shortly after the fire you realise you have the face of a horse!") if(!target.unEquip(target.wear_mask)) qdel(target.wear_mask) - target.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1) + target.equip_to_slot_if_possible(magichead, slot_wear_mask, TRUE, TRUE) target.flash_eyes() diff --git a/code/datums/spells/knock.dm b/code/datums/spells/knock.dm index 95c16978638..dc2efcc1e91 100644 --- a/code/datums/spells/knock.dm +++ b/code/datums/spells/knock.dm @@ -51,7 +51,7 @@ if(is_station_level(A.z)) A.req_access = list() A.req_one_access = list() - command_announcement.Announce("We have removed all access requirements on your station's airlocks. You can thank us later!", "Greetings!", 'sound/misc/notice2.ogg', , , "Space Wizard Federation Message") + GLOB.command_announcement.Announce("We have removed all access requirements on your station's airlocks. You can thank us later!", "Greetings!", 'sound/misc/notice2.ogg', , , "Space Wizard Federation Message") else ..() return diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm index 9db46b517db..9175fd677fb 100644 --- a/code/datums/spells/lichdom.dm +++ b/code/datums/spells/lichdom.dm @@ -28,7 +28,7 @@ config.continuous_rounds = 0 return ..() -/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets,mob/user = usr) +/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets, mob/user = usr) if(!config.continuous_rounds) existence_stops_round_end = 1 config.continuous_rounds = 1 @@ -36,7 +36,7 @@ for(var/mob/M in targets) var/list/hand_items = list() if(iscarbon(M)) - hand_items = list(M.get_active_hand(),M.get_inactive_hand()) + hand_items = list(M.get_active_hand(), M.get_inactive_hand()) if(marked_item && !stat_allowed) //sanity, shouldn't happen without badminry marked_item = null @@ -74,12 +74,9 @@ var/mob/old_body = current_body var/turf/body_turf = get_turf(old_body) current_body = lich - lich.Weaken(10+10*resurrections) + lich.Weaken(10 + 10 * resurrections) ++resurrections - lich.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(lich), slot_shoes) - lich.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(lich), slot_w_uniform) - lich.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(lich), slot_wear_suit) - lich.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(lich), slot_head) + equip_lich(lich) if(old_body && old_body.loc) if(iscarbon(old_body)) @@ -95,7 +92,7 @@ if(!marked_item) //linking item to the spell message = "" for(var/obj/item in hand_items) - if(ABSTRACT in item.flags || NODROP in item.flags) + if((ABSTRACT in item.flags) || (NODROP in item.flags)) continue marked_item = item to_chat(M, "You begin to focus your very being into the [item.name]...") @@ -127,7 +124,10 @@ H.unEquip(H.head) H.unEquip(H.shoes) H.unEquip(H.head) - H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit) - H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), slot_shoes) - H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform) + equip_lich(H) + +/obj/effect/proc_holder/spell/targeted/lichdom/proc/equip_lich(mob/living/carbon/human/H) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform) diff --git a/code/datums/spells/mime.dm b/code/datums/spells/mime.dm index 31066001270..11b0a75b275 100644 --- a/code/datums/spells/mime.dm +++ b/code/datums/spells/mime.dm @@ -141,6 +141,7 @@ else user.mind.AddSpell(S) to_chat(user, "You flip through the pages. Your understanding of the boundaries of reality increases. You can cast [spellname]!") + user.create_log(MISC_LOG, "learned the spell [spellname] ([S])") user.create_attack_log("[key_name(user)] learned the spell [spellname] ([S]).") onlearned(user) diff --git a/code/datums/spells/mime_malaise.dm b/code/datums/spells/mime_malaise.dm index 1c212c62125..1765b2f5741 100644 --- a/code/datums/spells/mime_malaise.dm +++ b/code/datums/spells/mime_malaise.dm @@ -49,6 +49,6 @@ equip_to_slot_if_possible(new /obj/item/clothing/mask/gas/mime/nodrop, slot_wear_mask, TRUE, TRUE) equip_to_slot_if_possible(new /obj/item/clothing/under/mime/nodrop, slot_w_uniform, TRUE, TRUE) equip_to_slot_if_possible(new /obj/item/clothing/suit/suspenders/nodrop, slot_wear_suit, TRUE, TRUE) - dna.SetSEState(MUTEBLOCK , TRUE, TRUE) - genemutcheck(src, MUTEBLOCK , null, MUTCHK_FORCED) - dna.default_blocks.Add(MUTEBLOCK) + dna.SetSEState(GLOB.muteblock , TRUE, TRUE) + genemutcheck(src, GLOB.muteblock , null, MUTCHK_FORCED) + dna.default_blocks.Add(GLOB.muteblock) diff --git a/code/datums/spells/rathens.dm b/code/datums/spells/rathens.dm index b2d35ff5393..4d98be324b2 100644 --- a/code/datums/spells/rathens.dm +++ b/code/datums/spells/rathens.dm @@ -21,14 +21,14 @@ A.remove(H) A.forceMove(get_turf(H)) spawn() - A.throw_at(get_edge_target_turf(H, pick(alldirs)), rand(1, 10), 5) + A.throw_at(get_edge_target_turf(H, pick(GLOB.alldirs)), rand(1, 10), 5) H.visible_message("[H]'s [A.name] flies out of their body in a magical explosion!",\ "Your [A.name] flies out of your body in a magical explosion!") H.Weaken(2) else var/obj/effect/decal/cleanable/blood/gibs/G = new/obj/effect/decal/cleanable/blood/gibs(get_turf(H)) spawn() - G.throw_at(get_edge_target_turf(H, pick(alldirs)), rand(1, 10), 5) + G.throw_at(get_edge_target_turf(H, pick(GLOB.alldirs)), rand(1, 10), 5) H.apply_damage(10, BRUTE, "chest") to_chat(H, "You have no appendix, but something had to give! Holy shit, what was that?") H.Weaken(3) diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm index aaef2229856..2a8e1d94526 100644 --- a/code/datums/spells/summonitem.dm +++ b/code/datums/spells/summonitem.dm @@ -41,7 +41,7 @@ else message = "You must hold the desired item in your hands to mark it for recall." - else if(marked_item && marked_item in hand_items) //unlinking item to the spell + else if(marked_item && (marked_item in hand_items)) //unlinking item to the spell message = "You remove the mark on [marked_item] to use elsewhere." name = "Instant Summons" marked_item = null @@ -75,7 +75,7 @@ B.transfer_identity(C) C.death() add_attack_logs(target, C, "Magically debrained INTENT: [uppertext(target.a_intent)]")*/ - if(C.stomach_contents && item_to_retrieve in C.stomach_contents) + if(C.stomach_contents && (item_to_retrieve in C.stomach_contents)) C.stomach_contents -= item_to_retrieve for(var/X in C.bodyparts) var/obj/item/organ/external/part = X @@ -104,12 +104,12 @@ if(target.hand) //left active hand - if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, 0, 1, 1)) - if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, 0, 1, 1)) + if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, FALSE, TRUE)) + if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, FALSE, TRUE)) butterfingers = 1 else //right active hand - if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, 0, 1, 1)) - if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, 0, 1, 1)) + if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_r_hand, FALSE, TRUE)) + if(!target.equip_to_slot_if_possible(item_to_retrieve, slot_l_hand, FALSE, TRUE)) butterfingers = 1 if(butterfingers) item_to_retrieve.loc = target.loc diff --git a/code/datums/spells/touch_attacks.dm b/code/datums/spells/touch_attacks.dm index d656bccac4a..c242a1aa52f 100644 --- a/code/datums/spells/touch_attacks.dm +++ b/code/datums/spells/touch_attacks.dm @@ -27,12 +27,12 @@ var/hand_handled = 1 attached_hand = new hand_path(src) if(user.hand) //left active hand - if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, 0, 1, 1)) - if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, 0, 1, 1)) + if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, FALSE, TRUE)) + if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, FALSE, TRUE)) hand_handled = 0 else //right active hand - if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, 0, 1, 1)) - if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, 0, 1, 1)) + if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, FALSE, TRUE)) + if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, FALSE, TRUE)) hand_handled = 0 if(!hand_handled) qdel(attached_hand) diff --git a/code/datums/spells/wizard.dm b/code/datums/spells/wizard.dm index fb4b80ff69f..6a951ac66a0 100644 --- a/code/datums/spells/wizard.dm +++ b/code/datums/spells/wizard.dm @@ -97,11 +97,11 @@ /obj/effect/proc_holder/spell/targeted/genetic/mutate/cast(list/targets, mob/user = usr) for(var/mob/living/target in targets) - target.dna.SetSEState(HULKBLOCK, 1) - genemutcheck(target, HULKBLOCK, null, MUTCHK_FORCED) + target.dna.SetSEState(GLOB.hulkblock, 1) + genemutcheck(target, GLOB.hulkblock, null, MUTCHK_FORCED) spawn(duration) - target.dna.SetSEState(HULKBLOCK, 0) - genemutcheck(target, HULKBLOCK, null, MUTCHK_FORCED) + target.dna.SetSEState(GLOB.hulkblock, 0) + genemutcheck(target, GLOB.hulkblock, null, MUTCHK_FORCED) ..() /obj/effect/proc_holder/spell/targeted/smoke @@ -304,7 +304,7 @@ sound = 'sound/magic/blind.ogg' /obj/effect/proc_holder/spell/targeted/genetic/blind - disabilities = BLIND + mutations = list(BLINDNESS) duration = 300 sound = 'sound/magic/blind.ogg' diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 479694de4d7..61decede9bc 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -113,13 +113,13 @@ /datum/status_effect/hippocraticOath/on_apply() //Makes the user passive, it's in their oath not to harm! ADD_TRAIT(owner, TRAIT_PACIFISM, "hippocraticOath") - var/datum/atom_hud/H = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/H = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] H.add_hud_to(owner) return ..() /datum/status_effect/hippocraticOath/on_remove() REMOVE_TRAIT(owner, TRAIT_PACIFISM, "hippocraticOath") - var/datum/atom_hud/H = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/H = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] H.remove_hud_from(owner) /datum/status_effect/hippocraticOath/tick() @@ -190,7 +190,7 @@ L.adjustBrainLoss(-3.5) L.adjustCloneLoss(-1) //Becasue apparently clone damage is the bastion of all health if(ishuman(L)) - var/var/mob/living/carbon/human/H = L + var/mob/living/carbon/human/H = L for(var/obj/item/organ/external/E in H.bodyparts) if(prob(10)) E.mend_fracture() diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index db6aef6ea0e..d8b5e4d9cbe 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -107,7 +107,7 @@ if(needs_to_bleed) var/turf/T = get_turf(owner) new /obj/effect/temp_visual/bleed/explode(T) - for(var/d in alldirs) + for(var/d in GLOB.alldirs) new /obj/effect/temp_visual/dir_setting/bloodsplatter(T, d) playsound(T, "desceration", 200, 1, -1) owner.adjustBruteLoss(bleed_damage) diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm index 896f4f999a9..2580b1c9935 100644 --- a/code/datums/status_effects/status_effect.dm +++ b/code/datums/status_effects/status_effect.dm @@ -5,7 +5,7 @@ /datum/status_effect var/id = "effect" //Used for screen alerts. var/duration = -1 //How long the status effect lasts in DECISECONDS. Enter -1 for an effect that never ends unless removed through some means. - var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second. + var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second. Setting this to -1 will stop processing if duration is also unlimited. var/mob/living/owner //The mob affected by the status effect. var/status_type = STATUS_EFFECT_UNIQUE //How many of the effect can be on one mob, and what happens when you try to add another var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted @@ -31,7 +31,8 @@ var/obj/screen/alert/status_effect/A = owner.throw_alert(id, alert_type) A.attached_effect = src //so the alert can reference us, if it needs to linked_alert = A //so we can reference the alert, if we need to - START_PROCESSING(SSfastprocess, src) + if(duration > 0 || initial(tick_interval) > 0) //don't process if we don't care + START_PROCESSING(SSfastprocess, src) return TRUE /datum/status_effect/Destroy() @@ -41,6 +42,9 @@ LAZYREMOVE(owner.status_effects, src) on_remove() owner = null + if(linked_alert) + linked_alert.attached_effect = null + linked_alert = null return ..() /datum/status_effect/process() @@ -85,6 +89,13 @@ desc = "You don't feel any different..." var/datum/status_effect/attached_effect +/obj/screen/alert/status_effect/Destroy() + if(attached_effect) + attached_effect.linked_alert = null + attached_effect = null + return ..() + + ////////////////// // HELPER PROCS // ////////////////// diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index f17e9840e4f..a18a9d74f28 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -16,7 +16,7 @@ #define SUPPLY_MISC 8 #define SUPPLY_VEND 9 -var/list/all_supply_groups = list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY_ENGINEER,SUPPLY_MEDICAL,SUPPLY_SCIENCE,SUPPLY_ORGANIC,SUPPLY_MATERIALS,SUPPLY_MISC,SUPPLY_VEND) +GLOBAL_LIST_INIT(all_supply_groups, list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY_ENGINEER,SUPPLY_MEDICAL,SUPPLY_SCIENCE,SUPPLY_ORGANIC,SUPPLY_MATERIALS,SUPPLY_MISC,SUPPLY_VEND)) /proc/get_supply_group_name(var/cat) switch(cat) @@ -1204,7 +1204,7 @@ var/list/all_supply_groups = list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY_ENGINE containername = "hydroponics crate" announce_beacons = list("Hydroponics" = list("Hydroponics")) -/datum/supply_packs/misc/hydroponics/hydrotank +/datum/supply_packs/organic/hydroponics/hydrotank name = "Hydroponics Watertank Crate" contains = list(/obj/item/watertank) cost = 10 @@ -1434,6 +1434,8 @@ var/list/all_supply_groups = list(SUPPLY_EMERGENCY,SUPPLY_SECURITY,SUPPLY_ENGINE contains = list(/obj/structure/filingcabinet/chestdrawer, /obj/item/camera_film, /obj/item/hand_labeler, + /obj/item/hand_labeler_refill, + /obj/item/hand_labeler_refill, /obj/item/stack/tape_roll, /obj/item/paper_bin, /obj/item/pen, diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm index a5155cceb4a..a0c9a19e4b0 100644 --- a/code/datums/uplink_item.dm +++ b/code/datums/uplink_item.dm @@ -108,7 +108,6 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) return desc /datum/uplink_item/proc/buy(var/obj/item/uplink/hidden/U, var/mob/user) - ..() if(!istype(U)) return 0 diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm index 57d8c11f80b..558669df3c6 100644 --- a/code/datums/weather/weather_types/ash_storm.dm +++ b/code/datums/weather/weather_types/ash_storm.dm @@ -36,7 +36,7 @@ var/list/outside_areas = list() var/list/eligible_areas = list() for(var/z in impacted_z_levels) - eligible_areas += space_manager.areas_in_z["[z]"] + eligible_areas += GLOB.space_manager.areas_in_z["[z]"] for(var/i in 1 to eligible_areas.len) var/area/place = eligible_areas[i] if(place.outdoors) diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm index 85b8d3fd2af..2bfefa5624e 100644 --- a/code/datums/weather/weather_types/radiation_storm.dm +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -26,8 +26,8 @@ /datum/weather/rad_storm/telegraph() ..() status_alarm(TRUE) - pre_maint_all_access = maint_all_access - if(!maint_all_access) + pre_maint_all_access = GLOB.maint_all_access + if(!GLOB.maint_all_access) make_maint_all_access() @@ -51,7 +51,7 @@ /datum/weather/rad_storm/end() if(..()) return - priority_announcement.Announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert") + GLOB.priority_announcement.Announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert") status_alarm(FALSE) if(!pre_maint_all_access) revoke_maint_all_access() diff --git a/code/datums/wires/nuclearbomb.dm b/code/datums/wires/nuclearbomb.dm index 63687ad8839..3b8ff5db098 100644 --- a/code/datums/wires/nuclearbomb.dm +++ b/code/datums/wires/nuclearbomb.dm @@ -72,7 +72,7 @@ if(N.icon_state == "nuclearbomb2") N.icon_state = "nuclearbomb1" N.timing = 0 - bomb_set = 0 + GLOB.bomb_set = 0 if(NUCLEARBOMB_WIRE_LIGHT) N.lighthack = !N.lighthack diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm index 07cf919db2d..907e6a695e1 100644 --- a/code/datums/wires/wires.dm +++ b/code/datums/wires/wires.dm @@ -5,9 +5,9 @@ #define MAX_FLAG 65535 -var/list/same_wires = list() +GLOBAL_LIST_EMPTY(same_wires) // 12 colours, if you're adding more than 12 wires then add more colours here -var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown", "gold", "gray", "cyan", "navy", "purple", "pink") +GLOBAL_LIST_INIT(wireColours, list("red", "blue", "green", "black", "orange", "brown", "gold", "gray", "cyan", "navy", "purple", "pink")) /datum/wires @@ -39,11 +39,11 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown", // Get the same wires else // We don't have any wires to copy yet, generate some and then copy it. - if(!same_wires[holder_type]) + if(!GLOB.same_wires[holder_type]) GenerateWires() - same_wires[holder_type] = src.wires.Copy() + GLOB.same_wires[holder_type] = src.wires.Copy() else - var/list/wires = same_wires[holder_type] + var/list/wires = GLOB.same_wires[holder_type] src.wires = wires // Reference the wires list. /datum/wires/Destroy() @@ -51,7 +51,7 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown", return ..() /datum/wires/proc/GenerateWires() - var/list/colours_to_pick = wireColours.Copy() // Get a copy, not a reference. + var/list/colours_to_pick = GLOB.wireColours.Copy() // Get a copy, not a reference. var/list/indexes_to_pick = list() //Generate our indexes for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i) @@ -81,13 +81,13 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown", ui = new(user, src, ui_key, "wires.tmpl", holder.name, window_x, window_y) ui.open() -/datum/wires/ui_data(mob/user, ui_key = "main", datum/topic_state/state = physical_state) +/datum/wires/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.physical_state) var/data[0] var/list/replace_colours = null if(ishuman(user)) var/mob/living/carbon/human/H = user var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) - if(eyes && H.disabilities & COLOURBLIND) + if(eyes && (COLOURBLIND in H.mutations)) replace_colours = eyes.replace_colours diff --git a/code/defines/procs/AStar.dm b/code/defines/procs/AStar.dm index e593888c265..1f8c83f5f04 100644 --- a/code/defines/procs/AStar.dm +++ b/code/defines/procs/AStar.dm @@ -155,7 +155,7 @@ Actual Adjacent procs : var/list/L = new() var/turf/simulated/T - for(var/dir in cardinal) + for(var/dir in GLOB.cardinal) T = get_step(src,dir) if(!T || (simulated_only && !istype(T))) continue diff --git a/code/defines/procs/admin.dm b/code/defines/procs/admin.dm index b7036f9fbdc..fb8ca665906 100644 --- a/code/defines/procs/admin.dm +++ b/code/defines/procs/admin.dm @@ -7,7 +7,7 @@ /proc/key_name_helper(whom, include_name, include_link = FALSE, type = null) if(include_link != FALSE && include_link != TRUE) - log_runtime(EXCEPTION("Key_name was called with an incorrect include_link [include_link]"), src) + log_runtime(EXCEPTION("Key_name was called with an incorrect include_link [include_link]")) var/mob/M var/client/C diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm index 3a70d05029e..a2b80440ecb 100644 --- a/code/defines/procs/announce.dm +++ b/code/defines/procs/announce.dm @@ -1,7 +1,7 @@ -/var/datum/announcement/minor/minor_announcement = new() -/var/datum/announcement/priority/priority_announcement = new(do_log = 0) -/var/datum/announcement/priority/command/command_announcement = new(do_log = 0, do_newscast = 0) -/var/datum/announcement/priority/command/event/event_announcement = new(do_log = 0, do_newscast = 0) +GLOBAL_DATUM_INIT(minor_announcement, /datum/announcement/minor, new()) +GLOBAL_DATUM_INIT(priority_announcement, /datum/announcement/priority, new(do_log = 0)) +GLOBAL_DATUM_INIT(command_announcement, /datum/announcement/priority/command, new(do_log = 0, do_newscast = 0)) +GLOBAL_DATUM_INIT(event_announcement, /datum/announcement/priority/command/event, new(do_log = 0, do_newscast = 0)) /datum/announcement var/title = "Attention" diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm index 86862eb9fcc..76e5a1fd0a6 100644 --- a/code/defines/procs/dbcore.dm +++ b/code/defines/procs/dbcore.dm @@ -29,13 +29,6 @@ #define BLOB 14 // TODO: Investigate more recent type additions and see if I can handle them. - Nadrew - -// Deprecated! See global.dm for new configuration vars -/* -var/DB_SERVER = "" // This is the location of your MySQL server (localhost is USUALLY fine) -var/DB_PORT = 3306 // This is the port your MySQL server is running on (3306 is the default) -*/ - DBConnection var/_db_con // This variable contains a reference to the actual database connection. var/dbi // This variable is a string containing the DBI MySQL requires. diff --git a/code/defines/procs/radio.dm b/code/defines/procs/radio.dm index 84d3ddaae78..7c0dc4de7f8 100644 --- a/code/defines/procs/radio.dm +++ b/code/defines/procs/radio.dm @@ -24,62 +24,9 @@ return freq_text -/datum/reception - var/obj/machinery/message_server/message_server = null - var/telecomms_reception = TELECOMMS_RECEPTION_NONE - var/message = "" - -/datum/receptions - var/obj/machinery/message_server/message_server = null - var/sender_reception = TELECOMMS_RECEPTION_NONE - var/list/receiver_reception = new - /proc/get_message_server() - if(message_servers) - for(var/obj/machinery/message_server/MS in message_servers) + if(GLOB.message_servers) + for(var/obj/machinery/message_server/MS in GLOB.message_servers) if(MS.active) return MS return null - -/proc/check_signal(var/datum/signal/signal) - return signal && signal.data["done"] - -/proc/get_sender_reception(var/atom/sender, var/datum/signal/signal) - return check_signal(signal) ? TELECOMMS_RECEPTION_SENDER : TELECOMMS_RECEPTION_NONE - -/proc/get_receiver_reception(var/receiver, var/datum/signal/signal) - if(receiver && check_signal(signal)) - var/turf/pos = get_turf(receiver) - // Maybe should get tie-in to the space manager? - if(pos && (pos.z in signal.data["level"])) - return TELECOMMS_RECEPTION_RECEIVER - return TELECOMMS_RECEPTION_NONE - -/proc/get_reception(var/atom/sender, var/receiver, var/message = "", var/do_sleep = 1) - var/datum/reception/reception = new - - // check if telecomms I/O route 1459 is stable - reception.message_server = get_message_server() - - var/datum/signal/signal = sender.telecomms_process(do_sleep) // Be aware that this proc calls sleep, to simulate transmition delays - reception.telecomms_reception |= get_sender_reception(sender, signal) - reception.telecomms_reception |= get_receiver_reception(receiver, signal) - reception.message = signal && signal.data["compression"] > 0 ? Gibberish(message, signal.data["compression"] + 50) : message - - return reception - -/proc/get_receptions(var/atom/sender, var/list/atom/receivers, var/do_sleep = 1) - var/datum/receptions/receptions = new - receptions.message_server = get_message_server() - - var/datum/signal/signal - if(sender) - signal = sender.telecomms_process(do_sleep) - receptions.sender_reception = get_sender_reception(sender, signal) - - for(var/atom/receiver in receivers) - if(!signal) - signal = receiver.telecomms_process() - receptions.receiver_reception[receiver] = get_receiver_reception(receiver, signal) - - return receptions diff --git a/code/defines/procs/records.dm b/code/defines/procs/records.dm index 256ae51dbf2..a74680ec578 100644 --- a/code/defines/procs/records.dm +++ b/code/defines/procs/records.dm @@ -20,7 +20,7 @@ G.fields["religion"] = "Unknown" G.fields["photo_front"] = front G.fields["photo_side"] = side - data_core.general += G + GLOB.data_core.general += G qdel(dummy) return G @@ -36,11 +36,11 @@ R.fields["ma_crim"] = "None" R.fields["ma_crim_d"] = "No major crime convictions." R.fields["notes"] = "No notes." - data_core.security += R + GLOB.data_core.security += R return R /proc/find_security_record(field, value) - return find_record(field, value, data_core.security) + return find_record(field, value, GLOB.data_core.security) /proc/find_record(field, value, list/L) for(var/datum/data/record/R in L) diff --git a/code/defines/procs/statistics.dm b/code/defines/procs/statistics.dm index b2b643541ec..094e4f9ca2b 100644 --- a/code/defines/procs/statistics.dm +++ b/code/defines/procs/statistics.dm @@ -1,35 +1,3 @@ -/proc/sql_poll_players() - if(!config.sql_enabled) - return - var/playercount = 0 - for(var/mob/M in GLOB.player_list) - if(M.client) - playercount += 1 - establish_db_connection() - if(!dbcon.IsConnected()) - log_game("SQL ERROR during player polling. Failed to connect.") - else - var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("legacy_population")] (playercount, time) VALUES ([playercount], '[sqltime]')") - if(!query.Execute()) - var/err = query.ErrorMsg() - log_game("SQL ERROR during player polling. Error : \[[err]\]\n") - - -/proc/sql_poll_admins() - if(!config.sql_enabled) - return - var/admincount = GLOB.admins.len - establish_db_connection() - if(!dbcon.IsConnected()) - log_game("SQL ERROR during admin polling. Failed to connect.") - else - var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("legacy_population")] (admincount, time) VALUES ([admincount], '[sqltime]')") - if(!query.Execute()) - var/err = query.ErrorMsg() - log_game("SQL ERROR during admin polling. Error : \[[err]\]\n") - /proc/sql_report_round_start() // TODO if(!config.sql_enabled) @@ -67,10 +35,10 @@ var/coord = "[H.x], [H.y], [H.z]" // to_chat(world, "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.getBrainLoss()], [H.getOxyLoss()])") establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) log_game("SQL ERROR during death reporting. Failed to connect.") else - var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.getBrainLoss()], [H.getOxyLoss()], '[coord]')") + var/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.getBrainLoss()], [H.getOxyLoss()], '[coord]')") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") @@ -102,42 +70,33 @@ var/coord = "[H.x], [H.y], [H.z]" // to_chat(world, "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])") establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) log_game("SQL ERROR during death reporting. Failed to connect.") else - var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.getBrainLoss()], [H.getOxyLoss()], '[coord]')") + var/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.getBrainLoss()], [H.getOxyLoss()], '[coord]')") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during death reporting. Error : \[[err]\]\n") -/proc/statistic_cycle() - if(!config.sql_enabled) - return - while(1) - sql_poll_players() - sleep(600) - sql_poll_admins() - sleep(6000) //Poll every ten minutes - //This proc is used for feedback. It is executed at round end. /proc/sql_commit_feedback() - if(!blackbox) + if(!GLOB.blackbox) log_game("Round ended without a blackbox recorder. No feedback was sent to the database.") return //content is a list of lists. Each item in the list is a list with two fields, a variable name and a value. Items MUST only have these two values. - var/list/datum/feedback_variable/content = blackbox.get_round_feedback() + var/list/datum/feedback_variable/content = GLOB.blackbox.get_round_feedback() if(!content) log_game("Round ended without any feedback being generated. No feedback was sent to the database.") return establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) log_game("SQL ERROR during feedback reporting. Failed to connect.") else - var/DBQuery/max_query = dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM [format_table_name("feedback")]") + var/DBQuery/max_query = GLOB.dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM [format_table_name("feedback")]") max_query.Execute() var/newroundid @@ -157,7 +116,7 @@ var/variable = item.get_variable() var/value = item.get_value() - var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("feedback")] (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')") + var/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("feedback")] (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR during feedback reporting. Error : \[[err]\]\n") diff --git a/code/defines/vox_sounds.dm b/code/defines/vox_sounds.dm index bb155337502..1d7bb9753a0 100644 --- a/code/defines/vox_sounds.dm +++ b/code/defines/vox_sounds.dm @@ -1,7 +1,7 @@ // List is required to compile the resources into the game when it loads. // Dynamically loading it has bad results with sounds overtaking each other, even with the wait variable. -var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', +GLOBAL_LIST_INIT(vox_sounds, list("," = 'sound/vox_fem/,.ogg', "." = 'sound/vox_fem/..ogg', "a" = 'sound/vox_fem/a.ogg', "abortions" = 'sound/vox_fem/abortions.ogg', @@ -1267,4 +1267,4 @@ var/list/vox_sounds = list("," = 'sound/vox_fem/,.ogg', "zero" = 'sound/vox_fem/zero.ogg', "zone" = 'sound/vox_fem/zone.ogg', "zulu" = 'sound/vox_fem/zulu.ogg' -) +)) diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 97eca30cbfe..edfae8fd53e 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -15,30 +15,30 @@ NOTE: there are two lists of areas in the end of this file: centcom and station /*Adding a wizard area teleport list because motherfucking lag -- Urist*/ /*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/ -var/list/teleportlocs = list() +GLOBAL_LIST_EMPTY(teleportlocs) /hook/startup/proc/process_teleport_locs() for(var/area/AR in world) if(AR.no_teleportlocs) continue - if(teleportlocs.Find(AR.name)) continue + if(GLOB.teleportlocs.Find(AR.name)) continue var/turf/picked = safepick(get_area_turfs(AR.type)) if(picked && is_station_level(picked.z)) - teleportlocs += AR.name - teleportlocs[AR.name] = AR + GLOB.teleportlocs += AR.name + GLOB.teleportlocs[AR.name] = AR - teleportlocs = sortAssoc(teleportlocs) + GLOB.teleportlocs = sortAssoc(GLOB.teleportlocs) return 1 -var/list/ghostteleportlocs = list() +GLOBAL_LIST_EMPTY(ghostteleportlocs) /hook/startup/proc/process_ghost_teleport_locs() for(var/area/AR in world) - if(ghostteleportlocs.Find(AR.name)) continue + if(GLOB.ghostteleportlocs.Find(AR.name)) continue var/list/turfs = get_area_turfs(AR.type) if(turfs.len) - ghostteleportlocs += AR.name - ghostteleportlocs[AR.name] = AR + GLOB.ghostteleportlocs += AR.name + GLOB.ghostteleportlocs[AR.name] = AR - ghostteleportlocs = sortAssoc(ghostteleportlocs) + GLOB.ghostteleportlocs = sortAssoc(GLOB.ghostteleportlocs) return 1 @@ -2109,14 +2109,11 @@ var/list/ghostteleportlocs = list() /area/tcommsat ambientsounds = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg') -/area/tcommsat/entrance - name = "\improper Telecoms Teleporter" - icon_state = "tcomsatentrance" - /area/tcommsat/chamber name = "\improper Telecoms Central Compartment" icon_state = "tcomsatcham" +// These areas are needed for MetaStation's AI sat /area/turret_protected/tcomsat name = "\improper Telecoms Satellite" icon_state = "tcomsatlob" @@ -2285,7 +2282,7 @@ var/list/ghostteleportlocs = list() */ // CENTCOM -var/list/centcom_areas = list ( +GLOBAL_LIST_INIT(centcom_areas, list( /area/centcom, /area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, @@ -2294,10 +2291,10 @@ var/list/centcom_areas = list ( /area/shuttle/transport1, /area/shuttle/administration/centcom, /area/shuttle/specops/centcom, -) +)) //SPACE STATION 13 -var/list/the_station_areas = list ( +GLOBAL_LIST_INIT(the_station_areas, list( /area/shuttle/arrival, /area/shuttle/escape, /area/shuttle/escape_pod1/station, @@ -2344,4 +2341,4 @@ var/list/the_station_areas = list ( /area/turret_protected/ai_upload, //do not try to simplify to "/area/turret_protected" --rastaf0 /area/turret_protected/ai_upload_foyer, /area/turret_protected/ai, -) +)) diff --git a/code/game/area/ai_monitored.dm b/code/game/area/ai_monitored.dm index 2ca607921ff..8f65ac634f4 100644 --- a/code/game/area/ai_monitored.dm +++ b/code/game/area/ai_monitored.dm @@ -3,16 +3,14 @@ var/obj/machinery/camera/motioncamera = null -/area/ai_monitored/New() - ..() +/area/ai_monitored/LateInitialize() + . = ..() // locate and store the motioncamera - spawn (20) // spawn on a delay to let turfs/objs load - for(var/obj/machinery/camera/M in src) - if(M.isMotion()) - motioncamera = M - M.area_motion = src - return - return + for(var/obj/machinery/camera/M in src) + if(M.isMotion()) + motioncamera = M + M.area_motion = src + break /area/ai_monitored/Entered(atom/movable/O) ..() diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index dbc0a8c567b..6ad45532641 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -110,7 +110,7 @@ /area/proc/reg_in_areas_in_z() if(contents.len) - var/list/areas_in_z = space_manager.areas_in_z + var/list/areas_in_z = GLOB.space_manager.areas_in_z var/z for(var/i in 1 to contents.len) var/atom/thing = contents[i] @@ -155,9 +155,9 @@ for(var/obj/machinery/alarm/AA in src) AA.update_icon() - air_alarm_repository.update_cache(src) + GLOB.air_alarm_repository.update_cache(src) return 1 - air_alarm_repository.update_cache(src) + GLOB.air_alarm_repository.update_cache(src) return 0 /area/proc/air_doors_close() @@ -434,7 +434,7 @@ else // There's a gravity generator on our z level // This would do well when integrated with the z level manager - if(T && gravity_generators["[T.z]"] && length(gravity_generators["[T.z]"])) + if(T && GLOB.gravity_generators["[T.z]"] && length(GLOB.gravity_generators["[T.z]"])) return 1 return 0 diff --git a/code/game/atoms.dm b/code/game/atoms.dm index f9d66372df5..abd224e409b 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -52,8 +52,8 @@ //its inherent color, the colored paint applied on it, special color effect etc... /atom/New(loc, ...) - if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New() - _preloader.load(src) + if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New() + GLOB._preloader.load(src) . = ..() attempt_init(arglist(args)) @@ -202,9 +202,7 @@ else return null -/atom/proc/check_eye(user as mob) - if(istype(user, /mob/living/silicon/ai)) // WHYYYY - return 1 +/atom/proc/check_eye(user) return /atom/proc/on_reagent_change() @@ -397,6 +395,17 @@ /atom/proc/get_spooked() return +/** + Base proc, intended to be overriden. + + This should only be called from one place: inside the slippery component. + Called after a human mob slips on this atom. + + If you want the person who slipped to have something special done to them, put it here. +*/ +/atom/proc/after_slip(mob/living/carbon/human/H) + return + /atom/proc/add_hiddenprint(mob/living/M as mob) if(isnull(M)) return if(isnull(M.key)) return @@ -516,7 +525,7 @@ A.fingerprintshidden |= fingerprintshidden.Copy() //admin A.fingerprintslast = fingerprintslast -var/list/blood_splatter_icons = list() +GLOBAL_LIST_EMPTY(blood_splatter_icons) /atom/proc/blood_splatter_index() return "\ref[initial(icon)]-[initial(icon_state)]" @@ -618,19 +627,19 @@ var/list/blood_splatter_icons = list() if(wear_suit) wear_suit.add_blood(blood_dna, color) wear_suit.blood_color = color - update_inv_wear_suit(1) + update_inv_wear_suit() else if(w_uniform) w_uniform.add_blood(blood_dna, color) w_uniform.blood_color = color - update_inv_w_uniform(1) + update_inv_w_uniform() if(head) head.add_blood(blood_dna, color) head.blood_color = color - update_inv_head(0,0) + update_inv_head() if(glasses) glasses.add_blood(blood_dna, color) glasses.blood_color = color - update_inv_glasses(0) + update_inv_glasses() if(gloves) var/obj/item/clothing/gloves/G = gloves G.add_blood(blood_dna, color) @@ -642,20 +651,20 @@ var/list/blood_splatter_icons = list() transfer_blood_dna(blood_dna) verbs += /mob/living/carbon/human/proc/bloody_doodle - update_inv_gloves(1) //handles bloody hands overlays and updating + update_inv_gloves() //handles bloody hands overlays and updating return 1 /obj/item/proc/add_blood_overlay(color) if(initial(icon) && initial(icon_state)) //try to find a pre-processed blood-splatter. otherwise, make a new one var/index = blood_splatter_index() - var/icon/blood_splatter_icon = blood_splatter_icons[index] + var/icon/blood_splatter_icon = GLOB.blood_splatter_icons[index] if(!blood_splatter_icon) blood_splatter_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply blood-splatters to the initial icon_state for each object blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent) blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY) //adds blood and the remaining white areas become transparant blood_splatter_icon = fcopy_rsc(blood_splatter_icon) - blood_splatter_icons[index] = blood_splatter_icon + GLOB.blood_splatter_icons[index] = blood_splatter_icon blood_overlay = image(blood_splatter_icon) blood_overlay.color = color @@ -722,12 +731,12 @@ var/list/blood_splatter_icons = list() this.icon_state = "vomittox_[pick(1,4)]" /atom/proc/get_global_map_pos() - if(!islist(global_map) || isemptylist(global_map)) return + if(!islist(GLOB.global_map) || isemptylist(GLOB.global_map)) return var/cur_x = null var/cur_y = null var/list/y_arr = null - for(cur_x=1,cur_x<=global_map.len,cur_x++) - y_arr = global_map[cur_x] + for(cur_x=1,cur_x<=GLOB.global_map.len,cur_x++) + y_arr = GLOB.global_map[cur_x] cur_y = y_arr.Find(src.z) if(cur_y) break @@ -795,7 +804,7 @@ var/list/blood_splatter_icons = list() return /atom/vv_edit_var(var_name, var_value) - if(!Debug2) + if(!GLOB.debug2) admin_spawned = TRUE . = ..() switch(var_name) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 0370fad0367..70926d7ba2b 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,6 +1,7 @@ /atom/movable layer = 3 appearance_flags = TILE_BOUND + glide_size = 8 // Default, adjusted when mobs move based on their movement delays var/last_move = null var/anchored = 0 var/move_resist = MOVE_RESIST_DEFAULT @@ -36,8 +37,8 @@ /atom/movable/attempt_init(loc, ...) var/turf/T = get_turf(src) - if(T && SSatoms.initialized != INITIALIZATION_INSSATOMS && space_manager.is_zlevel_dirty(T.z)) - space_manager.postpone_init(T.z, src) + if(T && SSatoms.initialized != INITIALIZATION_INSSATOMS && GLOB.space_manager.is_zlevel_dirty(T.z)) + GLOB.space_manager.postpone_init(T.z, src) return . = ..() @@ -131,13 +132,14 @@ /atom/movable/proc/setLoc(var/T, var/teleported=0) loc = T -/atom/movable/Move(atom/newloc, direct = 0) +/atom/movable/Move(atom/newloc, direct = 0, movetime) if(!loc || !newloc) return 0 var/atom/oldloc = loc if(loc != newloc) + glide_for(movetime) if(!(direct & (direct - 1))) //Cardinal move - . = ..() + . = ..(newloc, direct) // don't pass up movetime else //Diagonal move, split it into cardinal moves moving_diagonally = FIRST_DIAG_STEP var/first_step_dir @@ -203,7 +205,7 @@ src.move_speed = world.time - src.l_move_time src.l_move_time = world.time - if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct)) //movement failed due to buckled mob + if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct, movetime)) //movement failed due to buckled mob . = 0 // Called after a successful Move(). By this point, we've already moved @@ -216,6 +218,15 @@ update_parallax_contents() return TRUE +// Change glide size for the duration of one movement +/atom/movable/proc/glide_for(movetime) + if(movetime) + glide_size = world.icon_size/max(DS2TICKS(movetime), 1) + spawn(movetime) + glide_size = initial(glide_size) + else + glide_size = initial(glide_size) + // Previously known as HasEntered() // This is automatically called when something enters your square /atom/movable/Crossed(atom/movable/AM, oldloc) @@ -319,7 +330,6 @@ SSspacedrift.processing[src] = src return 1 - //called when src is thrown into hit_atom /atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum) set waitfor = 0 @@ -428,10 +438,10 @@ /atom/movable/proc/water_act(volume, temperature, source, method = REAGENT_TOUCH) //amount of water acting : temperature of water in kelvin : object that called it (for shennagins) return TRUE -/atom/movable/proc/handle_buckled_mob_movement(newloc,direct) +/atom/movable/proc/handle_buckled_mob_movement(newloc,direct,movetime) for(var/m in buckled_mobs) var/mob/living/buckled_mob = m - if(!buckled_mob.Move(newloc, direct)) + if(!buckled_mob.Move(newloc, direct, movetime)) forceMove(buckled_mob.loc) last_move = buckled_mob.last_move inertia_dir = last_move diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 71e6867280c..08a7b77daff 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -7,10 +7,10 @@ /* DATA HUD DATUMS */ /atom/proc/add_to_all_human_data_huds() - for(var/datum/atom_hud/data/human/hud in huds) hud.add_to_hud(src) + for(var/datum/atom_hud/data/human/hud in GLOB.huds) hud.add_to_hud(src) /atom/proc/remove_from_all_data_huds() - for(var/datum/atom_hud/data/hud in huds) hud.remove_from_hud(src) + for(var/datum/atom_hud/data/hud in GLOB.huds) hud.remove_from_hud(src) /datum/atom_hud/data @@ -142,7 +142,7 @@ //called when a human changes suit sensors /mob/living/carbon/proc/update_suit_sensors() - var/datum/atom_hud/data/human/medical/basic/B = huds[DATA_HUD_MEDICAL_BASIC] + var/datum/atom_hud/data/human/medical/basic/B = GLOB.huds[DATA_HUD_MEDICAL_BASIC] B.update_suit_sensors(src) @@ -220,22 +220,31 @@ var/perpname = get_visible_name(TRUE) //gets the name of the perp, works if they have an id or if their face is uncovered if(!SSticker) return //wait till the game starts or the monkeys runtime.... if(perpname) - var/datum/data/record/R = find_record("name", perpname, data_core.security) + var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security) if(R) switch(R.fields["criminal"]) - if("*Execute*") + if(SEC_RECORD_STATUS_EXECUTE) holder.icon_state = "hudexecute" return - if("*Arrest*") + if(SEC_RECORD_STATUS_ARREST) holder.icon_state = "hudwanted" return - if("Incarcerated") + if(SEC_RECORD_STATUS_SEARCH) + holder.icon_state = "hudsearch" + return + if(SEC_RECORD_STATUS_MONITOR) + holder.icon_state = "hudmonitor" + return + if(SEC_RECORD_STATUS_DEMOTE) + holder.icon_state = "huddemote" + return + if(SEC_RECORD_STATUS_INCARCERATED) holder.icon_state = "hudprisoner" return - if("Parolled") + if(SEC_RECORD_STATUS_PAROLLED) holder.icon_state = "hudparolled" return - if("Released") + if(SEC_RECORD_STATUS_RELEASED) holder.icon_state = "hudreleased" return holder.icon_state = null diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index e6d80529651..1a92210f570 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -4,91 +4,35 @@ * @author N3X15 */ -// What each index means: -#define DNA_OFF_LOWERBOUND 1 // changed as lists start at 1 not 0 -#define DNA_OFF_UPPERBOUND 2 -#define DNA_ON_LOWERBOUND 3 -#define DNA_ON_UPPERBOUND 4 - -// Define block bounds (off-low,off-high,on-low,on-high) -// Used in setupgame.dm -#define DNA_DEFAULT_BOUNDS list(1,2049,2050,4095) -#define DNA_HARDER_BOUNDS list(1,3049,3050,4095) -#define DNA_HARD_BOUNDS list(1,3490,3500,4095) - -// UI Indices (can change to mutblock style, if desired) -#define DNA_UI_HAIR_R 1 -#define DNA_UI_HAIR_G 2 -#define DNA_UI_HAIR_B 3 -#define DNA_UI_HAIR2_R 4 -#define DNA_UI_HAIR2_G 5 -#define DNA_UI_HAIR2_B 6 -#define DNA_UI_BEARD_R 7 -#define DNA_UI_BEARD_G 8 -#define DNA_UI_BEARD_B 9 -#define DNA_UI_BEARD2_R 10 -#define DNA_UI_BEARD2_G 11 -#define DNA_UI_BEARD2_B 12 -#define DNA_UI_SKIN_TONE 13 -#define DNA_UI_SKIN_R 14 -#define DNA_UI_SKIN_G 15 -#define DNA_UI_SKIN_B 16 -#define DNA_UI_HACC_R 17 -#define DNA_UI_HACC_G 18 -#define DNA_UI_HACC_B 19 -#define DNA_UI_HEAD_MARK_R 20 -#define DNA_UI_HEAD_MARK_G 21 -#define DNA_UI_HEAD_MARK_B 22 -#define DNA_UI_BODY_MARK_R 23 -#define DNA_UI_BODY_MARK_G 24 -#define DNA_UI_BODY_MARK_B 25 -#define DNA_UI_TAIL_MARK_R 26 -#define DNA_UI_TAIL_MARK_G 27 -#define DNA_UI_TAIL_MARK_B 28 -#define DNA_UI_EYES_R 29 -#define DNA_UI_EYES_G 30 -#define DNA_UI_EYES_B 31 -#define DNA_UI_GENDER 32 -#define DNA_UI_BEARD_STYLE 33 -#define DNA_UI_HAIR_STYLE 34 -/*#define DNA_UI_BACC_STYLE 23*/ -#define DNA_UI_HACC_STYLE 35 -#define DNA_UI_HEAD_MARK_STYLE 36 -#define DNA_UI_BODY_MARK_STYLE 37 -#define DNA_UI_TAIL_MARK_STYLE 38 -#define DNA_UI_LENGTH 38 // Update this when you add something, or you WILL break shit. - -#define DNA_SE_LENGTH 55 // Was STRUCDNASIZE, size 27. 15 new blocks added = 42, plus room to grow. - // Defines which values mean "on" or "off". // This is to make some of the more OP superpowers a larger PITA to activate, // and to tell our new DNA datum which values to set in order to turn something // on or off. -var/global/list/dna_activity_bounds[DNA_SE_LENGTH] -var/global/list/assigned_gene_blocks[DNA_SE_LENGTH] +GLOBAL_LIST_INIT(dna_activity_bounds, new(DNA_SE_LENGTH)) +GLOBAL_LIST_INIT(assigned_gene_blocks, new(DNA_SE_LENGTH)) // Used to determine what each block means (admin hax and species stuff on /vg/, mostly) -var/global/list/assigned_blocks[DNA_SE_LENGTH] +GLOBAL_LIST_INIT(assigned_blocks, new(DNA_SE_LENGTH)) -var/global/list/datum/dna/gene/dna_genes[0] +GLOBAL_LIST_EMPTY(dna_genes) -var/global/list/good_blocks[0] -var/global/list/bad_blocks[0] +GLOBAL_LIST_EMPTY(good_blocks) +GLOBAL_LIST_EMPTY(bad_blocks) /datum/dna // READ-ONLY, GETS OVERWRITTEN // DO NOT FUCK WITH THESE OR BYOND WILL EAT YOUR FACE - var/uni_identity="" // Encoded UI - var/struc_enzymes="" // Encoded SE - var/unique_enzymes="" // MD5 of player name + var/uni_identity = "" // Encoded UI + var/struc_enzymes = "" // Encoded SE + var/unique_enzymes = "" // MD5 of player name // Original Encoded SE, for use with Ryetalin - var/struc_enzymes_original="" // Encoded SE + var/struc_enzymes_original = "" // Encoded SE var/list/SE_original[DNA_SE_LENGTH] // Internal dirtiness checks - var/dirtyUI=0 - var/dirtySE=0 + var/dirtyUI = 0 + var/dirtySE = 0 // Okay to read, but you're an idiot if you do. // BLOCK = VALUE @@ -106,10 +50,10 @@ var/global/list/bad_blocks[0] // USE THIS WHEN COPYING STUFF OR YOU'LL GET CORRUPTION! /datum/dna/proc/Clone() var/datum/dna/new_dna = new() - new_dna.unique_enzymes=unique_enzymes - new_dna.struc_enzymes_original=struc_enzymes_original // will make clone's SE the same as the original, do we want this? + new_dna.unique_enzymes = unique_enzymes + new_dna.struc_enzymes_original = struc_enzymes_original // will make clone's SE the same as the original, do we want this? new_dna.blood_type = blood_type - new_dna.real_name=real_name + new_dna.real_name = real_name new_dna.species = new species.type for(var/b=1;b<=DNA_SE_LENGTH;b++) new_dna.SE[b]=SE[b] @@ -124,17 +68,17 @@ var/global/list/bad_blocks[0] /////////////////////////////////////// // Create random UI. -/datum/dna/proc/ResetUI(var/defer=0) +/datum/dna/proc/ResetUI(defer = FALSE) for(var/i=1,i<=DNA_UI_LENGTH,i++) switch(i) if(DNA_UI_SKIN_TONE) - SetUIValueRange(DNA_UI_SKIN_TONE,rand(1,220),220,1) // Otherwise, it gets fucked + SetUIValueRange(DNA_UI_SKIN_TONE, rand(1, 220), 220, 1) // Otherwise, it gets fucked else UI[i]=rand(0,4095) if(!defer) UpdateUI() -/datum/dna/proc/ResetUIFrom(var/mob/living/carbon/human/character) +/datum/dna/proc/ResetUIFrom(mob/living/carbon/human/character) // INITIALIZE! ResetUI(1) // Hair @@ -191,83 +135,90 @@ var/global/list/bad_blocks[0] UpdateUI() // Set a DNA UI block's raw value. -/datum/dna/proc/SetUIValue(var/block,var/value,var/defer=0) - if(block<=0) return - ASSERT(value>0) - ASSERT(value<=4095) +/datum/dna/proc/SetUIValue(block, value, defer = FALSE) + if(block <= 0) + return + ASSERT(value > 0) + ASSERT(value <= 4095) UI[block]=value - dirtyUI=1 + dirtyUI = 1 if(!defer) UpdateUI() // Get a DNA UI block's raw value. -/datum/dna/proc/GetUIValue(var/block) - if(block<=0) return 0 +/datum/dna/proc/GetUIValue(block) + if(block <= 0) + return FALSE return UI[block] // Set a DNA UI block's value, given a value and a max possible value. // Used in hair and facial styles (value being the index and maxvalue being the len of the hairstyle list) -/datum/dna/proc/SetUIValueRange(var/block,var/value,var/maxvalue,var/defer=0) - if(block<=0) +/datum/dna/proc/SetUIValueRange(block, value, maxvalue, defer = FALSE) + if(block <= 0) return if(value == 0) value = 1 - ASSERT(maxvalue<=4095) + ASSERT(maxvalue <= 4095) var/range = (4095 / maxvalue) if(value) - SetUIValue(block,round(value * range),defer) + SetUIValue(block,round(value * range), defer) // Getter version of above. -/datum/dna/proc/GetUIValueRange(var/block,var/maxvalue) - if(block<=0) return 0 +/datum/dna/proc/GetUIValueRange(block, maxvalue) + if(block <= 0) + return FALSE var/value = GetUIValue(block) - return round(1 +(value / 4096)*maxvalue) + return round(1 + (value / 4096) * maxvalue) // Is the UI gene "on" or "off"? // For UI, this is simply a check of if the value is > 2050. -/datum/dna/proc/GetUIState(var/block) - if(block<=0) return +/datum/dna/proc/GetUIState(block) + if(block <= 0) + return return UI[block] > 2050 // Set UI gene "on" (1) or "off" (0) -/datum/dna/proc/SetUIState(var/block,var/on,var/defer=0) - if(block<=0) return +/datum/dna/proc/SetUIState(block, on, defer = FALSE) + if(block <= 0) + return var/val if(on) - val=rand(2050,4095) + val = rand(2050, 4095) else - val=rand(1,2049) - SetUIValue(block,val,defer) + val=rand(1, 2049) + SetUIValue(block, val, defer) // Get a hex-encoded UI block. -/datum/dna/proc/GetUIBlock(var/block) +/datum/dna/proc/GetUIBlock(block) return EncodeDNABlock(GetUIValue(block)) // Do not use this unless you absolutely have to. // Set a block from a hex string. This is inefficient. If you can, use SetUIValue(). // Used in DNA modifiers. -/datum/dna/proc/SetUIBlock(var/block,var/value,var/defer=0) - if(block<=0) return - return SetUIValue(block,hex2num(value),defer) +/datum/dna/proc/SetUIBlock(block, value, defer = FALSE) + if(block <= 0) + return + return SetUIValue(block, hex2num(value), defer) // Get a sub-block from a block. -/datum/dna/proc/GetUISubBlock(var/block,var/subBlock) - return copytext(GetUIBlock(block),subBlock,subBlock+1) +/datum/dna/proc/GetUISubBlock(block, subBlock) + return copytext(GetUIBlock(block), subBlock, subBlock + 1) // Do not use this unless you absolutely have to. // Set a block from a hex string. This is inefficient. If you can, use SetUIValue(). // Used in DNA modifiers. -/datum/dna/proc/SetUISubBlock(var/block,var/subBlock, var/newSubBlock, var/defer=0) - if(block<=0) return - var/oldBlock=GetUIBlock(block) - var/newBlock="" - for(var/i=1, i<=length(oldBlock), i++) +/datum/dna/proc/SetUISubBlock(block, subBlock, newSubBlock, defer = FALSE) + if(block <= 0) + return + var/oldBlock = GetUIBlock(block) + var/newBlock = "" + for(var/i = 1, i <= length(oldBlock), i++) if(i==subBlock) - newBlock+=newSubBlock + newBlock += newSubBlock else - newBlock+=copytext(oldBlock,i,i+1) - SetUIBlock(block,newBlock,defer) + newBlock += copytext(oldBlock, i, i + 1) + SetUIBlock(block, newBlock, defer) /////////////////////////////////////// // STRUCTURAL ENZYMES @@ -276,126 +227,134 @@ var/global/list/bad_blocks[0] // "Zeroes out" all of the blocks. /datum/dna/proc/ResetSE() for(var/i = 1, i <= DNA_SE_LENGTH, i++) - SetSEValue(i,rand(1,1024),1) + SetSEValue(i, rand(1, 1024), 1) UpdateSE() // Set a DNA SE block's raw value. -/datum/dna/proc/SetSEValue(var/block,var/value,var/defer=0) +/datum/dna/proc/SetSEValue(block, value, defer = FALSE) - if(block<=0) return - ASSERT(value>=0) - ASSERT(value<=4095) - SE[block]=value - dirtySE=1 + if(block<=0) + return + ASSERT(value >= 0) + ASSERT(value <= 4095) + SE[block] = value + dirtySE = 1 if(!defer) UpdateSE() //testing("SetSEBlock([block],[value],[defer]): [value] -> [GetSEValue(block)]") // Get a DNA SE block's raw value. -/datum/dna/proc/GetSEValue(var/block) - if(block<=0) return 0 +/datum/dna/proc/GetSEValue(block) + if(block <= 0) + return FALSE return SE[block] // Set a DNA SE block's value, given a value and a max possible value. // Might be used for species? -/datum/dna/proc/SetSEValueRange(var/block,var/value,var/maxvalue) - if(block<=0) return - ASSERT(maxvalue<=4095) +/datum/dna/proc/SetSEValueRange(block, value, maxvalue) + if(block <= 0) + return + ASSERT(maxvalue <= 4095) var/range = round(4095 / maxvalue) if(value) - SetSEValue(block, value * range - rand(1,range-1)) + SetSEValue(block, value * range - rand(1, range - 1)) // Getter version of above. -/datum/dna/proc/GetSEValueRange(var/block,var/maxvalue) - if(block<=0) return 0 +/datum/dna/proc/GetSEValueRange(block, maxvalue) + if(block <= 0) + return FALSE var/value = GetSEValue(block) - return round(1 +(value / 4096)*maxvalue) + return round(1 + (value / 4096) * maxvalue) // Is the block "on" (1) or "off" (0)? (Un-assigned genes are always off.) -/datum/dna/proc/GetSEState(var/block) - if(block<=0) return 0 - var/list/BOUNDS=GetDNABounds(block) - var/value=GetSEValue(block) +/datum/dna/proc/GetSEState(block) + if(block <= 0) + return FALSE + var/list/BOUNDS = GetDNABounds(block) + var/value = GetSEValue(block) return (value >= BOUNDS[DNA_ON_LOWERBOUND]) // Set a block "on" or "off". -/datum/dna/proc/SetSEState(var/block,var/on,var/defer=0) - if(block<=0) return +/datum/dna/proc/SetSEState(block, on, defer = FALSE) + if(block <= 0) + return var/list/BOUNDS=GetDNABounds(block) var/val if(on) - val=rand(BOUNDS[DNA_ON_LOWERBOUND],BOUNDS[DNA_ON_UPPERBOUND]) + val = rand(BOUNDS[DNA_ON_LOWERBOUND], BOUNDS[DNA_ON_UPPERBOUND]) else - val=rand(1,BOUNDS[DNA_OFF_UPPERBOUND]) - SetSEValue(block,val,defer) + val = rand(1, BOUNDS[DNA_OFF_UPPERBOUND]) + SetSEValue(block, val, defer) // Get hex-encoded SE block. -/datum/dna/proc/GetSEBlock(var/block) +/datum/dna/proc/GetSEBlock(block) return EncodeDNABlock(GetSEValue(block)) // Do not use this unless you absolutely have to. // Set a block from a hex string. This is inefficient. If you can, use SetUIValue(). // Used in DNA modifiers. -/datum/dna/proc/SetSEBlock(var/block,var/value,var/defer=0) - if(block<=0) return +/datum/dna/proc/SetSEBlock(block, value, defer = FALSE) + if(block <= 0) + return var/nval=hex2num(value) //testing("SetSEBlock([block],[value],[defer]): [value] -> [nval]") - return SetSEValue(block,nval,defer) + return SetSEValue(block, nval, defer) -/datum/dna/proc/GetSESubBlock(var/block,var/subBlock) - return copytext(GetSEBlock(block),subBlock,subBlock+1) +/datum/dna/proc/GetSESubBlock(block, subBlock) + return copytext(GetSEBlock(block), subBlock, subBlock + 1) // Do not use this unless you absolutely have to. // Set a sub-block from a hex character. This is inefficient. If you can, use SetUIValue(). // Used in DNA modifiers. -/datum/dna/proc/SetSESubBlock(var/block,var/subBlock, var/newSubBlock, var/defer=0) - if(block<=0) return +/datum/dna/proc/SetSESubBlock(block, subBlock, newSubBlock, defer = FALSE) + if(block <= 0) + return var/oldBlock=GetSEBlock(block) - var/newBlock="" - for(var/i=1, i<=length(oldBlock), i++) + var/newBlock = "" + for(var/i = 1, i <= length(oldBlock), i++) if(i==subBlock) newBlock+=newSubBlock else - newBlock+=copytext(oldBlock,i,i+1) + newBlock += copytext(oldBlock, i, i + 1) //testing("SetSESubBlock([block],[subBlock],[newSubBlock],[defer]): [oldBlock] -> [newBlock]") - SetSEBlock(block,newBlock,defer) + SetSEBlock(block, newBlock, defer) -/proc/EncodeDNABlock(var/value) - return add_zero2(num2hex(value,1), 3) +/proc/EncodeDNABlock(value) + return add_zero2(num2hex(value, 1), 3) /datum/dna/proc/UpdateUI() - src.uni_identity="" + uni_identity = "" for(var/block in UI) uni_identity += EncodeDNABlock(block) //testing("New UI: [uni_identity]") - dirtyUI=0 + dirtyUI = 0 /datum/dna/proc/UpdateSE() //var/oldse=struc_enzymes - struc_enzymes="" + struc_enzymes = "" for(var/block in SE) struc_enzymes += EncodeDNABlock(block) //testing("Old SE: [oldse]") //testing("New SE: [struc_enzymes]") - dirtySE=0 + dirtySE = 0 // BACK-COMPAT! // Just checks our character has all the crap it needs. -/datum/dna/proc/check_integrity(var/mob/living/carbon/human/character) +/datum/dna/proc/check_integrity(mob/living/carbon/human/character) if(character) if(UI.len != DNA_UI_LENGTH) ResetUIFrom(character) - if(length(struc_enzymes)!= 3*DNA_SE_LENGTH) + if(length(struc_enzymes)!= 3 * DNA_SE_LENGTH) ResetSE() if(length(unique_enzymes) != 32) unique_enzymes = md5(character.real_name) else - if(length(uni_identity) != 3*DNA_UI_LENGTH) + if(length(uni_identity) != 3 * DNA_UI_LENGTH) uni_identity = "00600200A00E0110148FC01300B0095BD7FD3F4" - if(length(struc_enzymes)!= 3*DNA_SE_LENGTH) + if(length(struc_enzymes)!= 3 * DNA_SE_LENGTH) struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6" // BACK-COMPAT! @@ -413,7 +372,7 @@ var/global/list/bad_blocks[0] SE_original = SE.Copy() unique_enzymes = md5(character.real_name) - reg_dna[unique_enzymes] = character.real_name + GLOB.reg_dna[unique_enzymes] = character.real_name // Hmm, I wonder how to go about this without a huge convention break /datum/dna/serialize() diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm index 07979f40b7c..16eee549bf2 100644 --- a/code/game/dna/dna2_domutcheck.dm +++ b/code/game/dna/dna2_domutcheck.dm @@ -3,8 +3,8 @@ // M: Mob to mess with // connected: Machine we're in, type unchecked so I doubt it's used beyond monkeying // flags: See below, bitfield. -/proc/domutcheck(var/mob/living/M, var/connected=null, var/flags=0) - for(var/datum/dna/gene/gene in dna_genes) +/proc/domutcheck(mob/living/M, connected = null, flags = 0) + for(var/datum/dna/gene/gene in GLOB.dna_genes) if(!M || !M.dna) return if(!gene.block) @@ -13,7 +13,7 @@ domutation(gene, M, connected, flags) // Use this to force a mut check on a single gene! -/proc/genemutcheck(var/mob/living/M, var/block, var/connected=null, var/flags=0) +/proc/genemutcheck(mob/living/M, block, connected = null, flags = 0) if(ishuman(M)) // Would've done this via species instead of type, but the basic mob doesn't have a species, go figure. var/mob/living/carbon/human/H = M if(NO_DNA in H.dna.species.species_traits) @@ -23,13 +23,13 @@ if(block < 0) return - var/datum/dna/gene/gene = assigned_gene_blocks[block] + var/datum/dna/gene/gene = GLOB.assigned_gene_blocks[block] domutation(gene, M, connected, flags) -/proc/domutation(var/datum/dna/gene/gene, var/mob/living/M, var/connected=null, var/flags=0) +/proc/domutation(datum/dna/gene/gene, mob/living/M, connected = null, flags = 0) if(!gene || !istype(gene)) - return 0 + return FALSE // Current state var/gene_active = M.dna.GetSEState(gene.block) @@ -37,7 +37,7 @@ // Sanity checks, don't skip. if(!gene.can_activate(M,flags) && gene_active) //testing("[M] - Failed to activate [gene.name] (can_activate fail).") - return 0 + return FALSE var/defaultgenes // Do not mutate inherent species abilities if(ishuman(M)) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 9ef5dbfcab0..435133a3796 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -9,58 +9,61 @@ t = "0[t]" temp1 = t if(length(t) > u) - temp1 = copytext(t,2,u+1) + temp1 = copytext(t, 2, u + 1) return temp1 // DNA Gene activation boundaries, see dna2.dm. // Returns a list object with 4 numbers. -/proc/GetDNABounds(var/block) - var/list/BOUNDS=dna_activity_bounds[block] +/proc/GetDNABounds(block) + var/list/BOUNDS = GLOB.dna_activity_bounds[block] if(!istype(BOUNDS)) return DNA_DEFAULT_BOUNDS return BOUNDS // Give Random Bad Mutation to M -/proc/randmutb(var/mob/living/M) - if(!M || !M.dna) return +/proc/randmutb(mob/living/M) + if(!M || !M.dna) + return M.dna.check_integrity() - var/block = pick(bad_blocks) + var/block = pick(GLOB.bad_blocks) M.dna.SetSEState(block, 1) // Give Random Good Mutation to M -/proc/randmutg(var/mob/living/M) - if(!M || !M.dna) return +/proc/randmutg(mob/living/M) + if(!M || !M.dna) + return M.dna.check_integrity() - var/block = pick(good_blocks) + var/block = pick(GLOB.good_blocks) M.dna.SetSEState(block, 1) // Random Appearance Mutation -/proc/randmuti(var/mob/living/M) - if(!M || !M.dna) return +/proc/randmuti(mob/living/M) + if(!M || !M.dna) + return M.dna.check_integrity() - M.dna.SetUIValue(rand(1,DNA_UI_LENGTH),rand(1,4095)) + M.dna.SetUIValue(rand(1, DNA_UI_LENGTH), rand(1, 4095)) // Scramble UI or SE. -/proc/scramble(var/UI, var/mob/M, var/prob) - if(!M || !M.dna) return +/proc/scramble(UI, mob/M, prob) + if(!M || !M.dna) + return M.dna.check_integrity() if(UI) - for(var/i = 1, i <= DNA_UI_LENGTH-1, i++) + for(var/i = 1, i <= DNA_UI_LENGTH - 1, i++) if(prob(prob)) - M.dna.SetUIValue(i,rand(1,4095),1) + M.dna.SetUIValue(i, rand(1, 4095), 1) M.dna.UpdateUI() M.UpdateAppearance() else - for(var/i = 1, i <= DNA_SE_LENGTH-1, i++) + for(var/i = 1, i <= DNA_SE_LENGTH - 1, i++) if(prob(prob)) - M.dna.SetSEValue(i,rand(1,4095),1) + M.dna.SetSEValue(i, rand(1, 4095), 1) M.dna.UpdateSE() domutcheck(M, null) - return // I haven't yet figured out what the fuck this is supposed to do. -/proc/miniscramble(input,rs,rd) +/proc/miniscramble(input, rs, rd) var/output output = null if(input == "C" || input == "D" || input == "E" || input == "F") @@ -79,7 +82,7 @@ // input: YOUR TARGET // rs: RAD STRENGTH // rd: DURATION -/proc/miniscrambletarget(input,rs,rd) +/proc/miniscrambletarget(input, rs, rd) var/output = null switch(input) if("0") @@ -124,11 +127,11 @@ // Use mob.UpdateAppearance() instead. // Simpler. Don't specify UI in order for the mob to use its own. -/mob/proc/UpdateAppearance(var/list/UI=null) - if(istype(src, /mob/living/carbon/human)) +/mob/proc/UpdateAppearance(list/UI = null) + if(istype(src, /mob/living/carbon/human)) // WHY?! if(UI!=null) - src.dna.UI=UI - src.dna.UpdateUI() + dna.UI = UI + dna.UpdateUI() dna.check_integrity() var/mob/living/carbon/human/H = src var/obj/item/organ/external/head/head_organ = H.get_organ("head") @@ -169,9 +172,9 @@ H.regenerate_icons() - return 1 + return TRUE else - return 0 + return FALSE /* ORGAN WRITING PROCS @@ -219,9 +222,9 @@ // In absence of eyes, possibly randomize the eye color DNA? return - SetUIValueRange(DNA_UI_EYES_R, color2R(eyes_organ.eye_colour), 255, 1) - SetUIValueRange(DNA_UI_EYES_G, color2G(eyes_organ.eye_colour), 255, 1) - SetUIValueRange(DNA_UI_EYES_B, color2B(eyes_organ.eye_colour), 255, 1) + SetUIValueRange(DNA_UI_EYES_R, color2R(eyes_organ.eye_colour), 255, 1) + SetUIValueRange(DNA_UI_EYES_G, color2G(eyes_organ.eye_colour), 255, 1) + SetUIValueRange(DNA_UI_EYES_B, color2B(eyes_organ.eye_colour), 255, 1) /datum/dna/proc/head_traits_to_dna(obj/item/organ/external/head/head_organ) if(!head_organ) @@ -241,26 +244,26 @@ head_organ.ha_style = "None" var/headacc = GLOB.head_accessory_styles_list.Find(head_organ.ha_style) - SetUIValueRange(DNA_UI_HAIR_R, color2R(head_organ.hair_colour), 255, 1) - SetUIValueRange(DNA_UI_HAIR_G, color2G(head_organ.hair_colour), 255, 1) - SetUIValueRange(DNA_UI_HAIR_B, color2B(head_organ.hair_colour), 255, 1) + SetUIValueRange(DNA_UI_HAIR_R, color2R(head_organ.hair_colour), 255, 1) + SetUIValueRange(DNA_UI_HAIR_G, color2G(head_organ.hair_colour), 255, 1) + SetUIValueRange(DNA_UI_HAIR_B, color2B(head_organ.hair_colour), 255, 1) - SetUIValueRange(DNA_UI_HAIR2_R, color2R(head_organ.sec_hair_colour), 255, 1) - SetUIValueRange(DNA_UI_HAIR2_G, color2G(head_organ.sec_hair_colour), 255, 1) - SetUIValueRange(DNA_UI_HAIR2_B, color2B(head_organ.sec_hair_colour), 255, 1) + SetUIValueRange(DNA_UI_HAIR2_R, color2R(head_organ.sec_hair_colour), 255, 1) + SetUIValueRange(DNA_UI_HAIR2_G, color2G(head_organ.sec_hair_colour), 255, 1) + SetUIValueRange(DNA_UI_HAIR2_B, color2B(head_organ.sec_hair_colour), 255, 1) - SetUIValueRange(DNA_UI_BEARD_R, color2R(head_organ.facial_colour), 255, 1) - SetUIValueRange(DNA_UI_BEARD_G, color2G(head_organ.facial_colour), 255, 1) - SetUIValueRange(DNA_UI_BEARD_B, color2B(head_organ.facial_colour), 255, 1) + SetUIValueRange(DNA_UI_BEARD_R, color2R(head_organ.facial_colour), 255, 1) + SetUIValueRange(DNA_UI_BEARD_G, color2G(head_organ.facial_colour), 255, 1) + SetUIValueRange(DNA_UI_BEARD_B, color2B(head_organ.facial_colour), 255, 1) - SetUIValueRange(DNA_UI_BEARD2_R, color2R(head_organ.sec_facial_colour), 255, 1) - SetUIValueRange(DNA_UI_BEARD2_G, color2G(head_organ.sec_facial_colour), 255, 1) - SetUIValueRange(DNA_UI_BEARD2_B, color2B(head_organ.sec_facial_colour), 255, 1) + SetUIValueRange(DNA_UI_BEARD2_R, color2R(head_organ.sec_facial_colour), 255, 1) + SetUIValueRange(DNA_UI_BEARD2_G, color2G(head_organ.sec_facial_colour), 255, 1) + SetUIValueRange(DNA_UI_BEARD2_B, color2B(head_organ.sec_facial_colour), 255, 1) - SetUIValueRange(DNA_UI_HACC_R, color2R(head_organ.headacc_colour), 255, 1) - SetUIValueRange(DNA_UI_HACC_G, color2G(head_organ.headacc_colour), 255, 1) - SetUIValueRange(DNA_UI_HACC_B, color2B(head_organ.headacc_colour), 255, 1) + SetUIValueRange(DNA_UI_HACC_R, color2R(head_organ.headacc_colour), 255, 1) + SetUIValueRange(DNA_UI_HACC_G, color2G(head_organ.headacc_colour), 255, 1) + SetUIValueRange(DNA_UI_HACC_B, color2B(head_organ.headacc_colour), 255, 1) - SetUIValueRange(DNA_UI_HAIR_STYLE, hair, GLOB.hair_styles_full_list.len, 1) - SetUIValueRange(DNA_UI_BEARD_STYLE, beard, GLOB.facial_hair_styles_list.len, 1) - SetUIValueRange(DNA_UI_HACC_STYLE, headacc, GLOB.head_accessory_styles_list.len, 1) + SetUIValueRange(DNA_UI_HAIR_STYLE, hair, GLOB.hair_styles_full_list.len, 1) + SetUIValueRange(DNA_UI_BEARD_STYLE, beard, GLOB.facial_hair_styles_list.len, 1) + SetUIValueRange(DNA_UI_HACC_STYLE, headacc, GLOB.head_accessory_styles_list.len, 1) diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index de42b5b253f..a6ec98e8866 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -10,15 +10,15 @@ //list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0), /datum/dna2/record var/datum/dna/dna = null - var/types=0 - var/name="Empty" + var/types = 0 + var/name = "Empty" // Stuff for cloners - var/id=null - var/implant=null - var/ckey=null - var/mind=null - var/languages=null + var/id = null + var/implant = null + var/ckey = null + var/mind = null + var/languages = null /datum/dna2/record/proc/GetData() var/list/ser=list("data" = null, "owner" = null, "label" = null, "type" = null, "ue" = 0) @@ -28,7 +28,7 @@ ser["data"] = dna.SE else ser["data"] = dna.UI - ser["owner"] = src.dna.real_name + ser["owner"] = dna.real_name ser["label"] = name if(types & DNA2_BUF_UI) ser["type"] = "ui" @@ -54,13 +54,13 @@ desc = "It scans DNA structures." icon = 'icons/obj/cryogenic2.dmi' icon_state = "scanner_open" - density = 1 - anchored = 1.0 + density = TRUE + anchored = TRUE use_power = IDLE_POWER_USE idle_power_usage = 50 active_power_usage = 300 interact_offline = 1 - var/locked = 0 + var/locked = FALSE var/mob/living/carbon/occupant = null var/obj/item/reagent_containers/glass/beaker = null var/opened = 0 @@ -106,27 +106,29 @@ /obj/machinery/dna_scannernew/AllowDrop() return FALSE -/obj/machinery/dna_scannernew/relaymove(mob/user as mob) +/obj/machinery/dna_scannernew/relaymove(mob/user) if(user.stat) return - src.go_out() - return + go_out() /obj/machinery/dna_scannernew/verb/eject() set src in oview(1) set category = null set name = "Eject DNA Scanner" - if(usr.stat != 0) + if(usr.incapacitated()) return eject_occupant() add_fingerprint(usr) - return + +/obj/machinery/dna_scannernew/Destroy() + eject_occupant() + return ..() /obj/machinery/dna_scannernew/proc/eject_occupant() - src.go_out() + go_out() for(var/obj/O in src) if(!istype(O,/obj/item/circuitboard/clonescanner) && \ !istype(O,/obj/item/stock_parts) && \ @@ -142,14 +144,12 @@ set category = null set name = "Enter DNA Scanner" - if(usr.stat != 0) - return if(usr.incapacitated()) //are you cuffed, dying, lying, stunned or other return if(!ishuman(usr)) //Make sure they're a mob that has dna to_chat(usr, "Try as you might, you can not climb up into the [src].") return - if(src.occupant) + if(occupant) to_chat(usr, "The [src] is already occupied!") return if(usr.abiotic()) @@ -160,12 +160,11 @@ return usr.stop_pulling() usr.forceMove(src) - src.occupant = usr - src.icon_state = "scanner_occupied" - src.add_fingerprint(usr) - return + occupant = usr + icon_state = "scanner_occupied" + add_fingerprint(usr) -/obj/machinery/dna_scannernew/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) +/obj/machinery/dna_scannernew/MouseDrop_T(atom/movable/O, mob/user) if(!istype(O)) return if(O.loc == user) //no you can't pull things out of your ass @@ -204,27 +203,27 @@ if(user.pulling == L) user.stop_pulling() -/obj/machinery/dna_scannernew/attackby(var/obj/item/item as obj, var/mob/user as mob, params) - if(exchange_parts(user, item)) +/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params) + if(exchange_parts(user, I)) return - else if(istype(item, /obj/item/reagent_containers/glass)) + else if(istype(I, /obj/item/reagent_containers/glass)) if(beaker) to_chat(user, "A beaker is already loaded into the machine.") return if(!user.drop_item()) - to_chat(user, "\The [item] is stuck to you!") + to_chat(user, "\The [I] is stuck to you!") return - beaker = item - item.forceMove(src) - user.visible_message("[user] adds \a [item] to \the [src]!", "You add \a [item] to \the [src]!") + beaker = I + I.forceMove(src) + user.visible_message("[user] adds \a [I] to \the [src]!", "You add \a [I] to \the [src]!") return - if(istype(item, /obj/item/grab)) - var/obj/item/grab/G = item + if(istype(I, /obj/item/grab)) + var/obj/item/grab/G = I if(!ismob(G.affecting)) return - if(src.occupant) + if(occupant) to_chat(user, "The scanner is already occupied!") return if(G.affecting.abiotic()) @@ -237,7 +236,7 @@ to_chat(usr, "Close the maintenance panel first.") return put_in(G.affecting) - src.add_fingerprint(user) + add_fingerprint(user) qdel(G) return return ..() @@ -245,7 +244,7 @@ /obj/machinery/dna_scannernew/crowbar_act(mob/user, obj/item/I) if(default_deconstruction_crowbar(user, I)) for(var/obj/thing in contents) // in case there is something in the scanner - thing.forceMove(src.loc) + thing.forceMove(loc) /obj/machinery/dna_scannernew/screwdriver_act(mob/user, obj/item/I) if(occupant) @@ -254,15 +253,15 @@ if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", I)) return TRUE -/obj/machinery/dna_scannernew/relaymove(mob/user as mob) +/obj/machinery/dna_scannernew/relaymove(mob/user) if(user.incapacitated()) - return 0 //maybe they should be able to get out with cuffs, but whatever + return FALSE //maybe they should be able to get out with cuffs, but whatever go_out() -/obj/machinery/dna_scannernew/proc/put_in(var/mob/M) +/obj/machinery/dna_scannernew/proc/put_in(mob/M) M.forceMove(src) - src.occupant = M - src.icon_state = "scanner_occupied" + occupant = M + icon_state = "scanner_occupied" // search for ghosts, if the corpse is empty and the scanner is connected to a cloner if(locate(/obj/machinery/computer/cloning, get_step(src, NORTH)) \ @@ -271,20 +270,19 @@ || locate(/obj/machinery/computer/cloning, get_step(src, WEST))) occupant.notify_ghost_cloning(source = src) - return /obj/machinery/dna_scannernew/proc/go_out() - if(!src.occupant) + if(!occupant) to_chat(usr, "The scanner is empty!") return - if(src.locked) + if(locked) to_chat(usr, "The scanner is locked!") return - src.occupant.forceMove(src.loc) - src.occupant = null - src.icon_state = "scanner_open" + occupant.forceMove(loc) + occupant = null + icon_state = "scanner_open" /obj/machinery/dna_scannernew/ex_act(severity) if(occupant) @@ -301,18 +299,17 @@ // Checks if occupants can be irradiated/mutated - prevents exploits where wearing full rad protection would still let you gain mutations /obj/machinery/dna_scannernew/proc/radiation_check() if(!occupant) - return 1 + return TRUE if(ishuman(occupant)) var/mob/living/carbon/human/H = occupant if(NO_DNA in H.dna.species.species_traits) - return 1 + return TRUE var/radiation_protection = occupant.run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm.") if(radiation_protection > NEGATE_MUTATION_THRESHOLD) - return 1 - - return 0 + return TRUE + return FALSE /obj/machinery/computer/scan_consolenew name = "\improper DNA Modifier access console" @@ -320,7 +317,7 @@ icon = 'icons/obj/computer.dmi' icon_screen = "dna" icon_keyboard = "med_key" - density = 1 + density = TRUE circuit = /obj/item/circuitboard/scan_consolenew var/selected_ui_block = 1.0 var/selected_ui_subblock = 1.0 @@ -332,22 +329,22 @@ var/radiation_intensity = 1.0 var/list/datum/dna2/record/buffers[3] var/irradiating = 0 - var/injector_ready = 0 //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete + var/injector_ready = FALSE //Quick fix for issue 286 (screwdriver the screen twice to restore injector) -Pete var/obj/machinery/dna_scannernew/connected = null var/obj/item/disk/data/disk = null var/selected_menu_key = null - anchored = 1 + anchored = TRUE use_power = IDLE_POWER_USE idle_power_usage = 10 active_power_usage = 400 - var/waiting_for_user_input=0 // Fix for #274 (Mash create block injector without answering dialog to make unlimited injectors) - N3X + var/waiting_for_user_input = 0 // Fix for #274 (Mash create block injector without answering dialog to make unlimited injectors) - N3X -/obj/machinery/computer/scan_consolenew/attackby(obj/item/I as obj, mob/user as mob, params) +/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/disk/data)) //INSERT SOME diskS - if(!src.disk) + if(!disk) user.drop_item() I.forceMove(src) - src.disk = I + disk = I to_chat(user, "You insert [I].") SSnanoui.update_uis(src) // update all UIs attached to src() return @@ -364,39 +361,30 @@ if(!isnull(connected)) break spawn(250) - src.injector_ready = 1 - return - return + injector_ready = TRUE -/obj/machinery/computer/scan_consolenew/proc/all_dna_blocks(var/list/buffer) +/obj/machinery/computer/scan_consolenew/proc/all_dna_blocks(list/buffer) var/list/arr = list() for(var/i = 1, i <= buffer.len, i++) arr += "[i]:[EncodeDNABlock(buffer[i])]" return arr -/obj/machinery/computer/scan_consolenew/proc/setInjectorBlock(var/obj/item/dnainjector/I, var/blk, var/datum/dna2/record/buffer) +/obj/machinery/computer/scan_consolenew/proc/setInjectorBlock(obj/item/dnainjector/I, blk, datum/dna2/record/buffer) var/pos = findtext(blk,":") - if(!pos) return 0 + if(!pos) + return FALSE var/id = text2num(copytext(blk,1,pos)) - if(!id) return 0 + if(!id) + return FALSE I.block = id I.buf = buffer - return 1 + return TRUE -/* -/obj/machinery/computer/scan_consolenew/process() //not really used right now - if(stat & (NOPOWER|BROKEN)) - return - if(!( src.status )) //remove this - return - return -*/ - -/obj/machinery/computer/scan_consolenew/attack_ai(user as mob) - src.add_hiddenprint(user) +/obj/machinery/computer/scan_consolenew/attack_ai(mob/user) + add_hiddenprint(user) attack_hand(user) -/obj/machinery/computer/scan_consolenew/attack_hand(user as mob) +/obj/machinery/computer/scan_consolenew/attack_hand(mob/user) if(isnull(connected)) for(dir in list(NORTH,EAST,SOUTH,WEST)) connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir)) @@ -423,7 +411,7 @@ * * @return nothing */ -/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) +/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1) if(user == connected.occupant) return @@ -441,7 +429,7 @@ /obj/machinery/computer/scan_consolenew/ui_data(mob/user, datum/topic_state/state) var/data[0] data["selectedMenuKey"] = selected_menu_key - data["locked"] = src.connected.locked + data["locked"] = connected.locked data["hasOccupant"] = connected.occupant ? 1 : 0 data["isInjectorReady"] = injector_ready @@ -460,7 +448,7 @@ data["disk"] = diskData var/list/new_buffers = list() - for(var/datum/dna2/record/buf in src.buffers) + for(var/datum/dna2/record/buf in buffers) new_buffers += list(buf.GetData()) data["buffers"]=new_buffers @@ -477,7 +465,7 @@ data["selectedUITargetHex"] = selected_ui_target_hex var/occupantData[0] - if(!src.connected.occupant || !src.connected.occupant.dna) + if(!connected.occupant || !connected.occupant.dna) occupantData["name"] = null occupantData["stat"] = null occupantData["isViableSubject"] = null @@ -492,7 +480,7 @@ occupantData["name"] = connected.occupant.dna.real_name occupantData["stat"] = connected.occupant.stat occupantData["isViableSubject"] = 1 - if((NOCLONE in connected.occupant.mutations && connected.scan_level < 3) || !src.connected.occupant.dna || (NO_DNA in connected.occupant.dna.species.species_traits)) + if((NOCLONE in connected.occupant.mutations && connected.scan_level < 3) || !connected.occupant.dna || (NO_DNA in connected.occupant.dna.species.species_traits)) occupantData["isViableSubject"] = 0 occupantData["health"] = connected.occupant.health occupantData["maxHealth"] = connected.occupant.maxHealth @@ -516,173 +504,173 @@ /obj/machinery/computer/scan_consolenew/Topic(href, href_list) if(..()) - return 0 // don't update uis + return FALSE // don't update uis if(!istype(usr.loc, /turf)) - return 0 // don't update uis - if(!src || !src.connected) - return 0 // don't update uis + return FALSE // don't update uis + if(!src || !connected) + return FALSE // don't update uis if(irradiating) // Make sure that it isn't already irradiating someone... - return 0 // don't update uis + return FALSE // don't update uis add_fingerprint(usr) if(href_list["selectMenuKey"]) selected_menu_key = href_list["selectMenuKey"] - return 1 // return 1 forces an update to all Nano uis attached to src + return TRUE // return 1 forces an update to all Nano uis attached to src if(href_list["toggleLock"]) - if((src.connected && src.connected.occupant)) - src.connected.locked = !( src.connected.locked ) - return 1 // return 1 forces an update to all Nano uis attached to src + if((connected && connected.occupant)) + connected.locked = !(connected.locked) + return TRUE // return 1 forces an update to all Nano uis attached to src if(href_list["pulseRadiation"]) - irradiating = src.radiation_duration - var/lock_state = src.connected.locked - src.connected.locked = 1//lock it + irradiating = radiation_duration + var/lock_state = connected.locked + connected.locked = TRUE //lock it SSnanoui.update_uis(src) // update all UIs attached to src - sleep(10*src.radiation_duration) // sleep for radiation_duration seconds + sleep(10 * radiation_duration) // sleep for radiation_duration seconds irradiating = 0 - src.connected.locked = lock_state + connected.locked = lock_state - if(!src.connected.occupant) - return 1 // return 1 forces an update to all Nano uis attached to src + if(!connected.occupant) + return TRUE // return 1 forces an update to all Nano uis attached to src - var/radiation = (((src.radiation_intensity*3)+src.radiation_duration*3) / connected.damage_coeff) - src.connected.occupant.apply_effect(radiation,IRRADIATE,0) - if(src.connected.radiation_check()) - return 1 + var/radiation = (((radiation_intensity * 3) + radiation_duration * 3) / connected.damage_coeff) + connected.occupant.apply_effect(radiation, IRRADIATE, 0) + if(connected.radiation_check()) + return TRUE if(prob(95)) if(prob(75)) - randmutb(src.connected.occupant) + randmutb(connected.occupant) else - randmuti(src.connected.occupant) + randmuti(connected.occupant) else if(prob(95)) - randmutg(src.connected.occupant) + randmutg(connected.occupant) else - randmuti(src.connected.occupant) + randmuti(connected.occupant) - return 1 // return 1 forces an update to all Nano uis attached to src + return TRUE // return 1 forces an update to all Nano uis attached to src if(href_list["radiationDuration"]) if(text2num(href_list["radiationDuration"]) > 0) - if(src.radiation_duration < 20) - src.radiation_duration += 2 + if(radiation_duration < 20) + radiation_duration += 2 else - if(src.radiation_duration > 2) - src.radiation_duration -= 2 - return 1 // return 1 forces an update to all Nano uis attached to src + if(radiation_duration > 2) + radiation_duration -= 2 + return TRUE // return 1 forces an update to all Nano uis attached to src if(href_list["radiationIntensity"]) if(text2num(href_list["radiationIntensity"]) > 0) - if(src.radiation_intensity < 10) - src.radiation_intensity++ + if(radiation_intensity < 10) + radiation_intensity++ else - if(src.radiation_intensity > 1) - src.radiation_intensity-- - return 1 // return 1 forces an update to all Nano uis attached to src + if(radiation_intensity > 1) + radiation_intensity-- + return TRUE // return 1 forces an update to all Nano uis attached to src //////////////////////////////////////////////////////// if(href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) > 0) - if(src.selected_ui_target < 15) - src.selected_ui_target++ - src.selected_ui_target_hex = src.selected_ui_target + if(selected_ui_target < 15) + selected_ui_target++ + selected_ui_target_hex = selected_ui_target switch(selected_ui_target) if(10) - src.selected_ui_target_hex = "A" + selected_ui_target_hex = "A" if(11) - src.selected_ui_target_hex = "B" + selected_ui_target_hex = "B" if(12) - src.selected_ui_target_hex = "C" + selected_ui_target_hex = "C" if(13) - src.selected_ui_target_hex = "D" + selected_ui_target_hex = "D" if(14) - src.selected_ui_target_hex = "E" + selected_ui_target_hex = "E" if(15) - src.selected_ui_target_hex = "F" + selected_ui_target_hex = "F" else - src.selected_ui_target = 0 - src.selected_ui_target_hex = 0 - return 1 // return 1 forces an update to all Nano uis attached to src + selected_ui_target = 0 + selected_ui_target_hex = 0 + return TRUE // return 1 forces an update to all Nano uis attached to src if(href_list["changeUITarget"] && text2num(href_list["changeUITarget"]) < 1) - if(src.selected_ui_target > 0) - src.selected_ui_target-- - src.selected_ui_target_hex = src.selected_ui_target + if(selected_ui_target > 0) + selected_ui_target-- + selected_ui_target_hex = selected_ui_target switch(selected_ui_target) if(10) - src.selected_ui_target_hex = "A" + selected_ui_target_hex = "A" if(11) - src.selected_ui_target_hex = "B" + selected_ui_target_hex = "B" if(12) - src.selected_ui_target_hex = "C" + selected_ui_target_hex = "C" if(13) - src.selected_ui_target_hex = "D" + selected_ui_target_hex = "D" if(14) - src.selected_ui_target_hex = "E" + selected_ui_target_hex = "E" else - src.selected_ui_target = 15 - src.selected_ui_target_hex = "F" - return 1 // return 1 forces an update to all Nano uis attached to src + selected_ui_target = 15 + selected_ui_target_hex = "F" + return TRUE // return 1 forces an update to all Nano uis attached to src if(href_list["selectUIBlock"] && href_list["selectUISubblock"]) // This chunk of code updates selected block / sub-block based on click var/select_block = text2num(href_list["selectUIBlock"]) var/select_subblock = text2num(href_list["selectUISubblock"]) if((select_block <= DNA_UI_LENGTH) && (select_block >= 1)) - src.selected_ui_block = select_block + selected_ui_block = select_block if((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1)) - src.selected_ui_subblock = select_subblock - return 1 // return 1 forces an update to all Nano uis attached to src + selected_ui_subblock = select_subblock + return TRUE // return 1 forces an update to all Nano uis attached to src if(href_list["pulseUIRadiation"]) - var/block = src.connected.occupant.dna.GetUISubBlock(src.selected_ui_block,src.selected_ui_subblock) + var/block = connected.occupant.dna.GetUISubBlock(selected_ui_block, selected_ui_subblock) - irradiating = src.radiation_duration - var/lock_state = src.connected.locked - src.connected.locked = 1//lock it + irradiating = radiation_duration + var/lock_state = connected.locked + connected.locked = TRUE //lock it SSnanoui.update_uis(src) // update all UIs attached to src - sleep(10*src.radiation_duration) // sleep for radiation_duration seconds + sleep(10 * radiation_duration) // sleep for radiation_duration seconds irradiating = 0 - src.connected.locked = lock_state + connected.locked = lock_state - if(!src.connected.occupant) - return 1 + if(!connected.occupant) + return TRUE - if(prob((80 + (src.radiation_duration / 2)))) - var/radiation = (src.radiation_intensity+src.radiation_duration) - src.connected.occupant.apply_effect(radiation,IRRADIATE,0) + if(prob((80 + (radiation_duration / 2)))) + var/radiation = (radiation_intensity + radiation_duration) + connected.occupant.apply_effect(radiation,IRRADIATE,0) - if(src.connected.radiation_check()) - return 1 + if(connected.radiation_check()) + return TRUE - block = miniscrambletarget(num2text(selected_ui_target), src.radiation_intensity, src.radiation_duration) - src.connected.occupant.dna.SetUISubBlock(src.selected_ui_block,src.selected_ui_subblock,block) - src.connected.occupant.UpdateAppearance() + block = miniscrambletarget(num2text(selected_ui_target), radiation_intensity, radiation_duration) + connected.occupant.dna.SetUISubBlock(selected_ui_block, selected_ui_subblock, block) + connected.occupant.UpdateAppearance() else - var/radiation = ((src.radiation_intensity*2)+src.radiation_duration) - src.connected.occupant.apply_effect(radiation,IRRADIATE,0) - if(src.connected.radiation_check()) - return 1 + var/radiation = ((radiation_intensity * 2) + radiation_duration) + connected.occupant.apply_effect(radiation, IRRADIATE, 0) + if(connected.radiation_check()) + return TRUE - if(prob(20+src.radiation_intensity)) - randmutb(src.connected.occupant) - domutcheck(src.connected.occupant,src.connected) + if(prob(20 + radiation_intensity)) + randmutb(connected.occupant) + domutcheck(connected.occupant, connected) else - randmuti(src.connected.occupant) - src.connected.occupant.UpdateAppearance() - return 1 // return 1 forces an update to all Nano uis attached to src + randmuti(connected.occupant) + connected.occupant.UpdateAppearance() + return TRUE // return 1 forces an update to all Nano uis attached to src //////////////////////////////////////////////////////// if(href_list["injectRejuvenators"]) if(!connected.occupant) - return 0 + return FALSE var/inject_amount = round(text2num(href_list["injectRejuvenators"]), 5) // round to nearest 5 if(inject_amount < 0) // Since the user can actually type the commands himself, some sanity checking inject_amount = 0 @@ -690,7 +678,7 @@ inject_amount = 50 connected.beaker.reagents.trans_to(connected.occupant, inject_amount) connected.beaker.reagents.reaction(connected.occupant) - return 1 // return 1 forces an update to all Nano uis attached to src + return TRUE // return 1 forces an update to all Nano uis attached to src //////////////////////////////////////////////////////// @@ -698,73 +686,73 @@ var/select_block = text2num(href_list["selectSEBlock"]) var/select_subblock = text2num(href_list["selectSESubblock"]) if((select_block <= DNA_SE_LENGTH) && (select_block >= 1)) - src.selected_se_block = select_block + selected_se_block = select_block if((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1)) - src.selected_se_subblock = select_subblock + selected_se_subblock = select_subblock //testing("User selected block [selected_se_block] (sent [select_block]), subblock [selected_se_subblock] (sent [select_block]).") - return 1 // return 1 forces an update to all Nano uis attached to src + return TRUE // return 1 forces an update to all Nano uis attached to src if(href_list["pulseSERadiation"]) - var/block = src.connected.occupant.dna.GetSESubBlock(src.selected_se_block,src.selected_se_subblock) + var/block = connected.occupant.dna.GetSESubBlock(selected_se_block, selected_se_subblock) //var/original_block=block - //testing("Irradiating SE block [src.selected_se_block]:[src.selected_se_subblock] ([block])...") + //testing("Irradiating SE block [selected_se_block]:[selected_se_subblock] ([block])...") - irradiating = src.radiation_duration - var/lock_state = src.connected.locked - src.connected.locked = 1 //lock it + irradiating = radiation_duration + var/lock_state = connected.locked + connected.locked = TRUE //lock it SSnanoui.update_uis(src) // update all UIs attached to src - sleep(10*src.radiation_duration) // sleep for radiation_duration seconds + sleep(10 * radiation_duration) // sleep for radiation_duration seconds irradiating = 0 - src.connected.locked = lock_state + connected.locked = lock_state - if(src.connected.occupant) - if(prob((80 + ((src.radiation_duration / 2) + (connected.precision_coeff ** 3))))) - var/radiation = ((src.radiation_intensity+src.radiation_duration) / connected.damage_coeff) - src.connected.occupant.apply_effect(radiation,IRRADIATE,0) + if(connected.occupant) + if(prob((80 + ((radiation_duration / 2) + (connected.precision_coeff ** 3))))) + var/radiation = ((radiation_intensity + radiation_duration) / connected.damage_coeff) + connected.occupant.apply_effect(radiation, IRRADIATE, 0) - if(src.connected.radiation_check()) + if(connected.radiation_check()) return 1 var/real_SE_block=selected_se_block - block = miniscramble(block, src.radiation_intensity, src.radiation_duration) + block = miniscramble(block, radiation_intensity, radiation_duration) if(prob(20)) - if(src.selected_se_block > 1 && src.selected_se_block < DNA_SE_LENGTH/2) + if(selected_se_block > 1 && selected_se_block < DNA_SE_LENGTH/2) real_SE_block++ - else if(src.selected_se_block > DNA_SE_LENGTH/2 && src.selected_se_block < DNA_SE_LENGTH) + else if(selected_se_block > DNA_SE_LENGTH/2 && selected_se_block < DNA_SE_LENGTH) real_SE_block-- - //testing("Irradiated SE block [real_SE_block]:[src.selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!") - connected.occupant.dna.SetSESubBlock(real_SE_block,selected_se_subblock,block) - domutcheck(src.connected.occupant,src.connected) + //testing("Irradiated SE block [real_SE_block]:[selected_se_subblock] ([original_block] now [block]) [(real_SE_block!=selected_se_block) ? "(SHIFTED)":""]!") + connected.occupant.dna.SetSESubBlock(real_SE_block, selected_se_subblock, block) + domutcheck(connected.occupant, connected) else - var/radiation = (((src.radiation_intensity*2)+src.radiation_duration) / connected.damage_coeff) - src.connected.occupant.apply_effect(radiation,IRRADIATE,0) + var/radiation = (((radiation_intensity * 2) + radiation_duration) / connected.damage_coeff) + connected.occupant.apply_effect(radiation, IRRADIATE, 0) - if(src.connected.radiation_check()) + if(connected.radiation_check()) return 1 - if(prob(80-src.radiation_duration)) + if(prob(80 - radiation_duration)) //testing("Random bad mut!") - randmutb(src.connected.occupant) - domutcheck(src.connected.occupant,src.connected) + randmutb(connected.occupant) + domutcheck(connected.occupant, connected) else - randmuti(src.connected.occupant) + randmuti(connected.occupant) //testing("Random identity mut!") - src.connected.occupant.UpdateAppearance() - return 1 // return 1 forces an update to all Nano uis attached to src + connected.occupant.UpdateAppearance() + return TRUE // return 1 forces an update to all Nano uis attached to src if(href_list["ejectBeaker"]) if(connected.beaker) var/obj/item/reagent_containers/glass/B = connected.beaker B.forceMove(connected.loc) connected.beaker = null - return 1 + return TRUE if(href_list["ejectOccupant"]) connected.eject_occupant() - return 1 + return TRUE // Transfer Buffer Management if(href_list["bufferOption"]) @@ -772,113 +760,113 @@ // These bufferOptions do not require a bufferId if(bufferOption == "wipeDisk") - if((isnull(src.disk)) || (src.disk.read_only)) - //src.temphtml = "Invalid disk. Please try again." - return 0 + if((isnull(disk)) || (disk.read_only)) + //temphtml = "Invalid disk. Please try again." + return FALSE - src.disk.buf=null - //src.temphtml = "Data saved." - return 1 + disk.buf = null + //temphtml = "Data saved." + return TRUE if(bufferOption == "ejectDisk") - if(!src.disk) + if(!disk) return - src.disk.forceMove(get_turf(src)) - src.disk = null - return 1 + disk.forceMove(get_turf(src)) + disk = null + return TRUE // All bufferOptions from here on require a bufferId if(!href_list["bufferId"]) - return 0 + return FALSE var/bufferId = text2num(href_list["bufferId"]) if(bufferId < 1 || bufferId > 3) - return 0 // Not a valid buffer id + return FALSE // Not a valid buffer id if(bufferOption == "saveUI") - if(src.connected.occupant && src.connected.occupant.dna) - var/datum/dna2/record/databuf=new + if(connected.occupant && connected.occupant.dna) + var/datum/dna2/record/databuf = new databuf.types = DNA2_BUF_UI // DNA2_BUF_UE - databuf.dna = src.connected.occupant.dna.Clone() + databuf.dna = connected.occupant.dna.Clone() if(ishuman(connected.occupant)) databuf.dna.real_name=connected.occupant.name databuf.name = "Unique Identifier" - src.buffers[bufferId] = databuf - return 1 + buffers[bufferId] = databuf + return TRUE if(bufferOption == "saveUIAndUE") - if(src.connected.occupant && src.connected.occupant.dna) - var/datum/dna2/record/databuf=new + if(connected.occupant && connected.occupant.dna) + var/datum/dna2/record/databuf = new databuf.types = DNA2_BUF_UI|DNA2_BUF_UE - databuf.dna = src.connected.occupant.dna.Clone() + databuf.dna = connected.occupant.dna.Clone() if(ishuman(connected.occupant)) databuf.dna.real_name=connected.occupant.dna.real_name databuf.name = "Unique Identifier + Unique Enzymes" - src.buffers[bufferId] = databuf - return 1 + buffers[bufferId] = databuf + return TRUE if(bufferOption == "saveSE") - if(src.connected.occupant && src.connected.occupant.dna) - var/datum/dna2/record/databuf=new + if(connected.occupant && connected.occupant.dna) + var/datum/dna2/record/databuf = new databuf.types = DNA2_BUF_SE - databuf.dna = src.connected.occupant.dna.Clone() + databuf.dna = connected.occupant.dna.Clone() if(ishuman(connected.occupant)) - databuf.dna.real_name=connected.occupant.dna.real_name + databuf.dna.real_name = connected.occupant.dna.real_name databuf.name = "Structural Enzymes" - src.buffers[bufferId] = databuf - return 1 + buffers[bufferId] = databuf + return TRUE if(bufferOption == "clear") - src.buffers[bufferId]=new /datum/dna2/record() - return 1 + buffers[bufferId] = new /datum/dna2/record() + return TRUE if(bufferOption == "changeLabel") - var/datum/dna2/record/buf = src.buffers[bufferId] + var/datum/dna2/record/buf = buffers[bufferId] var/text = sanitize(input(usr, "New Label:", "Edit Label", buf.name) as text|null) buf.name = text - src.buffers[bufferId] = buf - return 1 + buffers[bufferId] = buf + return TRUE if(bufferOption == "transfer") - if(!src.connected.occupant || (NOCLONE in src.connected.occupant.mutations && connected.scan_level < 3) || !src.connected.occupant.dna) - return 1 + if(!connected.occupant || (NOCLONE in connected.occupant.mutations && connected.scan_level < 3) || !connected.occupant.dna) + return TRUE irradiating = 2 - var/lock_state = src.connected.locked - src.connected.locked = 1//lock it + var/lock_state = connected.locked + connected.locked = TRUE //lock it SSnanoui.update_uis(src) // update all UIs attached to src sleep(2 SECONDS) irradiating = 0 - src.connected.locked = lock_state + connected.locked = lock_state var/radiation = (rand(20,50) / connected.damage_coeff) - src.connected.occupant.apply_effect(radiation,IRRADIATE,0) + connected.occupant.apply_effect(radiation, IRRADIATE, 0) - if(src.connected.radiation_check()) - return 1 + if(connected.radiation_check()) + return TRUE - var/datum/dna2/record/buf = src.buffers[bufferId] + var/datum/dna2/record/buf = buffers[bufferId] if((buf.types & DNA2_BUF_UI)) if((buf.types & DNA2_BUF_UE)) - src.connected.occupant.real_name = buf.dna.real_name - src.connected.occupant.name = buf.dna.real_name - src.connected.occupant.UpdateAppearance(buf.dna.UI.Copy()) + connected.occupant.real_name = buf.dna.real_name + connected.occupant.name = buf.dna.real_name + connected.occupant.UpdateAppearance(buf.dna.UI.Copy()) else if(buf.types & DNA2_BUF_SE) - src.connected.occupant.dna.SE = buf.dna.SE.Copy() - src.connected.occupant.dna.UpdateSE() - domutcheck(src.connected.occupant,src.connected) - return 1 + connected.occupant.dna.SE = buf.dna.SE.Copy() + connected.occupant.dna.UpdateSE() + domutcheck(connected.occupant, connected) + return TRUE if(bufferOption == "createInjector") if(injector_ready && !waiting_for_user_input) var/success = 1 var/obj/item/dnainjector/I = new /obj/item/dnainjector - var/datum/dna2/record/buf = src.buffers[bufferId] + var/datum/dna2/record/buf = buffers[bufferId] buf = buf.copy() if(href_list["createBlockInjector"]) waiting_for_user_input=1 @@ -893,35 +881,35 @@ I.buf = buf waiting_for_user_input = 0 if(success) - I.forceMove(src.loc) + I.forceMove(loc) I.name += " ([buf.name])" if(connected) I.damage_coeff = connected.damage_coeff - src.injector_ready = 0 + injector_ready = FALSE spawn(300) - src.injector_ready = 1 - return 1 + injector_ready = TRUE + return TRUE if(bufferOption == "loadDisk") - if((isnull(src.disk)) || (!src.disk.buf)) - //src.temphtml = "Invalid disk. Please try again." - return 0 + if((isnull(disk)) || (!disk.buf)) + //temphtml = "Invalid disk. Please try again." + return FALSE - src.buffers[bufferId]=src.disk.buf.copy() - //src.temphtml = "Data loaded." - return 1 + buffers[bufferId] = disk.buf.copy() + //temphtml = "Data loaded." + return TRUE if(bufferOption == "saveDisk") - if((isnull(src.disk)) || (src.disk.read_only)) - //src.temphtml = "Invalid disk. Please try again." - return 0 + if((isnull(disk)) || (disk.read_only)) + //temphtml = "Invalid disk. Please try again." + return FALSE - var/datum/dna2/record/buf = src.buffers[bufferId] + var/datum/dna2/record/buf = buffers[bufferId] - src.disk.buf = buf.copy() - src.disk.name = "data disk - '[buf.dna.real_name]'" - //src.temphtml = "Data saved." - return 1 + disk.buf = buf.copy() + disk.name = "data disk - '[buf.dna.real_name]'" + //temphtml = "Data saved." + return TRUE /////////////////////////// DNA MACHINES diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm index 15e2a9cfff4..8b8a86009b9 100644 --- a/code/game/dna/genes/disabilities.dm +++ b/code/game/dna/genes/disabilities.dm @@ -7,114 +7,145 @@ ///////////////////// /datum/dna/gene/disability - name="DISABILITY" + name = "DISABILITY" // Mutation to give (or 0) - var/mutation=0 - - // Disability to give (or 0) - var/disability=0 + var/mutation = 0 // Activation message - var/activation_message="" + var/activation_message = "" // Yay, you're no longer growing 3 arms - var/deactivation_message="" + var/deactivation_message = "" -/datum/dna/gene/disability/can_activate(var/mob/M,var/flags) - return 1 // Always set! +/datum/dna/gene/disability/can_activate(mob/M, flags) + return TRUE // Always set! -/datum/dna/gene/disability/activate(var/mob/living/M, var/connected, var/flags) +/datum/dna/gene/disability/activate(mob/living/M, connected, flags) ..() - if(mutation && !(mutation in M.mutations)) - M.mutations.Add(mutation) - if(disability) - M.disabilities|=disability + M.mutations |= mutation if(activation_message) to_chat(M, "[activation_message]") else testing("[name] has no activation message.") -/datum/dna/gene/disability/deactivate(var/mob/living/M, var/connected, var/flags) +/datum/dna/gene/disability/deactivate(mob/living/M, connected, flags) ..() - if(mutation && (mutation in M.mutations)) - M.mutations.Remove(mutation) - if(disability) - M.disabilities &= ~disability + M.mutations.Remove(mutation) if(deactivation_message) to_chat(M, "[deactivation_message]") else testing("[name] has no deactivation message.") /datum/dna/gene/disability/hallucinate - name="Hallucinate" - activation_message="Your mind says 'Hello'." - deactivation_message ="Sanity returns. Or does it?" + name = "Hallucinate" + activation_message = "Your mind says 'Hello'." + deactivation_message = "Sanity returns. Or does it?" instability = -GENE_INSTABILITY_MODERATE - mutation=HALLUCINATE + mutation = HALLUCINATE /datum/dna/gene/disability/hallucinate/New() - block=HALLUCINATIONBLOCK + ..() + block = GLOB.hallucinationblock + +/datum/dna/gene/disability/hallucinate/OnMobLife(mob/living/carbon/human/H) + if(prob(1)) + H.Hallucinate(20) /datum/dna/gene/disability/epilepsy - name="Epilepsy" - activation_message="You get a headache." - deactivation_message ="Your headache is gone, at last." + name = "Epilepsy" + activation_message = "You get a headache." + deactivation_message = "Your headache is gone, at last." instability = -GENE_INSTABILITY_MODERATE - disability=EPILEPSY + mutation = EPILEPSY /datum/dna/gene/disability/epilepsy/New() - block=EPILEPSYBLOCK + ..() + block = GLOB.epilepsyblock + +/datum/dna/gene/disability/epilepsy/OnMobLife(mob/living/carbon/human/H) + if((prob(1) && H.paralysis < 1)) + H.visible_message("[H] starts having a seizure!","You have a seizure!") + H.Paralyse(10) + H.Jitter(1000) /datum/dna/gene/disability/cough - name="Coughing" - activation_message="You start coughing." - deactivation_message ="Your throat stops aching." + name = "Coughing" + activation_message = "You start coughing." + deactivation_message = "Your throat stops aching." instability = -GENE_INSTABILITY_MINOR - disability=COUGHING + mutation = COUGHING /datum/dna/gene/disability/cough/New() - block=COUGHBLOCK + ..() + block = GLOB.coughblock + +/datum/dna/gene/disability/cough/OnMobLife(mob/living/carbon/human/H) + if((prob(5) && H.paralysis <= 1)) + H.drop_item() + H.emote("cough") /datum/dna/gene/disability/clumsy - name="Clumsiness" - activation_message="You feel lightheaded." - deactivation_message ="You regain some control of your movements" + name = "Clumsiness" + activation_message = "You feel lightheaded." + deactivation_message = "You regain some control of your movements" instability = -GENE_INSTABILITY_MINOR - mutation=CLUMSY + mutation = CLUMSY /datum/dna/gene/disability/clumsy/New() - block=CLUMSYBLOCK + ..() + block = GLOB.clumsyblock /datum/dna/gene/disability/tourettes - name="Tourettes" - activation_message="You twitch." - deactivation_message ="Your mouth tastes like soap." + name = "Tourettes" + activation_message = "You twitch." + deactivation_message = "Your mouth tastes like soap." instability = -GENE_INSTABILITY_MODERATE - disability=TOURETTES + mutation = TOURETTES /datum/dna/gene/disability/tourettes/New() - block=TWITCHBLOCK + ..() + block = GLOB.twitchblock + +/datum/dna/gene/disability/tourettes/OnMobLife(mob/living/carbon/human/H) + if((prob(10) && H.paralysis <= 1)) + H.Stun(10) + switch(rand(1, 3)) + if(1) + H.emote("twitch") + if(2 to 3) + H.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]") + var/x_offset_old = H.pixel_x + var/y_offset_old = H.pixel_y + var/x_offset = H.pixel_x + rand(-2, 2) + var/y_offset = H.pixel_y + rand(-1, 1) + animate(H, pixel_x = x_offset, pixel_y = y_offset, time = 1) + animate(H, pixel_x = x_offset_old, pixel_y = y_offset_old, time = 1) /datum/dna/gene/disability/nervousness - name="Nervousness" + name = "Nervousness" activation_message="You feel nervous." deactivation_message ="You feel much calmer." - disability=NERVOUS + mutation = NERVOUS /datum/dna/gene/disability/nervousness/New() - block=NERVOUSBLOCK + ..() + block = GLOB.nervousblock +/datum/dna/gene/disability/nervousness/OnMobLife(mob/living/carbon/human/H) + if(prob(10)) + H.Stuttering(10) /datum/dna/gene/disability/blindness - name="Blindness" + name = "Blindness" activation_message = "You can't seem to see anything." deactivation_message = "You can see now, in case you didn't notice..." instability = -GENE_INSTABILITY_MAJOR - disability = BLIND + mutation = BLINDNESS /datum/dna/gene/disability/blindness/New() - block = BLINDBLOCK + ..() + block = GLOB.blindblock /datum/dna/gene/disability/blindness/activate(mob/M, connected, flags) ..() @@ -130,51 +161,54 @@ activation_message = "You feel a peculiar prickling in your eyes while your perception of colour changes." deactivation_message ="Your eyes tingle unsettlingly, though everything seems to become alot more colourful." instability = -GENE_INSTABILITY_MODERATE - disability = COLOURBLIND + mutation = COLOURBLIND /datum/dna/gene/disability/colourblindness/New() - block=COLOURBLINDBLOCK + ..() + block = GLOB.colourblindblock -/datum/dna/gene/disability/colourblindness/activate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/disability/colourblindness/activate(mob/M, connected, flags) ..() M.update_client_colour() //Handle the activation of the colourblindness on the mob. M.update_icons() //Apply eyeshine as needed. -/datum/dna/gene/disability/colourblindness/deactivate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/disability/colourblindness/deactivate(mob/M, connected, flags) ..() M.update_client_colour() //Handle the deactivation of the colourblindness on the mob. M.update_icons() //Remove eyeshine as needed. /datum/dna/gene/disability/deaf - name="Deafness" + name = "Deafness" activation_message="It's kinda quiet." deactivation_message ="You can hear again!" instability = -GENE_INSTABILITY_MAJOR - disability=DEAF + mutation = DEAF /datum/dna/gene/disability/deaf/New() - block=DEAFBLOCK + ..() + block = GLOB.deafblock -/datum/dna/gene/disability/deaf/activate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/disability/deaf/activate(mob/M, connected, flags) ..() M.MinimumDeafTicks(1) /datum/dna/gene/disability/nearsighted - name="Nearsightedness" + name = "Nearsightedness" activation_message="Your eyes feel weird..." deactivation_message ="You can see clearly now" instability = -GENE_INSTABILITY_MODERATE - disability=NEARSIGHTED + mutation = NEARSIGHTED /datum/dna/gene/disability/nearsighted/New() - block=GLASSESBLOCK + ..() + block = GLOB.glassesblock /datum/dna/gene/disability/nearsighted/activate(mob/living/M, connected, flags) - . = ..() + ..() M.update_nearsighted_effects() /datum/dna/gene/disability/nearsighted/deactivate(mob/living/M, connected, flags) - . = ..() + ..() M.update_nearsighted_effects() /datum/dna/gene/disability/lisp @@ -186,9 +220,9 @@ /datum/dna/gene/disability/lisp/New() ..() - block=LISPBLOCK + block = GLOB.lispblock -/datum/dna/gene/disability/lisp/OnSay(var/mob/M, var/message) +/datum/dna/gene/disability/lisp/OnSay(mob/M, message) return replacetext(message,"s","th") /datum/dna/gene/disability/comic @@ -196,10 +230,11 @@ desc = "This will only bring death and destruction." activation_message = "Uh oh!" deactivation_message = "Well thank god that's over with." - mutation=COMIC + mutation = COMIC /datum/dna/gene/disability/comic/New() - block = COMICBLOCK + ..() + block = GLOB.comicblock /datum/dna/gene/disability/wingdings name = "Alien Voice" @@ -210,9 +245,10 @@ mutation = WINGDINGS /datum/dna/gene/disability/wingdings/New() - block = WINGDINGSBLOCK + ..() + block = GLOB.wingdingsblock -/datum/dna/gene/disability/wingdings/OnSay(var/mob/M, var/message) +/datum/dna/gene/disability/wingdings/OnSay(mob/M, message) var/list/chars = string2charlist(message) var/garbled_message = "" for(var/C in chars) diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm index f74d0c7d2a0..1509cd098a4 100644 --- a/code/game/dna/genes/gene.dm +++ b/code/game/dna/genes/gene.dm @@ -11,63 +11,61 @@ /datum/dna/gene // Display name - var/name="BASE GENE" + var/name = "BASE GENE" // Probably won't get used but why the fuck not var/desc="Oh god who knows what this does." // Set in initialize()! // What gene activates this? - var/block=0 + var/block = 0 // Any of a number of GENE_ flags. - var/flags=0 + var/flags = 0 // Chance of the gene to cause adverse effects when active - var/instability=0 + var/instability = 0 /* * Is the gene active in this mob's DNA? */ -/datum/dna/gene/proc/is_active(var/mob/M) - return M.active_genes && type in M.active_genes +/datum/dna/gene/proc/is_active(mob/M) + return M.active_genes && (type in M.active_genes) // Return 1 if we can activate. // HANDLE MUTCHK_FORCED HERE! -/datum/dna/gene/proc/can_activate(var/mob/M, var/flags) - return 0 +/datum/dna/gene/proc/can_activate(mob/M, flags) + return FALSE // Called when the gene activates. Do your magic here. -/datum/dna/gene/proc/activate(var/mob/living/M, var/connected, var/flags) +/datum/dna/gene/proc/activate(mob/living/M, connected, flags) M.gene_stability -= instability - return /** * Called when the gene deactivates. Undo your magic here. * Only called when the block is deactivated. */ -/datum/dna/gene/proc/deactivate(var/mob/living/M, var/connected, var/flags) +/datum/dna/gene/proc/deactivate(mob/living/M, connected, flags) M.gene_stability += instability - return // This section inspired by goone's bioEffects. /** * Called in each life() tick. */ -/datum/dna/gene/proc/OnMobLife(var/mob/M) +/datum/dna/gene/proc/OnMobLife(mob/M) return /** * Called when the mob dies */ -/datum/dna/gene/proc/OnMobDeath(var/mob/M) +/datum/dna/gene/proc/OnMobDeath(mob/M) return /** * Called when the mob says shit */ -/datum/dna/gene/proc/OnSay(var/mob/M, var/message) +/datum/dna/gene/proc/OnSay(mob/M, message) return message /** @@ -75,10 +73,9 @@ * * @params M The subject. * @params g Gender (m or f) -* @params fat Fat? (0 or 1) */ -/datum/dna/gene/proc/OnDrawUnderlays(var/mob/M, var/g, var/fat) - return 0 +/datum/dna/gene/proc/OnDrawUnderlays(mob/M, g) + return FALSE ///////////////////// @@ -94,34 +91,34 @@ /datum/dna/gene/basic - name="BASIC GENE" + name = "BASIC GENE" // Mutation to give - var/mutation=0 + var/mutation = 0 // Activation probability - var/activation_prob=100 + var/activation_prob = 100 // Possible activation messages - var/list/activation_messages=list() + var/list/activation_messages = list() // Possible deactivation messages - var/list/deactivation_messages=list() + var/list/deactivation_messages = list() -/datum/dna/gene/basic/can_activate(var/mob/M,var/flags) +/datum/dna/gene/basic/can_activate(mob/M, flags) if(flags & MUTCHK_FORCED) - return 1 + return TRUE // Probability check return prob(activation_prob) -/datum/dna/gene/basic/activate(var/mob/M) +/datum/dna/gene/basic/activate(mob/M, connected, flags) ..() M.mutations.Add(mutation) if(activation_messages.len) var/msg = pick(activation_messages) to_chat(M, "[msg]") -/datum/dna/gene/basic/deactivate(var/mob/M) +/datum/dna/gene/basic/deactivate(mob/living/M, connected, flags) ..() M.mutations.Remove(mutation) if(deactivation_messages.len) diff --git a/code/game/dna/genes/goon_disabilities.dm b/code/game/dna/genes/goon_disabilities.dm index e6c55f02d11..7615f737cd0 100644 --- a/code/game/dna/genes/goon_disabilities.dm +++ b/code/game/dna/genes/goon_disabilities.dm @@ -13,13 +13,13 @@ activation_message = "You feel unable to express yourself at all." deactivation_message = "You feel able to speak freely again." instability = -GENE_INSTABILITY_MODERATE - disability = MUTE + mutation = MUTE /datum/dna/gene/disability/mute/New() ..() - block=MUTEBLOCK + block = GLOB.muteblock -/datum/dna/gene/disability/mute/OnSay(var/mob/M, var/message) +/datum/dna/gene/disability/mute/OnSay(mob/M, message) return "" //////////////////////////////////////// @@ -36,30 +36,29 @@ /datum/dna/gene/disability/radioactive/New() ..() - block=RADBLOCK + block = GLOB.radblock -/datum/dna/gene/disability/radioactive/can_activate(var/mob/M,var/flags) +/datum/dna/gene/disability/radioactive/can_activate(mob/M, flags) if(!..()) - return 0 + return FALSE if(ishuman(M)) var/mob/living/carbon/human/H = M if((RADIMMUNE in H.dna.species.species_traits) && !(flags & MUTCHK_FORCED)) - return 0 - return 1 + return FALSE + return TRUE -/datum/dna/gene/disability/radioactive/OnMobLife(var/mob/living/owner) - var/radiation_amount = abs(min(owner.radiation - 20,0)) - owner.apply_effect(radiation_amount, IRRADIATE) - for(var/mob/living/L in range(1, owner)) - if(L == owner) +/datum/dna/gene/disability/radioactive/OnMobLife(mob/living/carbon/human/H) + var/radiation_amount = abs(min(H.radiation - 20,0)) + H.apply_effect(radiation_amount, IRRADIATE) + for(var/mob/living/L in range(1, H)) + if(L == H) continue - to_chat(L, "You are enveloped by a soft green glow emanating from [owner].") + to_chat(L, "You are enveloped by a soft green glow emanating from [H].") L.apply_effect(5, IRRADIATE) - return -/datum/dna/gene/disability/radioactive/OnDrawUnderlays(var/mob/M,var/g,var/fat) - return "rads[fat]_s" +/datum/dna/gene/disability/radioactive/OnDrawUnderlays(mob/M, g) + return "rads_s" //////////////////////////////////////// // Other disabilities @@ -76,7 +75,7 @@ /datum/dna/gene/disability/fat/New() ..() - block=FATBLOCK + block = GLOB.fatblock // WAS: /datum/bioEffect/chav /datum/dna/gene/disability/speech/chav @@ -88,9 +87,9 @@ /datum/dna/gene/disability/speech/chav/New() ..() - block=CHAVBLOCK + block = GLOB.chavblock -/datum/dna/gene/disability/speech/chav/OnSay(var/mob/M, var/message) +/datum/dna/gene/disability/speech/chav/OnSay(mob/M, message) // THIS ENTIRE THING BEGS FOR REGEX message = replacetext(message,"dick","prat") message = replacetext(message,"comdom","knob'ead") @@ -127,9 +126,9 @@ /datum/dna/gene/disability/speech/swedish/New() ..() - block=SWEDEBLOCK + block = GLOB.swedeblock -/datum/dna/gene/disability/speech/swedish/OnSay(var/mob/M, var/message) +/datum/dna/gene/disability/speech/swedish/OnSay(mob/M, message) // svedish message = replacetextEx(message,"W","V") message = replacetextEx(message,"w","v") @@ -157,10 +156,10 @@ /datum/dna/gene/disability/unintelligable/New() ..() - block=SCRAMBLEBLOCK + block = GLOB.scrambleblock -/datum/dna/gene/disability/unintelligable/OnSay(var/mob/M, var/message) - var/prefix=copytext(message,1,2) +/datum/dna/gene/disability/unintelligable/OnSay(mob/M, message) + var/prefix = copytext(message,1,2) if(prefix == ";") message = copytext(message,2) else if(prefix in list(":","#")) @@ -175,7 +174,7 @@ var/cword = pick(words) words.Remove(cword) var/suffix = copytext(cword,length(cword)-1,length(cword)) - while(length(cword)>0 && suffix in list(".",",",";","!",":","?")) + while(length(cword)>0 && (suffix in list(".",",",";","!",":","?"))) cword = copytext(cword,1 ,length(cword)-1) suffix = copytext(cword,length(cword)-1,length(cword) ) if(length(cword)) @@ -197,7 +196,7 @@ /datum/dna/gene/disability/strong/New() ..() - block=STRONGBLOCK + block = GLOB.strongblock // WAS: /datum/bioEffect/horns /datum/dna/gene/disability/horns @@ -209,9 +208,9 @@ /datum/dna/gene/disability/horns/New() ..() - block=HORNSBLOCK + block = GLOB.hornsblock -/datum/dna/gene/disability/horns/OnDrawUnderlays(var/mob/M,var/g,var/fat) +/datum/dna/gene/disability/horns/OnDrawUnderlays(mob/M, g) return "horns_s" //////////////////////////////////////////////////////////////////////// @@ -223,11 +222,11 @@ deactivation_messages = list("You no longer feel uncomfortably hot.") mutation = IMMOLATE - spelltype=/obj/effect/proc_holder/spell/targeted/immolate + spelltype = /obj/effect/proc_holder/spell/targeted/immolate /datum/dna/gene/basic/grant_spell/immolate/New() ..() - block = IMMOLATEBLOCK + block = GLOB.immolateblock /obj/effect/proc_holder/spell/targeted/immolate name = "Incendiary Mitochondria" diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm index f49a250b0fa..87bbdf97c5c 100644 --- a/code/game/dna/genes/goon_powers.dm +++ b/code/game/dna/genes/goon_powers.dm @@ -2,26 +2,28 @@ // WAS: /datum/bioEffect/alcres /datum/dna/gene/basic/sober - name="Sober" - activation_messages=list("You feel unusually sober.") + name = "Sober" + activation_messages = list("You feel unusually sober.") deactivation_messages = list("You feel like you could use a stiff drink.") - mutation=SOBER + mutation = SOBER /datum/dna/gene/basic/sober/New() - block=SOBERBLOCK + ..() + block = GLOB.soberblock //WAS: /datum/bioEffect/psychic_resist /datum/dna/gene/basic/psychic_resist - name="Psy-Resist" + name = "Psy-Resist" desc = "Boosts efficiency in sectors of the brain commonly associated with meta-mental energies." activation_messages = list("Your mind feels closed.") deactivation_messages = list("You feel oddly exposed.") - mutation=PSY_RESIST + mutation = PSY_RESIST /datum/dna/gene/basic/psychic_resist/New() - block=PSYRESISTBLOCK + ..() + block = GLOB.psyresistblock ///////////////////////// // Stealth Enhancers @@ -30,16 +32,16 @@ /datum/dna/gene/basic/stealth instability = GENE_INSTABILITY_MODERATE -/datum/dna/gene/basic/stealth/can_activate(var/mob/M, var/flags) +/datum/dna/gene/basic/stealth/can_activate(mob/M, flags) // Can only activate one of these at a time. if(is_type_in_list(/datum/dna/gene/basic/stealth,M.active_genes)) testing("Cannot activate [type]: /datum/dna/gene/basic/stealth in M.active_genes.") - return 0 - return ..(M,flags) + return FALSE + return ..() -/datum/dna/gene/basic/stealth/deactivate(var/mob/M) - ..(M) - M.alpha=255 +/datum/dna/gene/basic/stealth/deactivate(mob/living/M, connected, flags) + ..() + M.alpha = 255 // WAS: /datum/bioEffect/darkcloak /datum/dna/gene/basic/stealth/darkcloak @@ -47,13 +49,14 @@ desc = "Enables the subject to bend low levels of light around themselves, creating a cloaking effect." activation_messages = list("You begin to fade into the shadows.") deactivation_messages = list("You become fully visible.") - activation_prob=25 + activation_prob = 25 mutation = CLOAK /datum/dna/gene/basic/stealth/darkcloak/New() - block=SHADOWBLOCK + ..() + block = GLOB.shadowblock -/datum/dna/gene/basic/stealth/darkcloak/OnMobLife(var/mob/M) +/datum/dna/gene/basic/stealth/darkcloak/OnMobLife(mob/M) var/turf/simulated/T = get_turf(M) if(!istype(T)) return @@ -69,13 +72,14 @@ desc = "The subject becomes able to subtly alter light patterns to become invisible, as long as they remain still." activation_messages = list("You feel one with your surroundings.") deactivation_messages = list("You feel oddly visible.") - activation_prob=25 + activation_prob = 25 mutation = CHAMELEON /datum/dna/gene/basic/stealth/chameleon/New() - block=CHAMELEONBLOCK + ..() + block = GLOB.chameleonblock -/datum/dna/gene/basic/stealth/chameleon/OnMobLife(var/mob/M) +/datum/dna/gene/basic/stealth/chameleon/OnMobLife(mob/M) if((world.time - M.last_movement) >= 30 && !M.stat && M.canmove && !M.restrained()) M.alpha -= 25 else @@ -86,27 +90,27 @@ /datum/dna/gene/basic/grant_spell var/obj/effect/proc_holder/spell/spelltype -/datum/dna/gene/basic/grant_spell/activate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/basic/grant_spell/activate(mob/M, connected, flags) M.AddSpell(new spelltype(null)) ..() - return 1 + return TRUE -/datum/dna/gene/basic/grant_spell/deactivate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/basic/grant_spell/deactivate(mob/M, connected, flags) for(var/obj/effect/proc_holder/spell/S in M.mob_spell_list) if(istype(S, spelltype)) M.RemoveSpell(S) ..() - return 1 + return TRUE /datum/dna/gene/basic/grant_verb var/verbtype -/datum/dna/gene/basic/grant_verb/activate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/basic/grant_verb/activate(mob/M, connected, flags) ..() M.verbs += verbtype - return 1 + return TRUE -/datum/dna/gene/basic/grant_verb/deactivate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/basic/grant_verb/deactivate(mob/M, connected, flags) ..() M.verbs -= verbtype @@ -123,7 +127,7 @@ /datum/dna/gene/basic/grant_spell/cryo/New() ..() - block = CRYOBLOCK + block = GLOB.cryoblock /obj/effect/proc_holder/spell/targeted/cryokinesis name = "Cryokinesis" @@ -183,8 +187,6 @@ new/obj/effect/self_deleting(C.loc, icon('icons/effects/genetics.dmi', "cryokinesis")) - return - /obj/effect/self_deleting density = 0 opacity = 0 @@ -193,12 +195,11 @@ desc = "" //layer = 15 -/obj/effect/self_deleting/New(var/atom/location, var/icon/I, var/duration = 20, var/oname = "something") - src.name = oname +/obj/effect/self_deleting/New(atom/location, icon/I, duration = 20, oname = "something") + name = oname loc=location - src.icon = I - spawn(duration) - qdel(src) + icon = I + QDEL_IN(src, duration) /////////////////////////////////////////////////////////////////////////////////////////// @@ -215,7 +216,7 @@ /datum/dna/gene/basic/grant_spell/mattereater/New() ..() - block = EATBLOCK + block = GLOB.eatblock /obj/effect/proc_holder/spell/targeted/eat name = "Eat" @@ -255,7 +256,7 @@ /obj/item/implant ) -/obj/effect/proc_holder/spell/targeted/eat/proc/doHeal(var/mob/user) +/obj/effect/proc_holder/spell/targeted/eat/proc/doHeal(mob/user) if(ishuman(user)) var/mob/living/carbon/human/H = user for(var/name in H.bodyparts_by_name) @@ -300,12 +301,12 @@ perform(targets, user = user) /obj/effect/proc_holder/spell/targeted/eat/proc/check_mouth(mob/user = usr) - var/can_eat = 1 + var/can_eat = TRUE if(iscarbon(user)) var/mob/living/carbon/C = user if((C.head && (C.head.flags_cover & HEADCOVERSMOUTH)) || (C.wear_mask && (C.wear_mask.flags_cover & MASKCOVERSMOUTH) && !C.wear_mask.mask_adjusted)) to_chat(C, "Your mouth is covered, preventing you from eating!") - can_eat = 0 + can_eat = FALSE return can_eat /obj/effect/proc_holder/spell/targeted/eat/cast(list/targets, mob/user = usr) @@ -320,17 +321,17 @@ if(!istype(limb)) to_chat(user, "You can't eat this part of them!") revert_cast() - return 0 + return FALSE if(istype(limb,/obj/item/organ/external/head)) // Bullshit, but prevents being unable to clone someone. to_chat(user, "You try to put \the [limb] in your mouth, but [the_item.p_their()] ears tickle your throat!") revert_cast() - return 0 + return FALSE if(istype(limb,/obj/item/organ/external/chest)) // Bullshit, but prevents being able to instagib someone. to_chat(user, "You try to put [the_item.p_their()] [limb] in your mouth, but it's too big to fit!") revert_cast() - return 0 + return FALSE user.visible_message("[user] begins stuffing [the_item]'s [limb.name] into [user.p_their()] gaping maw!") var/oldloc = H.loc if(!do_mob(user,H,EAT_MOB_DELAY)) @@ -350,7 +351,6 @@ playsound(user.loc, 'sound/items/eatfood.ogg', 50, 0) qdel(the_item) doHeal(user) - return //////////////////////////////////////////////////////////////////////// @@ -368,7 +368,7 @@ /datum/dna/gene/basic/grant_spell/jumpy/New() ..() - block = JUMPBLOCK + block = GLOB.jumpblock /obj/effect/proc_holder/spell/targeted/leap name = "Jump" @@ -387,7 +387,7 @@ action_icon_state = "genetic_jump" /obj/effect/proc_holder/spell/targeted/leap/cast(list/targets, mob/user = usr) - var/failure = 0 + var/failure = FALSE if(istype(user.loc,/mob/) || user.lying || user.stunned || user.buckled || user.stat) to_chat(user, "You can't jump right now!") return @@ -397,7 +397,7 @@ for(var/mob/M in range(user, 1)) if(M.pulling == user) if(!M.restrained() && M.stat == 0 && M.canmove && user.Adjacent(M)) - failure = 1 + failure = TRUE else M.stop_pulling() @@ -409,12 +409,12 @@ user.visible_message("[user] attempts to leap away but is slammed back down to the ground!", "You attempt to leap away but are suddenly slammed back down to the ground!", "You hear the flexing of powerful muscles and suddenly a crash as a body hits the floor.") - return 0 + return FALSE var/prevLayer = user.layer var/prevFlying = user.flying user.layer = 9 - user.flying = 1 + user.flying = TRUE for(var/i=0, i<10, i++) step(user, user.dir) if(i < 5) user.pixel_y += 8 @@ -463,7 +463,7 @@ /datum/dna/gene/basic/grant_spell/polymorph/New() ..() - block = POLYMORPHBLOCK + block = GLOB.polymorphblock /obj/effect/proc_holder/spell/targeted/polymorph name = "Polymorph" @@ -508,11 +508,11 @@ activation_messages = list("You suddenly notice more about others than you did before.") deactivation_messages = list("You no longer feel able to sense intentions.") instability = GENE_INSTABILITY_MINOR - mutation=EMPATH + mutation = EMPATH /datum/dna/gene/basic/grant_spell/empath/New() ..() - block = EMPATHBLOCK + block = GLOB.empathblock /obj/effect/proc_holder/spell/targeted/empath name = "Read Mind" @@ -614,4 +614,3 @@ to_chat(M, "You sense [user.name] reading your mind.") else if(prob(5) || M.mind.assigned_role=="Chaplain") to_chat(M, "You sense someone intruding upon your thoughts...") - return diff --git a/code/game/dna/genes/monkey.dm b/code/game/dna/genes/monkey.dm index 9be8256eebe..583b2c75836 100644 --- a/code/game/dna/genes/monkey.dm +++ b/code/game/dna/genes/monkey.dm @@ -1,10 +1,11 @@ /datum/dna/gene/monkey - name="Monkey" + name = "Monkey" /datum/dna/gene/monkey/New() - block=MONKEYBLOCK + ..() + block = GLOB.monkeyblock -/datum/dna/gene/monkey/can_activate(var/mob/M,var/flags) +/datum/dna/gene/monkey/can_activate(mob/M, flags) return ishuman(M) /datum/dna/gene/monkey/activate(mob/living/carbon/human/H, connected, flags) @@ -21,7 +22,7 @@ H.regenerate_icons() H.SetStunned(1) - H.canmove = 0 + H.canmove = FALSE H.icon = null H.invisibility = 101 var/has_primitive_form = H.dna.species.primitive_form // cache this diff --git a/code/game/dna/genes/powers.dm b/code/game/dna/genes/powers.dm index f8b231372dc..d893c64565c 100644 --- a/code/game/dna/genes/powers.dm +++ b/code/game/dna/genes/powers.dm @@ -3,109 +3,121 @@ /////////////////////////////////// /datum/dna/gene/basic/nobreath - name="No Breathing" - activation_messages=list("You feel no need to breathe.") - deactivation_messages=list("You feel the need to breathe, once more.") + name = "No Breathing" + activation_messages = list("You feel no need to breathe.") + deactivation_messages = list("You feel the need to breathe, once more.") instability = GENE_INSTABILITY_MODERATE mutation = BREATHLESS - activation_prob=25 + activation_prob = 25 /datum/dna/gene/basic/nobreath/New() - block = BREATHLESSBLOCK + ..() + block = GLOB.breathlessblock /datum/dna/gene/basic/regenerate - name="Regenerate" - activation_messages=list("Your wounds start healing.") - deactivation_messages=list("Your regenerative powers feel like they've vanished.") + name = "Regenerate" + activation_messages = list("Your wounds start healing.") + deactivation_messages = list("Your regenerative powers feel like they've vanished.") instability = GENE_INSTABILITY_MINOR - mutation=REGEN + mutation = REGEN /datum/dna/gene/basic/regenerate/New() - block=REGENERATEBLOCK + ..() + block = GLOB.regenerateblock + +/datum/dna/gene/basic/regenerate/OnMobLife(mob/living/carbon/human/H) + H.adjustBruteLoss(-0.1, FALSE) + H.adjustFireLoss(-0.1) /datum/dna/gene/basic/increaserun - name="Super Speed" - activation_messages=list("You feel swift and unencumbered.") - deactivation_messages=list("You feel slow.") + name = "Super Speed" + activation_messages = list("You feel swift and unencumbered.") + deactivation_messages = list("You feel slow.") instability = GENE_INSTABILITY_MINOR - mutation=RUN + mutation = RUN /datum/dna/gene/basic/increaserun/New() - block=INCREASERUNBLOCK + ..() + block = GLOB.increaserunblock -/datum/dna/gene/basic/increaserun/can_activate(var/mob/M,var/flags) +/datum/dna/gene/basic/increaserun/can_activate(mob/M, flags) if(!..()) - return 0 + return FALSE if(ishuman(M)) var/mob/living/carbon/human/H = M if(H.dna.species && H.dna.species.speed_mod && !(flags & MUTCHK_FORCED)) - return 0 - return 1 + return FALSE + return TRUE /datum/dna/gene/basic/heat_resist - name="Heat Resistance" - activation_messages=list("Your skin is icy to the touch.") - deactivation_messages=list("Your skin no longer feels icy to the touch.") + name = "Heat Resistance" + activation_messages = list("Your skin is icy to the touch.") + deactivation_messages = list("Your skin no longer feels icy to the touch.") instability = GENE_INSTABILITY_MODERATE mutation = HEATRES /datum/dna/gene/basic/heat_resist/New() - block=COLDBLOCK + ..() + block = GLOB.coldblock -/datum/dna/gene/basic/heat_resist/OnDrawUnderlays(var/mob/M,var/g,var/fat) - return "cold[fat]_s" +/datum/dna/gene/basic/heat_resist/OnDrawUnderlays(mob/M, g) + return "cold_s" /datum/dna/gene/basic/cold_resist - name="Cold Resistance" - activation_messages=list("Your body is filled with warmth.") - deactivation_messages=list("Your body is no longer filled with warmth.") + name = "Cold Resistance" + activation_messages = list("Your body is filled with warmth.") + deactivation_messages = list("Your body is no longer filled with warmth.") instability = GENE_INSTABILITY_MODERATE mutation = COLDRES /datum/dna/gene/basic/cold_resist/New() - block=FIREBLOCK + ..() + block = GLOB.fireblock -/datum/dna/gene/basic/cold_resist/OnDrawUnderlays(var/mob/M,var/g,var/fat) - return "fire[fat]_s" +/datum/dna/gene/basic/cold_resist/OnDrawUnderlays(mob/M, g) + return "fire_s" /datum/dna/gene/basic/noprints - name="No Prints" - activation_messages=list("Your fingers feel numb.") - deactivation_messages=list("your fingers no longer feel numb.") + name = "No Prints" + activation_messages = list("Your fingers feel numb.") + deactivation_messages = list("your fingers no longer feel numb.") instability = GENE_INSTABILITY_MINOR - mutation=FINGERPRINTS + mutation = FINGERPRINTS /datum/dna/gene/basic/noprints/New() - block=NOPRINTSBLOCK + ..() + block = GLOB.noprintsblock /datum/dna/gene/basic/noshock - name="Shock Immunity" - activation_messages=list("Your skin feels dry and unreactive.") - deactivation_messages=list("Your skin no longer feels dry and unreactive.") + name = "Shock Immunity" + activation_messages = list("Your skin feels dry and unreactive.") + deactivation_messages = list("Your skin no longer feels dry and unreactive.") instability = GENE_INSTABILITY_MODERATE - mutation=NO_SHOCK + mutation = NO_SHOCK /datum/dna/gene/basic/noshock/New() - block=SHOCKIMMUNITYBLOCK + ..() + block = GLOB.shockimmunityblock /datum/dna/gene/basic/midget - name="Midget" - activation_messages=list("Everything around you seems bigger now...") + name = "Midget" + activation_messages = list("Everything around you seems bigger now...") deactivation_messages = list("Everything around you seems to shrink...") instability = GENE_INSTABILITY_MINOR - mutation=DWARF + mutation = DWARF /datum/dna/gene/basic/midget/New() - block=SMALLSIZEBLOCK + ..() + block = GLOB.smallsizeblock -/datum/dna/gene/basic/midget/activate(var/mob/M, var/connected, var/flags) - ..(M,connected,flags) +/datum/dna/gene/basic/midget/activate(mob/M, connected, flags) + ..() M.pass_flags |= PASSTABLE M.resize = 0.8 M.update_transform() -/datum/dna/gene/basic/midget/deactivate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/basic/midget/deactivate(mob/M, connected, flags) ..() M.pass_flags &= ~PASSTABLE M.resize = 1.25 @@ -113,55 +125,54 @@ // OLD HULK BEHAVIOR /datum/dna/gene/basic/hulk - name="Hulk" - activation_messages=list("Your muscles hurt.") - deactivation_messages=list("Your muscles shrink.") + name = "Hulk" + activation_messages = list("Your muscles hurt.") + deactivation_messages = list("Your muscles shrink.") instability = GENE_INSTABILITY_MAJOR - mutation=HULK - activation_prob=15 + mutation = HULK + activation_prob = 15 /datum/dna/gene/basic/hulk/New() - block=HULKBLOCK + ..() + block = GLOB.hulkblock -/datum/dna/gene/basic/hulk/activate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/basic/hulk/activate(mob/M, connected, flags) ..() var/status = CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH M.status_flags &= ~status -/datum/dna/gene/basic/hulk/deactivate(var/mob/M, var/connected, var/flags) +/datum/dna/gene/basic/hulk/deactivate(mob/M, connected, flags) ..() M.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH -/datum/dna/gene/basic/hulk/OnDrawUnderlays(var/mob/M,var/g,var/fat) +/datum/dna/gene/basic/hulk/OnDrawUnderlays(mob/M, g) if(HULK in M.mutations) - if(fat) - return "hulk_[fat]_s" - else - return "hulk_[g]_s" - return 0 + return "hulk_[g]_s" + return FALSE -/datum/dna/gene/basic/hulk/OnMobLife(var/mob/living/carbon/human/M) +/datum/dna/gene/basic/hulk/OnMobLife(mob/living/carbon/human/M) if(!istype(M)) return if((HULK in M.mutations) && M.health <= 0) M.mutations.Remove(HULK) - M.dna.SetSEState(HULKBLOCK,0) - genemutcheck(M, HULKBLOCK,null,MUTCHK_FORCED) + M.dna.SetSEState(GLOB.hulkblock,0) + genemutcheck(M, GLOB.hulkblock,null,MUTCHK_FORCED) M.update_mutations() //update our mutation overlays M.update_body() M.status_flags |= CANSTUN | CANWEAKEN | CANPARALYSE | CANPUSH //temporary fix until the problem can be solved. to_chat(M, "You suddenly feel very weak.") /datum/dna/gene/basic/xray - name="X-Ray Vision" - activation_messages=list("The walls suddenly disappear.") - deactivation_messages=list("the walls around you re-appear.") + name = "X-Ray Vision" + activation_messages = list("The walls suddenly disappear.") + deactivation_messages = list("the walls around you re-appear.") instability = GENE_INSTABILITY_MAJOR - mutation=XRAY - activation_prob=15 + mutation = XRAY + activation_prob = 15 /datum/dna/gene/basic/xray/New() - block=XRAYBLOCK + ..() + block = GLOB.xrayblock /datum/dna/gene/basic/xray/activate(mob/living/M, connected, flags) ..() @@ -174,15 +185,16 @@ M.update_icons() //Remove eyeshine as needed. /datum/dna/gene/basic/tk - name="Telekenesis" + name = "Telekenesis" activation_messages = list("You feel smarter.") deactivation_messages = list("You feel dumber.") instability = GENE_INSTABILITY_MAJOR - mutation=TK - activation_prob=15 + mutation = TK + activation_prob = 15 /datum/dna/gene/basic/tk/New() - block=TELEBLOCK + ..() + block = GLOB.teleblock -/datum/dna/gene/basic/tk/OnDrawUnderlays(var/mob/M,var/g,var/fat) - return "telekinesishead[fat]_s" +/datum/dna/gene/basic/tk/OnDrawUnderlays(mob/M, g) + return "telekinesishead_s" diff --git a/code/game/dna/genes/vg_disabilities.dm b/code/game/dna/genes/vg_disabilities.dm index 79f1ca16411..c2ad1559b6a 100644 --- a/code/game/dna/genes/vg_disabilities.dm +++ b/code/game/dna/genes/vg_disabilities.dm @@ -8,11 +8,11 @@ /datum/dna/gene/disability/speech/loud/New() ..() - block=LOUDBLOCK + block = GLOB.loudblock -/datum/dna/gene/disability/speech/loud/OnSay(var/mob/M, var/message) +/datum/dna/gene/disability/speech/loud/OnSay(mob/M, message) message = replacetext(message,".","!") message = replacetext(message,"?","?!") message = replacetext(message,"!","!!") @@ -28,15 +28,15 @@ /datum/dna/gene/disability/dizzy/New() ..() - block=DIZZYBLOCK + block = GLOB.dizzyblock -/datum/dna/gene/disability/dizzy/OnMobLife(var/mob/living/carbon/human/M) +/datum/dna/gene/disability/dizzy/OnMobLife(mob/living/carbon/human/M) if(!istype(M)) return if(DIZZY in M.mutations) M.Dizzy(300) /datum/dna/gene/disability/dizzy/deactivate(mob/living/M, connected, flags) - . = ..() + ..() M.SetDizzy(0) diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 506ef5714f8..9092448e398 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -4,14 +4,14 @@ name = "Morphism" desc = "Enables the subject to reconfigure their appearance to that of any human." spelltype =/obj/effect/proc_holder/spell/targeted/morph - activation_messages=list("Your body feels if can alter its appearance.") + activation_messages = list("Your body feels if can alter its appearance.") deactivation_messages = list("Your body doesn't feel capable of altering its appearance.") instability = GENE_INSTABILITY_MINOR - mutation=MORPH + mutation = MORPH /datum/dna/gene/basic/grant_spell/morph/New() ..() - block = MORPHBLOCK + block = GLOB.morphblock /obj/effect/proc_holder/spell/targeted/morph name = "Morph" @@ -29,7 +29,8 @@ action_icon_state = "genetic_morph" /obj/effect/proc_holder/spell/targeted/morph/cast(list/targets, mob/user = usr) - if(!ishuman(user)) return + if(!ishuman(user)) + return if(istype(user.loc,/mob/)) to_chat(user, "You can't change your appearance right now!") @@ -173,24 +174,24 @@ M.update_dna() - M.visible_message("[src] morphs and changes [p_their()] appearance!", "You change your appearance!", "Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!") + M.visible_message("[M] morphs and changes [M.p_their()] appearance!", "You change your appearance!", "Oh, god! What the hell was that? It sounded like flesh getting squished and bone ground into a different shape!") /datum/dna/gene/basic/grant_spell/remotetalk - name="Telepathy" - activation_messages=list("You feel you can project your thoughts.") - deactivation_messages=list("You no longer feel you can project your thoughts.") + name = "Telepathy" + activation_messages = list("You feel you can project your thoughts.") + deactivation_messages = list("You no longer feel you can project your thoughts.") instability = GENE_INSTABILITY_MINOR - mutation=REMOTE_TALK + mutation = REMOTE_TALK spelltype =/obj/effect/proc_holder/spell/targeted/remotetalk /datum/dna/gene/basic/grant_spell/remotetalk/New() ..() - block=REMOTETALKBLOCK + block = GLOB.remotetalkblock -/datum/dna/gene/basic/grant_spell/remotetalk/activate(mob/user) +/datum/dna/gene/basic/grant_spell/remotetalk/activate(mob/living/M, connected, flags) ..() - user.AddSpell(new /obj/effect/proc_holder/spell/targeted/mindscan(null)) + M.AddSpell(new /obj/effect/proc_holder/spell/targeted/mindscan(null)) /datum/dna/gene/basic/grant_spell/remotetalk/deactivate(mob/user) ..() @@ -336,22 +337,23 @@ return ..() /datum/dna/gene/basic/grant_spell/remoteview - name="Remote Viewing" - activation_messages=list("Your mind can see things from afar.") - deactivation_messages=list("Your mind can no longer can see things from afar.") + name = "Remote Viewing" + activation_messages = list("Your mind can see things from afar.") + deactivation_messages = list("Your mind can no longer can see things from afar.") instability = GENE_INSTABILITY_MINOR - mutation=REMOTE_VIEW + mutation = REMOTE_VIEW spelltype =/obj/effect/proc_holder/spell/targeted/remoteview /datum/dna/gene/basic/grant_spell/remoteview/New() - block=REMOTEVIEWBLOCK + ..() + block = GLOB.remoteviewblock /obj/effect/proc_holder/spell/targeted/remoteview name = "Remote View" desc = "Spy on people from any range!" - charge_max = 600 + charge_max = 100 clothes_req = 0 stat_allowed = 0 @@ -363,18 +365,23 @@ /obj/effect/proc_holder/spell/targeted/remoteview/choose_targets(mob/user = usr) var/list/targets = list() - var/list/remoteviewers = new /list() - for(var/mob/M in GLOB.living_mob_list) + var/list/remoteviewers = list() + for(var/mob/M in GLOB.alive_mob_list) + if(M == user) + continue if(PSY_RESIST in M.mutations) continue if(REMOTE_VIEW in M.mutations) remoteviewers += M - if(!remoteviewers.len || remoteviewers.len == 1) + if(!LAZYLEN(remoteviewers)) to_chat(user, "No valid targets with remote view were found!") start_recharge() return - targets += input("Choose the target to spy on.", "Targeting") as mob in remoteviewers - + targets += input("Choose the target to spy on.", "Targeting") as null|anything in remoteviewers + if(!targets) + to_chat(user, "You decide against remote viewing.") + start_recharge() + return perform(targets, user = user) /obj/effect/proc_holder/spell/targeted/remoteview/cast(list/targets, mob/user = usr) @@ -386,15 +393,15 @@ var/mob/target - if(istype(H.l_hand, /obj/item/tk_grab) || istype(H.r_hand, /obj/item/tk_grab/)) + if(istype(H.l_hand, /obj/item/tk_grab) || istype(H.r_hand, /obj/item/tk_grab)) to_chat(H, "Your mind is too busy with that telekinetic grab.") H.remoteview_target = null - H.reset_perspective(0) + H.reset_perspective() return if(H.client.eye != user.client.mob) H.remoteview_target = null - H.reset_perspective(0) + H.reset_perspective() return for(var/mob/living/L in targets) @@ -405,4 +412,4 @@ H.reset_perspective(target) else H.remoteview_target = null - H.reset_perspective(0) + H.reset_perspective() diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm index ab34122ba90..a11e5d922ba 100644 --- a/code/game/gamemodes/blob/blob.dm +++ b/code/game/gamemodes/blob/blob.dm @@ -1,7 +1,7 @@ //Few global vars to track the blob -var/list/blobs = list() -var/list/blob_cores = list() -var/list/blob_nodes = list() +GLOBAL_LIST_EMPTY(blobs) +GLOBAL_LIST_EMPTY(blob_cores) +GLOBAL_LIST_EMPTY(blob_nodes) /datum/game_mode var/list/blob_overminds = list() @@ -196,16 +196,16 @@ var/list/blob_nodes = list() send_intercept(1) declared = 1 if(1) - event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg') + GLOB.event_announcement.Announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/AI/outbreak5.ogg') if(2) send_intercept(2) /datum/game_mode/proc/update_blob_icons_added(datum/mind/mob_mind) - var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_BLOB] + var/datum/atom_hud/antag/antaghud = GLOB.huds[ANTAG_HUD_BLOB] antaghud.join_hud(mob_mind.current) set_antag_hud(mob_mind.current, "hudblob") /datum/game_mode/proc/update_blob_icons_removed(datum/mind/mob_mind) - var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_BLOB] + var/datum/atom_hud/antag/antaghud = GLOB.huds[ANTAG_HUD_BLOB] antaghud.leave_hud(mob_mind.current) set_antag_hud(mob_mind.current, null) diff --git a/code/game/gamemodes/blob/blob_finish.dm b/code/game/gamemodes/blob/blob_finish.dm index 66131cfc9f9..b1ef70f6b4f 100644 --- a/code/game/gamemodes/blob/blob_finish.dm +++ b/code/game/gamemodes/blob/blob_finish.dm @@ -1,15 +1,15 @@ /datum/game_mode/blob/check_finished() if(infected_crew.len > burst)//Some blobs have yet to burst return 0 - if(blobwincount <= blobs.len)//Blob took over + if(blobwincount <= GLOB.blobs.len)//Blob took over return 1 - if(!blob_cores.len) // blob is dead + if(!GLOB.blob_cores.len) // blob is dead return 1 return ..() /datum/game_mode/blob/declare_completion() - if(blobwincount <= blobs.len) + if(blobwincount <= GLOB.blobs.len) feedback_set_details("round_end_result","blob win - blob took over") to_chat(world, "The blob has taken over the station!") to_chat(world, "The entire station was eaten by the Blob") @@ -21,7 +21,7 @@ to_chat(world, "Directive 7-12 has been successfully carried out preventing the Blob from spreading.") log_game("Blob mode completed with a tie (station destroyed).") - else if(!blob_cores.len) + else if(!GLOB.blob_cores.len) feedback_set_details("round_end_result","blob loss - blob eliminated") to_chat(world, "The staff has won!") to_chat(world, "The alien organism has been eradicated from the station") diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm index 4f667c51d61..6128c22f66d 100644 --- a/code/game/gamemodes/blob/blob_report.dm +++ b/code/game/gamemodes/blob/blob_report.dm @@ -3,7 +3,6 @@ var/interceptname = "" switch(report) if(0) - ..() return if(1) interceptname = "Level 5-6 Biohazard Response Procedures" @@ -42,7 +41,7 @@ to_chat(aiPlayer, "Laws Updated: [law]") print_command_report(intercepttext, interceptname) - event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg', from = "[command_name()] Update") + GLOB.event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg', from = "[command_name()] Update") /datum/station_state var/floor = 0 diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm index fb26ce91698..b7bcd737dfd 100644 --- a/code/game/gamemodes/blob/blobs/blob_mobs.dm +++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm @@ -51,7 +51,8 @@ speak_emote = list("pulses") var/obj/structure/blob/factory/factory = null var/list/human_overlays = list() - var/is_zombie = 0 + var/mob/living/carbon/human/oldguy + var/is_zombie = FALSE /mob/living/simple_animal/hostile/blob/blobspore/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE) ..() @@ -102,6 +103,7 @@ human_overlays = H.overlays update_icons() H.forceMove(src) + oldguy = H visible_message("The corpse of [H.name] suddenly rises!") /mob/living/simple_animal/hostile/blob/blobspore/death(gibbed) @@ -130,9 +132,9 @@ if(factory) factory.spores -= src factory = null - if(contents) - for(var/mob/M in contents) - M.loc = get_turf(src) + if(oldguy) + oldguy.forceMove(get_turf(src)) + oldguy = null return ..() diff --git a/code/game/gamemodes/blob/blobs/core.dm b/code/game/gamemodes/blob/blobs/core.dm index 8c3af0be2ca..672ab037cc5 100644 --- a/code/game/gamemodes/blob/blobs/core.dm +++ b/code/game/gamemodes/blob/blobs/core.dm @@ -13,7 +13,7 @@ var/selecting = 0 /obj/structure/blob/core/New(loc, var/h = 200, var/client/new_overmind = null, var/new_rate = 2, offspring) - blob_cores += src + GLOB.blob_cores += src START_PROCESSING(SSobj, src) GLOB.poi_list |= src adjustcolors(color) //so it atleast appears @@ -38,7 +38,7 @@ /obj/structure/blob/core/Destroy() - blob_cores -= src + GLOB.blob_cores -= src if(overmind) overmind.blob_core = null overmind = null @@ -75,7 +75,7 @@ else for(var/i = 1; i < 8; i += i) Pulse(0, i, color) - for(var/b_dir in alldirs) + for(var/b_dir in GLOB.alldirs) if(!prob(5)) continue var/obj/structure/blob/normal/B = locate() in get_step(src, b_dir) diff --git a/code/game/gamemodes/blob/blobs/node.dm b/code/game/gamemodes/blob/blobs/node.dm index b84e0a7a84c..d8fe4943586 100644 --- a/code/game/gamemodes/blob/blobs/node.dm +++ b/code/game/gamemodes/blob/blobs/node.dm @@ -7,7 +7,7 @@ point_return = 18 /obj/structure/blob/node/New(loc, var/h = 100) - blob_nodes += src + GLOB.blob_nodes += src START_PROCESSING(SSobj, src) ..(loc, h) @@ -21,7 +21,7 @@ src.overlays += C /obj/structure/blob/node/Destroy() - blob_nodes -= src + GLOB.blob_nodes -= src STOP_PROCESSING(SSobj, src) return ..() diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index 74ed59d2469..0c2342328a2 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -35,11 +35,15 @@ color = blob_reagent_datum.complementary_color ..() + START_PROCESSING(SSobj, src) -/mob/camera/blob/Life(seconds, times_fired) +/mob/camera/blob/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/mob/camera/blob/process() if(!blob_core) qdel(src) - ..() /mob/camera/blob/Login() ..() diff --git a/code/game/gamemodes/blob/powers.dm b/code/game/gamemodes/blob/powers.dm index 548f2759ba0..6f2eed39499 100644 --- a/code/game/gamemodes/blob/powers.dm +++ b/code/game/gamemodes/blob/powers.dm @@ -22,10 +22,10 @@ set name = "Jump to Node" set desc = "Transport back to a selected node." - if(blob_nodes.len) + if(GLOB.blob_nodes.len) var/list/nodes = list() - for(var/i = 1; i <= blob_nodes.len; i++) - var/obj/structure/blob/node/B = blob_nodes[i] + for(var/i = 1; i <= GLOB.blob_nodes.len; i++) + var/obj/structure/blob/node/B = GLOB.blob_nodes[i] nodes["Blob Node #[i] ([get_location_name(B)])"] = B var/node_name = input(src, "Choose a node to jump to.", "Node Jump") in nodes var/obj/structure/blob/node/chosen_node = nodes[node_name] @@ -357,7 +357,7 @@ if(!surrounding_turfs.len) return - for(var/mob/living/simple_animal/hostile/blob/blobspore/BS in GLOB.living_mob_list) + for(var/mob/living/simple_animal/hostile/blob/blobspore/BS in GLOB.alive_mob_list) if(isturf(BS.loc) && get_dist(BS, T) <= 35) BS.LoseTarget() BS.Goto(pick(surrounding_turfs), BS.move_to_delay) @@ -463,7 +463,7 @@ color = blob_reagent_datum.complementary_color - for(var/obj/structure/blob/BL in blobs) + for(var/obj/structure/blob/BL in GLOB.blobs) BL.adjustcolors(blob_reagent_datum.color) for(var/mob/living/simple_animal/hostile/blob/BLO) diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index b97c8311507..886975a2c92 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -18,8 +18,8 @@ /obj/structure/blob/New(loc) ..() - blobs += src - setDir(pick(cardinal)) + GLOB.blobs += src + setDir(pick(GLOB.cardinal)) update_icon() if(atmosblock) air_update_turf(1) @@ -29,8 +29,8 @@ if(atmosblock) atmosblock = FALSE air_update_turf(1) - blobs -= src - if(isturf(loc)) //Necessary because Expand() is retarded and spawns a blob and then deletes it + GLOB.blobs -= src + if(isturf(loc)) //Necessary because Expand() is screwed up and spawns a blob and then deletes it playsound(src.loc, 'sound/effects/splat.ogg', 50, 1) return ..() diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm index afad318a517..91dd553fe0d 100644 --- a/code/game/gamemodes/changeling/changeling.dm +++ b/code/game/gamemodes/changeling/changeling.dm @@ -2,7 +2,7 @@ #define LING_DEAD_GENETICDAMAGE_HEAL_CAP 50 //The lowest value of geneticdamage handle_changeling() can take it to while dead. #define LING_ABSORB_RECENT_SPEECH 8 //The amount of recent spoken lines to gain on absorbing a mob -var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega") +GLOBAL_LIST_INIT(possible_changeling_IDs, list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega")) /datum/game_mode var/list/datum/mind/changelings = list() @@ -162,12 +162,12 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" update_change_icons_removed(changeling_mind) /datum/game_mode/proc/update_change_icons_added(datum/mind/changeling) - var/datum/atom_hud/antag/linghud = huds[ANTAG_HUD_CHANGELING] + var/datum/atom_hud/antag/linghud = GLOB.huds[ANTAG_HUD_CHANGELING] linghud.join_hud(changeling.current) set_antag_hud(changeling.current, "hudchangeling") /datum/game_mode/proc/update_change_icons_removed(datum/mind/changeling) - var/datum/atom_hud/antag/linghud = huds[ANTAG_HUD_CHANGELING] + var/datum/atom_hud/antag/linghud = GLOB.huds[ANTAG_HUD_CHANGELING] linghud.leave_hud(changeling.current) set_antag_hud(changeling.current, null) @@ -253,9 +253,9 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon" honorific = "Ms." else honorific = "Mr." - if(possible_changeling_IDs.len) - changelingID = pick(possible_changeling_IDs) - possible_changeling_IDs -= changelingID + if(GLOB.possible_changeling_IDs.len) + changelingID = pick(GLOB.possible_changeling_IDs) + GLOB.possible_changeling_IDs -= changelingID changelingID = "[honorific] [changelingID]" else changelingID = "[honorific] [rand(1,999)]" diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm index b6a0213f82f..9c33ffaaca5 100644 --- a/code/game/gamemodes/changeling/evolution_menu.dm +++ b/code/game/gamemodes/changeling/evolution_menu.dm @@ -1,4 +1,4 @@ -var/list/sting_paths +GLOBAL_LIST_EMPTY(sting_paths) // totally stolen from the new player panel. YAYY /datum/action/changeling/evolution_menu @@ -12,8 +12,8 @@ var/list/sting_paths return var/datum/changeling/changeling = usr.mind.changeling - if(!sting_paths) - sting_paths = init_subtypes(/datum/action/changeling) + if(!GLOB.sting_paths || !GLOB.sting_paths.len) + GLOB.sting_paths = init_subtypes(/datum/action/changeling) var/dat = create_menu(changeling) usr << browse(dat, "window=powers;size=600x700")//900x480 @@ -230,7 +230,7 @@ var/list/sting_paths "} var/i = 1 - for(var/datum/action/changeling/cling_power in sting_paths) + for(var/datum/action/changeling/cling_power in GLOB.sting_paths) if(cling_power.dna_cost <= 0) //Let's skip the crap we start with. Keeps the evolution menu uncluttered. continue diff --git a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm index 4663fef8b97..34a2d67b58b 100644 --- a/code/game/gamemodes/changeling/powers/augmented_eyesight.dm +++ b/code/game/gamemodes/changeling/powers/augmented_eyesight.dm @@ -49,7 +49,7 @@ /obj/item/organ/internal/cyberimp/eyes/shield/ling/on_life() ..() var/obj/item/organ/internal/eyes/E = owner.get_int_organ(/obj/item/organ/internal/eyes) - if(owner.eye_blind || owner.eye_blurry || (owner.disabilities & BLIND) || (owner.disabilities & NEARSIGHTED) || (E.damage > 0)) + if(owner.eye_blind || owner.eye_blurry || (BLINDNESS in owner.mutations) || (NEARSIGHTED in owner.mutations) || (E.damage > 0)) owner.reagents.add_reagent("oculine", 1) /obj/item/organ/internal/cyberimp/eyes/shield/ling/prepare_eat() diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm index 7de16801153..4b53e5ce082 100644 --- a/code/game/gamemodes/changeling/powers/chameleon_skin.dm +++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm @@ -11,19 +11,19 @@ var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1 if(!istype(H)) // req_human could be done in can_sting stuff. return - if(H.dna.GetSEState(CHAMELEONBLOCK)) - H.dna.SetSEState(CHAMELEONBLOCK, 0) - genemutcheck(H, CHAMELEONBLOCK, null, MUTCHK_FORCED) + if(H.dna.GetSEState(GLOB.chameleonblock)) + H.dna.SetSEState(GLOB.chameleonblock, 0) + genemutcheck(H, GLOB.chameleonblock, null, MUTCHK_FORCED) else - H.dna.SetSEState(CHAMELEONBLOCK, 1) - genemutcheck(H, CHAMELEONBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.chameleonblock, 1) + genemutcheck(H, GLOB.chameleonblock, null, MUTCHK_FORCED) feedback_add_details("changeling_powers","CS") return TRUE /datum/action/changeling/chameleon_skin/Remove(mob/user) var/mob/living/carbon/C = user - if(C.dna.GetSEState(CHAMELEONBLOCK)) - C.dna.SetSEState(CHAMELEONBLOCK, 0) - genemutcheck(C, CHAMELEONBLOCK, null, MUTCHK_FORCED) + if(C.dna.GetSEState(GLOB.chameleonblock)) + C.dna.SetSEState(GLOB.chameleonblock, 0) + genemutcheck(C, GLOB.chameleonblock, null, MUTCHK_FORCED) ..() diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm index d403059b0c7..61882b85287 100644 --- a/code/game/gamemodes/changeling/powers/fakedeath.dm +++ b/code/game/gamemodes/changeling/powers/fakedeath.dm @@ -16,11 +16,8 @@ user.emote("deathgasp") user.timeofdeath = world.time user.status_flags |= FAKEDEATH //play dead - user.update_stat("fakedeath sting") + user.updatehealth("fakedeath sting") user.update_canmove() - user.med_hud_set_health() - user.handle_hud_icons_health() - user.med_hud_set_status() user.mind.changeling.regenerating = TRUE addtimer(CALLBACK(src, .proc/ready_to_regenerate, user), LING_FAKEDEATH_TIME) diff --git a/code/game/gamemodes/changeling/powers/hivemind.dm b/code/game/gamemodes/changeling/powers/hivemind.dm index af375cad368..98336608da4 100644 --- a/code/game/gamemodes/changeling/powers/hivemind.dm +++ b/code/game/gamemodes/changeling/powers/hivemind.dm @@ -23,7 +23,7 @@ return // HIVE MIND UPLOAD/DOWNLOAD DNA -var/list/datum/dna/hivemind_bank = list() +GLOBAL_LIST_EMPTY(hivemind_bank) /datum/action/changeling/hivemind_upload name = "Hive Channel DNA" @@ -36,7 +36,7 @@ var/list/datum/dna/hivemind_bank = list() var/datum/changeling/changeling = user.mind.changeling var/list/names = list() for(var/datum/dna/DNA in (changeling.absorbed_dna+changeling.protected_dna)) - if(!(DNA in hivemind_bank)) + if(!(DNA in GLOB.hivemind_bank)) names += DNA.real_name if(names.len <= 0) @@ -51,7 +51,7 @@ var/list/datum/dna/hivemind_bank = list() if(!chosen_dna) return - hivemind_bank += chosen_dna + GLOB.hivemind_bank += chosen_dna to_chat(user, "We channel the DNA of [chosen_name] to the air.") feedback_add_details("changeling_powers","HU") return 1 @@ -75,7 +75,7 @@ var/list/datum/dna/hivemind_bank = list() /datum/action/changeling/hivemind_download/sting_action(var/mob/user) var/datum/changeling/changeling = user.mind.changeling var/list/names = list() - for(var/datum/dna/DNA in hivemind_bank) + for(var/datum/dna/DNA in GLOB.hivemind_bank) if(!(DNA in changeling.absorbed_dna)) names[DNA.real_name] = DNA diff --git a/code/game/gamemodes/changeling/powers/humanform.dm b/code/game/gamemodes/changeling/powers/humanform.dm index f9b214c513c..1f90f7eb702 100644 --- a/code/game/gamemodes/changeling/powers/humanform.dm +++ b/code/game/gamemodes/changeling/powers/humanform.dm @@ -24,8 +24,8 @@ if(!user) return 0 to_chat(user, "We transform our appearance.") - user.dna.SetSEState(MONKEYBLOCK,0,1) - genemutcheck(user,MONKEYBLOCK,null,MUTCHK_FORCED) + user.dna.SetSEState(GLOB.monkeyblock,0,1) + genemutcheck(user,GLOB.monkeyblock,null,MUTCHK_FORCED) if(istype(user)) user.set_species(chosen_dna.species.type) user.dna = chosen_dna.Clone() diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm index d225ac6886a..ce62242ca0f 100644 --- a/code/game/gamemodes/changeling/powers/mutations.dm +++ b/code/game/gamemodes/changeling/powers/mutations.dm @@ -95,8 +95,8 @@ user.unEquip(user.head) user.unEquip(user.wear_suit) - user.equip_to_slot_if_possible(new suit_type(user), slot_wear_suit, 1, 1, 1) - user.equip_to_slot_if_possible(new helmet_type(user), slot_head, 1, 1, 1) + user.equip_to_slot_if_possible(new suit_type(user), slot_wear_suit, TRUE, TRUE) + user.equip_to_slot_if_possible(new helmet_type(user), slot_head, TRUE, TRUE) var/datum/changeling/changeling = user.mind.changeling changeling.chem_recharge_slowdown += recharge_slowdown diff --git a/code/game/gamemodes/changeling/powers/spiders.dm b/code/game/gamemodes/changeling/powers/spiders.dm index 82b2db6ac7b..778ec768e55 100644 --- a/code/game/gamemodes/changeling/powers/spiders.dm +++ b/code/game/gamemodes/changeling/powers/spiders.dm @@ -1,7 +1,7 @@ /datum/action/changeling/spiders name = "Spread Infestation" desc = "Our form divides, creating arachnids which will grow into deadly beasts." - helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 5 DNA absorptions." + helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 5 stored DNA." button_icon_state = "spread_infestation" chemical_cost = 45 dna_cost = 1 diff --git a/code/game/gamemodes/changeling/powers/swap_form.dm b/code/game/gamemodes/changeling/powers/swap_form.dm index e0fc1107729..0e02df12d88 100644 --- a/code/game/gamemodes/changeling/powers/swap_form.dm +++ b/code/game/gamemodes/changeling/powers/swap_form.dm @@ -18,7 +18,7 @@ if((NOCLONE || SKELETON || HUSK) in target.mutations) to_chat(user, "DNA of [target] is ruined beyond usability!") return - if(!istype(target) || issmall(target) || NO_DNA in target.dna.species.species_traits) + if(!istype(target) || issmall(target) || (NO_DNA in target.dna.species.species_traits)) to_chat(user, "[target] is not compatible with this ability.") return if(target.mind.changeling) diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm index 2a42d531f0f..1a9dd15c65e 100644 --- a/code/game/gamemodes/cult/cult.dm +++ b/code/game/gamemodes/cult/cult.dm @@ -1,4 +1,4 @@ -var/global/list/all_cults = list() +GLOBAL_LIST_EMPTY(all_cults) /datum/game_mode var/list/datum/mind/cult = list() @@ -110,11 +110,11 @@ var/global/list/all_cults = list() modePlayer += cult acolytes_needed = acolytes_needed + round((num_players_started() / 10)) - if(!summon_spots.len) - while(summon_spots.len < SUMMON_POSSIBILITIES) - var/area/summon = pick(return_sorted_areas() - summon_spots) + if(!GLOB.summon_spots.len) + while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES) + var/area/summon = pick(return_sorted_areas() - GLOB.summon_spots) if(summon && is_station_level(summon.z) && summon.valid_territory) - summon_spots += summon + GLOB.summon_spots += summon for(var/datum/mind/cult_mind in cult) SEND_SOUND(cult_mind.current, 'sound/ambience/antag/bloodcult.ogg') @@ -146,7 +146,7 @@ var/global/list/all_cults = list() else explanation = "Free objective." if("eldergod") - explanation = "Summon [SSticker.cultdat.entity_name] by invoking the 'Tear Reality' rune.The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin." + explanation = "Summon [SSticker.cultdat.entity_name] by invoking the 'Tear Reality' rune.The summoning can only be accomplished in [english_list(GLOB.summon_spots)] - where the veil is weak enough for the ritual to begin." to_chat(cult_mind.current, "Objective #[obj_count]: [explanation]") cult_mind.memory += "Objective #[obj_count]: [explanation]
" @@ -189,6 +189,7 @@ var/global/list/all_cults = list() C.Grant(cult_mind.current) SEND_SOUND(cult_mind.current, 'sound/ambience/antag/bloodcult.ogg') cult_mind.current.create_attack_log("Has been converted to the cult!") + cult_mind.current.create_log(CONVERSION_LOG, "converted to the cult") if(jobban_isbanned(cult_mind.current, ROLE_CULTIST) || jobban_isbanned(cult_mind.current, ROLE_SYNDICATE)) replace_jobbanned_player(cult_mind.current, ROLE_CULTIST) update_cult_icons_added(cult_mind) @@ -213,13 +214,13 @@ var/global/list/all_cults = list() /datum/game_mode/proc/update_cult_icons_added(datum/mind/cult_mind) - var/datum/atom_hud/antag/culthud = huds[ANTAG_HUD_CULT] + var/datum/atom_hud/antag/culthud = GLOB.huds[ANTAG_HUD_CULT] culthud.join_hud(cult_mind.current) set_antag_hud(cult_mind.current, "hudcultist") /datum/game_mode/proc/update_cult_icons_removed(datum/mind/cult_mind) - var/datum/atom_hud/antag/culthud = huds[ANTAG_HUD_CULT] + var/datum/atom_hud/antag/culthud = GLOB.huds[ANTAG_HUD_CULT] culthud.leave_hud(cult_mind.current) set_antag_hud(cult_mind.current, null) @@ -262,7 +263,7 @@ var/global/list/all_cults = list() for(var/datum/mind/cult_mind in cult) if(cult_mind.current && cult_mind.current.stat!=2) var/area/A = get_area(cult_mind.current ) - if( is_type_in_list(A, centcom_areas)) + if( is_type_in_list(A, GLOB.centcom_areas)) acolytes_survived++ else if(A == SSshuttle.emergency.areaInstance && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE) //snowflaked into objectives because shitty bay shuttles had areas to auto-determine this acolytes_survived++ diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm index 375a02251bc..fcc39124233 100644 --- a/code/game/gamemodes/cult/cult_comms.dm +++ b/code/game/gamemodes/cult/cult_comms.dm @@ -23,7 +23,7 @@ if(!message) return - if((user.disabilities & MUTE) || user.mind.miming) //Under vow of silence/mute? + if((MUTE in user.mutations) || user.mind.miming) //Under vow of silence/mute? user.visible_message("[user] appears to whisper to themselves.","You begin to whisper to yourself.") //Make them do *something* abnormal. else user.whisper("O bidai nabora se[pick("'","`")]sma!") // Otherwise book club sayings. @@ -32,7 +32,7 @@ if(!user) return - if(!((user.disabilities & MUTE) || user.mind.miming)) // If they aren't mute/miming, commence the whisperting + if(!((MUTE in user.mutations) || user.mind.miming)) // If they aren't mute/miming, commence the whisperting user.whisper(message) var/my_message if(istype(user, /mob/living/simple_animal/slaughter/cult)) //Harbringers of the Slaughter @@ -46,3 +46,4 @@ to_chat(M, " (F) [my_message] ") log_say("(CULT) [message]", user) + user.create_log(SAY_LOG, "(CULT) [message]") diff --git a/code/game/gamemodes/cult/cult_datums.dm b/code/game/gamemodes/cult/cult_datums.dm index 825f0c32f3b..73c7dc2cf03 100644 --- a/code/game/gamemodes/cult/cult_datums.dm +++ b/code/game/gamemodes/cult/cult_datums.dm @@ -72,36 +72,60 @@ /datum/cult_info/fire - name = "Cult of Pyr'Kaeus" + name = "Cult of Kha'Rin" theme = "fire" - tome_icon = "firetome" + tome_icon = "helltome" - entity_name = "Pyr'Kaeus" + entity_name = "Kha'Rin" entity_title1 = "The Burning One" entity_title2 = "The One Who Consumes" entity_title3 = "The Harbinger of Fire" - entity_icon_state = "narbee" + entity_icon_state = "kha'rin" + entity_spawn_animation = "kha'rin_spawn_anim" - cult_wall_icon_state = "firecult" - cult_floor_icon_state = "cultfire" + cult_wall_icon_state = "hellcult" + cult_floor_icon_state = "culthell" + cult_girder_icon_state = "hell_girder" - artificer_name = "Igniting Ember" - artificer_icon_state = "fireartificer" + artificer_name = "Summoner" + artificer_icon_state = "summoner" - behemoth_name = "Devouring Hatred" - behemoth_icon_state = "firejuggernaut" + behemoth_name = "Incarnation of Pain" + behemoth_icon_state = "incarnation_of_pain" - wraith_name = "Living Flame" - wraith_icon_state = "firewraith" + wraith_name = "Hell Knight" + wraith_icon_state = "hell_knight" + wraith_jaunt_out_animation = "infernal_rift_out" + wraith_jaunt_in_animation = "infernal_rift_in" - juggernaut_name = "Pyre Armor" - juggernaut_icon_state = "firejuggernaut" + juggernaut_name = "Incarnation of Pain" + juggernaut_icon_state = "incarnation_of_pain" - harvester_name = "Coal Seeker"//or nipple pincher... - harvester_icon_state = "fireharvester" + harvester_name = "Lost Soul" + harvester_icon_state = "lost_soul" - shade_name = "Charred Soul" - shade_icon_state = "shade" + shade_name = "Ifrit" + shade_icon_state = "ifrit" + + pylon_icon_state = "hell_pylon" + pylon_icon_state_off = "hell_pylon_off" + + forge_icon_state = "hell_forge" + forge_icon_state_off = "hell_forge_off" + + altar_icon_state = "hell_altar" + altar_icon_state_off = "hell_altar_off" + + archives_icon_state = "hell_archives" + archives_icon_state_off = "hell_archives_off" + + runed_metal_icon_state = "sheet_runed_hell" + + airlock_runed_icon_file = 'icons/obj/doors/airlocks/cult/runed/hell.dmi' + airlock_runed_overlays_file = 'icons/obj/doors/airlocks/cult/runed/hell-overlays.dmi' + + airlock_unruned_icon_file = 'icons/obj/doors/airlocks/cult/unruned/hell.dmi' + airlock_unruned_overlays_file = 'icons/obj/doors/airlocks/cult/unruned/hell-overlays.dmi' /datum/cult_info/death name = "Cult of Mortality" diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index f9ee181356d..c0daac2a01a 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -269,7 +269,7 @@ "The shuttle dispatcher was found dead with bloody symbols carved into their flesh. The shuttle will be delayed by two minutes.", "Steve repeatedly touched a lightbulb until his hands fell off. The shuttle will be delayed by two minutes.") var/message = pick(curses) - command_announcement.Announce("[message]", "System Failure", 'sound/misc/notice1.ogg') + GLOB.command_announcement.Announce("[message]", "System Failure", 'sound/misc/notice1.ogg') /obj/item/cult_shift name = "veil shifter" @@ -298,7 +298,7 @@ return if(!iscultist(user)) user.unEquip(src, 1) - step(src, pick(alldirs)) + step(src, pick(GLOB.alldirs)) to_chat(user, "\The [src] flickers out of your hands, too eager to move!") return diff --git a/code/game/gamemodes/cult/cult_objectives.dm b/code/game/gamemodes/cult/cult_objectives.dm index caf607ce010..f1a188022a0 100644 --- a/code/game/gamemodes/cult/cult_objectives.dm +++ b/code/game/gamemodes/cult/cult_objectives.dm @@ -114,10 +114,10 @@ if(prob(40))//split the chance of this objectives += "eldergod" - explanation = "Summon [SSticker.cultdat.entity_name] on the Station via the use of the Tear Reality rune. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin." + explanation = "Summon [SSticker.cultdat.entity_name] on the Station via the use of the Tear Reality rune. The veil is weak enough in [english_list(GLOB.summon_spots)] for the ritual to begin." else objectives += "slaughter" - explanation = "Bring the Slaughter via the rune 'Bring forth the slaughter'. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin." + explanation = "Bring the Slaughter via the rune 'Bring forth the slaughter'. The veil is weak enough in [english_list(GLOB.summon_spots)] for the ritual to begin." for(var/datum/mind/cult_mind in cult) if(cult_mind) @@ -155,12 +155,12 @@ /datum/game_mode/cult/proc/get_possible_sac_targets() var/list/possible_sac_targets = list() for(var/mob/living/carbon/human/player in GLOB.player_list) - if(player.mind && !is_convertable_to_cult(player.mind) && (player.stat != DEAD)) + if(player.mind && !is_convertable_to_cult(player.mind) && (player.stat != DEAD) && (!player.mind.offstation_role) ) possible_sac_targets += player.mind if(!possible_sac_targets.len) //There are no living Unconvertables on the station. Looking for a Sacrifice Target among the ordinary crewmembers for(var/mob/living/carbon/human/player in GLOB.player_list) - if(is_secure_level(player.z)) //We can't sacrifice people that are on the centcom z-level + if(is_secure_level(player.z) || player.mind.offstation_role) //We can't sacrifice people that are on the centcom z-level or offstation roles continue if(player.mind && !(player.mind in cult) && (player.stat != DEAD))//make DAMN sure they are not dead possible_sac_targets += player.mind @@ -174,7 +174,7 @@ updated_memory = replacetext("[cult_mind.memory]", "[previous_target]", "[sacrifice_target]") updated_memory = replacetext("[updated_memory]", "[previous_role]", "[sacrifice_target.assigned_role]") cult_mind.memory = updated_memory - + /datum/game_mode/cult/proc/pick_objective() var/list/possible_objectives = list() @@ -254,7 +254,7 @@ for(var/mob/living/L in GLOB.player_list) if(L.stat != DEAD && !(L.mind in cult)) var/area/A = get_area(L) - if(is_type_in_list(A.loc, centcom_areas)) + if(is_type_in_list(A.loc, GLOB.centcom_areas)) escaped_shuttle++ if(!escaped_shuttle) bonus = 1 diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index de8846d292e..618abec4470 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -152,7 +152,7 @@ return 1 return ..() -var/list/blacklisted_pylon_turfs = typecacheof(list( +GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list( /turf/simulated/floor/engine/cult, /turf/space, /turf/simulated/floor/plating/lava, @@ -160,7 +160,7 @@ var/list/blacklisted_pylon_turfs = typecacheof(list( /turf/simulated/wall/cult, /turf/simulated/wall/cult/artificer, /turf/unsimulated/wall - )) + ))) /obj/structure/cult/functional/pylon name = "pylon" @@ -214,7 +214,7 @@ var/list/blacklisted_pylon_turfs = typecacheof(list( if(istype(T, /turf/simulated/floor/engine/cult)) cultturfs |= T continue - if(is_type_in_typecache(T, blacklisted_pylon_turfs)) + if(is_type_in_typecache(T, GLOB.blacklisted_pylon_turfs)) continue else validturfs |= T diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 445050529af..9422ffcc716 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -217,8 +217,8 @@ if(!((CULT_ELDERGOD in cult_mode.objectives) || (CULT_SLAUGHTER in cult_mode.objectives))) to_chat(user, "[SSticker.cultdat.entity_name]'s power does not wish to be unleashed!") return 0 - if(!(A in summon_spots)) - to_chat(user, "[SSticker.cultdat.entity_name] can only be summoned where the veil is weak - in [english_list(summon_spots)]!") + if(!(A in GLOB.summon_spots)) + to_chat(user, "[SSticker.cultdat.entity_name] can only be summoned where the veil is weak - in [english_list(GLOB.summon_spots)]!") return 0 var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [SSticker.cultdat.entity_name]!", "No") if(confirm_final == "No" || confirm_final == null) @@ -278,10 +278,10 @@ if(ispath(rune_to_scribe, /obj/effect/rune/narsie) || ispath(rune_to_scribe, /obj/effect/rune/slaughter))//may need to change this - Fethas if(finale_runes_ok(user,rune_to_scribe)) A = get_area(src) - if(!(A in summon_spots)) // Check again to make sure they didn't move - to_chat(user, "The ritual can only begin where the veil is weak - in [english_list(summon_spots)]!") + if(!(A in GLOB.summon_spots)) // Check again to make sure they didn't move + to_chat(user, "The ritual can only begin where the veil is weak - in [english_list(GLOB.summon_spots)]!") return - command_announcement.Announce("Figments from an eldritch god are being summoned somewhere on the station from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg') + GLOB.command_announcement.Announce("Figments from an eldritch god are being summoned somewhere on the station from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg') for(var/B in spiral_range_turfs(1, user, 1)) var/turf/T = B var/obj/machinery/shield/N = new(T) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index d918bead0de..8c83c88f3d0 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -1,5 +1,5 @@ -var/list/sacrificed = list() -var/list/non_revealed_runes = (subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed) +GLOBAL_LIST_EMPTY(sacrificed) +GLOBAL_LIST_INIT(non_revealed_runes, (subtypesof(/obj/effect/rune) - /obj/effect/rune/malformed)) /* This file contains runes. @@ -255,7 +255,7 @@ structure_check() searches for nearby cultist structures required for the invoca qdel(paper_to_imbue) rune_in_use = 0 -var/list/teleport_runes = list() +GLOBAL_LIST_EMPTY(teleport_runes) /obj/effect/rune/teleport cultist_name = "Teleport" cultist_desc = "warps everything above it to another chosen teleport rune." @@ -270,10 +270,10 @@ var/list/teleport_runes = list() var/area/A = get_area(src) var/locname = initial(A.name) listkey = set_keyword ? "[set_keyword] [locname]":"[locname]" - teleport_runes += src + GLOB.teleport_runes += src /obj/effect/rune/teleport/Destroy() - teleport_runes -= src + GLOB.teleport_runes -= src return ..() /obj/effect/rune/teleport/invoke(var/list/invokers) @@ -281,7 +281,7 @@ var/list/teleport_runes = list() var/list/potential_runes = list() var/list/teleportnames = list() var/list/duplicaterunecount = list() - for(var/R in teleport_runes) + for(var/R in GLOB.teleport_runes) var/obj/effect/rune/teleport/T = R var/resultkey = T.listkey if(resultkey in teleportnames) @@ -332,10 +332,12 @@ var/list/teleport_runes = list() user.forceMove(get_turf(actual_selected_rune)) var/mob/living/carbon/human/H = user if(user.z != T.z) - H.bleed(5) + if(istype(H)) + H.bleed(5) user.apply_damage(5, BRUTE) else - H.bleed(rand(5,10)) + if(istype(H)) + H.bleed(rand(5,10)) else fail_invoke() @@ -349,7 +351,7 @@ var/list/teleport_runes = list() req_cultists = 1 allow_excess_invokers = TRUE rune_in_use = FALSE - + /obj/effect/rune/convert/do_invoke_glow() return @@ -410,7 +412,7 @@ var/list/teleport_runes = list() var/sacrifice_fulfilled var/datum/game_mode/cult/cult_mode = SSticker.mode if(offering.mind) - sacrificed.Add(offering.mind) + GLOB.sacrificed.Add(offering.mind) if(is_sacrifice_target(offering.mind)) sacrifice_fulfilled = TRUE new /obj/effect/temp_visual/cult/sac(loc) @@ -720,7 +722,7 @@ var/list/teleport_runes = list() log_game("Astral Communion rune failed - more than one user") return list() var/turf/T = get_turf(src) - if(!user in T.contents) + if(!(user in T.contents)) to_chat(user, "You must be standing on top of [src]!") log_game("Astral Communion rune failed - user not standing on rune") return list() @@ -832,7 +834,8 @@ var/list/teleport_runes = list() fail_invoke() log_game("Summon Cultist rune failed - target in away mission") return - if((cultist_to_summon.reagents.has_reagent("holywater") || cultist_to_summon.restrained()) && invokers.len < 3) + var/hard_summon = (cultist_to_summon.reagents && cultist_to_summon.reagents.has_reagent("holywater")) || cultist_to_summon.restrained() + if(hard_summon && invokers.len < 3) to_chat(user, "The summoning of [cultist_to_summon] is being blocked somehow! You need 3 chanters to counter it!") fail_invoke() new /obj/effect/temp_visual/cult/sparks(get_turf(cultist_to_summon)) //observer warning @@ -840,7 +843,7 @@ var/list/teleport_runes = list() return ..() - if(cultist_to_summon.reagents.has_reagent("holywater") || cultist_to_summon.restrained()) + if(hard_summon) summontime = 20 if(do_after(user, summontime, target = loc)) diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm index c0c4f7280f5..e7fb06c1b94 100644 --- a/code/game/gamemodes/cult/talisman.dm +++ b/code/game/gamemodes/cult/talisman.dm @@ -132,7 +132,7 @@ var/list/potential_runes = list() var/list/teleportnames = list() var/list/duplicaterunecount = list() - for(var/R in teleport_runes) + for(var/R in GLOB.teleport_runes) var/obj/effect/rune/teleport/T = R var/resultkey = T.listkey if(resultkey in teleportnames) diff --git a/code/game/gamemodes/devil/devil.dm b/code/game/gamemodes/devil/devil.dm index ab5f5796d2e..06933891ba6 100644 --- a/code/game/gamemodes/devil/devil.dm +++ b/code/game/gamemodes/devil/devil.dm @@ -1,4 +1,4 @@ -var/global/list/whiteness = list ( +GLOBAL_LIST_INIT(whiteness, list( /obj/item/clothing/under/color/white = 2, /obj/item/clothing/under/rank/bartender = 1, /obj/item/clothing/under/rank/chef = 1, @@ -21,7 +21,7 @@ var/global/list/whiteness = list ( /obj/item/clothing/under/noble_clothes = 1, /obj/item/clothing/under/sl_suit = 1, /obj/item/clothing/under/burial = 1 -) +)) @@ -32,9 +32,9 @@ var/global/list/whiteness = list ( var/mob/living/carbon/human/H = attacker if(H.w_uniform && istype(H.w_uniform, /obj/item/clothing/under)) var/obj/item/clothing/under/U = H.w_uniform - if(whiteness[U.type]) + if(GLOB.whiteness[U.type]) src.visible_message("[src] seems to have been harmed by the purity of [attacker]'s clothes.", "Unsullied white clothing is disrupting your form.") - return whiteness[U.type] + 1 + return GLOB.whiteness[U.type] + 1 if(BANE_TOOLBOX) if(istype(weapon,/obj/item/storage/toolbox)) src.visible_message("The [weapon] seems unusually robust this time.", "The [weapon] is your unmaking!") diff --git a/code/game/gamemodes/devil/devilinfo.dm b/code/game/gamemodes/devil/devilinfo.dm index abd90172ee9..ecbeb54f7f7 100644 --- a/code/game/gamemodes/devil/devilinfo.dm +++ b/code/game/gamemodes/devil/devilinfo.dm @@ -13,8 +13,8 @@ #define DEVILRESURRECTTIME 600 -var/global/list/allDevils = list() -var/global/list/lawlorify = list ( +GLOBAL_LIST_EMPTY(allDevils) +GLOBAL_LIST_INIT(lawlorify, list ( LORE = list( OBLIGATION_FOOD = "This devil seems to always offer it's victims food before slaughtering them.", OBLIGATION_FIDDLE = "This devil will never turn down a musical challenge.", @@ -77,7 +77,7 @@ var/global/list/lawlorify = list ( BANISH_DESTRUCTION = "If your corpse is destroyed, you will be unable to resurrect.", BANISH_FUNERAL_GARB = "If your corpse is clad in funeral garments, you will be unable to resurrect." ) - ) + )) /datum/devilinfo var/datum/mind/owner = null @@ -111,11 +111,11 @@ var/global/list/lawlorify = list ( return devil /proc/devilInfo(name, saveDetails = 0) - if(allDevils[lowertext(name)]) - return allDevils[lowertext(name)] + if(GLOB.allDevils[lowertext(name)]) + return GLOB.allDevils[lowertext(name)] else var/datum/devilinfo/devil = randomDevilInfo(name) - allDevils[lowertext(name)] = devil + GLOB.allDevils[lowertext(name)] = devil devil.exists = saveDetails return devil @@ -444,9 +444,9 @@ var/global/list/lawlorify = list ( D.oldform.revive() // Heal the old body too, so the devil doesn't resurrect, then immediately regress into a dead body. if(body.stat == DEAD) // Not sure why this would happen create_new_body() - else if(blobstart.len > 0) + else if(GLOB.blobstart.len > 0) // teleport the body so repeated beatdowns aren't an option) - body.forceMove(get_turf(pick(blobstart))) + body.forceMove(get_turf(pick(GLOB.blobstart))) // give them the devil lawyer outfit in case they got stripped if(ishuman(body)) var/mob/living/carbon/human/H = body @@ -456,8 +456,8 @@ var/global/list/lawlorify = list ( check_regression() /datum/devilinfo/proc/create_new_body() - if(blobstart.len > 0) - var/turf/targetturf = get_turf(pick(blobstart)) + if(GLOB.blobstart.len > 0) + var/turf/targetturf = get_turf(pick(GLOB.blobstart)) var/mob/currentMob = owner.current if(QDELETED(currentMob)) currentMob = owner.get_ghost() @@ -511,10 +511,10 @@ var/global/list/lawlorify = list ( to_chat(owner, "However, your infernal form is not without weaknesses.") to_chat(owner, "You may not use violence to coerce someone into selling their soul.") to_chat(owner, "You may not directly and knowingly physically harm a devil, other than yourself.") - to_chat(owner,lawlorify[LAW][bane]) - to_chat(owner,lawlorify[LAW][ban]) - to_chat(owner,lawlorify[LAW][obligation]) - to_chat(owner,lawlorify[LAW][banish]) + to_chat(owner,GLOB.lawlorify[LAW][bane]) + to_chat(owner,GLOB.lawlorify[LAW][ban]) + to_chat(owner,GLOB.lawlorify[LAW][obligation]) + to_chat(owner,GLOB.lawlorify[LAW][banish]) to_chat(owner, "

Remember, the crew can research your weaknesses if they find out your devil name.
") diff --git a/code/game/gamemodes/devil/game_mode.dm b/code/game/gamemodes/devil/game_mode.dm index f8b980f2dfd..74ff27468cc 100644 --- a/code/game/gamemodes/devil/game_mode.dm +++ b/code/game/gamemodes/devil/game_mode.dm @@ -17,7 +17,7 @@ to_chat(world,text) /datum/game_mode/proc/auto_declare_completion_devils() - /var/text = "" + var/text = "" if(devils.len) text += "
The devils were:" for(var/D in devils) @@ -34,7 +34,7 @@ var/trueName= randomDevilName() devil_mind.devilinfo = devilInfo(trueName, 1) devil_mind.devilinfo.ascendable = ascendable - devil_mind.store_memory("Your diabolical true name is [devil_mind.devilinfo.truename]
[lawlorify[LAW][devil_mind.devilinfo.ban]]
You may not use violence to coerce someone into selling their soul.
You may not directly and knowingly physically harm a devil, other than yourself.
[lawlorify[LAW][devil_mind.devilinfo.bane]]
[lawlorify[LAW][devil_mind.devilinfo.obligation]]
[lawlorify[LAW][devil_mind.devilinfo.banish]]
") + devil_mind.store_memory("Your diabolical true name is [devil_mind.devilinfo.truename]
[GLOB.lawlorify[LAW][devil_mind.devilinfo.ban]]
You may not use violence to coerce someone into selling their soul.
You may not directly and knowingly physically harm a devil, other than yourself.
[GLOB.lawlorify[LAW][devil_mind.devilinfo.bane]]
[GLOB.lawlorify[LAW][devil_mind.devilinfo.obligation]]
[GLOB.lawlorify[LAW][devil_mind.devilinfo.banish]]
") devil_mind.devilinfo.link_with_mob(devil_mind.current) if(devil_mind.assigned_role == "Clown") to_chat(devil_mind.current, "Your infernal nature allows you to wield weapons without harming yourself.") @@ -47,8 +47,8 @@ var/mob/living/silicon/S = devil_mind.current S.laws.set_sixsixsix_law("You may not use violence to coerce someone into selling their soul.") S.laws.set_sixsixsix_law("You may not directly and knowingly physically harm a devil, other than yourself.") - S.laws.set_sixsixsix_law("[lawlorify[LAW][devil_mind.devilinfo.ban]]") - S.laws.set_sixsixsix_law("[lawlorify[LAW][devil_mind.devilinfo.obligation]]") + S.laws.set_sixsixsix_law("[GLOB.lawlorify[LAW][devil_mind.devilinfo.ban]]") + S.laws.set_sixsixsix_law("[GLOB.lawlorify[LAW][devil_mind.devilinfo.obligation]]") S.laws.set_sixsixsix_law("Accomplish your objectives at all costs.") // unsure about the second "quantity" arg and how it fits with the antag refactor @@ -76,18 +76,18 @@ return "Target is not a devil." var/text = "
The devil's true name is: [ply.devilinfo.truename]
" text += "The devil's bans were:
" - text += " [lawlorify[LORE][ply.devilinfo.ban]]
" - text += " [lawlorify[LORE][ply.devilinfo.bane]]
" - text += " [lawlorify[LORE][ply.devilinfo.obligation]]
" - text += " [lawlorify[LORE][ply.devilinfo.banish]]

" + text += " [GLOB.lawlorify[LORE][ply.devilinfo.ban]]
" + text += " [GLOB.lawlorify[LORE][ply.devilinfo.bane]]
" + text += " [GLOB.lawlorify[LORE][ply.devilinfo.obligation]]
" + text += " [GLOB.lawlorify[LORE][ply.devilinfo.banish]]

" return text /datum/game_mode/proc/update_devil_icons_added(datum/mind/devil_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] + var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_DEVIL] hud.join_hud(devil_mind.current) set_antag_hud(devil_mind.current, "huddevil") /datum/game_mode/proc/update_devil_icons_removed(datum/mind/devil_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_DEVIL] + var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_DEVIL] hud.leave_hud(devil_mind.current) set_antag_hud(devil_mind.current, null) diff --git a/code/game/gamemodes/devil/true_devil/inventory.dm b/code/game/gamemodes/devil/true_devil/inventory.dm index 437203e2e91..3f5446d88bc 100644 --- a/code/game/gamemodes/devil/true_devil/inventory.dm +++ b/code/game/gamemodes/devil/true_devil/inventory.dm @@ -5,7 +5,7 @@ return 1 return 0 -/mob/living/carbon/true_devil/update_inv_r_hand(var/update_icons=1) +/mob/living/carbon/true_devil/update_inv_r_hand() ..() if(r_hand) var/t_state = r_hand.item_state @@ -17,11 +17,10 @@ devil_overlays[DEVIL_R_HAND_LAYER] = I else devil_overlays[DEVIL_R_HAND_LAYER] = null - if(update_icons) - update_icons() + update_icons() -/mob/living/carbon/true_devil/update_inv_l_hand(var/update_icons=1) +/mob/living/carbon/true_devil/update_inv_l_hand() ..() if(l_hand) var/t_state = l_hand.item_state @@ -33,8 +32,7 @@ devil_overlays[DEVIL_L_HAND_LAYER] = I else devil_overlays[DEVIL_L_HAND_LAYER] = null - if(update_icons) - update_icons() + update_icons() /mob/living/carbon/true_devil/proc/remove_overlay(cache_index) if(devil_overlays[cache_index]) diff --git a/code/game/gamemodes/factions.dm b/code/game/gamemodes/factions.dm deleted file mode 100644 index 1780881a51d..00000000000 --- a/code/game/gamemodes/factions.dm +++ /dev/null @@ -1,97 +0,0 @@ - -// Normal factions: - -/datum/faction - var/name // the name of the faction - var/desc // small paragraph explaining the traitor faction - - var/list/restricted_species = list() // only members of these species can be recruited. - var/list/members = list() // a list of mind datums that belong to this faction - var/max_op = 0 // the maximum number of members a faction can have (0 for no max) - -// Factions, members of the syndicate coalition: - -/datum/faction/syndicate - - var/list/alliances = list() // these alliances work together - var/list/equipment = list() // associative list of equipment available for this faction and its prices - var/friendly_identification // 0 to 2, the level of identification of fellow operatives or allied factions - // 0 - no identification clues - // 1 - faction gives key words and phrases - // 2 - faction reveals complete identity/job of other agents - var/operative_notes // some notes to pass onto each operative - - var/uplink_contents // the contents of the uplink - -/datum/faction/syndicate/proc/assign_objectives(var/datum/mind/traitor) - ..() - - -/* ----- Begin defining syndicate factions ------ */ - -/datum/faction/syndicate/Cybersun_Industries - name = "Cybersun Industries" - desc = "Cybersun Industries is a well-known organization that bases its business model primarily on the research and development of human-enhancing computer \ - and mechanical technology. They are notorious for their aggressive corporate tactics, and have been known to subsidize the Gorlex Marauder warlords as a form of paid terrorism. \ - Their competent coverups and unchallenged mind-manipulation and augmentation technology makes them a large threat to Nanotrasen. In the recent years of \ - the syndicate coalition, Cybersun Industries have established themselves as the leaders of the coalition, succeededing the founding group, the Gorlex Marauders." - - alliances = list("MI13") - friendly_identification = 1 - max_op = 3 - - // Friendly to everyone. (with Tiger Cooperative too, only because they are a member of the coalition. This is the only reason why the Tiger Cooperative are even allowed in the coalition) - -/datum/faction/syndicate/Donk - name = "Donk Corporation" - desc = "Donk.co is led by a group of ex-pirates, who used to be at a state of all-out war against Waffle.co because of an obscure political scandal, but have recently come to a war limitation. \ - They now consist of a series of colonial governments and companies. They were the first to officially begin confrontations against Nanotrasen because of an incident where \ - Nanotrasen purposely swindled them out of a fortune, sending their controlled colonies into a terrible poverty. Their missions against Nanotrasen \ - revolve around stealing valuables and kidnapping and executing key personnel, ransoming their lives for money. They merged with a splinter-cell of Waffle.co who wanted to end \ - hostilities and formed the Gorlex Marauders." - - alliances = list("Gorlex Marauders") - friendly_identification = 2 - operative_notes = "Most other syndicate operatives are not to be trusted, except fellow Donk members and members of the Gorlex Marauders. We do not approve of mindless killing of innocent workers; \"get in, get done, get out\" is our motto. Members of Waffle.co are to be killed on sight; they are not allowed to be on the station while we're around." - - // Neutral to everyone, friendly to Marauders - -/datum/faction/syndicate/Waffle - name = "Waffle Corporation" - desc = "Waffle.co is an interstellar company that produces the best waffles in the galaxy. Their waffles have been rumored to be dipped in the most exotic and addictive \ - drug known to man. They were involved in a political scandal with Donk.co, and have since been in constant war with them. Because of their constant exploits of the galactic \ - economy and stock market, they have been able to bribe their way into amassing a large arsenal of weapons of mass destruction. They target Nanotrasen because of their communistic \ - threat, and their economic threat. Their leaders often have a twisted sense of humor, often misleading and intentionally putting their operatives into harm for laughs.\ - A splinter-cell of Waffle.co merged with Donk.co and formed the Gorlex Marauders and have been a constant ally since. The Waffle.co has lost an overwhelming majority of its military to the Gorlex Marauders." - - alliances = list("Gorlex Marauders") - friendly_identification = 2 - operative_notes = "Most other syndicate operatives are not to be trusted, except for members of the Gorlex Marauders. Do not trust fellow members of the Waffle.co (but try not to rat them out), as they might have been assigned opposing objectives. We encourage humorous terrorism against Nanotrasen; we like to see our operatives creatively kill people while getting the job done." - - // Neutral to everyone, friendly to Marauders - - -/* ----- Begin defining miscellaneous factions ------ */ - -/datum/faction/Wizard - name = "Wizards Federation" - desc = "The Wizards Federation is a mysterious organization of magically-talented individuals who act as an equal collective, and have no heirarchy. It is unknown how the wizards \ - are even able to communicate; some suggest a form of telepathic hive-mind. Not much is known about the wizards or their philosphies and motives. They appear to attack random \ - civilian, corporate, planetary, orbital, pretty much any sort of organized facility they come across. Members of the Wizards Federation are considered amongst the most dangerous \ - individuals in the known universe, and have been labeled threats to humanity by most governments. As such, they are enemies of both Nanotrasen and the Syndicate." - -/datum/faction/Cult - name = "The Cult of the Elder Gods" - desc = "The Cult of the Elder Gods is highly untrusted but otherwise elusive religious organization bent on the revival of the so-called \"Elder Gods\" into the mortal realm. Despite their obvious dangeorus practices, \ - no confirmed reports of violence by members of the Cult have been reported, only rumor and unproven claims. Their nature is unknown, but recent discoveries have hinted to the possibility \ - of being able to de-convert members of this cult through what has been dubbed \"religious warfare\"." - - -// These can maybe be added into a game mode or a mob? - -/datum/faction/Exolitics - name = "Exolitics United" - desc = "The Exolitics are an ancient alien race with an energy-based anatomy. Their culture, communication, morales and knowledge is unknown. They are so radically different to humans that their \ - attempts of communication with other life forms is completely incomprehensible. Members of this alien race are capable of broadcasting subspace transmissions from their bodies. \ - The religious leaders of the Tiger Cooperative claim to have the technology to decypher and interpret their messages, which have been confirmed as religious propaganda. Their motives are unknown \ - but they are otherwise not considered much of a threat to anyone. They are virtually indestructable because of their nonphysical composition, and have the frighetning ability to make anything stop existing in a second." diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 258d6ea20c6..2b604839c62 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -80,8 +80,8 @@ // feedback_set_details("revision","[revdata.revision]") feedback_set_details("server_ip","[world.internet_address]:[world.port]") generate_station_goals() - start_state = new /datum/station_state() - start_state.count() + GLOB.start_state = new /datum/station_state() + GLOB.start_state.count() return 1 ///process() @@ -92,15 +92,15 @@ //Called by the gameticker /datum/game_mode/proc/process_job_tasks() var/obj/machinery/message_server/useMS = null - if(message_servers) - for(var/obj/machinery/message_server/MS in message_servers) + if(GLOB.message_servers) + for(var/obj/machinery/message_server/MS in GLOB.message_servers) if(MS.active) useMS = MS break for(var/mob/M in GLOB.player_list) if(M.mind) var/obj/item/pda/P=null - for(var/obj/item/pda/check_pda in PDAs) + for(var/obj/item/pda/check_pda in GLOB.PDAs) if(check_pda.owner==M.name) P=check_pda break @@ -164,11 +164,11 @@ if(ishuman(M)) if(!M.stat) surviving_humans++ - if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations) + if(M.loc && M.loc.loc && (M.loc.loc.type in escape_locations)) escaped_humans++ if(!M.stat) surviving_total++ - if(M.loc && M.loc.loc && M.loc.loc.type in escape_locations) + if(M.loc && M.loc.loc && (M.loc.loc.type in escape_locations)) escaped_total++ if(M.loc && M.loc.loc && M.loc.loc.type == SSshuttle.emergency.areaInstance.type && SSshuttle.emergency.mode >= SHUTTLE_ENDGAME) @@ -292,7 +292,7 @@ /datum/game_mode/proc/get_living_heads() . = list() for(var/mob/living/carbon/human/player in GLOB.mob_list) - var/list/real_command_positions = command_positions.Copy() - "Nanotrasen Representative" + var/list/real_command_positions = GLOB.command_positions.Copy() - "Nanotrasen Representative" if(player.stat != DEAD && player.mind && (player.mind.assigned_role in real_command_positions)) . |= player.mind @@ -303,7 +303,7 @@ /datum/game_mode/proc/get_all_heads() . = list() for(var/mob/player in GLOB.mob_list) - var/list/real_command_positions = command_positions.Copy() - "Nanotrasen Representative" + var/list/real_command_positions = GLOB.command_positions.Copy() - "Nanotrasen Representative" if(player.mind && (player.mind.assigned_role in real_command_positions)) . |= player.mind @@ -313,7 +313,7 @@ /datum/game_mode/proc/get_living_sec() . = list() for(var/mob/living/carbon/human/player in GLOB.mob_list) - if(player.stat != DEAD && player.mind && (player.mind.assigned_role in security_positions)) + if(player.stat != DEAD && player.mind && (player.mind.assigned_role in GLOB.security_positions)) . |= player.mind //////////////////////////////////////// @@ -322,14 +322,14 @@ /datum/game_mode/proc/get_all_sec() . = list() for(var/mob/living/carbon/human/player in GLOB.mob_list) - if(player.mind && (player.mind.assigned_role in security_positions)) + if(player.mind && (player.mind.assigned_role in GLOB.security_positions)) . |= player.mind /datum/game_mode/proc/check_antagonists_topic(href, href_list[]) return 0 /datum/game_mode/New() - newscaster_announcements = pick(newscaster_standard_feeds) + newscaster_announcements = pick(GLOB.newscaster_standard_feeds) ////////////////////////// //Reports player logouts// @@ -512,11 +512,11 @@ proc/display_roundstart_logout_report() G.print_result() /datum/game_mode/proc/update_eventmisc_icons_added(datum/mind/mob_mind) - var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_EVENTMISC] + var/datum/atom_hud/antag/antaghud = GLOB.huds[ANTAG_HUD_EVENTMISC] antaghud.join_hud(mob_mind.current) set_antag_hud(mob_mind.current, "hudevent") /datum/game_mode/proc/update_eventmisc_icons_removed(datum/mind/mob_mind) - var/datum/atom_hud/antag/antaghud = huds[ANTAG_HUD_EVENTMISC] + var/datum/atom_hud/antag/antaghud = GLOB.huds[ANTAG_HUD_EVENTMISC] antaghud.leave_hud(mob_mind.current) set_antag_hud(mob_mind.current, null) diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm index 2b4d095b327..142ae33c078 100644 --- a/code/game/gamemodes/heist/heist.dm +++ b/code/game/gamemodes/heist/heist.dm @@ -1,9 +1,8 @@ /* VOX HEIST ROUNDTYPE */ - -var/global/list/raider_spawn = list() -var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective. Clumsy, rewrite sometime. +GLOBAL_LIST_EMPTY(raider_spawn) +GLOBAL_LIST_EMPTY(cortical_stacks) //Stacks for 'leave nobody behind' objective. Clumsy, rewrite sometime. /datum/game_mode/ var/list/datum/mind/raiders = list() //Antags. @@ -70,10 +69,10 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' //Spawn the vox! for(var/datum/mind/raider in raiders) - if(index > raider_spawn.len) + if(index > GLOB.raider_spawn.len) index = 1 - raider.current.loc = raider_spawn[index] + raider.current.loc = GLOB.raider_spawn[index] index++ create_vox(raider) @@ -128,16 +127,16 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' //Now apply cortical stack. var/obj/item/implant/cortical/I = new(vox) I.implant(vox) - cortical_stacks += I + GLOB.cortical_stacks += I vox.equip_vox_raider() vox.regenerate_icons() /datum/game_mode/proc/is_raider_crew_safe() - if(cortical_stacks.len == 0) + if(GLOB.cortical_stacks.len == 0) return 0 - for(var/obj/stack in cortical_stacks) + for(var/obj/stack in GLOB.cortical_stacks) if(get_area(stack) != locate(/area/shuttle/vox) && get_area(stack) != locate(/area/vox_station)) return 0 //this is stupid as fuck return 1 diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 9ca0025a0ab..c1a907f9191 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -186,7 +186,7 @@ var/unlock_sound //Sound played when an ability is unlocked var/uses -/datum/AI_Module/proc/upgrade(mob/living/silicon/AI/AI) //Apply upgrades! +/datum/AI_Module/proc/upgrade(mob/living/silicon/ai/AI) //Apply upgrades! return /datum/AI_Module/large //Big, powerful stuff that can only be used once. @@ -224,14 +224,14 @@ /datum/action/innate/ai/nuke_station/proc/set_us_up_the_bomb() to_chat(owner_AI, "Nuclear device armed.") - event_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg') + GLOB.event_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", new_sound = 'sound/AI/aimalf.ogg') set_security_level("delta") owner_AI.nuking = TRUE var/obj/machinery/doomsday_device/DOOM = new /obj/machinery/doomsday_device(owner_AI) owner_AI.doomsday_device = DOOM owner_AI.doomsday_device.start() for(var/obj/item/pinpointer/point in GLOB.pinpointer_list) - for(var/mob/living/silicon/ai/A in ai_list) + for(var/mob/living/silicon/ai/A in GLOB.ai_list) if((A.stat != DEAD) && A.nuking) point.the_disk = A //The pinpointer now tracks the AI core qdel(src) @@ -256,7 +256,7 @@ if(SSshuttle.emergency.mode == SHUTTLE_STRANDED) SSshuttle.emergency.mode = SHUTTLE_DOCKED SSshuttle.emergency.timer = world.time - priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg') + GLOB.priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg') return ..() /obj/machinery/doomsday_device/proc/start() @@ -271,12 +271,12 @@ /obj/machinery/doomsday_device/process() var/turf/T = get_turf(src) if(!T || !is_station_level(T.z)) - minor_announcement.Announce("DOOMSDAY DEVICE OUT OF STATION RANGE, ABORTING", "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", 'sound/misc/notice1.ogg') + GLOB.minor_announcement.Announce("DOOMSDAY DEVICE OUT OF STATION RANGE, ABORTING", "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", 'sound/misc/notice1.ogg') SSshuttle.emergencyNoEscape = 0 if(SSshuttle.emergency.mode == SHUTTLE_STRANDED) SSshuttle.emergency.mode = SHUTTLE_DOCKED SSshuttle.emergency.timer = world.time - priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg') + GLOB.priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg') qdel(src) if(!timing) STOP_PROCESSING(SSfastprocess, src) @@ -289,7 +289,7 @@ else if(!(sec_left % 60) && !announced) var/message = "[sec_left] SECONDS UNTIL DOOMSDAY DEVICE ACTIVATION!" - minor_announcement.Announce(message, "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", 'sound/misc/notice1.ogg') + GLOB.minor_announcement.Announce(message, "ERROR ER0RR $R0RRO$!R41.%%!!(%$^^__+ @#F0E4", 'sound/misc/notice1.ogg') announced = 10 announced = max(0, announced-1) @@ -318,7 +318,7 @@ unlock_text = "You establish a power diversion to your turrets, upgrading their health and damage." unlock_sound = 'sound/items/rped.ogg' -/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/AI/AI) +/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/ai/AI) for(var/obj/machinery/porta_turret/turret in GLOB.machines) var/turf/T = get_turf(turret) if(is_station_level(T.z)) @@ -352,10 +352,10 @@ post_status("alert", "lockdown") - minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert") + GLOB.minor_announcement.Announce("Hostile runtime detected in door controllers. Isolation lockdown protocols are now in effect. Please remain calm.", "Network Alert") to_chat(owner, "Lockdown Initiated. Network reset in 90 seconds.") spawn(900) - minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network reset:") + GLOB.minor_announcement.Announce("Automatic system reboot complete. Have a secure day.","Network reset:") //Destroy RCDs: Detonates all non-cyborg RCDs on the station. /datum/AI_Module/large/destroy_rcd @@ -613,7 +613,7 @@ var/turf/T = turfs[n] if(!isfloorturf(T)) success = FALSE - var/datum/camerachunk/C = cameranet.getCameraChunk(T.x, T.y, T.z) + var/datum/camerachunk/C = GLOB.cameranet.getCameraChunk(T.x, T.y, T.z) if(!C.visibleTurfs[T]) alert_msg = "You don't have camera vision of this location!" success = FALSE @@ -689,7 +689,7 @@ /datum/action/innate/ai/reactivate_cameras/Activate() var/fixed_cameras = 0 - for(var/V in cameranet.cameras) + for(var/V in GLOB.cameranet.cameras) if(!uses) break var/obj/machinery/camera/C = V @@ -722,7 +722,7 @@ AI.update_sight() var/upgraded_cameras = 0 - for(var/V in cameranet.cameras) + for(var/V in GLOB.cameranet.cameras) var/obj/machinery/camera/C = V if(C.assembly) var/upgraded = FALSE @@ -730,7 +730,7 @@ if(!C.isXRay()) C.upgradeXRay() //Update what it can see. - cameranet.updateVisibility(C, 0) + GLOB.cameranet.updateVisibility(C, 0) upgraded = TRUE if(!C.isEmpProof()) diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm index f8ac70b31dc..5cd46ca89b5 100644 --- a/code/game/gamemodes/meteor/meteor.dm +++ b/code/game/gamemodes/meteor/meteor.dm @@ -13,7 +13,7 @@ /datum/game_mode/meteor/post_setup() spawn(rand(waittime_l, waittime_h)) - command_announcement.Announce("The station is on the path of an incoming wave of meteors. Reinforce the hull and prepare damage control parties.", "Incoming Meteors", 'sound/effects/siren.ogg') + GLOB.command_announcement.Announce("The station is on the path of an incoming wave of meteors. Reinforce the hull and prepare damage control parties.", "Incoming Meteors", 'sound/effects/siren.ogg') spawn(initialmeteordelay) sendmeteors() ..() @@ -25,7 +25,7 @@ var/waitduration = rand(3000,6000) while(waveduration - world.time > 0) sleep(max(65 - text2num("[wave]0") / 2, 40)) - spawn() spawn_meteors(6, meteors_normal) + spawn() spawn_meteors(6, GLOB.meteors_normal) wave++ sleep(waitduration) sendmeteors() diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index 507fedddd32..0743a6f686d 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -1,18 +1,18 @@ //Meteors probability of spawning during a given wave -/var/list/meteors_normal = list(/obj/effect/meteor/dust=3, /obj/effect/meteor/medium=8, /obj/effect/meteor/big=3, \ - /obj/effect/meteor/flaming=1, /obj/effect/meteor/irradiated=3) //for normal meteor event +GLOBAL_LIST_INIT(meteors_normal, list(/obj/effect/meteor/dust=3, /obj/effect/meteor/medium=8, /obj/effect/meteor/big=3, \ + /obj/effect/meteor/flaming=1, /obj/effect/meteor/irradiated=3)) //for normal meteor event -/var/list/meteors_threatening = list(/obj/effect/meteor/medium=4, /obj/effect/meteor/big=8, \ - /obj/effect/meteor/flaming=3, /obj/effect/meteor/irradiated=3) //for threatening meteor event +GLOBAL_LIST_INIT(meteors_threatening, list(/obj/effect/meteor/medium=4, /obj/effect/meteor/big=8, \ + /obj/effect/meteor/flaming=3, /obj/effect/meteor/irradiated=3)) //for threatening meteor event -/var/list/meteors_catastrophic = list(/obj/effect/meteor/medium=5, /obj/effect/meteor/big=75, \ - /obj/effect/meteor/flaming=10, /obj/effect/meteor/irradiated=10, /obj/effect/meteor/tunguska = 1) //for catastrophic meteor event +GLOBAL_LIST_INIT(meteors_catastrophic, list(/obj/effect/meteor/medium=5, /obj/effect/meteor/big=75, \ + /obj/effect/meteor/flaming=10, /obj/effect/meteor/irradiated=10, /obj/effect/meteor/tunguska = 1)) //for catastrophic meteor event -/var/list/meteors_dust = list(/obj/effect/meteor/dust) //for space dust event +GLOBAL_LIST_INIT(meteors_dust, list(/obj/effect/meteor/dust)) //for space dust event -/var/list/meteors_gore = list(/obj/effect/meteor/gore) //Meaty Gore +GLOBAL_LIST_INIT(meteors_gore, list(/obj/effect/meteor/gore)) //Meaty Gore -/var/list/meteors_ops = list(/obj/effect/meteor/goreops) //Meaty Ops +GLOBAL_LIST_INIT(meteors_ops, list(/obj/effect/meteor/goreops)) //Meaty Ops /////////////////////////////// @@ -27,7 +27,7 @@ var/turf/pickedgoal var/max_i = 10//number of tries to spawn meteor. while(!istype(pickedstart, /turf/space)) - var/startSide = pick(cardinal) + var/startSide = pick(GLOB.cardinal) pickedstart = spaceDebrisStartLoc(startSide, 1) pickedgoal = spaceDebrisFinishLoc(startSide, 1) max_i-- diff --git a/code/game/gamemodes/miniantags/abduction/abduction.dm b/code/game/gamemodes/miniantags/abduction/abduction.dm index ea22ba9f54e..60de5ba4238 100644 --- a/code/game/gamemodes/miniantags/abduction/abduction.dm +++ b/code/game/gamemodes/miniantags/abduction/abduction.dm @@ -47,7 +47,7 @@ /datum/game_mode/abduction/proc/make_abductor_team(team_number,preset_agent=null,preset_scientist=null) //Team Name - team_names[team_number] = "Mothership [pick(possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names + team_names[team_number] = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names //Team Objective var/datum/objective/experiment/team_objective = new team_objective.team = team_number @@ -267,6 +267,7 @@ SSticker.mode.abductors -= abductor_mind abductor_mind.special_role = null abductor_mind.current.create_attack_log("No longer abductor") + abductor_mind.current.create_log(CONVERSION_LOG, "No longer abductor") if(issilicon(abductor_mind.current)) to_chat(abductor_mind.current, "You have been turned into a robot! You are no longer an abductor.") else @@ -274,11 +275,11 @@ SSticker.mode.update_abductor_icons_removed(abductor_mind) /datum/game_mode/proc/update_abductor_icons_added(datum/mind/alien_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_ABDUCTOR] + var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR] hud.join_hud(alien_mind.current) set_antag_hud(alien_mind.current, ((alien_mind in abductors) ? "abductor" : "abductee")) /datum/game_mode/proc/update_abductor_icons_removed(datum/mind/alien_mind) - var/datum/atom_hud/antag/hud = huds[ANTAG_HUD_ABDUCTOR] + var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR] hud.leave_hud(alien_mind.current) set_antag_hud(alien_mind.current, null) diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm index 23d9792ca4c..e23e37c349e 100644 --- a/code/game/gamemodes/miniantags/abduction/gland.dm +++ b/code/game/gamemodes/miniantags/abduction/gland.dm @@ -69,7 +69,7 @@ active = 0 if(initial(uses) == 1) uses = initial(uses) - var/datum/atom_hud/abductor/hud = huds[DATA_HUD_ABDUCTOR] + var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR] hud.remove_from_hud(owner) clear_mind_control() . = ..() @@ -78,7 +78,7 @@ ..() if(special != 2 && uses) // Special 2 means abductor surgery Start() - var/datum/atom_hud/abductor/hud = huds[DATA_HUD_ABDUCTOR] + var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR] hud.add_to_hud(owner) update_gland_hud() @@ -277,14 +277,14 @@ ..() if(ishuman(owner)) owner.gene_stability += GENE_INSTABILITY_MODERATE // give them this gene for free - owner.dna.SetSEState(SHOCKIMMUNITYBLOCK, TRUE) - genemutcheck(owner, SHOCKIMMUNITYBLOCK, null, MUTCHK_FORCED) + owner.dna.SetSEState(GLOB.shockimmunityblock, TRUE) + genemutcheck(owner, GLOB.shockimmunityblock, null, MUTCHK_FORCED) /obj/item/organ/internal/heart/gland/electric/remove(mob/living/carbon/M, special = 0) if(ishuman(owner)) owner.gene_stability -= GENE_INSTABILITY_MODERATE // but return it to normal once it's removed - owner.dna.SetSEState(SHOCKIMMUNITYBLOCK, FALSE) - genemutcheck(owner, SHOCKIMMUNITYBLOCK, null, MUTCHK_FORCED) + owner.dna.SetSEState(GLOB.shockimmunityblock, FALSE) + genemutcheck(owner, GLOB.shockimmunityblock, null, MUTCHK_FORCED) return ..() /obj/item/organ/internal/heart/gland/electric/activate() diff --git a/code/game/gamemodes/miniantags/abduction/machinery/camera.dm b/code/game/gamemodes/miniantags/abduction/machinery/camera.dm index 951ee6806de..6fb401d31e9 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/camera.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/camera.dm @@ -73,7 +73,7 @@ var/mob/camera/aiEye/remote/remote_eye = C.remote_control var/obj/machinery/abductor/pad/P = target - if(cameranet.checkTurfVis(remote_eye.loc)) + if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) P.PadToLoc(remote_eye.loc) /datum/action/innate/teleport_out @@ -98,7 +98,7 @@ var/mob/camera/aiEye/remote/remote_eye = C.remote_control var/obj/machinery/abductor/pad/P = target - if(cameranet.checkTurfVis(remote_eye.loc)) + if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) P.MobToLoc(remote_eye.loc,C) /datum/action/innate/vest_mode_swap diff --git a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm index 04dda244a0c..6e1b4a39d3a 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/experiment.dm @@ -176,7 +176,7 @@ H.uncuff() return //Area not chosen / It's not safe area - teleport to arrivals - H.forceMove(pick(latejoin)) + H.forceMove(pick(GLOB.latejoin)) H.uncuff() return diff --git a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm index 85c120186e4..24e43b6583f 100644 --- a/code/game/gamemodes/miniantags/abduction/machinery/pad.dm +++ b/code/game/gamemodes/miniantags/abduction/machinery/pad.dm @@ -12,7 +12,7 @@ /obj/machinery/abductor/pad/proc/Send() if(teleport_target == null) - teleport_target = teleportlocs[pick(teleportlocs)] + teleport_target = GLOB.teleportlocs[pick(GLOB.teleportlocs)] flick("alien-pad", src) for(var/mob/living/target in loc) target.forceMove(teleport_target) diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index fa797ac929b..f99a00567ae 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -590,8 +590,6 @@ GrantBorerActions() RemoveInfestActions() forceMove(get_turf(host)) - - reset_perspective(null) machine = null host.reset_perspective(null) diff --git a/code/game/gamemodes/miniantags/borer/borer_event.dm b/code/game/gamemodes/miniantags/borer/borer_event.dm index f925a59d9fc..245b8fa7b41 100644 --- a/code/game/gamemodes/miniantags/borer/borer_event.dm +++ b/code/game/gamemodes/miniantags/borer/borer_event.dm @@ -12,7 +12,7 @@ /datum/event/borer_infestation/announce() if(successSpawn) - command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') + GLOB.command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg') /datum/event/borer_infestation/start() var/list/vents = list() diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index defa0de633d..059eed3541c 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -119,7 +119,7 @@ ..() add_language("Swarmer", 1) verbs -= /mob/living/verb/pulled - for(var/datum/atom_hud/data/diagnostic/diag_hud in huds) + for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) diag_hud.add_to_hud(src) updatename() @@ -330,7 +330,7 @@ to_chat(S, "An inhospitable area may be created as a result of destroying this object. Aborting.") return FALSE -/obj/machinery/telecomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) +/obj/machinery/tcomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) to_chat(S, "This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting.") return FALSE @@ -421,13 +421,13 @@ return FALSE /obj/structure/lattice/catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) - . = ..() var/turf/here = get_turf(src) for(var/A in here.contents) var/obj/structure/cable/C = A if(istype(C)) to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.") return FALSE + return ..() /obj/item/deactivated_swarmer/IntegrateAmount() return 50 diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm index 0d5ba13d682..fbceda6bd94 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm @@ -8,14 +8,14 @@ swarmer_report += "

Our long-range sensors have detected an odd signal emanating from your station's gateway. We recommend immediate investigation of your gateway, as something may have come \ through." print_command_report(swarmer_report, "Classified [command_name()] Update") - event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg') + GLOB.event_announcement.Announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", 'sound/AI/commandreport.ogg') /datum/event/spawn_swarmer/start() if(find_swarmer()) return 0 - if(!the_gateway) + if(!GLOB.the_gateway) return 0 - new /obj/effect/mob_spawn/swarmer(get_turf(the_gateway)) + new /obj/effect/mob_spawn/swarmer(get_turf(GLOB.the_gateway)) /datum/event/spawn_swarmer/proc/find_swarmer() diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm index 387cd03aceb..c0e22515553 100644 --- a/code/game/gamemodes/miniantags/guardian/guardian.dm +++ b/code/game/gamemodes/miniantags/guardian/guardian.dm @@ -112,7 +112,7 @@ summoner.death() -/mob/living/simple_animal/hostile/guardian/handle_hud_icons_health() +/mob/living/simple_animal/hostile/guardian/update_health_hud() if(summoner) var/resulthealth if(iscarbon(summoner)) @@ -121,8 +121,6 @@ resulthealth = round((summoner.health / summoner.maxHealth) * 100) if(hud_used) hud_used.guardianhealthdisplay.maptext = "
[resulthealth]%
" - med_hud_set_health() - med_hud_set_status() /mob/living/simple_animal/hostile/guardian/adjustHealth(amount, updating_health = TRUE) //The spirit is invincible, but passes on damage to the summoner var/damage = amount * damage_transfer @@ -164,7 +162,7 @@ if(loc == summoner) forceMove(get_turf(summoner)) new /obj/effect/temp_visual/guardian/phase(loc) - src.client.eye = loc + reset_perspective() cooldown = world.time + 30 /mob/living/simple_animal/hostile/guardian/proc/Recall(forced = FALSE) @@ -286,7 +284,7 @@ var/name_list = list("Aries", "Leo", "Sagittarius", "Taurus", "Virgo", "Capricorn", "Gemini", "Libra", "Aquarius", "Cancer", "Scorpio", "Pisces") /obj/item/guardiancreator/attack_self(mob/living/user) - for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.living_mob_list) + for(var/mob/living/simple_animal/hostile/guardian/G in GLOB.alive_mob_list) if(G.summoner == user) to_chat(user, "You already have a [mob_name]!") return @@ -296,11 +294,12 @@ if(used == TRUE) to_chat(user, "[used_message]") return + used = TRUE // Set this BEFORE the popup to prevent people using the injector more than once, polling ghosts multiple times, and receiving multiple guardians. var/choice = alert(user, "[confirmation_message]",, "Yes", "No") if(choice == "No") to_chat(user, "You decide against using the [name].") + used = FALSE return - used = TRUE to_chat(user, "[use_message]") var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_GUARDIAN, 0, 100) var/mob/dead/observer/theghost = null diff --git a/code/game/gamemodes/miniantags/guardian/types/healer.dm b/code/game/gamemodes/miniantags/guardian/types/healer.dm index bf2c92ffb28..e3217e0249a 100644 --- a/code/game/gamemodes/miniantags/guardian/types/healer.dm +++ b/code/game/gamemodes/miniantags/guardian/types/healer.dm @@ -33,7 +33,7 @@ /mob/living/simple_animal/hostile/guardian/healer/Life(seconds, times_fired) ..() - var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] medsensor.add_hud_to(src) /mob/living/simple_animal/hostile/guardian/healer/Stat() @@ -51,7 +51,7 @@ if(iscarbon(target)) changeNext_move(CLICK_CD_MELEE) if(heal_cooldown <= world.time && !stat) - var/mob/living/carbon/C = target + var/mob/living/carbon/human/C = target C.adjustBruteLoss(-5, robotic=1) C.adjustFireLoss(-5, robotic=1) C.adjustOxyLoss(-5) diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index ef90f44f4a0..a122351a4bb 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -136,7 +136,7 @@ for(var/atom/movable/AM in src) AM.forceMove(loc) if(prob(90)) - step(AM, pick(alldirs)) + step(AM, pick(GLOB.alldirs)) // Only execute the below if we successfully died if(!.) return FALSE diff --git a/code/game/gamemodes/miniantags/morph/morph_event.dm b/code/game/gamemodes/miniantags/morph/morph_event.dm index 28183e7d22e..e9465492a27 100644 --- a/code/game/gamemodes/miniantags/morph/morph_event.dm +++ b/code/game/gamemodes/miniantags/morph/morph_event.dm @@ -15,9 +15,9 @@ var/datum/mind/player_mind = new /datum/mind(key_of_morph) player_mind.active = 1 - if(!xeno_spawn) + if(!GLOB.xeno_spawn) return kill() - var/mob/living/simple_animal/hostile/morph/S = new /mob/living/simple_animal/hostile/morph(pick(xeno_spawn)) + var/mob/living/simple_animal/hostile/morph/S = new /mob/living/simple_animal/hostile/morph(pick(GLOB.xeno_spawn)) player_mind.transfer_to(S) player_mind.assigned_role = SPECIAL_ROLE_MORPH player_mind.special_role = SPECIAL_ROLE_MORPH diff --git a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm index ab54f6991b1..ed0a4a908ed 100644 --- a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm +++ b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm @@ -35,8 +35,8 @@ animation.dir = dir ExtinguishMob() - if(pulling && bloodcrawl == BLOODCRAWL_EAT) - if(istype(pulling, /mob/living/)) + if(pulling && HAS_TRAIT(src, TRAIT_BLOODCRAWL_EAT)) + if(isliving(pulling)) var/mob/living/victim = pulling if(victim.stat == CONSCIOUS) visible_message("[victim] kicks free of [B] just before entering it!") @@ -76,13 +76,17 @@ adjustToxLoss(-1000) if(istype(src, /mob/living/simple_animal/slaughter)) //rason, do not want humans to get this - var/mob/living/simple_animal/slaughter/demon = src demon.devoured++ to_chat(kidnapped, "You feel teeth sink into your flesh, and the--") kidnapped.adjustBruteLoss(1000) kidnapped.forceMove(src) demon.consumed_mobs.Add(kidnapped) + if(ishuman(kidnapped)) + var/mob/living/carbon/human/H = kidnapped + if(H.w_uniform && istype(H.w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/U = H.w_uniform + U.sensor_mode = SENSOR_OFF else kidnapped.ghostize() qdel(kidnapped) diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm index 1f525e93076..e3ce78d582a 100644 --- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm +++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm @@ -35,7 +35,6 @@ see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE var/boost = 0 - bloodcrawl = BLOODCRAWL_EAT var/devoured = 0 @@ -59,6 +58,7 @@ /mob/living/simple_animal/slaughter/New() ..() remove_from_all_data_huds() + ADD_TRAIT(src, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat") var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new AddSpell(bloodspell) whisper_action = new() @@ -139,7 +139,7 @@ /obj/effect/proc_holder/spell/targeted/sense_victims/cast(list/targets, mob/user) var/list/victims = targets - for(var/mob/living/L in GLOB.living_mob_list) + for(var/mob/living/L in GLOB.alive_mob_list) if(!L.stat && !iscultist(L) && L.key && L != usr) victims.Add(L) if(!targets.len) @@ -247,33 +247,37 @@ user.visible_message("[user] raises [src] to [user.p_their()] mouth and tears into it with [user.p_their()] teeth!", \ "An unnatural hunger consumes you. You raise [src] to your mouth and devour it!") playsound(user, 'sound/misc/demon_consume.ogg', 50, 1) - for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list) - if(knownspell.type == /obj/effect/proc_holder/spell/bloodcrawl) - qdel(src) - return - if(user.bloodcrawl == 0) + // Eating the heart for the first time. Gives basic bloodcrawling. This is the only time we need to insert the heart. + if(!HAS_TRAIT(user, TRAIT_BLOODCRAWL)) user.visible_message("[user]'s eyes flare a deep crimson!", \ "You feel a strange power seep into your body... you have absorbed the demon's blood-travelling powers!") - user.bloodcrawl = BLOODCRAWL - else if(user.bloodcrawl == BLOODCRAWL) - to_chat(user, "You feel diffr- CONSUME THEM! ") - user.bloodcrawl = BLOODCRAWL_EAT - else - to_chat(user, "...and you don't feel any different.") + ADD_TRAIT(user, TRAIT_BLOODCRAWL, "bloodcrawl") + user.drop_item() + insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E. + return TRUE - user.drop_item() - insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E + // Eating a 2nd heart. Gives the ability to drag people into blood and eat them. + if(HAS_TRAIT(user, TRAIT_BLOODCRAWL)) + to_chat(user, "You feel diffr- CONSUME THEM! ") + ADD_TRAIT(user, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat") + qdel(src) // Replacing their demon heart with another demon heart is pointless, just delete this one and return. + return TRUE + + // Eating any more than 2 demon hearts does nothing. + to_chat(user, "...and you don't feel any different.") + qdel(src) /obj/item/organ/internal/heart/demon/insert(mob/living/carbon/M, special = 0) - ..() + . = ..() if(M.mind) M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null)) /obj/item/organ/internal/heart/demon/remove(mob/living/carbon/M, special = 0) ..() if(M.mind) - M.bloodcrawl = 0 + REMOVE_TRAIT(M, TRAIT_BLOODCRAWL, "bloodcrawl") + REMOVE_TRAIT(M, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat") M.mind.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl) /obj/item/organ/internal/heart/demon/Stop() diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index bdc5f718ac6..ad1146c0bc8 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -68,6 +68,7 @@ proc/issyndicate(mob/living/M as mob) for(var/datum/objective/nuclear/O in operative_mind.objectives) operative_mind.objectives -= O operative_mind.current.create_attack_log("No longer nuclear operative") + operative_mind.current.create_log(CONVERSION_LOG, "No longer nuclear operative") if(issilicon(operative_mind.current)) to_chat(operative_mind.current, "You have been turned into a robot! You are no longer a Syndicate operative.") else @@ -78,12 +79,12 @@ proc/issyndicate(mob/living/M as mob) //////////////////////////////////////////////////////////////////////////////////////// /datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind) - var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS] + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] opshud.join_hud(synd_mind.current) set_antag_hud(synd_mind.current, "hudoperative") /datum/game_mode/proc/update_synd_icons_removed(datum/mind/synd_mind) - var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS] + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] opshud.leave_hud(synd_mind.current) set_antag_hud(synd_mind.current, null) @@ -402,7 +403,7 @@ proc/issyndicate(mob/living/M as mob) else text += "body destroyed" text += ")" - for(var/obj/item/uplink/H in world_uplinks) + for(var/obj/item/uplink/H in GLOB.world_uplinks) if(H && H.uplink_owner && H.uplink_owner==syndicate.key) TC_uses += H.used_TC purchases += H.purchase_log @@ -437,17 +438,17 @@ proc/issyndicate(mob/living/M as mob) for(var/datum/mind/M in SSticker.mode.syndicates) foecount++ if(!M || !M.current) - score_opkilled++ + GLOB.score_opkilled++ continue if(M.current.stat == DEAD) - score_opkilled++ + GLOB.score_opkilled++ else if(M.current.restrained()) - score_arrested++ + GLOB.score_arrested++ - if(foecount == score_arrested) - score_allarrested = 1 + if(foecount == GLOB.score_arrested) + GLOB.score_allarrested = 1 for(var/obj/machinery/nuclearbomb/nuke in world) if(nuke.r_code == "Nope") continue @@ -458,25 +459,25 @@ proc/issyndicate(mob/living/M as mob) var/list/fiftythousand_penalty = list(/area/security/main, /area/security/brig, /area/security/armoury, /area/security/checkpoint2) if(is_type_in_list(A, thousand_penalty)) - score_nuked_penalty = 1000 + GLOB.score_nuked_penalty = 1000 else if(is_type_in_list(A, fiftythousand_penalty)) - score_nuked_penalty = 50000 + GLOB.score_nuked_penalty = 50000 else if(istype(A, /area/engine)) - score_nuked_penalty = 100000 + GLOB.score_nuked_penalty = 100000 else - score_nuked_penalty = 10000 + GLOB.score_nuked_penalty = 10000 break - var/killpoints = score_opkilled * 250 - var/arrestpoints = score_arrested * 1000 - score_crewscore += killpoints - score_crewscore += arrestpoints - if(score_nuked) - score_crewscore -= score_nuked_penalty + var/killpoints = GLOB.score_opkilled * 250 + var/arrestpoints = GLOB.score_arrested * 1000 + GLOB.score_crewscore += killpoints + GLOB.score_crewscore += arrestpoints + if(GLOB.score_nuked) + GLOB.score_crewscore -= GLOB.score_nuked_penalty @@ -524,11 +525,11 @@ proc/issyndicate(mob/living/M as mob) dat += "
" - dat += "Operatives Arrested: [score_arrested] ([score_arrested * 1000] Points)
" - dat += "All Operatives Arrested: [score_allarrested ? "Yes" : "No"] (Score tripled)
" + dat += "Operatives Arrested: [GLOB.score_arrested] ([GLOB.score_arrested * 1000] Points)
" + dat += "All Operatives Arrested: [GLOB.score_allarrested ? "Yes" : "No"] (Score tripled)
" - dat += "Operatives Killed: [score_opkilled] ([score_opkilled * 1000] Points)
" - dat += "Station Destroyed: [score_nuked ? "Yes" : "No"] (-[score_nuked_penalty] Points)
" + dat += "Operatives Killed: [GLOB.score_opkilled] ([GLOB.score_opkilled * 1000] Points)
" + dat += "Station Destroyed: [GLOB.score_nuked ? "Yes" : "No"] (-[GLOB.score_nuked_penalty] Points)
" dat += "
" return dat diff --git a/code/game/gamemodes/nuclear/nuclear_challenge.dm b/code/game/gamemodes/nuclear/nuclear_challenge.dm index 35c26408c5b..48116911640 100644 --- a/code/game/gamemodes/nuclear/nuclear_challenge.dm +++ b/code/game/gamemodes/nuclear/nuclear_challenge.dm @@ -48,7 +48,7 @@ if(!check_allowed(user) || !war_declaration) return - event_announcement.Announce(war_declaration, "Declaration of War", 'sound/effects/siren.ogg') + GLOB.event_announcement.Announce(war_declaration, "Declaration of War", 'sound/effects/siren.ogg') to_chat(user, "You've attracted the attention of powerful forces within the syndicate. A bonus bundle of telecrystals has been granted to your team. Great things await you if you complete the mission.") to_chat(user, "Your bonus telecrystals have been split between your team's uplinks.") diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index eec24d0e1ed..8e38f106cc7 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -5,7 +5,7 @@ #define NUKE_UNWRENCHED 4 #define NUKE_MOBILE 5 -var/bomb_set +GLOBAL_VAR(bomb_set) /obj/machinery/nuclearbomb name = "\improper Nuclear Fission Explosive" @@ -48,11 +48,10 @@ var/bomb_set /obj/machinery/nuclearbomb/process() if(timing) - bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. + GLOB.bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed. timeleft = max(timeleft - 2, 0) // 2 seconds per process() if(timeleft <= 0) - spawn - explode() + INVOKE_ASYNC(src, .proc/explode) SSnanoui.update_uis(src) return @@ -195,7 +194,7 @@ var/bomb_set /obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "nuclear_bomb.tmpl", "Nuke Control Panel", 450, 550, state = physical_state) + ui = new(user, src, ui_key, "nuclear_bomb.tmpl", "Nuke Control Panel", 450, 550, state = GLOB.physical_state) ui.open() ui.set_auto_update(1) @@ -310,13 +309,13 @@ var/bomb_set message_admins("[key_name_admin(usr)] engaged a nuclear bomb (JMP)") if(!is_syndicate) set_security_level("delta") - bomb_set = 1 //There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke/N + GLOB.bomb_set = 1 //There can still be issues with this resetting when there are multiple bombs. Not a big deal though for Nuke/N else - bomb_set = 0 + GLOB.bomb_set = 0 else if(!is_syndicate) set_security_level(previous_level) - bomb_set = 0 + GLOB.bomb_set = 0 if(!lighthack) icon_state = "nuclearbomb1" if(href_list["safety"]) @@ -325,7 +324,7 @@ var/bomb_set if(!is_syndicate) set_security_level(previous_level) timing = 0 - bomb_set = 0 + GLOB.bomb_set = 0 if(href_list["anchor"]) if(removal_stage == NUKE_MOBILE) anchored = 0 @@ -347,6 +346,9 @@ var/bomb_set /obj/machinery/nuclearbomb/blob_act(obj/structure/blob/B) if(timing == -1.0) return + if(timing) //boom + INVOKE_ASYNC(src, .proc/explode) + return qdel(src) /obj/machinery/nuclearbomb/tesla_act(power, explosive) @@ -369,7 +371,7 @@ var/bomb_set SSticker.mode.explosion_in_progress = 1 sleep(100) - enter_allowed = 0 + GLOB.enter_allowed = 0 var/off_station = 0 var/turf/bomb_location = get_turf(src) @@ -453,9 +455,9 @@ var/bomb_set STOP_PROCESSING(SSobj, src) return ..() - if(blobstart.len > 0) + if(GLOB.blobstart.len > 0) GLOB.poi_list.Remove(src) - var/obj/item/disk/nuclear/NEWDISK = new(pick(blobstart)) + var/obj/item/disk/nuclear/NEWDISK = new(pick(GLOB.blobstart)) transfer_fingerprints_to(NEWDISK) message_admins("[src] has been destroyed at ([diskturf.x], [diskturf.y], [diskturf.z] - JMP). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z] - JMP).") log_game("[src] has been destroyed in ([diskturf.x], [diskturf.y], [diskturf.z]). Moving it to ([NEWDISK.x], [NEWDISK.y], [NEWDISK.z]).") diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index f193856b3d9..e8f4c22e377 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -88,6 +88,7 @@ name = "advanced pinpointer" desc = "A larger version of the normal pinpointer, this unit features a helpful quantum entanglement detection system to locate various objects that do not broadcast a locator signal." var/mode = 0 // Mode 0 locates disk, mode 1 locates coordinates. + var/modelocked = FALSE // If true, user cannot change mode. var/turf/location = null var/obj/target = null @@ -121,6 +122,10 @@ if(usr.stat || usr.restrained()) return + if(modelocked) + to_chat(usr, "[src] is locked. It can only track one specific target.") + return + active = 0 icon_state = icon_off target = null @@ -156,7 +161,7 @@ if("Item") var/list/item_names[0] var/list/item_paths[0] - for(var/objective in potential_theft_objectives) + for(var/objective in GLOB.potential_theft_objectives) var/datum/theft_objective/T = objective var/name = initial(T.name) item_names += name @@ -215,7 +220,7 @@ if(mode) //Check in case the mode changes while operating worklocation() return - if(bomb_set) //If the bomb is set, lead to the shuttle + if(GLOB.bomb_set) //If the bomb is set, lead to the shuttle mode = 1 //Ensures worklocation() continues to work worklocation() playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) //Plays a beep @@ -244,7 +249,7 @@ if(!mode) workdisk() return - if(!bomb_set) + if(!GLOB.bomb_set) mode = 0 workdisk() playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index eb667d4994d..0da5d8a3a0a 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1,6 +1,6 @@ GLOBAL_LIST_EMPTY(all_objectives) -var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datum/theft_objective/steal - /datum/theft_objective/number - /datum/theft_objective/unique +GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective) - /datum/theft_objective/steal - /datum/theft_objective/number - /datum/theft_objective/unique)) /datum/objective var/datum/mind/owner = null //Who owns the objective. @@ -231,7 +231,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu return 0 /datum/objective/block - explanation_text = "Do not allow any lifeforms, be it organic or synthetic to escape on the shuttle alive. AIs, Cyborgs, and pAIs are not considered alive." + explanation_text = "Do not allow any lifeforms, be it organic or synthetic to escape on the shuttle alive. AIs, Cyborgs, Maintenance drones, and pAIs are not considered alive." martyr_compatible = 1 /datum/objective/block/check_completion() @@ -243,15 +243,14 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu return 0 var/area/A = SSshuttle.emergency.areaInstance - var/list/protected_mobs = list(/mob/living/silicon/ai, /mob/living/silicon/pai, /mob/living/silicon/robot) for(var/mob/living/player in GLOB.player_list) - if(player.type in protected_mobs) - continue + if(issilicon(player)) + continue // If they're silicon, they're not considered alive, skip them. if(player.mind && player.stat != DEAD) if(get_area(player) == A) - return 0 + return 0 // If there are any other organic mobs on the shuttle, you failed the objective. return 1 @@ -359,7 +358,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu var/loop=50 while(!steal_target && loop > 0) loop-- - var/thefttype = pick(potential_theft_objectives) + var/thefttype = pick(GLOB.potential_theft_objectives) var/datum/theft_objective/O = new thefttype if(owner.assigned_role in O.protected_jobs) continue @@ -377,7 +376,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu /datum/objective/steal/proc/select_target() - var/list/possible_items_all = potential_theft_objectives+"custom" + var/list/possible_items_all = GLOB.potential_theft_objectives+"custom" var/new_target = input("Select target:", "Objective target", null) as null|anything in possible_items_all if(!new_target) return if(new_target == "custom") @@ -400,6 +399,9 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu if(!steal_target) return 1 // Free Objective + if(!owner.current) + return FALSE + var/list/all_items = owner.current.GetAllContents() for(var/obj/I in all_items) @@ -476,7 +478,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datu n_p++ target_amount = min(target_amount, n_p) - explanation_text = "Absorb [target_amount] compatible genomes." + explanation_text = "Acquire [target_amount] compatible genomes. The 'Extract DNA Sting' can be used to stealthily get genomes without killing somebody." return target_amount /datum/objective/absorb/check_completion() diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index ac0b3705198..a38982905bc 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -218,7 +218,7 @@ if(SSshuttle.emergency.mode == SHUTTLE_STRANDED) SSshuttle.emergency.mode = SHUTTLE_DOCKED SSshuttle.emergency.timer = world.time - command_announcement.Announce("Hostile enviroment resolved. You have 3 minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg') + GLOB.command_announcement.Announce("Hostile enviroment resolved. You have 3 minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg') return ..() if(finished != 0) return TRUE @@ -229,7 +229,7 @@ //Deals with converting players to the revolution// /////////////////////////////////////////////////// /datum/game_mode/proc/add_revolutionary(datum/mind/rev_mind) - if(rev_mind.assigned_role in command_positions) + if(rev_mind.assigned_role in GLOB.command_positions) return 0 var/mob/living/carbon/human/H = rev_mind.current//Check to see if the potential rev is implanted if(ismindshielded(H)) @@ -244,6 +244,7 @@ rev_mind.current.Stun(5) to_chat(rev_mind.current, " You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!") rev_mind.current.create_attack_log("Has been converted to the revolution!") + rev_mind.current.create_log(CONVERSION_LOG, "converted to the revolution") rev_mind.special_role = SPECIAL_ROLE_REV update_rev_icons_added(rev_mind) if(jobban_isbanned(rev_mind.current, ROLE_REV) || jobban_isbanned(rev_mind.current, ROLE_SYNDICATE)) @@ -262,7 +263,7 @@ revolutionaries -= rev_mind rev_mind.special_role = null rev_mind.current.create_attack_log("Has renounced the revolution!") - + rev_mind.current.create_log(CONVERSION_LOG, "renounced the revolution") if(beingborged) to_chat(rev_mind.current, "The frame's firmware detects and deletes your neural reprogramming! You remember nothing[remove_head ? "." : " but the name of the one who flashed you."]") message_admins("[key_name_admin(rev_mind.current)] [ADMIN_QUE(rev_mind.current,"?")] ([ADMIN_FLW(rev_mind.current,"FLW")]) has been borged while being a [remove_head ? "leader" : " member"] of the revolution.") @@ -283,7 +284,7 @@ //Adds the rev hud to a new convert// ///////////////////////////////////// /datum/game_mode/proc/update_rev_icons_added(datum/mind/rev_mind) - var/datum/atom_hud/antag/revhud = huds[ANTAG_HUD_REV] + var/datum/atom_hud/antag/revhud = GLOB.huds[ANTAG_HUD_REV] revhud.join_hud(rev_mind.current) set_antag_hud(rev_mind.current, ((rev_mind in head_revolutionaries) ? "hudheadrevolutionary" : "hudrevolutionary")) @@ -291,7 +292,7 @@ //Removes the hud from deconverted revs// ///////////////////////////////////////// /datum/game_mode/proc/update_rev_icons_removed(datum/mind/rev_mind) - var/datum/atom_hud/antag/revhud = huds[ANTAG_HUD_REV] + var/datum/atom_hud/antag/revhud = GLOB.huds[ANTAG_HUD_REV] revhud.leave_hud(rev_mind.current) set_antag_hud(rev_mind.current, null) @@ -335,7 +336,7 @@ if(head_revolutionaries.len || GAMEMODE_IS_REVOLUTION) var/num_revs = 0 var/num_survivors = 0 - for(var/mob/living/carbon/survivor in GLOB.living_mob_list) + for(var/mob/living/carbon/survivor in GLOB.alive_mob_list) if(survivor.ckey) num_survivors++ if(survivor.mind) @@ -372,35 +373,35 @@ for(var/datum/mind/M in SSticker.mode.head_revolutionaries) foecount++ if(!M || !M.current) - score_opkilled++ + GLOB.score_opkilled++ continue if(M.current.stat == DEAD) - score_opkilled++ + GLOB.score_opkilled++ else if(M.current.restrained()) - score_arrested++ + GLOB.score_arrested++ - if(foecount == score_arrested) - score_allarrested = 1 + if(foecount == GLOB.score_arrested) + GLOB.score_allarrested = 1 for(var/mob/living/carbon/human/player in world) if(player.mind) var/role = player.mind.assigned_role if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director")) if(player.stat == DEAD) - score_deadcommand++ + GLOB.score_deadcommand++ - var/arrestpoints = score_arrested * 1000 - var/killpoints = score_opkilled * 500 - var/comdeadpts = score_deadcommand * 500 - if(score_traitorswon) - score_crewscore -= 10000 + var/arrestpoints = GLOB.score_arrested * 1000 + var/killpoints = GLOB.score_opkilled * 500 + var/comdeadpts = GLOB.score_deadcommand * 500 + if(GLOB.score_traitorswon) + GLOB.score_crewscore -= 10000 - score_crewscore += arrestpoints - score_crewscore += killpoints - score_crewscore -= comdeadpts + GLOB.score_crewscore += arrestpoints + GLOB.score_crewscore += killpoints + GLOB.score_crewscore -= comdeadpts /datum/game_mode/revolution/get_scoreboard_stats() @@ -438,12 +439,12 @@ dat += "Number of Surviving Loyal Crew: [loycount]
" dat += "
" - dat += "Revolution Heads Arrested: [score_arrested] ([score_arrested * 1000] Points)
" - dat += "All Revolution Heads Arrested: [score_allarrested ? "Yes" : "No"] (Score tripled)
" + dat += "Revolution Heads Arrested: [GLOB.score_arrested] ([GLOB.score_arrested * 1000] Points)
" + dat += "All Revolution Heads Arrested: [GLOB.score_allarrested ? "Yes" : "No"] (Score tripled)
" - dat += "Revolution Heads Slain: [score_opkilled] ([score_opkilled * 500] Points)
" - dat += "Command Staff Slain: [score_deadcommand] (-[score_deadcommand * 500] Points)
" - dat += "Revolution Successful: [score_traitorswon ? "Yes" : "No"] (-[score_traitorswon * 10000] Points)
" + dat += "Revolution Heads Slain: [GLOB.score_opkilled] ([GLOB.score_opkilled * 500] Points)
" + dat += "Command Staff Slain: [GLOB.score_deadcommand] (-[GLOB.score_deadcommand * 500] Points)
" + dat += "Revolution Successful: [GLOB.score_traitorswon ? "Yes" : "No"] (-[GLOB.score_traitorswon * 10000] Points)
" dat += "
" return dat diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm index 5dd462296b9..69eaef9051b 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -1,8 +1,8 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 -var/hsboxspawn = 1 -var/list - hrefs = list( +// Someone needs to properly path this file, or just delete it since its unticked and was last properly touched >4 years ago +GLOBAL_VAR_INIT(hsboxspawn, 1) +GLOBAL_LIST_INIT(sandbox_hrefs, list( "hsbsuit" = "Suit Up (Space Travel Gear)", "hsbmetal" = "Spawn 50 Metal", "hsbglass" = "Spawn 50 Glass", @@ -13,7 +13,7 @@ var/list "hsbfueltank" = "Spawn Welding Fuel Tank", "hsbwater tank" = "Spawn Water Tank", "hsbtoolbox" = "Spawn Toolbox", - "hsbmedkit" = "Spawn Medical Kit") + "hsbmedkit" = "Spawn Medical Kit")) mob var/datum/hSB/sandbox = null @@ -39,8 +39,8 @@ datum/hSB hsbpanel += "Administration Tools:
" hsbpanel += "- Toggle Object Spawning

" hsbpanel += "Regular Tools:
" - for(var/T in hrefs) - hsbpanel += "- [hrefs[T]]
" + for(var/T in GLOB.sandbox_hrefs) + hsbpanel += "- [GLOB.sandbox_hrefs[T]]
" if(hsboxspawn) hsbpanel += "- Spawn Object

" usr << browse(hsbpanel, "window=hsbpanel") diff --git a/code/game/gamemodes/scoreboard.dm b/code/game/gamemodes/scoreboard.dm index 379b4fbdcd9..069b0915c00 100644 --- a/code/game/gamemodes/scoreboard.dm +++ b/code/game/gamemodes/scoreboard.dm @@ -22,12 +22,12 @@ // Who is alive/dead, who escaped for(var/mob/living/silicon/ai/I in GLOB.mob_list) if(I.stat == DEAD && is_station_level(I.z)) - score_deadaipenalty++ - score_deadcrew++ + GLOB.score_deadaipenalty++ + GLOB.score_deadcrew++ for(var/mob/living/carbon/human/I in GLOB.mob_list) if(I.stat == DEAD && is_station_level(I.z)) - score_deadcrew++ + GLOB.score_deadcrew++ if(SSshuttle.emergency.mode >= SHUTTLE_ENDGAME) for(var/mob/living/player in GLOB.mob_list) @@ -36,7 +36,7 @@ var/turf/location = get_turf(player.loc) var/area/escape_zone = locate(/area/shuttle/escape) if(location in escape_zone) - score_escapees++ + GLOB.score_escapees++ @@ -50,21 +50,21 @@ var/turf/location = get_turf(E.loc) var/area/escape_zone = SSshuttle.emergency.areaInstance - if(E.stat != DEAD && location in escape_zone) // Escapee Scores + if(E.stat != DEAD && (location in escape_zone)) // Escapee Scores cash_score = get_score_container_worth(E) - if(cash_score > score_richestcash) - score_richestcash = cash_score - score_richestname = E.real_name - score_richestjob = E.job - score_richestkey = E.key + if(cash_score > GLOB.score_richestcash) + GLOB.score_richestcash = cash_score + GLOB.score_richestname = E.real_name + GLOB.score_richestjob = E.job + GLOB.score_richestkey = E.key dmg_score = E.getBruteLoss() + E.getFireLoss() + E.getToxLoss() + E.getOxyLoss() - if(dmg_score > score_dmgestdamage) - score_dmgestdamage = dmg_score - score_dmgestname = E.real_name - score_dmgestjob = E.job - score_dmgestkey = E.key + if(dmg_score > GLOB.score_dmgestdamage) + GLOB.score_dmgestdamage = dmg_score + GLOB.score_dmgestname = E.real_name + GLOB.score_dmgestjob = E.job + GLOB.score_dmgestkey = E.key if(SSticker && SSticker.mode) SSticker.mode.set_scoreboard_gvars() @@ -75,73 +75,73 @@ if(!is_station_level(A.z)) continue for(var/obj/item/stock_parts/cell/C in A.contents) if(C.charge < 2300) - score_powerloss++ //200 charge leeway + GLOB.score_powerloss++ //200 charge leeway // Check how much uncleaned mess is on the station for(var/obj/effect/decal/cleanable/M in world) if(!is_station_level(M.z)) continue if(istype(M, /obj/effect/decal/cleanable/blood/gibs)) - score_mess += 3 + GLOB.score_mess += 3 if(istype(M, /obj/effect/decal/cleanable/blood)) - score_mess += 1 + GLOB.score_mess += 1 if(istype(M, /obj/effect/decal/cleanable/vomit)) - score_mess += 1 + GLOB.score_mess += 1 // Bonus Modifiers //var/traitorwins = score_traitorswon - var/deathpoints = score_deadcrew * 25 //done - var/researchpoints = score_researchdone * 30 - var/eventpoints = score_eventsendured * 50 - var/escapoints = score_escapees * 25 //done - var/harvests = score_stuffharvested * 5 //done - var/shipping = score_stuffshipped * 5 - var/mining = score_oremined * 2 //done - var/meals = score_meals * 5 //done, but this only counts cooked meals, not drinks served - var/power = score_powerloss * 20 + var/deathpoints = GLOB.score_deadcrew * 25 //done + var/researchpoints = GLOB.score_researchdone * 30 + var/eventpoints = GLOB.score_eventsendured * 50 + var/escapoints = GLOB.score_escapees * 25 //done + var/harvests = GLOB.score_stuffharvested * 5 //done + var/shipping = GLOB.score_stuffshipped * 5 + var/mining = GLOB.score_oremined * 2 //done + var/meals = GLOB.score_meals * 5 //done, but this only counts cooked meals, not drinks served + var/power = GLOB.score_powerloss * 20 var/messpoints - if(score_mess != 0) - messpoints = score_mess //done - var/plaguepoints = score_disease * 30 + if(GLOB.score_mess != 0) + messpoints = GLOB.score_mess //done + var/plaguepoints = GLOB.score_disease * 30 // Good Things - score_crewscore += shipping - score_crewscore += harvests - score_crewscore += mining - score_crewscore += researchpoints - score_crewscore += eventpoints - score_crewscore += escapoints + GLOB.score_crewscore += shipping + GLOB.score_crewscore += harvests + GLOB.score_crewscore += mining + GLOB.score_crewscore += researchpoints + GLOB.score_crewscore += eventpoints + GLOB.score_crewscore += escapoints if(power == 0) - score_crewscore += 2500 - score_powerbonus = 1 + GLOB.score_crewscore += 2500 + GLOB.score_powerbonus = 1 - if(score_mess == 0) - score_crewscore += 3000 - score_messbonus = 1 + if(GLOB.score_mess == 0) + GLOB.score_crewscore += 3000 + GLOB.score_messbonus = 1 - score_crewscore += meals - if(score_allarrested) - score_crewscore *= 3 // This needs to be here for the bonus to be applied properly + GLOB.score_crewscore += meals + if(GLOB.score_allarrested) + GLOB.score_crewscore *= 3 // This needs to be here for the bonus to be applied properly - score_crewscore -= deathpoints - if(score_deadaipenalty) - score_crewscore -= 250 - score_crewscore -= power + GLOB.score_crewscore -= deathpoints + if(GLOB.score_deadaipenalty) + GLOB.score_crewscore -= 250 + GLOB.score_crewscore -= power - score_crewscore -= messpoints - score_crewscore -= plaguepoints + GLOB.score_crewscore -= messpoints + GLOB.score_crewscore -= plaguepoints // Show the score - might add "ranks" later to_chat(world, "The crew's final score is:") - to_chat(world, "[score_crewscore]") + to_chat(world, "[GLOB.score_crewscore]") for(var/mob/E in GLOB.player_list) if(E.client && !E.get_preference(DISABLE_SCOREBOARD)) E.scorestats() @@ -178,30 +178,30 @@ General Statistics
The Good:
- Useful Items Shipped: [score_stuffshipped] ([score_stuffshipped * 5] Points)
- Hydroponics Harvests: [score_stuffharvested] ([score_stuffharvested * 5] Points)
- Ore Mined: [score_oremined] ([score_oremined * 2] Points)
- Refreshments Prepared: [score_meals] ([score_meals * 5] Points)
- Research Completed: [score_researchdone] ([score_researchdone * 30] Points)
"} - if(SSshuttle.emergency.mode == SHUTTLE_ENDGAME) dat += "Shuttle Escapees: [score_escapees] ([score_escapees * 25] Points)
" - dat += {"Random Events Endured: [score_eventsendured] ([score_eventsendured * 50] Points)
- Whole Station Powered: [score_powerbonus ? "Yes" : "No"] ([score_powerbonus * 2500] Points)
- Ultra-Clean Station: [score_mess ? "No" : "Yes"] ([score_messbonus * 3000] Points)

+ Useful Items Shipped: [GLOB.score_stuffshipped] ([GLOB.score_stuffshipped * 5] Points)
+ Hydroponics Harvests: [GLOB.score_stuffharvested] ([GLOB.score_stuffharvested * 5] Points)
+ Ore Mined: [GLOB.score_oremined] ([GLOB.score_oremined * 2] Points)
+ Refreshments Prepared: [GLOB.score_meals] ([GLOB.score_meals * 5] Points)
+ Research Completed: [GLOB.score_researchdone] ([GLOB.score_researchdone * 30] Points)
"} + if(SSshuttle.emergency.mode == SHUTTLE_ENDGAME) dat += "Shuttle Escapees: [GLOB.score_escapees] ([GLOB.score_escapees * 25] Points)
" + dat += {"Random Events Endured: [GLOB.score_eventsendured] ([GLOB.score_eventsendured * 50] Points)
+ Whole Station Powered: [GLOB.score_powerbonus ? "Yes" : "No"] ([GLOB.score_powerbonus * 2500] Points)
+ Ultra-Clean Station: [GLOB.score_mess ? "No" : "Yes"] ([GLOB.score_messbonus * 3000] Points)

The bad:
- Dead bodies on Station: [score_deadcrew] (-[score_deadcrew * 25] Points)
- Uncleaned Messes: [score_mess] (-[score_mess] Points)
- Station Power Issues: [score_powerloss] (-[score_powerloss * 20] Points)
- Rampant Diseases: [score_disease] (-[score_disease * 30] Points)
- AI Destroyed: [score_deadaipenalty ? "Yes" : "No"] (-[score_deadaipenalty * 250] Points)

+ Dead bodies on Station: [GLOB.score_deadcrew] (-[GLOB.score_deadcrew * 25] Points)
+ Uncleaned Messes: [GLOB.score_mess] (-[GLOB.score_mess] Points)
+ Station Power Issues: [GLOB.score_powerloss] (-[GLOB.score_powerloss * 20] Points)
+ Rampant Diseases: [GLOB.score_disease] (-[GLOB.score_disease * 30] Points)
+ AI Destroyed: [GLOB.score_deadaipenalty ? "Yes" : "No"] (-[GLOB.score_deadaipenalty * 250] Points)

The Weird
- Food Eaten: [score_foodeaten] bites/sips
- Times a Clown was Abused: [score_clownabuse]

+ Food Eaten: [GLOB.score_foodeaten] bites/sips
+ Times a Clown was Abused: [GLOB.score_clownabuse]

"} - if(score_escapees) - dat += {"Richest Escapee: [score_richestname], [score_richestjob]: $[num2text(score_richestcash,50)] ([score_richestkey])
- Most Battered Escapee: [score_dmgestname], [score_dmgestjob]: [score_dmgestdamage] damage ([score_dmgestkey])
"} + if(GLOB.score_escapees) + dat += {"Richest Escapee: [GLOB.score_richestname], [GLOB.score_richestjob]: $[num2text(GLOB.score_richestcash,50)] ([GLOB.score_richestkey])
+ Most Battered Escapee: [GLOB.score_dmgestname], [GLOB.score_dmgestjob]: [GLOB.score_dmgestdamage] damage ([GLOB.score_dmgestkey])
"} else if(SSshuttle.emergency.mode <= SHUTTLE_STRANDED) dat += "The station wasn't evacuated!
" @@ -212,11 +212,11 @@ dat += {"

- FINAL SCORE: [score_crewscore]
+ FINAL SCORE: [GLOB.score_crewscore]
"} var/score_rating = "The Aristocrats!" - switch(score_crewscore) + switch(GLOB.score_crewscore) if(-99999 to -50000) score_rating = "Even the Singularity Deserves Better" if(-49999 to -5000) score_rating = "Singularity Fodder" if(-4999 to -1000) score_rating = "You're All Fired" diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index 507aaec0135..f6ba6504381 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -5,11 +5,11 @@ var/assigned = pick(blocksLeft) blocksLeft.Remove(assigned) if(good) - good_blocks += assigned + GLOB.good_blocks += assigned else - bad_blocks += assigned - assigned_blocks[assigned]=name - dna_activity_bounds[assigned]=activity_bounds + GLOB.bad_blocks += assigned + GLOB.assigned_blocks[assigned]=name + GLOB.dna_activity_bounds[assigned]=activity_bounds //Debug message_admins("[name] assigned to block #[assigned].") // testing("[name] assigned to block #[assigned].") return assigned @@ -17,9 +17,9 @@ /proc/setupgenetics() if(prob(50)) - BLOCKADD = rand(-300,300) + GLOB.blockadd = rand(-300,300) if(prob(75)) - DIFFMUT = rand(0,20) + GLOB.diffmut = rand(0,20) //Thanks to nexis for the fancy code @@ -34,70 +34,70 @@ //message_admins("Assigning DNA blocks:") // Standard muts - BLINDBLOCK = getAssignedBlock("BLIND", numsToAssign) - COLOURBLINDBLOCK = getAssignedBlock("COLOURBLIND", numsToAssign) - DEAFBLOCK = getAssignedBlock("DEAF", numsToAssign) - HULKBLOCK = getAssignedBlock("HULK", numsToAssign, DNA_HARD_BOUNDS, good=1) - TELEBLOCK = getAssignedBlock("TELE", numsToAssign, DNA_HARD_BOUNDS, good=1) - FIREBLOCK = getAssignedBlock("FIRE", numsToAssign, DNA_HARDER_BOUNDS, good=1) - XRAYBLOCK = getAssignedBlock("XRAY", numsToAssign, DNA_HARDER_BOUNDS, good=1) - CLUMSYBLOCK = getAssignedBlock("CLUMSY", numsToAssign) - FAKEBLOCK = getAssignedBlock("FAKE", numsToAssign) - COUGHBLOCK = getAssignedBlock("COUGH", numsToAssign) - GLASSESBLOCK = getAssignedBlock("GLASSES", numsToAssign) - EPILEPSYBLOCK = getAssignedBlock("EPILEPSY", numsToAssign) - TWITCHBLOCK = getAssignedBlock("TWITCH", numsToAssign) - NERVOUSBLOCK = getAssignedBlock("NERVOUS", numsToAssign) - WINGDINGSBLOCK = getAssignedBlock("WINGDINGS", numsToAssign) + GLOB.blindblock = getAssignedBlock("BLINDNESS", numsToAssign) + GLOB.colourblindblock = getAssignedBlock("COLOURBLIND", numsToAssign) + GLOB.deafblock = getAssignedBlock("DEAF", numsToAssign) + GLOB.hulkblock = getAssignedBlock("HULK", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.teleblock = getAssignedBlock("TELE", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.fireblock = getAssignedBlock("FIRE", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.xrayblock = getAssignedBlock("XRAY", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.clumsyblock = getAssignedBlock("CLUMSY", numsToAssign) + GLOB.fakeblock = getAssignedBlock("FAKE", numsToAssign) + GLOB.coughblock = getAssignedBlock("COUGH", numsToAssign) + GLOB.glassesblock = getAssignedBlock("GLASSES", numsToAssign) + GLOB.epilepsyblock = getAssignedBlock("EPILEPSY", numsToAssign) + GLOB.twitchblock = getAssignedBlock("TWITCH", numsToAssign) + GLOB.nervousblock = getAssignedBlock("NERVOUS", numsToAssign) + GLOB.wingdingsblock = getAssignedBlock("WINGDINGS", numsToAssign) // Bay muts - BREATHLESSBLOCK = getAssignedBlock("BREATHLESS", numsToAssign, DNA_HARD_BOUNDS, good=1) - REMOTEVIEWBLOCK = getAssignedBlock("REMOTEVIEW", numsToAssign, DNA_HARDER_BOUNDS, good=1) - REGENERATEBLOCK = getAssignedBlock("REGENERATE", numsToAssign, DNA_HARDER_BOUNDS, good=1) - INCREASERUNBLOCK = getAssignedBlock("INCREASERUN", numsToAssign, DNA_HARDER_BOUNDS, good=1) - REMOTETALKBLOCK = getAssignedBlock("REMOTETALK", numsToAssign, DNA_HARDER_BOUNDS, good=1) - MORPHBLOCK = getAssignedBlock("MORPH", numsToAssign, DNA_HARDER_BOUNDS, good=1) - COLDBLOCK = getAssignedBlock("COLD", numsToAssign, good=1) - HALLUCINATIONBLOCK = getAssignedBlock("HALLUCINATION", numsToAssign) - NOPRINTSBLOCK = getAssignedBlock("NOPRINTS", numsToAssign, DNA_HARD_BOUNDS, good=1) - SHOCKIMMUNITYBLOCK = getAssignedBlock("SHOCKIMMUNITY", numsToAssign, good=1) - SMALLSIZEBLOCK = getAssignedBlock("SMALLSIZE", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.breathlessblock = getAssignedBlock("BREATHLESS", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.remoteviewblock = getAssignedBlock("REMOTEVIEW", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.regenerateblock = getAssignedBlock("REGENERATE", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.increaserunblock = getAssignedBlock("INCREASERUN", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.remotetalkblock = getAssignedBlock("REMOTETALK", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.morphblock = getAssignedBlock("MORPH", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.coldblock = getAssignedBlock("COLD", numsToAssign, good=1) + GLOB.hallucinationblock = getAssignedBlock("HALLUCINATION", numsToAssign) + GLOB.noprintsblock = getAssignedBlock("NOPRINTS", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.shockimmunityblock = getAssignedBlock("SHOCKIMMUNITY", numsToAssign, good=1) + GLOB.smallsizeblock = getAssignedBlock("SMALLSIZE", numsToAssign, DNA_HARD_BOUNDS, good=1) // // Goon muts ///////////////////////////////////////////// // Disabilities - LISPBLOCK = getAssignedBlock("LISP", numsToAssign) - MUTEBLOCK = getAssignedBlock("MUTE", numsToAssign) - RADBLOCK = getAssignedBlock("RAD", numsToAssign) - FATBLOCK = getAssignedBlock("FAT", numsToAssign) - CHAVBLOCK = getAssignedBlock("CHAV", numsToAssign) - SWEDEBLOCK = getAssignedBlock("SWEDE", numsToAssign) - SCRAMBLEBLOCK = getAssignedBlock("SCRAMBLE", numsToAssign) - STRONGBLOCK = getAssignedBlock("STRONG", numsToAssign, good=1) - HORNSBLOCK = getAssignedBlock("HORNS", numsToAssign) - COMICBLOCK = getAssignedBlock("COMIC", numsToAssign) + GLOB.lispblock = getAssignedBlock("LISP", numsToAssign) + GLOB.muteblock = getAssignedBlock("MUTE", numsToAssign) + GLOB.radblock = getAssignedBlock("RAD", numsToAssign) + GLOB.fatblock = getAssignedBlock("FAT", numsToAssign) + GLOB.chavblock = getAssignedBlock("CHAV", numsToAssign) + GLOB.swedeblock = getAssignedBlock("SWEDE", numsToAssign) + GLOB.scrambleblock = getAssignedBlock("SCRAMBLE", numsToAssign) + GLOB.strongblock = getAssignedBlock("STRONG", numsToAssign, good=1) + GLOB.hornsblock = getAssignedBlock("HORNS", numsToAssign) + GLOB.comicblock = getAssignedBlock("COMIC", numsToAssign) // Powers - SOBERBLOCK = getAssignedBlock("SOBER", numsToAssign, good=1) - PSYRESISTBLOCK = getAssignedBlock("PSYRESIST", numsToAssign, DNA_HARD_BOUNDS, good=1) - SHADOWBLOCK = getAssignedBlock("SHADOW", numsToAssign, DNA_HARDER_BOUNDS, good=1) - CHAMELEONBLOCK = getAssignedBlock("CHAMELEON", numsToAssign, DNA_HARDER_BOUNDS, good=1) - CRYOBLOCK = getAssignedBlock("CRYO", numsToAssign, DNA_HARD_BOUNDS, good=1) - EATBLOCK = getAssignedBlock("EAT", numsToAssign, DNA_HARD_BOUNDS, good=1) - JUMPBLOCK = getAssignedBlock("JUMP", numsToAssign, DNA_HARD_BOUNDS, good=1) - IMMOLATEBLOCK = getAssignedBlock("IMMOLATE", numsToAssign) - EMPATHBLOCK = getAssignedBlock("EMPATH", numsToAssign, DNA_HARD_BOUNDS, good=1) - POLYMORPHBLOCK = getAssignedBlock("POLYMORPH", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.soberblock = getAssignedBlock("SOBER", numsToAssign, good=1) + GLOB.psyresistblock = getAssignedBlock("PSYRESIST", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.shadowblock = getAssignedBlock("SHADOW", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.chameleonblock = getAssignedBlock("CHAMELEON", numsToAssign, DNA_HARDER_BOUNDS, good=1) + GLOB.cryoblock = getAssignedBlock("CRYO", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.eatblock = getAssignedBlock("EAT", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.jumpblock = getAssignedBlock("JUMP", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.immolateblock = getAssignedBlock("IMMOLATE", numsToAssign) + GLOB.empathblock = getAssignedBlock("EMPATH", numsToAssign, DNA_HARD_BOUNDS, good=1) + GLOB.polymorphblock = getAssignedBlock("POLYMORPH", numsToAssign, DNA_HARDER_BOUNDS, good=1) // // /vg/ Blocks ///////////////////////////////////////////// // Disabilities - LOUDBLOCK = getAssignedBlock("LOUD", numsToAssign) - DIZZYBLOCK = getAssignedBlock("DIZZY", numsToAssign) + GLOB.loudblock = getAssignedBlock("LOUD", numsToAssign) + GLOB.dizzyblock = getAssignedBlock("DIZZY", numsToAssign) // @@ -105,7 +105,7 @@ /////////////////////////////////////////////. // Monkeyblock is always last. - MONKEYBLOCK = DNA_SE_LENGTH + GLOB.monkeyblock = DNA_SE_LENGTH // And the genes that actually do the work. (domutcheck improvements) var/list/blocks_assigned[DNA_SE_LENGTH] @@ -114,7 +114,7 @@ if(G.block) if(G.block in blocks_assigned) warning("DNA2: Gene [G.name] trying to use already-assigned block [G.block] (used by [english_list(blocks_assigned[G.block])])") - dna_genes.Add(G) + GLOB.dna_genes.Add(G) var/list/assignedToBlock[0] if(blocks_assigned[G.block]) assignedToBlock=blocks_assigned[G.block] @@ -124,31 +124,15 @@ // I WILL HAVE A LIST OF GENES THAT MATCHES THE RANDOMIZED BLOCKS GODDAMNIT! for(var/block=1;block<=DNA_SE_LENGTH;block++) - var/name = assigned_blocks[block] - for(var/datum/dna/gene/gene in dna_genes) + var/name = GLOB.assigned_blocks[block] + for(var/datum/dna/gene/gene in GLOB.dna_genes) if(gene.name == name || gene.block == block) - if(gene.block in assigned_gene_blocks) - warning("DNA2: Gene [gene.name] trying to add to already assigned gene block list (used by [english_list(assigned_gene_blocks[block])])") - assigned_gene_blocks[block] = gene + if(gene.block in GLOB.assigned_gene_blocks) + warning("DNA2: Gene [gene.name] trying to add to already assigned gene block list (used by [english_list(GLOB.assigned_gene_blocks[block])])") + GLOB.assigned_gene_blocks[block] = gene //testing("DNA2: [numsToAssign.len] blocks are unused: [english_list(numsToAssign)]") -/proc/setupfactions() - - // Populate the factions list: - for(var/x in typesof(/datum/faction)) - var/datum/faction/F = new x - if(!F.name) - qdel(F) - continue - else - SSticker.factions.Add(F) - SSticker.availablefactions.Add(F) - - // Populate the syndicate coalition: - for(var/datum/faction/syndicate/S in SSticker.factions) - SSticker.syndicate_coalition.Add(S) - /proc/setupcult() var/static/datum/cult_info/picked_cult // Only needs to get picked once diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm index b4b4b265711..9cd91817af4 100644 --- a/code/game/gamemodes/shadowling/shadowling.dm +++ b/code/game/gamemodes/shadowling/shadowling.dm @@ -158,6 +158,7 @@ Made by Xhuis new_thrall_mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL update_shadow_icons_added(new_thrall_mind) new_thrall_mind.current.create_attack_log("Became a thrall") + new_thrall_mind.current.create_log(CONVERSION_LOG, "Became a thrall") new_thrall_mind.current.add_language("Shadowling Hivemind") new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/lesser_shadow_walk(null)) new_thrall_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_vision/thrall(null)) @@ -171,7 +172,7 @@ Made by Xhuis replace_jobbanned_player(new_thrall_mind.current, ROLE_SHADOWLING) if(!victory_warning_announced && (length(shadowling_thralls) >= warning_threshold))//are the slings very close to winning? victory_warning_announced = TRUE //then let's give the station a warning - command_announcement.Announce("Large concentration of psychic bluespace energy detected by long-ranged scanners. Shadowling ascension event imminent. Prevent it at all costs!", "Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg') + GLOB.command_announcement.Announce("Large concentration of psychic bluespace energy detected by long-ranged scanners. Shadowling ascension event imminent. Prevent it at all costs!", "Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg') return 1 /datum/game_mode/proc/remove_thrall(datum/mind/thrall_mind, var/kill = 0) @@ -179,6 +180,7 @@ Made by Xhuis return 0 //If there is no mind, the mind isn't a thrall, or the mind's mob isn't alive, return shadowling_thralls.Remove(thrall_mind) thrall_mind.current.create_attack_log("Dethralled") + thrall_mind.current.create_log(CONVERSION_LOG, "Dethralled") thrall_mind.special_role = null update_shadow_icons_removed(thrall_mind) for(var/obj/effect/proc_holder/spell/S in thrall_mind.spell_list) @@ -236,6 +238,7 @@ Made by Xhuis update_shadow_icons_removed(ling_mind) shadows.Remove(ling_mind) ling_mind.current.create_attack_log("Deshadowlinged") + ling_mind.current.create_log(CONVERSION_LOG, "Deshadowlinged") ling_mind.special_role = null for(var/obj/effect/proc_holder/spell/S in ling_mind.spell_list) ling_mind.RemoveSpell(S) @@ -322,12 +325,12 @@ Made by Xhuis */ /datum/game_mode/proc/update_shadow_icons_added(datum/mind/shadow_mind) - var/datum/atom_hud/antag/shadow_hud = huds[ANTAG_HUD_SHADOW] + var/datum/atom_hud/antag/shadow_hud = GLOB.huds[ANTAG_HUD_SHADOW] shadow_hud.join_hud(shadow_mind.current) set_antag_hud(shadow_mind.current, ((shadow_mind in shadows) ? "hudshadowling" : "hudshadowlingthrall")) /datum/game_mode/proc/update_shadow_icons_removed(datum/mind/shadow_mind) //This should never actually occur, but it's here anyway. - var/datum/atom_hud/antag/shadow_hud = huds[ANTAG_HUD_SHADOW] + var/datum/atom_hud/antag/shadow_hud = GLOB.huds[ANTAG_HUD_SHADOW] shadow_hud.leave_hud(shadow_mind.current) set_antag_hud(shadow_mind.current, null) diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index 1671c4a03b0..2cafb1bc219 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -375,7 +375,7 @@ to_chat(target, "You focus your telepathic energies abound, harnessing and drawing together the strength of your thralls.") - for(M in GLOB.living_mob_list) + for(M in GLOB.alive_mob_list) if(is_thrall(M)) thralls++ to_chat(M, "You feel hooks sink into your mind and pull.") @@ -413,7 +413,7 @@ else if(thralls >= victory_threshold) to_chat(target, "You are now powerful enough to ascend. Use the Ascendance ability when you are ready. This will kill all of your thralls.") to_chat(target, "You may find Ascendance in the Shadowling Evolution tab.") - for(M in GLOB.living_mob_list) + for(M in GLOB.alive_mob_list) if(is_shadow(M)) var/obj/effect/proc_holder/spell/targeted/collective_mind/CM if(CM in M.mind.spell_list) @@ -716,7 +716,7 @@ if(SSshuttle.emergency.mode == SHUTTLE_CALL) var/more_minutes = 6000 var/timer = SSshuttle.emergency.timeLeft(1) + more_minutes - event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 10 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg') + GLOB.event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 10 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg') SSshuttle.emergency.setTimer(timer) SSshuttle.emergency.canRecall = FALSE user.mind.spell_list.Remove(src) //Can only be used once! diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm index 514a16174b1..7896a4aab61 100644 --- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm @@ -1,5 +1,5 @@ //In here: Hatch and Ascendance -var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "Noaey'gief", "Mii`mahza", "Amerziox", "Gyrg-mylin", "Kanet'pruunance", "Vigistaezian") //Unpronouncable 2: electric boogalo) +GLOBAL_LIST_INIT(possibleShadowlingNames, list("U'ruan", "Y`shej", "Nex", "Hel-uae", "Noaey'gief", "Mii`mahza", "Amerziox", "Gyrg-mylin", "Kanet'pruunance", "Vigistaezian")) //Unpronouncable 2: electric boogalo) /obj/effect/proc_holder/spell/targeted/shadowling_hatch name = "Hatch" desc = "Casts off your disguise." @@ -66,8 +66,8 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N H.status_flags = temp_flags sleep(10) playsound(H.loc, 'sound/effects/ghost.ogg', 100, 1) - var/newNameId = pick(possibleShadowlingNames) - possibleShadowlingNames.Remove(newNameId) + var/newNameId = pick(GLOB.possibleShadowlingNames) + GLOB.possibleShadowlingNames.Remove(newNameId) H.real_name = newNameId H.name = user.real_name H.SetStunned(0) diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm index de9f8fc0eb7..4175883fc1a 100644 --- a/code/game/gamemodes/steal_items.dm +++ b/code/game/gamemodes/steal_items.dm @@ -76,12 +76,12 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C) /datum/theft_objective/blueprints name = "the station blueprints" - typepath = /obj/item/areaeditor/blueprints + typepath = /obj/item/areaeditor/blueprints/ce protected_jobs = list("Chief Engineer") altitems = list(/obj/item/photo) /datum/objective_item/steal/blueprints/check_special_completion(obj/item/I) - if(istype(I, /obj/item/areaeditor/blueprints)) + if(istype(I, /obj/item/areaeditor/blueprints/ce)) return 1 if(istype(I, /obj/item/photo)) var/obj/item/photo/P = I @@ -89,11 +89,6 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/aicard/C) return 1 return 0 -/datum/theft_objective/voidsuit - name = "a nasa voidsuit" - typepath = /obj/item/clothing/suit/space/nasavoid - protected_jobs = list("Research Director") - /datum/theft_objective/capmedal name = "the medal of captaincy" typepath = /obj/item/clothing/accessory/medal/gold/captain diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 30f559c7ee2..c7ab4490f48 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -102,7 +102,7 @@ var/TC_uses = 0 var/uplink_true = 0 var/purchases = "" - for(var/obj/item/uplink/H in world_uplinks) + for(var/obj/item/uplink/H in GLOB.world_uplinks) if(H && H.uplink_owner && H.uplink_owner==traitor.key) TC_uses += H.used_TC uplink_true=1 diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index ac5ddc92f98..3caf860383d 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -227,6 +227,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha if(istype(spell, /obj/effect/proc_holder/spell)) owner.mind.AddSpell(spell) powers += spell + owner.update_sight() // Life updates conditionally, so we need to update sight here in case the vamp gets new vision based on his powers. Maybe one day refactor to be more OOP and on the vampire's ability datum. /datum/vampire/proc/get_ability(path) for(var/P in powers) @@ -244,6 +245,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha powers -= ability owner.mind.spell_list.Remove(ability) qdel(ability) + owner.update_sight() // Life updates conditionally, so we need to update sight here in case the vamp loses his vision based powers. Maybe one day refactor to be more OOP and on the vampire's ability datum. /datum/vampire/proc/update_owner(var/mob/living/carbon/human/current) //Called when a vampire gets cloned. This updates vampire.owner to the new body. if(current.mind && current.mind.vampire && current.mind.vampire.owner && (current.mind.vampire.owner != current)) @@ -348,6 +350,7 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha SSticker.mode.vampires -= vampire_mind vampire_mind.special_role = null vampire_mind.current.create_attack_log("De-vampired") + vampire_mind.current.create_log(CONVERSION_LOG, "De-vampired") if(vampire_mind.vampire) vampire_mind.vampire.remove_vampire_powers() QDEL_NULL(vampire_mind.vampire) @@ -359,12 +362,12 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha //prepare for copypaste /datum/game_mode/proc/update_vampire_icons_added(datum/mind/vampire_mind) - var/datum/atom_hud/antag/vamp_hud = huds[ANTAG_HUD_VAMPIRE] + var/datum/atom_hud/antag/vamp_hud = GLOB.huds[ANTAG_HUD_VAMPIRE] vamp_hud.join_hud(vampire_mind.current) set_antag_hud(vampire_mind.current, ((vampire_mind in vampires) ? "hudvampire" : "hudvampirethrall")) /datum/game_mode/proc/update_vampire_icons_removed(datum/mind/vampire_mind) - var/datum/atom_hud/antag/vampire_hud = huds[ANTAG_HUD_VAMPIRE] + var/datum/atom_hud/antag/vampire_hud = GLOB.huds[ANTAG_HUD_VAMPIRE] vampire_hud.leave_hud(vampire_mind.current) set_antag_hud(vampire_mind.current, null) diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index 24e47577c31..2c7cee9d61a 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -243,7 +243,7 @@ scramble(1, H, 100) H.real_name = random_name(H.gender, H.dna.species.name) //Give them a name that makes sense for their species. H.sync_organ_dna(assimilate = 1) - H.update_body(0) + H.update_body() H.reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover. H.reset_markings() //...Or markings. H.dna.ResetUIFrom(H) @@ -397,7 +397,7 @@ /obj/effect/proc_holder/spell/vampire/bats/choose_targets(mob/user = usr) var/list/turf/locs = new - for(var/direction in alldirs) //looking for bat spawns + for(var/direction in GLOB.alldirs) //looking for bat spawns if(locs.len == num_bats) //we found 2 locations and thats all we need break var/turf/T = get_step(usr, direction) //getting a loc in that direction diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm index 0068a20f468..205fd63d9c6 100644 --- a/code/game/gamemodes/wizard/artefact.dm +++ b/code/game/gamemodes/wizard/artefact.dm @@ -226,7 +226,7 @@ user.ghostize(1) /////////////////////Multiverse Blade//////////////////// -var/global/list/multiverse = list() +GLOBAL_LIST_EMPTY(multiverse) /obj/item/multisword name = "multiverse sword" @@ -252,11 +252,11 @@ var/global/list/multiverse = list() /obj/item/multisword/New() ..() - multiverse |= src + GLOB.multiverse |= src /obj/item/multisword/Destroy() - multiverse.Remove(src) + GLOB.multiverse.Remove(src) return ..() /obj/item/multisword/attack(mob/living/M as mob, mob/living/user as mob) //to prevent accidental friendly fire or out and out grief. @@ -303,7 +303,7 @@ var/global/list/multiverse = list() evil = FALSE else cooldown = world.time + cooldown_between_uses - for(var/obj/item/multisword/M in multiverse) + for(var/obj/item/multisword/M in GLOB.multiverse) if(M.assigned == assigned) M.cooldown = cooldown @@ -809,7 +809,7 @@ var/global/list/multiverse = list() return return ..() -/obj/item/voodoo/check_eye(mob/user as mob) +/obj/item/voodoo/check_eye(mob/user) if(loc != user) user.reset_perspective(null) user.unset_machine() @@ -842,7 +842,7 @@ var/global/list/multiverse = list() user.unset_machine() if("r_leg","l_leg") to_chat(user, "You move the doll's legs around.") - var/turf/T = get_step(target,pick(cardinal)) + var/turf/T = get_step(target,pick(GLOB.cardinal)) target.Move(T) if("r_arm","l_arm") //use active hand on random nearby mob @@ -866,7 +866,7 @@ var/global/list/multiverse = list() possible = list() if(!link) return - for(var/mob/living/carbon/human/H in GLOB.living_mob_list) + for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) if(md5(H.dna.uni_identity) in link.fingerprints) possible |= H diff --git a/code/game/gamemodes/wizard/raginmages.dm b/code/game/gamemodes/wizard/raginmages.dm index 57a4f4e17de..cc52b431249 100644 --- a/code/game/gamemodes/wizard/raginmages.dm +++ b/code/game/gamemodes/wizard/raginmages.dm @@ -145,7 +145,7 @@ /datum/game_mode/wizard/raginmages/proc/makeBody(var/mob/dead/observer/G) if(!G || !G.key) return // Let's not steal someone's soul here - var/mob/living/carbon/human/new_character = new(pick(latejoin)) + var/mob/living/carbon/human/new_character = new(pick(GLOB.latejoin)) G.client.prefs.copy_to(new_character) new_character.key = G.key return new_character diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm index 4f2d20b373a..82f6d833d16 100644 --- a/code/game/gamemodes/wizard/rightandwrong.dm +++ b/code/game/gamemodes/wizard/rightandwrong.dm @@ -109,6 +109,7 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) H.mind.add_antag_datum(/datum/antagonist/survivalist/guns) H.create_attack_log("was made into a survivalist, and trusts no one!") + H.create_log(CONVERSION_LOG, "was made into a survivalist") var/gun_type = pick(GLOB.summoned_guns) var/obj/item/gun/G = new gun_type(get_turf(H)) @@ -130,6 +131,7 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE) H.mind.add_antag_datum(/datum/antagonist/survivalist/magic) H.create_attack_log("was made into a survivalist, and trusts no one!") + H.create_log(CONVERSION_LOG, "was made into a survivalist") var/magic_type = pick(GLOB.summoned_magic) var/lucky = FALSE diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index cf0ce4843f0..4bda254d930 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -69,9 +69,6 @@ to_chat(user, "\"Come now, do not capture your fellow's soul.\"") return ..() - M.create_attack_log("Has had their soul captured with [src.name] by [key_name(user)]") - user.create_attack_log("Used the [src.name] to capture the soul of [key_name(M)]") - if(optional) if(!M.ckey) to_chat(user, "They have no soul!") @@ -283,7 +280,7 @@ SH.mind.transfer_to(C) if(iscultist(C)) var/datum/action/innate/cultcomm/CC = new() - CC.Grant(C) //We have to grant the cult comms again because they're lost during the mind transfer. + CC.Grant(C) //We have to grant the cult comms again because they're lost during the mind transfer. qdel(T) qdel(SH) to_chat(C, "You are still bound to serve your creator, follow their orders and help them complete their goals at all costs.") @@ -353,7 +350,7 @@ /obj/item/soulstone/proc/get_shade_type() return /mob/living/simple_animal/shade/cult - + /obj/item/soulstone/anybody/get_shade_type() return /mob/living/simple_animal/shade diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index f97f14a9975..b76b31255e9 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -6,34 +6,36 @@ var/category = "Offensive" var/log_name = "XX" //What it shows up as in logs var/cost = 2 - var/refundable = 1 + var/refundable = TRUE var/surplus = -1 // -1 for infinite, not used by anything atm var/obj/effect/proc_holder/spell/S = null //Since spellbooks can be used by only one person anyway we can track the actual spell var/buy_word = "Learn" var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook /datum/spellbook_entry/proc/IsSpellAvailable() // For config prefs / gamemode restrictions - these are round applied - return 1 + return TRUE /datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user, obj/item/spellbook/book) // Specific circumstances - if(book.uses= aspell.level_max) to_chat(user, "This spell cannot be improved further.") - return 0 + return FALSE else aspell.name = initial(aspell.name) aspell.spell_level++ - aspell.charge_max = round(initial(aspell.charge_max) - aspell.spell_level * (initial(aspell.charge_max) - aspell.cooldown_min)/ aspell.level_max) + aspell.charge_max = round(initial(aspell.charge_max) - aspell.spell_level * (initial(aspell.charge_max) - aspell.cooldown_min) / aspell.level_max) if(aspell.charge_max < aspell.charge_counter) aspell.charge_counter = aspell.charge_max switch(aspell.spell_level) @@ -51,37 +53,39 @@ aspell.name = "Instant [aspell.name]" if(aspell.spell_level >= aspell.level_max) to_chat(user, "This spell cannot be strengthened any further.") - return 1 + return TRUE //No same spell found - just learn it - feedback_add_details("wizard_spell_learned",log_name) - user.mind.AddSpell(S) - to_chat(user, "You have learned [S.name].") - return 1 + feedback_add_details("wizard_spell_learned", log_name) + user.mind.AddSpell(newspell) + to_chat(user, "You have learned [newspell.name].") + return TRUE /datum/spellbook_entry/proc/CanRefund(mob/living/carbon/human/user, obj/item/spellbook/book) if(!refundable) - return 0 + return FALSE if(!S) S = new spell_type() for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list) if(initial(S.name) == initial(aspell.name)) - return 1 - return 0 + return TRUE + return FALSE /datum/spellbook_entry/proc/Refund(mob/living/carbon/human/user, obj/item/spellbook/book) //return point value or -1 for failure var/area/wizard_station/A = locate() if(!(user in A.contents)) - to_chat(user, "You can only refund spells at the wizard lair") + to_chat(user, "You can only refund spells at the wizard lair.") return -1 - if(!S) + if(!S) //This happens when the spell's source is from another spellbook, from loadouts, or adminery, this create a new template temporary spell S = new spell_type() var/spell_levels = 0 for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list) if(initial(S.name) == initial(aspell.name)) spell_levels = aspell.spell_level user.mind.spell_list.Remove(aspell) - QDEL_NULL(S) - return cost * (spell_levels+1) + qdel(aspell) + if(S) //If we created a temporary spell above, delete it now. + qdel(S) + return cost * (spell_levels + 1) return -1 /datum/spellbook_entry/proc/GetInfo() @@ -448,7 +452,7 @@ //Weapons and Armors /datum/spellbook_entry/item/battlemage name = "Battlemage Armour" - desc = "An ensorceled suit of armour, protected by a powerful shield. The shield can completely negate sixteen attacks before being permanently depleted." + desc = "An ensorceled suit of armour, protected by a powerful shield. The shield can completely negate sixteen attacks before being permanently depleted. Despite appearance it is NOT spaceproof." item_path = /obj/item/clothing/suit/space/hardsuit/shielded/wizard limit = 1 category = "Weapons and Armors" @@ -571,6 +575,48 @@ category = "Summons" limit = 1 +//Spell loadouts datum, list of loadouts is in wizloadouts.dm +/datum/spellbook_entry/loadout + name = "Standard Loadout" + cost = 10 + category = "Standard" + refundable = FALSE + buy_word = "Summon" + var/list/items_path = list() + var/list/spells_path = list() + var/destroy_spellbook = FALSE //Destroy the spellbook when bought, for loadouts containing non-standard items/spells, otherwise wiz can refund spells + +/datum/spellbook_entry/loadout/GetInfo() + var/dat = "" + dat += "[name]" + if(cost > 0) + dat += " Cost:[cost]
" + else + dat += " No Cost
" + dat += "[desc]
" + return dat + +/datum/spellbook_entry/loadout/Buy(mob/living/carbon/human/user, obj/item/spellbook/book) + if(destroy_spellbook) + var/response = alert(user, "The [src] loadout cannot be refunded once bought. Are you sure this is what you want?", "No refunds!", "No", "Yes") + if(response == "No") + return FALSE + to_chat(user, "[book] crumbles to ashes as you acquire its knowledge.") + qdel(book) + else if(items_path.len) + var/response = alert(user, "The [src] loadout contains items that will not be refundable if bought. Are you sure this is what you want?", "No refunds!", "No", "Yes") + if(response == "No") + return FALSE + if(items_path.len) + var/obj/item/storage/box/wizard/B = new(src) + for(var/path in items_path) + new path(B) + user.put_in_hands(B) + for(var/path in spells_path) + var/obj/effect/proc_holder/spell/S = new path() + LearnSpell(user, book, S) + return TRUE + /obj/item/spellbook name = "spell book" desc = "The legendary book of spells of the wizard." @@ -587,12 +633,13 @@ var/mob/living/carbon/human/owner var/list/datum/spellbook_entry/entries = list() var/list/categories = list() - var/list/main_categories = list("Spells", "Magical Items") + var/list/main_categories = list("Spells", "Magical Items", "Loadouts") var/list/spell_categories = list("Offensive", "Defensive", "Mobility", "Assistance", "Rituals") var/list/item_categories = list("Artefacts", "Weapons and Armors", "Staves", "Summons") + var/list/loadout_categories = list("Standard", "Unique") /obj/item/spellbook/proc/initialize() - var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon + var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon - /datum/spellbook_entry/loadout for(var/T in entry_types) var/datum/spellbook_entry/E = new T if(E.IsSpellAvailable()) @@ -676,6 +723,12 @@ if("Summons") dat += "Magical items geared towards bringing in outside forces to aid you.

" dat += "Items are not bound to you and can be stolen. Additionaly they cannot typically be returned once purchased.
" + if("Standard") + dat += "These battle-tested spell sets are easy to use and provide good balance between offense and defense.

" + dat += "They all cost, and are worth, 10 spell points. You are able to refund any of the spells included as long as you stay in the wizard den.
" + if("Unique") + dat += "These esoteric loadouts usually contain spells or items that cannot be bought elsewhere in this spellbook.

" + dat += "Recommended for experienced wizards looking for something new. No refunds once purchased!
" return dat /obj/item/spellbook/proc/wrap(content) @@ -720,23 +773,24 @@ cat_dat[main_category] = "
" dat += "
  • [main_category]
  • " dat += "" + dat += "
      " switch(main_tab) if("Spells") - dat += "
        " - for(var/category in categories) - if(category in item_categories) - continue - cat_dat[category] = "
        " - dat += "
      • [category]
      • " - dat += "
      • Points remaining : [uses]
      • " - if("Magical Items") - dat += "
          " for(var/category in categories) if(category in spell_categories) - continue - cat_dat[category] = "
          " - dat += "
        • [category]
        • " - dat += "
        • Points remaining : [uses]
        • " + cat_dat[category] = "
          " + dat += "
        • [category]
        • " + if("Magical Items") + for(var/category in categories) + if(category in item_categories) + cat_dat[category] = "
          " + dat += "
        • [category]
        • " + if("Loadouts") + for(var/category in categories) + if(category in loadout_categories) + cat_dat[category] = "
          " + dat += "
        • [category]
        • " + dat += "
        • Points remaining : [uses]
        • " dat += "
        " var/datum/spellbook_entry/E @@ -801,6 +855,8 @@ tab = spell_categories[1] else if(main_tab == "Magical Items") tab = item_categories[1] + else if(main_tab == "Loadouts") + tab = loadout_categories[1] else if(href_list["page"]) tab = sanitize(href_list["page"]) attack_self(H) @@ -837,6 +893,7 @@ else user.mind.AddSpell(S) to_chat(user, "you rapidly read through the arcane book. Suddenly you realize you understand [spellname]!") + user.create_log(MISC_LOG, "learned the spell [spellname] ([S])") user.create_attack_log("[key_name(user)] learned the spell [spellname] ([S]).") onlearned(user) @@ -954,7 +1011,7 @@ magichead.voicechange = 1 //NEEEEIIGHH if(!user.unEquip(user.wear_mask)) qdel(user.wear_mask) - user.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1) + user.equip_to_slot_if_possible(magichead, slot_wear_mask, TRUE, TRUE) qdel(src) else to_chat(user, "I say thee neigh") diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index ba310ed0e8f..a0bb4c349af 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -30,14 +30,14 @@ wizard.assigned_role = SPECIAL_ROLE_WIZARD //So they aren't chosen for other jobs. wizard.special_role = SPECIAL_ROLE_WIZARD wizard.original = wizard.current - if(wizardstart.len == 0) + if(GLOB.wizardstart.len == 0) to_chat(wizard.current, "A starting location for you could not be found, please report this bug!") return 0 return 1 /datum/game_mode/wizard/pre_setup() for(var/datum/mind/wiz in wizards) - wiz.current.loc = pick(wizardstart) + wiz.current.loc = pick(GLOB.wizardstart) ..() return 1 @@ -59,6 +59,7 @@ SSticker.mode.wizards -= wizard_mind wizard_mind.special_role = null wizard_mind.current.create_attack_log("De-wizarded") + wizard_mind.current.create_log(CONVERSION_LOG, "De-wizarded") wizard_mind.current.spellremove(wizard_mind.current) wizard_mind.current.faction = list("Station") if(issilicon(wizard_mind.current)) @@ -68,12 +69,12 @@ SSticker.mode.update_wiz_icons_removed(wizard_mind) /datum/game_mode/proc/update_wiz_icons_added(datum/mind/wiz_mind) - var/datum/atom_hud/antag/wizhud = huds[ANTAG_HUD_WIZ] + var/datum/atom_hud/antag/wizhud = GLOB.huds[ANTAG_HUD_WIZ] wizhud.join_hud(wiz_mind.current) set_antag_hud(wiz_mind.current, ((wiz_mind in wizards) ? "hudwizard" : "apprentice")) /datum/game_mode/proc/update_wiz_icons_removed(datum/mind/wiz_mind) - var/datum/atom_hud/antag/wizhud = huds[ANTAG_HUD_WIZ] + var/datum/atom_hud/antag/wizhud = GLOB.huds[ANTAG_HUD_WIZ] wizhud.leave_hud(wiz_mind.current) set_antag_hud(wiz_mind.current, null) @@ -134,22 +135,31 @@ qdel(wizard_mob.r_store) qdel(wizard_mob.l_store) - wizard_mob.equip_to_slot_or_del(new /obj/item/radio/headset(wizard_mob), slot_l_ear) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(wizard_mob), slot_w_uniform) - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes) - if(!isplasmaman(wizard_mob)) //handled in the species file for plasmen on the afterjob equip proc for now - wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit) + if(isplasmaman(wizard_mob)) + wizard_mob.equipOutfit(new /datum/outfit/plasmaman/wizard) + wizard_mob.internal = wizard_mob.r_hand + wizard_mob.update_action_buttons_icon() + else + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(wizard_mob), slot_w_uniform) wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head) + wizard_mob.dna.species.after_equip_job(null, wizard_mob) + wizard_mob.rejuvenate() //fix any damage taken by naked vox/plasmamen/etc while round setups + wizard_mob.equip_to_slot_or_del(new /obj/item/radio/headset(wizard_mob), slot_l_ear) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes) + wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit) wizard_mob.equip_to_slot_or_del(new /obj/item/storage/backpack/satchel(wizard_mob), slot_back) - wizard_mob.equip_to_slot_or_del(new /obj/item/storage/box/survival(wizard_mob), slot_in_backpack) + if(wizard_mob.dna.species.speciesbox) + wizard_mob.equip_to_slot_or_del(new wizard_mob.dna.species.speciesbox(wizard_mob), slot_in_backpack) + else + wizard_mob.equip_to_slot_or_del(new /obj/item/storage/box/survival(wizard_mob), slot_in_backpack) wizard_mob.equip_to_slot_or_del(new /obj/item/teleportation_scroll(wizard_mob), slot_r_store) var/obj/item/spellbook/spellbook = new /obj/item/spellbook(wizard_mob) spellbook.owner = wizard_mob - wizard_mob.equip_to_slot_or_del(spellbook, slot_r_hand) + wizard_mob.equip_to_slot_or_del(spellbook, slot_l_hand) wizard_mob.faction = list("wizard") - wizard_mob.dna.species.after_equip_job(null, wizard_mob) + to_chat(wizard_mob, "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.") to_chat(wizard_mob, "The spellbook is bound to you, and others cannot use it.") @@ -157,7 +167,7 @@ wizard_mob.mind.store_memory("Remember: do not forget to prepare your spells.") wizard_mob.update_icons() wizard_mob.gene_stability += DEFAULT_GENE_STABILITY //magic - return 1 + return TRUE // Checks if the game should end due to all wizards and apprentices being dead, or MMI'd/Borged /datum/game_mode/wizard/check_finished() diff --git a/code/game/gamemodes/wizard/wizloadouts.dm b/code/game/gamemodes/wizard/wizloadouts.dm new file mode 100644 index 00000000000..0e53d30f1bf --- /dev/null +++ b/code/game/gamemodes/wizard/wizloadouts.dm @@ -0,0 +1,71 @@ +//Contains wizard loadouts and associated unique spells + +//Standard loadouts, which are meant to be suggestions for beginners. Should always be worth exactly 10 spell points, and only contain standard wizard spells/items. +/datum/spellbook_entry/loadout/mutant + name = "Offense Focus : Mutant" + desc = "A spellset focused around the Mutate spell as its main source of damage, which provides stun protection, laser eyes, and strong punches.
        \ + Ethereal Jaunt and Blink provide escape and mobility, while Magic Missile and Disintegrate can be used together for dangerous or key targets.
        \ + As this set lacks any form of healing or resurrection, healing items should be acquired from the station, and you should be careful to avoid being hurt in the first place.

        \ + Provides Mutate, Ethereal Jaunt, Blink, Magic Missile, and Disintegrate." + log_name = "OM" + spells_path = list(/obj/effect/proc_holder/spell/targeted/genetic/mutate, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/turf_teleport/blink, \ + /obj/effect/proc_holder/spell/targeted/projectile/magic_missile, /obj/effect/proc_holder/spell/targeted/touch/disintegrate) + +/datum/spellbook_entry/loadout/lich + name = "Defense Focus : Lich" + desc = "This spellset uses the Bind Soul spell to safeguard your life as a lich and allow for more dangerous offensive spells to be used.
        \ + Ethereal Jaunt provides escape, Fireball and Rod Form are your offensive spells, and Disable Tech and Greater Forcewall provides utility in disabling sec equipment or blocking their path.
        \ + Care should be taken in hiding the item you choose as your phylactery after using Bind Soul, as you cannot revive if it destroyed or too far from your body!

        \ +
        Provides Bind Soul, Ethereal Jaunt, Fireball, Rod Form, Disable Tech, and Greater Forcewall." + log_name = "DL" + spells_path = list(/obj/effect/proc_holder/spell/targeted/lichdom, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/fireball, \ + /obj/effect/proc_holder/spell/targeted/rod_form, /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech, /obj/effect/proc_holder/spell/targeted/forcewall/greater) + +/datum/spellbook_entry/loadout/wands + name = "Utility Focus : Wands" + desc = "This set contain a Belt of Wands, providing offensive, defensive, and utility wands. Wands have limited charges, but can be partially recharged with the Charge spell included.
        \ + Ethereal Jaunt and Blink provide escape and mobility, while Disintegrate and Repulse can be used to annihilate or push away anyone that gets too close to you.
        \ + Do not lose any of your wands to the station's crew, as they are extremely deadly even in their hands. Remember that the Revive wand can be used on yourself for a full heal!

        \ +
        Provides a Belt of Wands, Charge, Ethereal Jaunt, Blink, Repulse, and Disintegrate." + log_name = "UW" + items_path = list(/obj/item/storage/belt/wands/full) + spells_path = list(/obj/effect/proc_holder/spell/targeted/charge, /obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/turf_teleport/blink, \ + /obj/effect/proc_holder/spell/aoe_turf/repulse, /obj/effect/proc_holder/spell/targeted/touch/disintegrate) + +//Unique loadouts, which are more gimmicky. Should contain some unique spell or item that separates it from just buying standard wiz spells, and be balanced around a 10 spell point cost. +/datum/spellbook_entry/loadout/mimewiz + name = "Silencio" + desc = "...

        \ +
        Provides Finger Gun and Invisible Greater Wall manuals, Mime Robes, a Cane and Duct Tape, Ethereal Jaunt, Blink, Teleport, Mime Malaise, Knock, and Stop Time." + log_name = "SHH" + items_path = list(/obj/item/spellbook/oneuse/mime/fingergun, /obj/item/spellbook/oneuse/mime/greaterwall, /obj/item/clothing/suit/wizrobe/mime, /obj/item/clothing/head/wizard/mime, \ + /obj/item/clothing/mask/gas/mime/wizard, /obj/item/clothing/shoes/sandal/marisa, /obj/item/cane, /obj/item/stack/tape_roll) + spells_path = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/turf_teleport/blink, /obj/effect/proc_holder/spell/targeted/area_teleport/teleport, \ + /obj/effect/proc_holder/spell/targeted/touch/mime_malaise, /obj/effect/proc_holder/spell/aoe_turf/knock, /obj/effect/proc_holder/spell/aoe_turf/conjure/timestop) + category = "Unique" + destroy_spellbook = TRUE + +/datum/spellbook_entry/loadout/mimewiz/Buy(mob/living/carbon/human/user, obj/item/spellbook/book) + if(user.mind) + user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mime/speak(null)) + user.mind.miming = TRUE + ..() + +/datum/spellbook_entry/loadout/gunreaper + name = "Gunslinging Reaper" + desc = "Cloned over and over, the souls aboard this station yearn for a deserved rest.
        \ + Bring them to the afterlife, one trigger pull at a time.
        \ + You will likely need to scavenge additional ammo or weapons aboard the station.

        \ +
        Provides a .357 Revolver, 4 speedloaders of ammo, Ethereal Jaunt, Blink, Summon Item, No Clothes, and Bind Soul, with a unique outfit." + log_name = "GR" + items_path = list(/obj/item/gun/projectile/revolver, /obj/item/ammo_box/a357, /obj/item/ammo_box/a357, /obj/item/ammo_box/a357, /obj/item/ammo_box/a357, /obj/item/clothing/under/syndicate) + spells_path = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt, /obj/effect/proc_holder/spell/targeted/turf_teleport/blink, \ + /obj/effect/proc_holder/spell/targeted/summonitem, /obj/effect/proc_holder/spell/noclothes, /obj/effect/proc_holder/spell/targeted/lichdom/gunslinger) + category = "Unique" + destroy_spellbook = TRUE + +/obj/effect/proc_holder/spell/targeted/lichdom/gunslinger/equip_lich(mob/living/carbon/human/H) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_suit(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), slot_shoes) + H.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(H), slot_gloves) + H.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(H), slot_w_uniform) diff --git a/code/game/jobs/job/central.dm b/code/game/jobs/job/central.dm index 796db23b36e..f91460ba234 100644 --- a/code/game/jobs/job/central.dm +++ b/code/game/jobs/job/central.dm @@ -34,6 +34,9 @@ /obj/item/implant/dust ) backpack = /obj/item/storage/backpack/satchel + backpack_contents = list( + /obj/item/stamp/centcom = 1, + ) box = /obj/item/storage/box/centcomofficer cybernetic_implants = list( /obj/item/organ/internal/cyberimp/chest/nutriment/plus diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 03ac85c8d57..d5c5089c8af 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -12,9 +12,6 @@ var/department_flag = 0 var/department_head = list() - //Players will be allowed to spawn in as jobs that are set to "Station" - var/list/faction = list("Station") - //How many players can be this job var/total_positions = 0 @@ -53,6 +50,8 @@ var/exp_type = "" var/disabilities_allowed = 1 + var/transfer_allowed = TRUE // If false, ID computer will always discourage transfers to this job, even if player is eligible + var/hidden_from_job_prefs = FALSE // if true, job preferences screen never shows this job. var/admin_only = 0 var/spawn_ert = 0 @@ -171,9 +170,9 @@ if(box && H.dna.species.speciesbox) box = H.dna.species.speciesbox - if(allow_loadout && H.client && (H.client.prefs.gear && H.client.prefs.gear.len)) - for(var/gear in H.client.prefs.gear) - var/datum/gear/G = gear_datums[gear] + if(allow_loadout && H.client && (H.client.prefs.loadout_gear && H.client.prefs.loadout_gear.len)) + for(var/gear in H.client.prefs.loadout_gear) + var/datum/gear/G = GLOB.gear_datums[gear] if(G) var/permitted = FALSE @@ -210,7 +209,7 @@ if(gear_leftovers.len) for(var/datum/gear/G in gear_leftovers) - var/atom/placed_in = H.equip_or_collect(G.spawn_item(null, H.client.prefs.gear[G.display_name])) + var/atom/placed_in = H.equip_or_collect(G.spawn_item(null, H.client.prefs.loadout_gear[G.display_name])) if(istype(placed_in)) if(isturf(placed_in)) to_chat(H, "Placing [G.display_name] on [placed_in]!") @@ -265,6 +264,8 @@ PDA.name = "PDA-[H.real_name] ([PDA.ownjob])" /datum/job/proc/would_accept_job_transfer_from_player(mob/player) + if(!transfer_allowed) + return FALSE if(!guest_jobbans(title)) // actually checks if job is a whitelisted position return TRUE if(!istype(player)) diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm index 259afa12c9e..2d1b091a10d 100644 --- a/code/game/jobs/job/medical.dm +++ b/code/game/jobs/job/medical.dm @@ -30,7 +30,7 @@ l_ear = /obj/item/radio/headset/heads/cmo id = /obj/item/card/id/cmo suit_store = /obj/item/flashlight/pen - l_hand = /obj/item/storage/firstaid/adv + l_hand = /obj/item/storage/firstaid/doctor pda = /obj/item/pda/heads/cmo backpack_contents = list( /obj/item/melee/classic_baton/telescopic = 1 @@ -68,7 +68,7 @@ l_ear = /obj/item/radio/headset/headset_med id = /obj/item/card/id/medical suit_store = /obj/item/flashlight/pen - l_hand = /obj/item/storage/firstaid/adv + l_hand = /obj/item/storage/firstaid/doctor pda = /obj/item/pda/medical backpack = /obj/item/storage/backpack/medic @@ -315,4 +315,3 @@ satchel = /obj/item/storage/backpack/satchel_med dufflebag = /obj/item/storage/backpack/duffel/medical box = /obj/item/storage/box/engineer - diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm index 20364b57677..a32656598df 100644 --- a/code/game/jobs/job/security.dm +++ b/code/game/jobs/job/security.dm @@ -149,7 +149,7 @@ if(visualsOnly) return - H.dna.SetSEState(SOBERBLOCK,1) + H.dna.SetSEState(GLOB.soberblock,1) H.mutations += SOBER H.check_mutations = 1 @@ -217,7 +217,7 @@ glasses = /obj/item/clothing/glasses/hud/health/sunglasses id = /obj/item/card/id/security suit_store = /obj/item/flashlight/pen - l_hand = /obj/item/storage/firstaid/adv + l_hand = /obj/item/storage/firstaid/doctor pda = /obj/item/pda/medical implants = list(/obj/item/implant/mindshield) backpack = /obj/item/storage/backpack/medic diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm index 5325f077f4f..b6321765861 100644 --- a/code/game/jobs/job/silicon.dm +++ b/code/game/jobs/job/silicon.dm @@ -17,7 +17,7 @@ return 0 /datum/job/ai/is_position_available() - return (empty_playable_ai_cores.len != 0) + return (GLOB.empty_playable_ai_cores.len != 0) /datum/job/cyborg diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm index 4e773d42ad9..c56d27bb408 100644 --- a/code/game/jobs/job/supervisor.dm +++ b/code/game/jobs/job/supervisor.dm @@ -1,4 +1,4 @@ -var/datum/announcement/minor/captain_announcement = new(do_newscast = 0) +GLOBAL_DATUM_INIT(captain_announcement, /datum/announcement/minor, new(do_newscast = 0)) // Why the hell are captain announcements minor /datum/job/captain title = "Captain" flag = JOB_CAPTAIN @@ -23,7 +23,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0) /datum/job/captain/announce(mob/living/carbon/human/H) . = ..() - captain_announcement.Announce("All hands, Captain [H.real_name] on deck!") + GLOB.captain_announcement.Announce("All hands, Captain [H.real_name] on deck!") /datum/outfit/job/captain name = "Captain" @@ -112,6 +112,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0) selection_color = "#ddddff" req_admin_notify = 1 is_command = 1 + transfer_allowed = FALSE minimal_player_age = 21 access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS, ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_EVA, ACCESS_HEADS, @@ -155,6 +156,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0) selection_color = "#ddddff" req_admin_notify = 1 is_command = 1 + transfer_allowed = FALSE minimal_player_age = 21 access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS, ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_EVA, ACCESS_HEADS, @@ -198,6 +200,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0) selection_color = "#ddddff" req_admin_notify = 1 is_legal = 1 + transfer_allowed = FALSE minimal_player_age = 30 access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS, ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_EVA, ACCESS_HEADS, @@ -230,7 +233,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0) -//var/global/lawyer = 0//Checks for another lawyer //This changed clothes on 2nd lawyer, both IA get the same dreds. +//GLOBAL_VAR_INIT(lawyer, 0) //Checks for another lawyer //This changed clothes on 2nd lawyer, both IA get the same dreds. | This was deprecated back in 2014, and its now 2020 /datum/job/lawyer title = "Internal Affairs Agent" flag = JOB_LAWYER diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm index 7d4f5ccc622..f2b8cf31671 100644 --- a/code/game/jobs/job/support.dm +++ b/code/game/jobs/job/support.dm @@ -33,9 +33,9 @@ if(visualsOnly) return - H.dna.SetSEState(SOBERBLOCK,1) - genemutcheck(H, SOBERBLOCK, null, MUTCHK_FORCED) - H.dna.default_blocks.Add(SOBERBLOCK) + H.dna.SetSEState(GLOB.soberblock,1) + genemutcheck(H, GLOB.soberblock, null, MUTCHK_FORCED) + H.dna.default_blocks.Add(GLOB.soberblock) H.check_mutations = 1 @@ -286,13 +286,13 @@ var/obj/item/organ/internal/cyberimp/brain/clown_voice/implant = new implant.insert(H) - H.dna.SetSEState(CLUMSYBLOCK, TRUE) - genemutcheck(H, CLUMSYBLOCK, null, MUTCHK_FORCED) - H.dna.default_blocks.Add(CLUMSYBLOCK) + H.dna.SetSEState(GLOB.clumsyblock, TRUE) + genemutcheck(H, GLOB.clumsyblock, null, MUTCHK_FORCED) + H.dna.default_blocks.Add(GLOB.clumsyblock) if(!ismachine(H)) - H.dna.SetSEState(COMICBLOCK, TRUE) - genemutcheck(H, COMICBLOCK, null, MUTCHK_FORCED) - H.dna.default_blocks.Add(COMICBLOCK) + H.dna.SetSEState(GLOB.comicblock, TRUE) + genemutcheck(H, GLOB.comicblock, null, MUTCHK_FORCED) + H.dna.default_blocks.Add(GLOB.comicblock) H.check_mutations = TRUE H.add_language("Clownish") @@ -450,3 +450,24 @@ /obj/item/storage/box/lip_stick = 1, /obj/item/storage/box/barber = 1 ) + +/datum/job/explorer + title = "Explorer" + flag = JOB_EXPLORER + department_flag = JOBCAT_SUPPORT + total_positions = 0 + spawn_positions = 0 + supervisors = "the head of personnel" + selection_color = "#dddddd" + access = list(ACCESS_MAINT_TUNNELS, ACCESS_GATEWAY, ACCESS_EVA, ACCESS_EXTERNAL_AIRLOCKS) + minimal_access = list(ACCESS_MAINT_TUNNELS, ACCESS_GATEWAY, ACCESS_EVA, ACCESS_EXTERNAL_AIRLOCKS) + outfit = /datum/outfit/job/explorer + hidden_from_job_prefs = TRUE + +/datum/outfit/job/explorer + // This outfit is never used, because there are no slots for this job. + // To get it, you have to go to the HOP and ask for a transfer to it. + name = "Explorer" + jobtype = /datum/job/explorer + uniform = /obj/item/clothing/under/color/random + shoes = /obj/item/clothing/shoes/black diff --git a/code/game/jobs/job/syndicate.dm b/code/game/jobs/job/syndicate.dm index f7c5659f86c..f1bf52cbc8a 100644 --- a/code/game/jobs/job/syndicate.dm +++ b/code/game/jobs/job/syndicate.dm @@ -51,7 +51,7 @@ U.implant(H) U.hidden_uplink.uses = 500 H.faction += "syndicate" - var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS] + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] opshud.join_hud(H.mind.current) H.mind.offstation_role = TRUE set_antag_hud(H.mind.current, "hudoperative") diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm index 7823b4b6f4a..f0e6f9bff42 100644 --- a/code/game/jobs/job_exp.dm +++ b/code/game/jobs/job_exp.dm @@ -1,6 +1,6 @@ // Playtime requirements for special roles (hours) -var/global/list/role_playtime_requirements = list( +GLOBAL_LIST_INIT(role_playtime_requirements, list( // NT ROLES ROLE_PAI = 0, ROLE_POSIBRAIN = 5, // Same as cyborg job. @@ -35,7 +35,7 @@ var/global/list/role_playtime_requirements = list( ROLE_RAIDER = 10, ROLE_ALIEN = 10, ROLE_ABDUCTOR = 10, -) +)) // Client Verbs @@ -113,7 +113,7 @@ var/global/list/role_playtime_requirements = list( var/isexempt = text2num(play_records[EXP_TYPE_EXEMPT]) if(isexempt) return 0 - var/minimal_player_hrs = role_playtime_requirements[role] + var/minimal_player_hrs = GLOB.role_playtime_requirements[role] if(!minimal_player_hrs) return 0 var/req_mins = minimal_player_hrs * 60 @@ -163,7 +163,7 @@ var/global/list/role_playtime_requirements = list( return "[key] has no records." var/return_text = "
          " var/list/exp_data = list() - for(var/category in exp_jobsmap) + for(var/category in GLOB.exp_jobsmap) if(text2num(play_records[category])) exp_data[category] = text2num(play_records[category]) else @@ -238,7 +238,7 @@ var/global/list/role_playtime_requirements = list( /client/proc/update_exp_client(var/minutes, var/announce_changes = 0) if(!src ||!ckey) return - var/DBQuery/exp_read = dbcon.NewQuery("SELECT exp FROM [format_table_name("player")] WHERE ckey='[ckey]'") + var/DBQuery/exp_read = GLOB.dbcon.NewQuery("SELECT exp FROM [format_table_name("player")] WHERE ckey='[ckey]'") if(!exp_read.Execute()) var/err = exp_read.ErrorMsg() log_game("SQL ERROR during exp_update_client read. Error : \[[err]\]\n") @@ -252,7 +252,7 @@ var/global/list/role_playtime_requirements = list( if(!hasread) return var/list/play_records = list() - for(var/rtype in exp_jobsmap) + for(var/rtype in GLOB.exp_jobsmap) if(text2num(read_records[rtype])) play_records[rtype] = text2num(read_records[rtype]) else @@ -270,9 +270,9 @@ var/global/list/role_playtime_requirements = list( added_living += minutes if(announce_changes) to_chat(mob,"You got: [minutes] Living EXP!") - for(var/category in exp_jobsmap) - if(exp_jobsmap[category]["titles"]) - if(myrole in exp_jobsmap[category]["titles"]) + for(var/category in GLOB.exp_jobsmap) + if(GLOB.exp_jobsmap[category]["titles"]) + if(myrole in GLOB.exp_jobsmap[category]["titles"]) play_records[category] += minutes if(announce_changes) to_chat(mob,"You got: [minutes] [category] EXP!") @@ -290,13 +290,13 @@ var/global/list/role_playtime_requirements = list( var/new_exp = list2params(play_records) prefs.exp = new_exp new_exp = sanitizeSQL(new_exp) - var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("player")] SET exp = '[new_exp]',lastseen = Now() WHERE ckey='[ckey]'") + var/DBQuery/update_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET exp = '[new_exp]',lastseen = Now() WHERE ckey='[ckey]'") if(!update_query.Execute()) var/err = update_query.ErrorMsg() log_game("SQL ERROR during exp_update_client write 1. Error : \[[err]\]\n") message_admins("SQL ERROR during exp_update_client write 1. Error : \[[err]\]\n") return - var/DBQuery/update_query_history = dbcon.NewQuery("INSERT INTO [format_table_name("playtime_history")] (ckey, date, time_living, time_ghost) VALUES ('[ckey]',CURDATE(),[added_living],[added_ghost]) ON DUPLICATE KEY UPDATE time_living=time_living+VALUES(time_living),time_ghost=time_ghost+VALUES(time_ghost)") + var/DBQuery/update_query_history = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("playtime_history")] (ckey, date, time_living, time_ghost) VALUES ('[ckey]',CURDATE(),[added_living],[added_ghost]) ON DUPLICATE KEY UPDATE time_living=time_living+VALUES(time_living),time_ghost=time_ghost+VALUES(time_ghost)") if(!update_query_history.Execute()) var/err = update_query_history.ErrorMsg() log_game("SQL ERROR during exp_update_client write 2. Error : \[[err]\]\n") diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm index b0d70fb3003..81cc54aa3c3 100644 --- a/code/game/jobs/jobs.dm +++ b/code/game/jobs/jobs.dm @@ -1,9 +1,8 @@ -var/list/assistant_occupations = list( -) +GLOBAL_LIST_EMPTY(assistant_occupations) -var/list/command_positions = list( +GLOBAL_LIST_INIT(command_positions, list( "Captain", "Head of Personnel", "Head of Security", @@ -11,18 +10,18 @@ var/list/command_positions = list( "Research Director", "Chief Medical Officer", "Nanotrasen Representative" -) +)) -var/list/engineering_positions = list( +GLOBAL_LIST_INIT(engineering_positions, list( "Chief Engineer", "Station Engineer", "Life Support Specialist", "Mechanic" -) +)) -var/list/medical_positions = list( +GLOBAL_LIST_INIT(medical_positions, list( "Chief Medical Officer", "Medical Doctor", "Geneticist", @@ -31,18 +30,18 @@ var/list/medical_positions = list( "Virologist", "Paramedic", "Coroner" -) +)) -var/list/science_positions = list( +GLOBAL_LIST_INIT(science_positions, list( "Research Director", "Scientist", "Geneticist", //Part of both medical and science "Roboticist", -) +)) //BS12 EDIT -var/list/support_positions = list( +GLOBAL_LIST_INIT(support_positions, list( "Head of Personnel", "Bartender", "Botanist", @@ -59,20 +58,21 @@ var/list/support_positions = list( "Barber", "Magistrate", "Nanotrasen Representative", - "Blueshield" -) + "Blueshield", + "Explorer" +)) -var/list/supply_positions = list( +GLOBAL_LIST_INIT(supply_positions, list( "Head of Personnel", "Quartermaster", "Cargo Technician", "Shaft Miner" -) +)) -var/list/service_positions = support_positions - supply_positions + list("Head of Personnel") +GLOBAL_LIST_INIT(service_positions, (support_positions - supply_positions + list("Head of Personnel"))) -var/list/security_positions = list( +GLOBAL_LIST_INIT(security_positions, list( "Head of Security", "Warden", "Detective", @@ -80,21 +80,21 @@ var/list/security_positions = list( "Brig Physician", "Security Pod Pilot", "Magistrate" -) +)) -var/list/civilian_positions = list( +GLOBAL_LIST_INIT(civilian_positions, list( "Civilian" -) +)) -var/list/nonhuman_positions = list( +GLOBAL_LIST_INIT(nonhuman_positions, list( "AI", "Cyborg", "Drone", "pAI" -) +)) -var/list/whitelisted_positions = list( +GLOBAL_LIST_INIT(whitelisted_positions, list( "Blueshield", "Nanotrasen Representative", "Barber", @@ -102,11 +102,11 @@ var/list/whitelisted_positions = list( "Brig Physician", "Magistrate", "Security Pod Pilot", -) +)) /proc/guest_jobbans(var/job) - return (job in whitelisted_positions) + return (job in GLOB.whitelisted_positions) /proc/get_job_datums() var/list/occupations = list() @@ -130,7 +130,7 @@ var/list/whitelisted_positions = list( return titles -var/global/list/exp_jobsmap = list( +GLOBAL_LIST_INIT(exp_jobsmap, list( EXP_TYPE_LIVING = list(), // all living mobs EXP_TYPE_CREW = list(titles = command_positions | engineering_positions | medical_positions | science_positions | support_positions | supply_positions | security_positions | civilian_positions | list("AI","Cyborg") | whitelisted_positions), // crew positions EXP_TYPE_SPECIAL = list(), // antags, ERT, etc @@ -145,4 +145,4 @@ var/global/list/exp_jobsmap = list( EXP_TYPE_SILICON = list(titles = list("AI","Cyborg")), EXP_TYPE_SERVICE = list(titles = service_positions), EXP_TYPE_WHITELIST = list(titles = whitelisted_positions) // karma-locked jobs -) +)) diff --git a/code/game/jobs/whitelist.dm b/code/game/jobs/whitelist.dm index 503dd33258e..ab1bd3b8067 100644 --- a/code/game/jobs/whitelist.dm +++ b/code/game/jobs/whitelist.dm @@ -1,6 +1,6 @@ #define WHITELISTFILE "data/whitelist.txt" -var/list/whitelist = list() +GLOBAL_LIST_EMPTY(whitelist) /hook/startup/proc/loadWhitelist() if(config.usewhitelist) @@ -8,8 +8,8 @@ var/list/whitelist = list() return 1 /proc/load_whitelist() - whitelist = file2list(WHITELISTFILE) - if(!whitelist.len) whitelist = null + GLOB.whitelist = file2list(WHITELISTFILE) + if(!GLOB.whitelist.len) GLOB.whitelist = null /* /proc/check_whitelist(mob/M, var/rank) if(!whitelist) @@ -25,11 +25,11 @@ var/list/whitelist = list() return 1 if(check_rights(R_ADMIN, 0, M)) return 1 - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(usr, "Unable to connect to whitelist database. Please try again later.
          ") return 0 else - var/DBQuery/query = dbcon.NewQuery("SELECT job FROM [format_table_name("whitelist")] WHERE ckey='[M.ckey]'") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT job FROM [format_table_name("whitelist")] WHERE ckey='[M.ckey]'") query.Execute() @@ -46,7 +46,7 @@ var/list/whitelist = list() -/var/list/alien_whitelist = list() +GLOBAL_LIST_EMPTY(alien_whitelist) /hook/startup/proc/loadAlienWhitelist() if(config.usealienwhitelist) @@ -58,7 +58,7 @@ var/list/whitelist = list() if(!text) log_config("Failed to load config/alienwhitelist.txt\n") else - alien_whitelist = splittext(text, "\n") + GLOB.alien_whitelist = splittext(text, "\n") //todo: admin aliens /proc/is_alien_whitelisted(mob/M, var/species) @@ -70,13 +70,13 @@ var/list/whitelist = list() return 1 if(check_rights(R_ADMIN, 0)) return 1 - if(!alien_whitelist) + if(!GLOB.alien_whitelist) return 0 - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(usr, "Unable to connect to whitelist database. Please try again later.
          ") return 0 else - var/DBQuery/query = dbcon.NewQuery("SELECT species FROM [format_table_name("whitelist")] WHERE ckey='[M.ckey]'") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT species FROM [format_table_name("whitelist")] WHERE ckey='[M.ckey]'") query.Execute() while(query.NextRow()) diff --git a/code/game/machinery/Freezer.dm b/code/game/machinery/Freezer.dm index 097d2e26da2..d9243005ead 100644 --- a/code/game/machinery/Freezer.dm +++ b/code/game/machinery/Freezer.dm @@ -118,7 +118,7 @@ // auto update every Master Controller tick ui.set_auto_update(1) -/obj/machinery/atmospherics/unary/cold_sink/freezer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/atmospherics/unary/cold_sink/freezer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["on"] = on ? 1 : 0 data["gasPressure"] = round(air_contents.return_pressure()) @@ -287,7 +287,7 @@ // auto update every Master Controller tick ui.set_auto_update(1) -/obj/machinery/atmospherics/unary/heat_reservoir/heater/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/atmospherics/unary/heat_reservoir/heater/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["on"] = on ? 1 : 0 data["gasPressure"] = round(air_contents.return_pressure()) diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 3185cdcddd4..332df41f086 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -30,15 +30,11 @@ /obj/machinery/pdapainter/New() ..() var/blocked = list(/obj/item/pda/silicon/ai, /obj/item/pda/silicon/robot, /obj/item/pda/silicon/pai, /obj/item/pda/heads, - /obj/item/pda/clear, /obj/item/pda/syndicate) + /obj/item/pda/clear, /obj/item/pda/syndicate, /obj/item/pda/chameleon, /obj/item/pda/chameleon/broken) - for(var/P in typesof(/obj/item/pda)-blocked) - var/obj/item/pda/D = new P - - //D.name = "PDA Style [colorlist.len+1]" //Gotta set the name, otherwise it all comes up as "PDA" - D.name = D.icon_state //PDAs don't have unique names, but using the sprite names works. - - src.colorlist += D + for(var/thing in typesof(/obj/item/pda) - blocked) + var/obj/item/pda/P = thing + colorlist[initial(P.icon_state)] = initial(P.desc) /obj/machinery/pdapainter/Destroy() QDEL_NULL(storedpda) @@ -104,8 +100,8 @@ if(!in_range(src, user)) return - storedpda.icon_state = P.icon_state - storedpda.desc = P.desc + storedpda.icon_state = P + storedpda.desc = colorlist[P] else to_chat(user, "The [src] is empty.") diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 81409b5de86..70d88e92b71 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -23,6 +23,7 @@ var/initial_bin_rating = 1 var/min_health = -25 var/controls_inside = FALSE + var/auto_eject_dead = FALSE idle_power_usage = 1250 active_power_usage = 2500 @@ -81,8 +82,19 @@ go_out() /obj/machinery/sleeper/process() - if(filtering > 0) - if(beaker) + for(var/mob/M as mob in src) // makes sure that simple mobs don't get stuck inside a sleeper when they resist out of occupant's grasp + if(M == occupant) + continue + else + M.forceMove(loc) + + if(occupant) + if(auto_eject_dead && occupant.stat == DEAD) + playsound(loc, 'sound/machines/buzz-sigh.ogg', 40) + go_out() + return + + if(filtering > 0 && beaker) // To prevent runtimes from drawing blood from runtime, and to prevent getting IPC blood. if(!istype(occupant) || !occupant.dna || (NO_BLOOD in occupant.dna.species.species_traits)) filtering = 0 @@ -94,7 +106,6 @@ occupant.reagents.trans_to(beaker, 3) occupant.transfer_blood_to(beaker, 1) - if(occupant) for(var/A in occupant.reagents.addiction_list) var/datum/reagent/R = A @@ -106,12 +117,6 @@ occupant.reagents.addiction_list.Remove(R) qdel(R) - for(var/mob/M as mob in src) // makes sure that simple mobs don't get stuck inside a sleeper when they resist out of occupant's grasp - if(M == occupant) - continue - else - M.forceMove(loc) - updateDialog() return @@ -201,6 +206,7 @@ data["maxchem"] = max_chem data["minhealth"] = min_health data["dialysis"] = filtering + data["auto_eject_dead"] = auto_eject_dead if(beaker) data["isBeakerLoaded"] = 1 if(beaker.reagents) @@ -255,12 +261,22 @@ inject_chemical(usr,href_list["chemical"],text2num(href_list["amount"])) else to_chat(usr, "This person is not in good enough condition for sleepers to be effective! Use another means of treatment, such as cryogenics!") + if(href_list["removebeaker"]) remove_beaker() + if(href_list["togglefilter"]) toggle_filter() + if(href_list["ejectify"]) eject() + + if(href_list["auto_eject_dead_on"]) + auto_eject_dead = TRUE + + if(href_list["auto_eject_dead_off"]) + auto_eject_dead = FALSE + add_fingerprint(usr) return 1 diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm index 6b6f3087ad2..1ee30b6e9d0 100644 --- a/code/game/machinery/adv_med.dm +++ b/code/game/machinery/adv_med.dm @@ -314,9 +314,9 @@ occupantData["intOrgan"] = intOrganData - occupantData["blind"] = (occupant.disabilities & BLIND) - occupantData["colourblind"] = (occupant.disabilities & COLOURBLIND) - occupantData["nearsighted"] = (occupant.disabilities & NEARSIGHTED) + occupantData["blind"] = (BLINDNESS in occupant.mutations) + occupantData["colourblind"] = (COLOURBLIND in occupant.mutations) + occupantData["nearsighted"] = (NEARSIGHTED in occupant.mutations) data["occupant"] = occupantData return data @@ -425,6 +425,7 @@ var/AN = "" var/open = "" var/infected = "" + var/dead = "" var/robot = "" var/imp = "" var/bled = "" @@ -439,6 +440,8 @@ splint = "Splinted:" if(e.status & ORGAN_BROKEN) AN = "[e.broken_description]:" + if(e.status & ORGAN_DEAD) + dead = "DEAD:" if(e.is_robotic()) robot = "Robotic:" if(e.open) @@ -454,9 +457,9 @@ infected = "Acute Infection:" if(INFECTION_LEVEL_TWO + 200 to INFECTION_LEVEL_TWO + 300) infected = "Acute Infection+:" - if(INFECTION_LEVEL_TWO + 300 to INFECTION_LEVEL_TWO + 400) + if(INFECTION_LEVEL_TWO + 300 to INFECTION_LEVEL_TWO + 399) infected = "Acute Infection++:" - if(INFECTION_LEVEL_THREE to INFINITY) + if(INFECTION_LEVEL_TWO + 400 to INFINITY) infected = "Septic:" var/unknown_body = 0 @@ -467,11 +470,14 @@ imp += "Unknown body present:" if(!AN && !open && !infected & !imp) AN = "None:" - dat += "
    " + dat += "" dat += "" for(var/obj/item/organ/internal/i in occupant.internal_organs) var/mech = i.desc var/infection = "None" + var/dead = "" + if(i.status & ORGAN_DEAD) + dead = "DEAD:" switch(i.germ_level) if(1 to INFECTION_LEVEL_ONE + 200) infection = "Mild Infection:" @@ -483,18 +489,20 @@ infection = "Acute Infection:" if(INFECTION_LEVEL_TWO + 200 to INFECTION_LEVEL_TWO + 300) infection = "Acute Infection+:" - if(INFECTION_LEVEL_TWO + 300 to INFINITY) + if(INFECTION_LEVEL_TWO + 300 to INFECTION_LEVEL_TWO + 399) infection = "Acute Infection++:" + if(INFECTION_LEVEL_TWO + 400 to INFINITY) + infection = "Septic:" dat += "" - dat += "" + dat += "" dat += "" dat += "
    [e.name][e.burn_dam][e.brute_dam][robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured][e.name][e.burn_dam][e.brute_dam][robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured][dead]
    [i.name]N/A[i.damage][infection]:[mech][i.name]N/A[i.damage][infection]:[mech][dead]
    " - if(occupant.disabilities & BLIND) + if(BLINDNESS in occupant.mutations) dat += "Cataracts detected.
    " - if(occupant.disabilities & COLOURBLIND) + if(COLOURBLIND in occupant.mutations) dat += "Photoreceptor abnormalities detected.
    " - if(occupant.disabilities & NEARSIGHTED) + if(NEARSIGHTED in occupant.mutations) dat += "Retinal misalignment detected.
    " else dat += "[src] is empty." diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 24b8bb27735..446004f345b 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -227,7 +227,7 @@ if(SSradio) SSradio.remove_object(src, frequency) radio_connection = null - air_alarm_repository.update_cache(src) + GLOB.air_alarm_repository.update_cache(src) QDEL_NULL(wires) if(alarm_area && alarm_area.master_air_alarm == src) alarm_area.master_air_alarm = null @@ -241,7 +241,7 @@ if(name == "alarm") name = "[alarm_area.name] Air Alarm" apply_preset(1) // Don't cycle. - air_alarm_repository.update_cache(src) + GLOB.air_alarm_repository.update_cache(src) /obj/machinery/alarm/Initialize() ..() @@ -658,7 +658,7 @@ data["danger"] = danger return data -/obj/machinery/alarm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/alarm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/list/href_list = state.href_list(user) @@ -774,7 +774,7 @@ return thresholds -/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/obj/machinery/alarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "air_alarm.tmpl", name, 570, 410, state = state) diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index 6d54135946b..442d1fac8a0 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -357,7 +357,7 @@ if(istype(O,/obj/machinery/air_sensor) || istype(O, /obj/machinery/meter)) return O:id_tag in sensors -/obj/machinery/computer/general_air_control/linkWith(mob/user, obj/O, link/context) +/obj/machinery/computer/general_air_control/linkWith(mob/user, obj/O, context) sensors[O:id_tag] = reject_bad_name(clean_input(user, "Choose a sensor label:", "Sensor Label"), allow_numbers=1) return 1 diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index efcdada302d..d91fba5fa5c 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -40,8 +40,7 @@ list("name" = "High temperature canister", "icon" = "hot"), list("name" = "Plasma containing canister", "icon" = "plasma") ) - -var/datum/canister_icons/canister_icon_container = new() +GLOBAL_DATUM_INIT(canister_icon_container, /datum/canister_icons, new()) /obj/machinery/portable_atmospherics/canister name = "canister" @@ -97,19 +96,19 @@ var/datum/canister_icons/canister_icon_container = new() //passed to the ui to render the color lists colorcontainer = list( "prim" = list( - "options" = canister_icon_container.possiblemaincolor, + "options" = GLOB.canister_icon_container.possiblemaincolor, "name" = "Primary color", ), "sec" = list( - "options" = canister_icon_container.possibleseccolor, + "options" = GLOB.canister_icon_container.possibleseccolor, "name" = "Secondary color", ), "ter" = list( - "options" = canister_icon_container.possibletertcolor, + "options" = GLOB.canister_icon_container.possibletertcolor, "name" = "Tertiary color", ), "quart" = list( - "options" = canister_icon_container.possiblequartcolor, + "options" = GLOB.canister_icon_container.possiblequartcolor, "name" = "Quaternary color", ) ) @@ -127,7 +126,7 @@ var/datum/canister_icons/canister_icon_container = new() possibledecals = list() var/i - var/list/L = canister_icon_container.possibledecals + var/list/L = GLOB.canister_icon_container.possibledecals for(i=1;i<=L.len;i++) var/list/LL = L[i] LL = LL.Copy() //make sure we don't edit the datum list @@ -220,25 +219,25 @@ update_flag //template modification exploit prevention, used in Topic() /obj/machinery/portable_atmospherics/canister/proc/is_a_color(var/inputVar, var/checkColor = "all") if(checkColor == "prim" || checkColor == "all") - for(var/list/L in canister_icon_container.possiblemaincolor) + for(var/list/L in GLOB.canister_icon_container.possiblemaincolor) if(L["icon"] == inputVar) return 1 if(checkColor == "sec" || checkColor == "all") - for(var/list/L in canister_icon_container.possibleseccolor) + for(var/list/L in GLOB.canister_icon_container.possibleseccolor) if(L["icon"] == inputVar) return 1 if(checkColor == "ter" || checkColor == "all") - for(var/list/L in canister_icon_container.possibletertcolor) + for(var/list/L in GLOB.canister_icon_container.possibletertcolor) if(L["icon"] == inputVar) return 1 if(checkColor == "quart" || checkColor == "all") - for(var/list/L in canister_icon_container.possiblequartcolor) + for(var/list/L in GLOB.canister_icon_container.possiblequartcolor) if(L["icon"] == inputVar) return 1 return 0 /obj/machinery/portable_atmospherics/canister/proc/is_a_decal(var/inputVar) - for(var/list/L in canister_icon_container.possibledecals) + for(var/list/L in GLOB.canister_icon_container.possibledecals) if(L["icon"] == inputVar) return 1 return 0 @@ -354,7 +353,7 @@ update_flag /obj/machinery/portable_atmospherics/canister/attack_hand(var/mob/user as mob) return src.ui_interact(user) -/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = physical_state) +/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.physical_state) if(src.destroyed) return diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm index e4bdef2f147..0144a7f93c2 100644 --- a/code/game/machinery/atmoalter/pump.dm +++ b/code/game/machinery/atmoalter/pump.dm @@ -115,7 +115,7 @@ /obj/machinery/portable_atmospherics/pump/attack_hand(var/mob/user as mob) ui_interact(user) -/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = physical_state) +/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.physical_state) // update the ui if it exists, returns null if no ui is passed/found ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) @@ -127,7 +127,7 @@ // auto update every Master Controller tick ui.set_auto_update(1) -/obj/machinery/portable_atmospherics/pump/ui_data(mob/user, ui_key = "main", datum/topic_state/state = physical_state) +/obj/machinery/portable_atmospherics/pump/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.physical_state) var/data[0] data["portConnected"] = connected_port ? 1 : 0 data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 1016e270f6d..36e340d1a12 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -116,7 +116,7 @@ ui_interact(user) return -/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = physical_state) +/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.physical_state) // update the ui if it exists, returns null if no ui is passed/found ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) @@ -128,7 +128,7 @@ // auto update every Master Controller tick ui.set_auto_update(1) -/obj/machinery/portable_atmospherics/scrubber/ui_data(mob/user, ui_key = "main", datum/topic_state/state = physical_state) +/obj/machinery/portable_atmospherics/scrubber/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.physical_state) var/data[0] data["portConnected"] = connected_port ? 1 : 0 data["tankPressure"] = round(air_contents.return_pressure() > 0 ? air_contents.return_pressure() : 0) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 9d9db841b1e..7a0c2483b40 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -38,7 +38,7 @@ var/list/categories = list("Tools", "Electronics", "Construction", "Communication", "Security", "Machinery", "Medical", "Miscellaneous", "Dinnerware", "Imported") /obj/machinery/autolathe/New() - AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert)) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert)) ..() component_parts = list() component_parts += new /obj/item/circuitboard/autolathe(null) @@ -66,7 +66,7 @@ /obj/machinery/autolathe/Destroy() QDEL_NULL(wires) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_all() return ..() @@ -86,8 +86,8 @@ ui = new(user, src, ui_key, "autolathe.tmpl", name, 800, 550) ui.open() -/obj/machinery/autolathe/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) - GET_COMPONENT(materials, /datum/component/material_container) +/obj/machinery/autolathe/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/data[0] data["screen"] = screen data["total_amount"] = materials.total_amount @@ -138,7 +138,7 @@ /obj/machinery/autolathe/proc/design_cost_data(datum/design/D) var/list/data = list() var/coeff = get_coeff(D) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/has_metal = 1 if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] / coeff))) has_metal = 0 @@ -152,7 +152,7 @@ return data /obj/machinery/autolathe/proc/queue_data(list/data) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/temp_metal = materials.amount(MAT_METAL) var/temp_glass = materials.amount(MAT_GLASS) data["processing"] = being_built.len ? get_processing_line() : null @@ -288,7 +288,7 @@ //multiplier checks : only stacks can have one and its value is 1, 10 ,25 or max_multiplier var/multiplier = text2num(href_list["multiplier"]) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/max_multiplier = min(design_last_ordered.maxstack, design_last_ordered.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/design_last_ordered.materials[MAT_METAL]):INFINITY,design_last_ordered.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/design_last_ordered.materials[MAT_GLASS]):INFINITY) var/is_stack = ispath(design_last_ordered.build_path, /obj/item/stack) @@ -342,7 +342,7 @@ for(var/obj/item/stock_parts/matter_bin/MB in component_parts) tot_rating += MB.rating tot_rating *= 25000 - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.max_amount = tot_rating * 3 for(var/obj/item/stock_parts/manipulator/M in component_parts) prod_coeff += M.rating - 1 @@ -355,7 +355,7 @@ desc = initial(desc)+"\nIt's building \a [initial(D.name)]." var/is_stack = ispath(D.build_path, /obj/item/stack) var/coeff = get_coeff(D) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/metal_cost = D.materials[MAT_METAL] var/glass_cost = D.materials[MAT_GLASS] var/power = max(2000, (metal_cost+glass_cost)*multiplier/5) @@ -387,7 +387,7 @@ return 0 var/coeff = get_coeff(D) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/metal_amount = materials.amount(MAT_METAL) if(custom_metal) metal_amount = custom_metal diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index c097a19f4f8..24ffb494422 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -34,20 +34,16 @@ var/in_use_lights = 0 // TO BE IMPLEMENTED var/toggle_sound = 'sound/items/wirecutter.ogg' - -/obj/machinery/camera/New() - ..() +/obj/machinery/camera/Initialize() + . = ..() wires = new(src) assembly = new(src) assembly.state = 4 assembly.anchored = 1 assembly.update_icon() - cameranet.cameras += src - cameranet.addCamera(src) - -/obj/machinery/camera/Initialize() - ..() + GLOB.cameranet.cameras += src + GLOB.cameranet.addCamera(src) if(is_station_level(z) && prob(3) && !start_active) toggle_cam(null, FALSE) wires.CutAll() @@ -61,8 +57,8 @@ bug.current = null bug = null QDEL_NULL(wires) - cameranet.removeCamera(src) //Will handle removal from the camera network and the chunks, so we don't need to worry about that - cameranet.cameras -= src + GLOB.cameranet.removeCamera(src) //Will handle removal from the camera network and the chunks, so we don't need to worry about that + GLOB.cameranet.cameras -= src var/area/ai_monitored/A = get_area(src) if(istype(A)) A.motioncamera = null @@ -77,7 +73,7 @@ update_icon() var/list/previous_network = network network = list() - cameranet.removeCamera(src) + GLOB.cameranet.removeCamera(src) stat |= EMPED set_light(0) emped = emped+1 //Increase the number of consecutive EMP's @@ -91,7 +87,7 @@ stat &= ~EMPED update_icon() if(can_use()) - cameranet.addCamera(src) + GLOB.cameranet.addCamera(src) emped = 0 //Resets the consecutive EMP count spawn(100) if(!QDELETED(src)) @@ -116,7 +112,7 @@ /obj/machinery/camera/proc/setViewRange(num = 7) view_range = num - cameranet.updateVisibility(src, 0) + GLOB.cameranet.updateVisibility(src, 0) /obj/machinery/camera/singularity_pull(S, current_size) if (status && current_size >= STAGE_FIVE) // If the singulo is strong enough to pull anchored objects and the camera is still active, turn off the camera as it gets ripped off the wall. @@ -285,11 +281,11 @@ /obj/machinery/camera/proc/toggle_cam(mob/user, displaymessage = TRUE) status = !status if(can_use()) - cameranet.addCamera(src) + GLOB.cameranet.addCamera(src) else set_light(0) - cameranet.removeCamera(src) - cameranet.updateChunk(x, y, z) + GLOB.cameranet.removeCamera(src) + GLOB.cameranet.updateChunk(x, y, z) var/change_msg = "deactivates" if(status) change_msg = "reactivates" @@ -376,7 +372,7 @@ return null /obj/machinery/camera/proc/Togglelight(on = FALSE) - for(var/mob/living/silicon/ai/A in ai_list) + for(var/mob/living/silicon/ai/A in GLOB.ai_list) for(var/obj/machinery/camera/cam in A.lit_cameras) if(cam == src) return @@ -428,6 +424,6 @@ assembly.update_icon() /obj/machinery/camera/portable/process() //Updates whenever the camera is moved. - if(cameranet && get_turf(src) != prev_turf) - cameranet.updatePortableCamera(src) + if(GLOB.cameranet && get_turf(src) != prev_turf) + GLOB.cameranet.updatePortableCamera(src) prev_turf = get_turf(src) diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 98f84cb75ec..c7d95370613 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -92,7 +92,7 @@ C.network = uniquelist(tempnetwork) tempnetwork = difflist(C.network,GLOB.restricted_camera_networks) if(!tempnetwork.len) // Camera isn't on any open network - remove its chunk from AI visibility. - cameranet.removeCamera(C) + GLOB.cameranet.removeCamera(C) C.c_tag = input diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 85b83b88c06..c0949fb3c9d 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -2,8 +2,8 @@ // EMP -/obj/machinery/camera/emp_proof/New() - ..() +/obj/machinery/camera/emp_proof/Initialize() + . = ..() upgradeEmpProof() // X-RAY @@ -11,20 +11,20 @@ /obj/machinery/camera/xray icon_state = "xraycam" // Thanks to Krutchen for the icons. -/obj/machinery/camera/xray/New() - ..() +/obj/machinery/camera/xray/Initialize() + . = ..() upgradeXRay() // MOTION -/obj/machinery/camera/motion/New() - ..() +/obj/machinery/camera/motion/Initialize() + . = ..() upgradeMotion() // ALL UPGRADES -/obj/machinery/camera/all/New() - ..() +/obj/machinery/camera/all/Initialize() + . = ..() upgradeEmpProof() upgradeXRay() upgradeMotion() @@ -74,7 +74,7 @@ assembly.upgrades.Add(new /obj/item/analyzer(assembly)) setPowerUsage() //Update what it can see. - cameranet.updateVisibility(src, 0) + GLOB.cameranet.updateVisibility(src, 0) // If you are upgrading Motion, and it isn't in the camera's New(), add it to the machines list. /obj/machinery/camera/proc/upgradeMotion() diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 5e6bd1640fb..1c247b23c03 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -17,7 +17,7 @@ return var/list/L = list() - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in GLOB.cameranet.cameras) L.Add(C) camera_sort(L) @@ -226,9 +226,9 @@ return 0 if(isrobot(M)) var/mob/living/silicon/robot/R = M - if(!(R.camera && R.camera.can_use()) && !cameranet.checkCameraVis(M)) + if(!(R.camera && R.camera.can_use()) && !GLOB.cameranet.checkCameraVis(M)) return 0 - else if(!cameranet.checkCameraVis(M)) + else if(!GLOB.cameranet.checkCameraVis(M)) return 0 return 1 diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 721162c0794..c622b12c94c 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -4,7 +4,19 @@ //Potential replacement for genetics revives or something I dunno (?) #define CLONE_BIOMASS 150 -#define BIOMASS_MEAT_AMOUNT 50 + +#define BIOMASS_BASE_AMOUNT 50 // How much biomass a BIOMASSABLE item gives the cloning pod + +// Not a comprehensive list: Further PRs should add appropriate items here. +// Meat as usual, monstermeat covers goliath, xeno, spider, bear meat +GLOBAL_LIST_INIT(cloner_biomass_items, list(\ +/obj/item/reagent_containers/food/snacks/meat,\ +/obj/item/reagent_containers/food/snacks/monstermeat, +/obj/item/reagent_containers/food/snacks/carpmeat, +/obj/item/reagent_containers/food/snacks/salmonmeat, +/obj/item/reagent_containers/food/snacks/catfishmeat, +/obj/item/reagent_containers/food/snacks/tofurkey)) + #define MINIMUM_HEAL_LEVEL 40 #define CLONE_INITIAL_DAMAGE 190 #define BRAIN_INITIAL_DAMAGE 90 // our minds are too feeble for 190 @@ -15,8 +27,9 @@ desc = "An electronically-lockable pod for growing organic tissue." density = 1 icon = 'icons/obj/cloning.dmi' - icon_state = "pod_0" + icon_state = "pod_idle" req_access = list(ACCESS_GENETICS) //For premature unlocking. + var/mob/living/carbon/human/occupant var/heal_level //The clone is released once its health reaches this level. var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine. @@ -153,7 +166,7 @@ for(var/i=new_SE.len;i<=DNA_SE_LENGTH;i++) new_SE += rand(1,1024) buf.dna.SE=new_SE - buf.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) + buf.dna.SetSEValueRange(GLOB.monkeyblock,0xDAC, 0xFFF) //Disk stuff. /obj/item/disk/data/New() @@ -302,13 +315,14 @@ attempting = 0 return 1 -//Grow clones to maturity then kick them out. FREELOADERS +//Grow clones to maturity then kick them out. FREELOADERS /obj/machinery/clonepod/process() - var/show_message = 0 - for(var/obj/item/reagent_containers/food/snacks/meat/meat in range(1, src)) - qdel(meat) - biomass += BIOMASS_MEAT_AMOUNT - show_message = 1 + var/show_message = FALSE + for(var/obj/item/item in range(1, src)) + if(is_type_in_list(item, GLOB.cloner_biomass_items)) + qdel(item) + biomass += BIOMASS_BASE_AMOUNT + show_message = TRUE if(show_message) visible_message("[src] sucks in and processes the nearby biomass.") @@ -381,11 +395,11 @@ to_chat(user, "You force an emergency ejection.") go_out() -//Removing cloning pod biomass - else if(istype(I, /obj/item/reagent_containers/food/snacks/meat)) +// A user can feed in biomass sources manually. + else if(is_type_in_list(I, GLOB.cloner_biomass_items)) if(user.drop_item()) to_chat(user, "[src] processes [I].") - biomass += BIOMASS_MEAT_AMOUNT + biomass += BIOMASS_BASE_AMOUNT qdel(I) else return ..() @@ -405,7 +419,9 @@ /obj/machinery/clonepod/screwdriver_act(mob/user, obj/item/I) . = TRUE - default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]", I) + // These icon states don't really matter since we need to call update_icon() to handle panel open/closed overlays anyway. + default_deconstruction_screwdriver(user, null, null, I) + update_icon() /obj/machinery/clonepod/wrench_act(mob/user, obj/item/I) . = TRUE @@ -531,11 +547,17 @@ /obj/machinery/clonepod/update_icon() ..() - icon_state = "pod_0" + cut_overlays() + + if(panel_open) + add_overlay("panel_open") + if(occupant && !(stat & NOPOWER)) - icon_state = "pod_1" - else if(mess && !panel_open) - icon_state = "pod_g" + icon_state = "pod_cloning" + else if(mess) + icon_state = "pod_mess" + else + icon_state = "pod_idle" /obj/machinery/clonepod/relaymove(mob/user) if(user.stat == CONSCIOUS) diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index ad11d6fb7c5..21fddce64b7 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -61,7 +61,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/computer/operating/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/operating/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/mob/living/carbon/human/occupant if(table) diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index d53903857ef..ba139e50855 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -158,7 +158,7 @@ var/open_for_latejoin = alert(user, "Would you like this core to be open for latejoining AIs?", "Latejoin", "Yes", "Yes", "No") == "Yes" var/obj/structure/AIcore/deactivated/D = new(loc) if(open_for_latejoin) - empty_playable_ai_cores += D + GLOB.empty_playable_ai_cores += D else if(brain.brainmob.mind) SSticker.mode.remove_cultist(brain.brainmob.mind, 1) @@ -248,8 +248,8 @@ circuit = new(src) /obj/structure/AIcore/deactivated/Destroy() - if(src in empty_playable_ai_cores) - empty_playable_ai_cores -= src + if(src in GLOB.empty_playable_ai_cores) + GLOB.empty_playable_ai_cores -= src return ..() /client/proc/empty_ai_core_toggle_latejoin() @@ -269,11 +269,11 @@ var/obj/structure/AIcore/deactivated/D = cores[id] if(!D) return - if(D in empty_playable_ai_cores) - empty_playable_ai_cores -= D + if(D in GLOB.empty_playable_ai_cores) + GLOB.empty_playable_ai_cores -= D to_chat(src, "\The [id] is now not available for latejoining AIs.") else - empty_playable_ai_cores += D + GLOB.empty_playable_ai_cores += D to_chat(src, "\The [id] is now available for latejoining AIs.") diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index f8c2979e043..123cee3ae4e 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -1,5 +1,5 @@ -var/global/list/priority_air_alarms = list() -var/global/list/minor_air_alarms = list() +GLOBAL_LIST_EMPTY(priority_air_alarms) +GLOBAL_LIST_EMPTY(minor_air_alarms) /obj/machinery/computer/atmos_alert @@ -12,7 +12,7 @@ var/global/list/minor_air_alarms = list() /obj/machinery/computer/atmos_alert/New() ..() - SSalarms.atmosphere_alarm.register(src, /obj/machinery/computer/station_alert/update_icon) + SSalarms.atmosphere_alarm.register(src, /obj/machinery/computer/station_alert/.proc/update_icon) /obj/machinery/computer/atmos_alert/Destroy() SSalarms.atmosphere_alarm.unregister(src) @@ -67,12 +67,11 @@ var/global/list/minor_air_alarms = list() var/obj/machinery/alarm/air_alarm = alarm_source.source if(istype(air_alarm)) var/list/new_ref = list("atmos_reset" = 1) - air_alarm.Topic(href, new_ref, state = air_alarm_topic) + air_alarm.Topic(href, new_ref, state = GLOB.air_alarm_topic) update_icon() return 1 - -var/datum/topic_state/air_alarm_topic/air_alarm_topic = new() +GLOBAL_DATUM_INIT(air_alarm_topic, /datum/topic_state/air_alarm_topic, new) /datum/topic_state/air_alarm_topic/href_list(var/mob/user) var/list/extra_href = list() diff --git a/code/game/machinery/computer/brigcells.dm b/code/game/machinery/computer/brigcells.dm index 378c10d9783..a391bfa4021 100644 --- a/code/game/machinery/computer/brigcells.dm +++ b/code/game/machinery/computer/brigcells.dm @@ -30,7 +30,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/computer/brigcells/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/brigcells/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/list/timers = list() for(var/obj/machinery/door_timer/T in GLOB.celltimers_list) diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm index 2f8321b57bb..993a1c5cbaa 100644 --- a/code/game/machinery/computer/buildandrepair.dm +++ b/code/game/machinery/computer/buildandrepair.dm @@ -45,7 +45,6 @@ var/list/req_components = null var/powernet = null var/list/records = null - var/frame_desc = null var/contain_parts = 1 toolspeed = 1 usesound = 'sound/items/deconstruct.ogg' @@ -64,7 +63,7 @@ var/atom/A = B if(!ispath(A)) continue - nice_list += list("[req_components[A]] [initial(A.name)]") + nice_list += list("[req_components[A]] [initial(A.name)]\s") . += "Required components: [english_list(nice_list)]." /obj/item/circuitboard/message_monitor @@ -296,19 +295,6 @@ name = "Circuit board (Operating Computer)" build_path = /obj/machinery/computer/operating origin_tech = "programming=2;biotech=3" -/obj/item/circuitboard/comm_monitor - name = "Circuit board (Telecommunications Monitor)" - build_path = /obj/machinery/computer/telecomms/monitor - origin_tech = "programming=3;magnets=3;bluespace=2" -/obj/item/circuitboard/comm_server - name = "Circuit board (Telecommunications Server Monitor)" - build_path = /obj/machinery/computer/telecomms/server - origin_tech = "programming=3;magnets=3;bluespace=2" -/obj/item/circuitboard/comm_traffic - name = "Circuitboard (Telecommunications Traffic Control)" - build_path = /obj/machinery/computer/telecomms/traffic - origin_tech = "programming=3;magnets=3;bluespace=2" - /obj/item/circuitboard/shuttle name = "circuit board (Shuttle)" diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index f67158f82b0..3f8fc080bf8 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -53,6 +53,9 @@ return TRUE /obj/machinery/computer/security/check_eye(mob/user) + if((stat & (NOPOWER|BROKEN)) || user.incapacitated() || !user.has_vision()) + user.unset_machine() + return if(!(user in watchers)) user.unset_machine() return @@ -65,8 +68,6 @@ return if(!can_access_camera(C, user)) user.unset_machine() - return - return 1 /obj/machinery/computer/security/on_unset_machine(mob/user) watchers.Remove(user) @@ -113,7 +114,7 @@ access = get_all_accesses() // Assume captain level access when emagged else if(ishuman(user)) access = user.get_access() - else if((isAI(user) || isrobot(user)) && CanUseTopic(user, default_state) == STATUS_INTERACTIVE) + else if((isAI(user) || isrobot(user)) && CanUseTopic(user, GLOB.default_state) == STATUS_INTERACTIVE) access = get_all_accesses() // Assume captain level access when AI else if(user.can_admin_interact()) access = get_all_accesses() @@ -131,11 +132,11 @@ ui.open() -/obj/machinery/computer/security/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/security/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/list/cameras = list() - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in GLOB.cameranet.cameras) if(isCameraFarAway(C)) continue if(!can_access_camera(C, user)) @@ -183,7 +184,7 @@ return 1 if(href_list["switchTo"]) - var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.cameras + var/obj/machinery/camera/C = locate(href_list["switchTo"]) in GLOB.cameranet.cameras if(!C) return 1 @@ -209,7 +210,7 @@ // Check if camera is accessible when jumping /obj/machinery/computer/security/proc/can_access_camera(var/obj/machinery/camera/C, var/mob/M) - if(CanUseTopic(M, default_state) != STATUS_INTERACTIVE || M.incapacitated() || !M.has_vision()) + if(CanUseTopic(M, GLOB.default_state) != STATUS_INTERACTIVE || M.incapacitated() || !M.has_vision()) return 0 if(isrobot(M)) @@ -302,7 +303,7 @@ T = get_step(T, direct) console.jump_on_click(src, T) return - return ..(n,direct) + return ..() // Other computer monitors. /obj/machinery/computer/security/telescreen diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index b70addea909..bc1bfe6135b 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -37,17 +37,14 @@ eyeobj.RemoveImages() eyeobj.eye_user = null user.remote_control = null - user.remote_view = FALSE current_user = null user.unset_machine() playsound(src, 'sound/machines/terminal_off.ogg', 25, 0) /obj/machinery/computer/camera_advanced/check_eye(mob/user) - if((stat & (NOPOWER|BROKEN)) || !Adjacent(user) || !user.has_vision() || user.incapacitated()) + if((stat & (NOPOWER|BROKEN)) || (!Adjacent(user) && !user.has_unlimited_silicon_privilege) || !user.has_vision() || user.incapacitated()) user.unset_machine() - return 0 - return 1 /obj/machinery/computer/camera_advanced/Destroy() if(current_user) @@ -75,7 +72,7 @@ if(!eyeobj.eye_initialized) var/camera_location - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in GLOB.cameranet.cameras) if(!C.can_use()) continue if(C.network&networks) @@ -99,8 +96,6 @@ current_user = user eyeobj.eye_user = user eyeobj.name = "Camera Eye ([user.name])" - // This should be able to be excised once the full view refactor rolls out - user.remote_view = 1 user.remote_control = eyeobj user.reset_perspective(eyeobj) @@ -139,7 +134,7 @@ T = get_turf(T) loc = T if(use_static) - cameranet.visibility(src, GetViewerClient()) + GLOB.cameranet.visibility(src, GetViewerClient()) if(visible_icon) if(eye_user.client) eye_user.client.images -= user_image @@ -189,7 +184,7 @@ var/list/L = list() - for(var/obj/machinery/camera/cam in cameranet.cameras) + for(var/obj/machinery/camera/cam in GLOB.cameranet.cameras) L.Add(cam) camera_sort(L) diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 07ab3f5d62b..978ba25b8d3 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -1,6 +1,6 @@ //Keeps track of the time for the ID console. Having it as a global variable prevents people from dismantling/reassembling it to //increase the slots of many jobs. -var/time_last_changed_position = 0 +GLOBAL_VAR_INIT(time_last_changed_position, 0) /obj/machinery/computer/card name = "identification computer" @@ -25,7 +25,8 @@ var/time_last_changed_position = 0 /datum/job/ntnavyofficer, /datum/job/ntspecops, /datum/job/civilian, - /datum/job/syndicateofficer + /datum/job/syndicateofficer, + /datum/job/explorer // blacklisted so that HOPs don't try prioritizing it, then wonder why that doesn't work ) // Jobs that appear in the list, and you can prioritize, but not open/close slots for var/list/blacklisted_partial = list( @@ -133,7 +134,7 @@ var/time_last_changed_position = 0 if(!istype(id_card)) return ..() - if(!scan && ACCESS_CHANGE_IDS in id_card.access) + if(!scan && (ACCESS_CHANGE_IDS in id_card.access)) user.drop_item() id_card.loc = src scan = id_card @@ -160,7 +161,7 @@ var/time_last_changed_position = 0 if(job) if(!job_blacklisted_full(job) && !job_blacklisted_partial(job) && job_in_department(job, FALSE)) if((job.total_positions <= GLOB.player_list.len * (max_relative_positions / 100))) - var/delta = (world.time / 10) - time_last_changed_position + var/delta = (world.time / 10) - GLOB.time_last_changed_position if((change_position_cooldown < delta) || (opened_positions[job.title] < 0)) return 1 return -2 @@ -172,7 +173,7 @@ var/time_last_changed_position = 0 if(job) if(!job_blacklisted_full(job) && !job_blacklisted_partial(job) && job_in_department(job, FALSE)) if(job.total_positions > job.current_positions && !(job in SSjobs.prioritized_jobs)) - var/delta = (world.time / 10) - time_last_changed_position + var/delta = (world.time / 10) - GLOB.time_last_changed_position if((change_position_cooldown < delta) || (opened_positions[job.title] > 0)) return 1 return -2 @@ -236,13 +237,13 @@ var/time_last_changed_position = 0 ui = new(user, src, ui_key, "identification_computer.tmpl", src.name, 775, 700) ui.open() -/obj/machinery/computer/card/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/card/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["src"] = UID() data["station_name"] = station_name() data["mode"] = mode data["printing"] = printing - data["manifest"] = data_core ? data_core.get_manifest(0) : null + data["manifest"] = GLOB.data_core ? GLOB.data_core.get_manifest(0) : null data["target_name"] = modify ? modify.name : "-----" data["target_owner"] = modify && modify.registered_name ? modify.registered_name : "-----" data["target_rank"] = get_target_rank() @@ -260,19 +261,19 @@ var/time_last_changed_position = 0 var/list/job_formats = SSjobs.format_jobs_for_id_computer(modify) data["top_jobs"] = format_jobs(list("Captain", "Custom"), data["target_rank"], job_formats) - data["engineering_jobs"] = format_jobs(engineering_positions, data["target_rank"], job_formats) - data["medical_jobs"] = format_jobs(medical_positions, data["target_rank"], job_formats) - data["science_jobs"] = format_jobs(science_positions, data["target_rank"], job_formats) - data["security_jobs"] = format_jobs(security_positions, data["target_rank"], job_formats) - data["support_jobs"] = format_jobs(support_positions, data["target_rank"], job_formats) - data["civilian_jobs"] = format_jobs(civilian_positions, data["target_rank"], job_formats) - data["special_jobs"] = format_jobs(whitelisted_positions, data["target_rank"], job_formats) + data["engineering_jobs"] = format_jobs(GLOB.engineering_positions, data["target_rank"], job_formats) + data["medical_jobs"] = format_jobs(GLOB.medical_positions, data["target_rank"], job_formats) + data["science_jobs"] = format_jobs(GLOB.science_positions, data["target_rank"], job_formats) + data["security_jobs"] = format_jobs(GLOB.security_positions, data["target_rank"], job_formats) + data["support_jobs"] = format_jobs(GLOB.support_positions, data["target_rank"], job_formats) + data["civilian_jobs"] = format_jobs(GLOB.civilian_positions, data["target_rank"], job_formats) + data["special_jobs"] = format_jobs(GLOB.whitelisted_positions, data["target_rank"], job_formats) data["centcom_jobs"] = format_jobs(get_all_centcom_jobs(), data["target_rank"], job_formats) data["card_skins"] = format_card_skins(get_station_card_skins()) data["job_slots"] = format_job_slots() - var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - time_last_changed_position), 1) + var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) var/mins = round(time_to_wait / 60) var/seconds = time_to_wait - (60*mins) data["cooldown_mins"] = mins @@ -321,7 +322,7 @@ var/time_last_changed_position = 0 switch(href_list["choice"]) if("modify") if(modify) - data_core.manifest_modify(modify.registered_name, modify.assignment) + GLOB.data_core.manifest_modify(modify.registered_name, modify.assignment) modify.name = text("[modify.registered_name]'s ID Card ([modify.assignment])") if(ishuman(usr)) modify.forceMove(get_turf(src)) @@ -480,7 +481,7 @@ var/time_last_changed_position = 0 P.name = "crew manifest ([station_time_timestamp()])" P.info = {"

    Crew Manifest


    - [data_core ? data_core.get_manifest(0) : ""] + [GLOB.data_core ? GLOB.data_core.get_manifest(0) : ""] "} else if(modify && !mode) P.name = "access report" @@ -544,7 +545,7 @@ var/time_last_changed_position = 0 if(can_open_job(j) != 1) return 0 if(opened_positions[edit_job_target] >= 0) - time_last_changed_position = world.time / 10 + GLOB.time_last_changed_position = world.time / 10 j.total_positions++ opened_positions[edit_job_target]++ log_game("[key_name(usr)] has opened a job slot for job \"[j]\".") @@ -564,7 +565,7 @@ var/time_last_changed_position = 0 return 0 //Allow instant closing without cooldown if a position has been opened before if(opened_positions[edit_job_target] <= 0) - time_last_changed_position = world.time / 10 + GLOB.time_last_changed_position = world.time / 10 j.total_positions-- opened_positions[edit_job_target]-- log_game("[key_name(usr)] has closed a job slot for job \"[j]\".") diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index c06cbb32a04..3091caa82a2 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -129,7 +129,7 @@ ui = new(user, src, ui_key, "cloning_console.tmpl", "Cloning Console UI", 640, 520) ui.open() -/obj/machinery/computer/cloning/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/cloning/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["menu"] = src.menu data["scanner"] = sanitize("[src.scanner]") @@ -358,35 +358,37 @@ return if(scan_brain && !can_brainscan()) return - if((isnull(subject)) || (!(ishuman(subject))) || (!subject.dna) || (NO_SCAN in subject.dna.species.species_traits)) - scantemp = "Error: Unable to locate valid genetic data." - SSnanoui.update_uis(src) - return + if(isnull(subject) || (!(ishuman(subject))) || (!subject.dna)) + if(isalien(subject)) + scantemp = "Error: Xenomorphs are not scannable." + SSnanoui.update_uis(src) + return + // can add more conditions for specific non-human messages here + else + scantemp = "Error: Subject species is not scannable." + SSnanoui.update_uis(src) + return if(subject.get_int_organ(/obj/item/organ/internal/brain)) var/obj/item/organ/internal/brain/Brn = subject.get_int_organ(/obj/item/organ/internal/brain) if(istype(Brn)) if(NO_SCAN in Brn.dna.species.species_traits) - scantemp = "Error: Subject's brain is incompatible." + scantemp = "Error: [Brn.dna.species.name_plural] are not scannable." SSnanoui.update_uis(src) return if(!subject.get_int_organ(/obj/item/organ/internal/brain)) - scantemp = "Error: No signs of intelligence detected." + scantemp = "Error: No brain detected in subject." SSnanoui.update_uis(src) return if(subject.suiciding) - scantemp = "Error: Subject's brain is not responding to scanning stimuli." + scantemp = "Error: Subject has committed suicide and is not scannable." SSnanoui.update_uis(src) return if((!subject.ckey) || (!subject.client)) - scantemp = "Error: Mental interface failure." + scantemp = "Error: Subject's brain is not responding. Further attempts after a short delay may succeed." SSnanoui.update_uis(src) return if((NOCLONE in subject.mutations) && src.scanner.scan_level < 2) - scantemp = "Error: Mental interface failure." - SSnanoui.update_uis(src) - return - if(scan_brain && !subject.get_int_organ(/obj/item/organ/internal/brain)) - scantemp = "Error: No brain found." + scantemp = "Error: Subject has incompatible genetic mutations." SSnanoui.update_uis(src) return if(!isnull(find_record(subject.ckey))) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 3b663bbe549..9a1fd08d289 100644 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -54,16 +54,16 @@ /obj/machinery/computer/communications/proc/change_security_level(var/new_level) tmp_alertlevel = new_level - var/old_level = security_level + var/old_level = GLOB.security_level if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN if(tmp_alertlevel < SEC_LEVEL_GREEN) tmp_alertlevel = SEC_LEVEL_GREEN if(tmp_alertlevel > SEC_LEVEL_BLUE) tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this set_security_level(tmp_alertlevel) - if(security_level != old_level) + if(GLOB.security_level != old_level) //Only notify the admins if an actual change happened log_game("[key_name(usr)] has changed the security level to [get_security_level()].") message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].") - switch(security_level) + switch(GLOB.security_level) if(SEC_LEVEL_GREEN) feedback_inc("alert_comms_green",1) if(SEC_LEVEL_BLUE) @@ -237,7 +237,7 @@ Nuke_request(input, usr) to_chat(usr, "Request sent.") log_game("[key_name(usr)] has requested the nuclear codes from Centcomm") - priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg') + GLOB.priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg') centcomm_message_cooldown = 1 spawn(6000)//10 minute cooldown centcomm_message_cooldown = 0 @@ -299,8 +299,8 @@ to_chat(usr, "Nano-Mob Hunter GO! game server is offline for extended maintenance. Contact your Central Command administrators for more info if desired.") if("ToggleATC") - atc.squelched = !atc.squelched - to_chat(usr, "ATC traffic is now: [atc.squelched ? "Disabled" : "Enabled"].") + GLOB.atc.squelched = !GLOB.atc.squelched + to_chat(usr, "ATC traffic is now: [GLOB.atc.squelched ? "Disabled" : "Enabled"].") SSnanoui.update_uis(src) return 1 @@ -337,7 +337,7 @@ // open the new ui window ui.open() -/obj/machinery/computer/communications/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/communications/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["is_ai"] = isAI(user) || isrobot(user) data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state @@ -364,7 +364,7 @@ ) ) - data["security_level"] = security_level + data["security_level"] = GLOB.security_level data["str_security_level"] = capitalize(get_security_level()) data["levels"] = list( list("id" = SEC_LEVEL_GREEN, "name" = "Green"), @@ -395,7 +395,7 @@ data["shuttle"] = shuttle - data["atcSquelched"] = atc.squelched + data["atcSquelched"] = GLOB.atc.squelched return data @@ -427,7 +427,7 @@ /proc/enable_prison_shuttle(var/mob/user); /proc/call_shuttle_proc(var/mob/user, var/reason) - if(sent_strike_team == 1) + if(GLOB.sent_strike_team == 1) to_chat(user, "Central Command will not allow the shuttle to be called. Consider all contracts terminated.") return @@ -456,7 +456,7 @@ to_chat(user, "Central Command does not currently have a shuttle available in your sector. Please try again later.") return - if(sent_strike_team == 1) + if(GLOB.sent_strike_team == 1) to_chat(user, "Central Command will not allow the shuttle to be called. Consider all contracts terminated.") return @@ -499,7 +499,6 @@ if(!frequency) return var/datum/signal/status_signal = new - status_signal.source = src status_signal.transmission_method = 1 status_signal.data["command"] = command @@ -507,13 +506,13 @@ if("message") status_signal.data["msg1"] = data1 status_signal.data["msg2"] = data2 - log_admin("STATUS: [user] set status screen message with [src]: [data1] [data2]") + log_admin("STATUS: [user] set status screen message: [data1] [data2]") //message_admins("STATUS: [user] set status screen with [PDA]. Message: [data1] [data2]") if("alert") status_signal.data["picture_state"] = data1 spawn(0) - frequency.post_signal(src, status_signal) + frequency.post_signal(null, status_signal) /obj/machinery/computer/communications/Destroy() diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index a3828af6be1..9464c43b107 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -52,7 +52,7 @@ ui = new(user, src, ui_key, "med_data.tmpl", name, 800, 380) ui.open() -/obj/machinery/computer/med_data/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/med_data/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["temp"] = temp data["scan"] = scan ? scan.name : null @@ -61,15 +61,15 @@ if(authenticated) switch(screen) if(MED_DATA_R_LIST) - if(!isnull(data_core.general)) + if(!isnull(GLOB.data_core.general)) var/list/records = list() data["records"] = records - for(var/datum/data/record/R in sortRecord(data_core.general)) + for(var/datum/data/record/R in sortRecord(GLOB.data_core.general)) records[++records.len] = list("ref" = "\ref[R]", "id" = R.fields["id"], "name" = R.fields["name"]) if(MED_DATA_RECORD) var/list/general = list() data["general"] = general - if(istype(active1, /datum/data/record) && data_core.general.Find(active1)) + if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)) var/list/fields = list() general["fields"] = fields fields[++fields.len] = list("field" = "Name:", "value" = active1.fields["name"], "edit" = null) @@ -90,7 +90,7 @@ var/list/medical = list() data["medical"] = medical - if(istype(active2, /datum/data/record) && data_core.medical.Find(active2)) + if(istype(active2, /datum/data/record) && GLOB.data_core.medical.Find(active2)) var/list/fields = list() medical["fields"] = fields fields[++fields.len] = list("field" = "Blood Type:", "value" = active2.fields["blood_type"], "edit" = "blood_type", "line_break" = 0) @@ -144,9 +144,9 @@ if(..()) return 1 - if(!data_core.general.Find(active1)) + if(!GLOB.data_core.general.Find(active1)) active1 = null - if(!data_core.medical.Find(active2)) + if(!GLOB.data_core.medical.Find(active2)) active2 = null if(href_list["temp"]) @@ -157,7 +157,7 @@ var/temp_href = splittext(href_list["temp_action"], "=") switch(temp_href[1]) if("del_all2") - for(var/datum/data/record/R in data_core.medical) + for(var/datum/data/record/R in GLOB.data_core.medical) qdel(R) setTemp("

    All records deleted.

    ") if("p_stat") @@ -421,10 +421,10 @@ if(href_list["d_rec"]) var/datum/data/record/R = locate(href_list["d_rec"]) var/datum/data/record/M = locate(href_list["d_rec"]) - if(!data_core.general.Find(R)) + if(!GLOB.data_core.general.Find(R)) setTemp("

    Record not found!

    ") return 1 - for(var/datum/data/record/E in data_core.medical) + for(var/datum/data/record/E in GLOB.data_core.medical) if(E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]) M = E active1 = R @@ -448,7 +448,7 @@ R.fields["cdi"] = "None" R.fields["cdi_d"] = "No diseases have been diagnosed at the moment." R.fields["notes"] = "No notes." - data_core.medical += R + GLOB.data_core.medical += R active2 = R screen = MED_DATA_RECORD @@ -459,7 +459,7 @@ var/t1 = copytext(trim(sanitize(input("Add Comment:", "Med. records", null, null) as message)), 1, MAX_MESSAGE_LEN) if(!t1 || ..() || active2 != a2) return 1 - active2.fields["comments"] += "Made by [authenticated] ([rank]) on [current_date_string] [station_time_timestamp()]
    [t1]" + active2.fields["comments"] += "Made by [authenticated] ([rank]) on [GLOB.current_date_string] [station_time_timestamp()]
    [t1]" if(href_list["del_c"]) var/index = min(max(text2num(href_list["del_c"]) + 1, 1), length(active2.fields["comments"])) @@ -473,13 +473,13 @@ active1 = null active2 = null t1 = lowertext(t1) - for(var/datum/data/record/R in data_core.medical) + for(var/datum/data/record/R in GLOB.data_core.medical) if(t1 == lowertext(R.fields["name"]) || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"])) active2 = R if(!active2) setTemp("

    Could not locate record [t1].

    ") else - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == active2.fields["name"] && E.fields["id"] == active2.fields["id"]) active1 = E screen = MED_DATA_RECORD @@ -491,7 +491,7 @@ sleep(50) var/obj/item/paper/P = new /obj/item/paper(loc) P.info = "
    Medical Record

    " - if(istype(active1, /datum/data/record) && data_core.general.Find(active1)) + if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)) P.info += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
    \nSex: [active1.fields["sex"]]
    \nAge: [active1.fields["age"]] @@ -500,7 +500,7 @@
    \nMental Status: [active1.fields["m_stat"]]
    "} else P.info += "General Record Lost!
    " - if(istype(active2, /datum/data/record) && data_core.medical.Find(active2)) + if(istype(active2, /datum/data/record) && GLOB.data_core.medical.Find(active2)) P.info += {"
    \n
    Medical Data

    \nBlood Type: [active2.fields["blood_type"]]
    \nDNA: [active2.fields["b_dna"]]
    \n @@ -532,7 +532,7 @@ if(stat & (BROKEN|NOPOWER)) return ..(severity) - for(var/datum/data/record/R in data_core.medical) + for(var/datum/data/record/R in GLOB.data_core.medical) if(prob(10/severity)) switch(rand(1,6)) if(1) diff --git a/code/game/machinery/computer/message.dm b/code/game/machinery/computer/message.dm index 55107809ce3..f2e4c5a7a52 100644 --- a/code/game/machinery/computer/message.dm +++ b/code/game/machinery/computer/message.dm @@ -18,7 +18,7 @@ var/noserver = "ALERT: No server detected." var/incorrectkey = "ALERT: Incorrect decryption key!" var/defaultmsg = "Welcome. Please select an option." - var/rebootmsg = "%$&(£: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!" + var/rebootmsg = "%$&(�: Critical %$$@ Error // !RestArting! - ?pLeaSe wAit!" //Computer properties var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message var/hacking = 0 // Is it being hacked into by the AI/Cyborg @@ -54,7 +54,7 @@ MK.loc = src.loc playsound(loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1) // Will help make emagging the console not so easy to get away with. - MK.info += "

    £%@%(*$%&(£&?*(%&£/{}" + MK.info += "

    �%@%(*$%&(�&?*(%&�/{}" update_icon() spawn(100*length(src.linkedServer.decryptkey)) UnmagConsole() @@ -75,8 +75,8 @@ ..() //Is the server isn't linked to a server, and there's a server available, default it to the first one in the list. if(!linkedServer) - if(message_servers && message_servers.len > 0) - linkedServer = message_servers[1] + if(GLOB.message_servers && GLOB.message_servers.len > 0) + linkedServer = GLOB.message_servers[1] return /obj/machinery/computer/message_monitor/attack_hand(var/mob/user as mob) @@ -288,11 +288,11 @@ if(auth) linkedServer.active = !linkedServer.active //Find a server if(href_list["find"]) - if(message_servers && message_servers.len > 1) - src.linkedServer = input(usr,"Please select a server.", "Select a server.", null) as null|anything in message_servers + if(GLOB.message_servers && GLOB.message_servers.len > 1) + src.linkedServer = input(usr,"Please select a server.", "Select a server.", null) as null|anything in GLOB.message_servers message = "NOTICE: Server selected." - else if(message_servers && message_servers.len > 0) - linkedServer = message_servers[1] + else if(GLOB.message_servers && GLOB.message_servers.len > 0) + linkedServer = GLOB.message_servers[1] message = "NOTICE: Only Single Server Detected - Server selected." else message = noserver @@ -396,13 +396,13 @@ if("Recepient") //Get out list of viable PDAs var/list/obj/item/pda/sendPDAs = list() - for(var/obj/item/pda/P in PDAs) + for(var/obj/item/pda/P in GLOB.PDAs) var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) if(!PM || !PM.can_receive()) continue sendPDAs += P - if(PDAs && PDAs.len > 0) + if(GLOB.PDAs && GLOB.PDAs.len > 0) customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortAtom(sendPDAs) else customrecepient = null @@ -436,7 +436,7 @@ return src.attack_hand(usr) var/obj/item/pda/PDARec = null - for(var/obj/item/pda/P in PDAs) + for(var/obj/item/pda/P in GLOB.PDAs) var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) if(!PM || !PM.can_receive()) @@ -486,11 +486,11 @@ /obj/item/paper/monitorkey/New() ..() spawn(10) - if(message_servers) - for(var/obj/machinery/message_server/server in message_servers) + if(GLOB.message_servers) + for(var/obj/machinery/message_server/server in GLOB.message_servers) if(!isnull(server)) if(!isnull(server.decryptkey)) - info = "

    Daily Key Reset


    The new message monitor key is '[server.decryptkey]'.
    Please keep this a secret and away from the clown.
    If necessary, change the password to a more secure one." + info = "

    Daily Key Reset

    \n\t
    The new message monitor key is '[server.decryptkey]'.
    Please keep this a secret and away from the clown.
    If necessary, change the password to a more secure one." info_links = info overlays += "paper_words" break diff --git a/code/game/machinery/computer/pod_tracking_console.dm b/code/game/machinery/computer/pod_tracking_console.dm index cd6450c700c..c4a6d5d440b 100644 --- a/code/game/machinery/computer/pod_tracking_console.dm +++ b/code/game/machinery/computer/pod_tracking_console.dm @@ -20,7 +20,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/computer/podtracker/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/podtracker/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/list/pods[0] for(var/obj/item/spacepod_equipment/misc/tracker/TR in world) diff --git a/code/game/machinery/computer/power.dm b/code/game/machinery/computer/power.dm index fce315a1db0..bb38e59c800 100644 --- a/code/game/machinery/computer/power.dm +++ b/code/game/machinery/computer/power.dm @@ -26,18 +26,18 @@ /obj/machinery/computer/monitor/Initialize() ..() - powermonitor_repository.update_cache() + GLOB.powermonitor_repository.update_cache() powernet = find_powernet() /obj/machinery/computer/monitor/Destroy() GLOB.power_monitors -= src - powermonitor_repository.update_cache() + GLOB.powermonitor_repository.update_cache() QDEL_NULL(power_monitor) return ..() /obj/machinery/computer/monitor/power_change() ..() - powermonitor_repository.update_cache() + GLOB.powermonitor_repository.update_cache() /obj/machinery/computer/monitor/proc/find_powernet() var/obj/structure/cable/attached = null diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 8ecd463bc35..6134860733a 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -36,7 +36,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/computer/robotics/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/robotics/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/list/robots = get_cyborgs(user) if(robots.len) diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index cb5e799b89e..8c815198d31 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -54,7 +54,7 @@ ui = new(user, src, ui_key, "secure_data.tmpl", name, 800, 800) ui.open() -/obj/machinery/computer/secure_data/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/secure_data/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["temp"] = temp data["scan"] = scan ? scan.name : null @@ -63,26 +63,32 @@ if(authenticated) switch(screen) if(SEC_DATA_R_LIST) - if(!isnull(data_core.general)) - for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order)) + if(!isnull(GLOB.data_core.general)) + for(var/datum/data/record/R in sortRecord(GLOB.data_core.general, sortBy, order)) var/crimstat = "null" - for(var/datum/data/record/E in data_core.security) + for(var/datum/data/record/E in GLOB.data_core.security) if(E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]) crimstat = E.fields["criminal"] break var/background = "''" switch(crimstat) - if("*Execute*") + if(SEC_RECORD_STATUS_EXECUTE) background = "'background-color:#5E0A1A'" - if("*Arrest*") + if(SEC_RECORD_STATUS_ARREST) background = "'background-color:#890E26'" - if("Incarcerated") + if(SEC_RECORD_STATUS_SEARCH) + background = "'background-color:#999900'" + if(SEC_RECORD_STATUS_MONITOR) + background = "'background-color:#004C99'" + if(SEC_RECORD_STATUS_DEMOTE) + background = "'background-color:#C2A111'" + if(SEC_RECORD_STATUS_INCARCERATED) background = "'background-color:#743B03'" - if("Parolled") + if(SEC_RECORD_STATUS_PAROLLED) background = "'background-color:#743B03'" - if("Released") + if(SEC_RECORD_STATUS_RELEASED) background = "'background-color:#216489'" - if("None") + if(SEC_RECORD_STATUS_NONE) background = "'background-color:#007f47'" if("null") crimstat = "No record." @@ -90,7 +96,7 @@ if(SEC_DATA_RECORD) var/list/general = list() data["general"] = general - if(istype(active1, /datum/data/record) && data_core.general.Find(active1)) + if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)) var/list/fields = list() general["fields"] = fields fields[++fields.len] = list("field" = "Name:", "value" = active1.fields["name"], "edit" = "name") @@ -112,7 +118,7 @@ var/list/security = list() data["security"] = security - if(istype(active2, /datum/data/record) && data_core.security.Find(active2)) + if(istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2)) var/list/fields = list() security["fields"] = fields fields[++fields.len] = list("field" = "Criminal Status:", "value" = active2.fields["criminal"], "edit" = "criminal", "line_break" = 1) @@ -133,9 +139,9 @@ if(..()) return 1 - if(!data_core.general.Find(active1)) + if(!GLOB.data_core.general.Find(active1)) active1 = null - if(!data_core.security.Find(active2)) + if(!GLOB.data_core.security.Find(active2)) active2 = null if(href_list["temp"]) @@ -145,7 +151,7 @@ var/temp_href = splittext(href_list["temp_action"], "=") switch(temp_href[1]) if("del_all2") - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in GLOB.data_core.security) qdel(R) update_all_mob_security_hud() setTemp("

    All records deleted.

    ") @@ -161,7 +167,7 @@ update_all_mob_security_hud() if("del_rg2") if(active1) - for(var/datum/data/record/R in data_core.medical) + for(var/datum/data/record/R in GLOB.data_core.medical) if(R.fields["name"] == active1.fields["name"] && R.fields["id"] == active1.fields["id"]) qdel(R) QDEL_NULL(active1) @@ -248,10 +254,10 @@ else if(href_list["d_rec"]) var/datum/data/record/R = locate(href_list["d_rec"]) var/datum/data/record/M = locate(href_list["d_rec"]) - if(!data_core.general.Find(R)) + if(!GLOB.data_core.general.Find(R)) setTemp("

    Record not found!

    ") return 1 - for(var/datum/data/record/E in data_core.security) + for(var/datum/data/record/E in GLOB.data_core.security) if(E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]) M = E active1 = R @@ -296,7 +302,7 @@ R.fields["ma_crim"] = "None" R.fields["ma_crim_d"] = "No major crime convictions." R.fields["notes"] = "No notes." - data_core.security += R + GLOB.data_core.security += R active2 = R screen = SEC_DATA_RECORD @@ -312,7 +318,7 @@ G.fields["p_stat"] = "Active" G.fields["m_stat"] = "Stable" G.fields["species"] = "Human" - data_core.general += G + GLOB.data_core.general += G active1 = G active2 = null @@ -323,7 +329,7 @@ sleep(50) var/obj/item/paper/P = new /obj/item/paper(loc) P.info = "
    Security Record

    " - if(istype(active1, /datum/data/record) && data_core.general.Find(active1)) + if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)) P.info += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
    \nSex: [active1.fields["sex"]]
    \nAge: [active1.fields["age"]] @@ -332,7 +338,7 @@
    \nMental Status: [active1.fields["m_stat"]]
    "} else P.info += "General Record Lost!
    " - if(istype(active2, /datum/data/record) && data_core.security.Find(active2)) + if(istype(active2, /datum/data/record) && GLOB.data_core.security.Find(active2)) P.info += {"
    \n
    Security Data

    \nCriminal Status: [active2.fields["criminal"]]
    \n
    \nMinor Crimes: [active2.fields["mi_crim"]] @@ -384,7 +390,7 @@ var/t1 = copytext(trim(sanitize(input("Add Comment:", "Secure. records", null, null) as message)), 1, MAX_MESSAGE_LEN) if(!t1 || ..() || active2 != a2) return 1 - active2.fields["comments"] += "Made by [authenticated] ([rank]) on [current_date_string] [station_time_timestamp()]
    [t1]" + active2.fields["comments"] += "Made by [authenticated] ([rank]) on [GLOB.current_date_string] [station_time_timestamp()]
    [t1]" else if(href_list["del_c"]) var/index = min(max(text2num(href_list["del_c"]) + 1, 1), length(active2.fields["comments"])) @@ -464,12 +470,15 @@ if("criminal") if(istype(active2, /datum/data/record)) var/list/buttons = list() - buttons[++buttons.len] = list("name" = "None", "icon" = "unlock", "href" = "criminal=none", "status" = (active2.fields["criminal"] == "None" ? "selected" : null)) - buttons[++buttons.len] = list("name" = "*Arrest*", "icon" = "lock", "href" = "criminal=arrest", "status" = (active2.fields["criminal"] == "*Arrest*" ? "selected" : null)) - buttons[++buttons.len] = list("name" = "Incarcerated", "icon" = "lock", "href" = "criminal=incarcerated", "status" = (active2.fields["criminal"] == "Incarcerated" ? "selected" : null)) - buttons[++buttons.len] = list("name" = "*Execute*", "icon" = "lock", "href" = "criminal=execute", "status" = (active2.fields["criminal"] == "*Execute*" ? "selected" : null)) - buttons[++buttons.len] = list("name" = "Parolled", "icon" = "unlock-alt", "href" = "criminal=parolled", "status" = (active2.fields["criminal"] == "Parolled" ? "selected" : null)) - buttons[++buttons.len] = list("name" = "Released", "icon" = "unlock", "href" = "criminal=released", "status" = (active2.fields["criminal"] == "Released" ? "selected" : null)) + buttons[++buttons.len] = list("name" = "None", "icon" = "unlock", "href" = "criminal=none", "status" = (active2.fields["criminal"] == SEC_RECORD_STATUS_NONE ? "selected" : null)) + buttons[++buttons.len] = list("name" = "*Arrest*", "icon" = "lock", "href" = "criminal=arrest", "status" = (active2.fields["criminal"] == SEC_RECORD_STATUS_ARREST ? "selected" : null)) + buttons[++buttons.len] = list("name" = "Search", "icon" = "lock", "href" = "criminal=search", "status" = (active2.fields["criminal"] == SEC_RECORD_STATUS_SEARCH ? "selected" : null)) + buttons[++buttons.len] = list("name" = "Monitor", "icon" = "unlock", "href" = "criminal=monitor", "status" = (active2.fields["criminal"] == SEC_RECORD_STATUS_MONITOR ? "selected" : null)) + buttons[++buttons.len] = list("name" = "Demote", "icon" = "lock", "href" = "criminal=demote", "status" = (active2.fields["criminal"] == SEC_RECORD_STATUS_DEMOTE ? "selected" : null)) + buttons[++buttons.len] = list("name" = "Incarcerated", "icon" = "lock", "href" = "criminal=incarcerated", "status" = (active2.fields["criminal"] == SEC_RECORD_STATUS_INCARCERATED ? "selected" : null)) + buttons[++buttons.len] = list("name" = "*Execute*", "icon" = "lock", "href" = "criminal=execute", "status" = (active2.fields["criminal"] == SEC_RECORD_STATUS_EXECUTE ? "selected" : null)) + buttons[++buttons.len] = list("name" = "Parolled", "icon" = "unlock-alt", "href" = "criminal=parolled", "status" = (active2.fields["criminal"] == SEC_RECORD_STATUS_PAROLLED ? "selected" : null)) + buttons[++buttons.len] = list("name" = "Released", "icon" = "unlock", "href" = "criminal=released", "status" = (active2.fields["criminal"] == SEC_RECORD_STATUS_RELEASED ? "selected" : null)) setTemp("

    Criminal Status

    ", buttons) if("rank") var/list/L = list("Head of Personnel", "Captain", "AI") @@ -538,7 +547,7 @@ ..(severity) return - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in GLOB.data_core.security) if(prob(10/severity)) switch(rand(1,6)) if(1) @@ -548,7 +557,7 @@ if(3) R.fields["age"] = rand(5, 85) if(4) - R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released") + R.fields["criminal"] = pick(SEC_RECORD_STATUS_NONE, SEC_RECORD_STATUS_ARREST, SEC_RECORD_STATUS_SEARCH, SEC_RECORD_STATUS_MONITOR, SEC_RECORD_STATUS_DEMOTE, SEC_RECORD_STATUS_INCARCERATED, SEC_RECORD_STATUS_PAROLLED, SEC_RECORD_STATUS_RELEASED) if(5) R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit") if(6) diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index e3c2918f335..b7361db01a3 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -52,7 +52,7 @@ ui = new(user, src, ui_key, "skills_data.tmpl", name, 800, 380) ui.open() -/obj/machinery/computer/skills/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/skills/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["temp"] = temp data["scan"] = scan ? scan.name : null @@ -61,13 +61,13 @@ if(authenticated) switch(screen) if(SKILL_DATA_R_LIST) - if(!isnull(data_core.general)) - for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order)) + if(!isnull(GLOB.data_core.general)) + for(var/datum/data/record/R in sortRecord(GLOB.data_core.general, sortBy, order)) data["records"] += list(list("ref" = "\ref[R]", "id" = R.fields["id"], "name" = R.fields["name"], "rank" = R.fields["rank"], "fingerprint" = R.fields["fingerprint"])) if(SKILL_DATA_RECORD) var/list/general = list() data["general"] = general - if(istype(active1, /datum/data/record) && data_core.general.Find(active1)) + if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)) var/list/fields = list() general["fields"] = fields fields[++fields.len] = list("field" = "Name:", "value" = active1.fields["name"], "name" = "name") @@ -93,7 +93,7 @@ if(..()) return 1 - if(!data_core.general.Find(active1)) + if(!GLOB.data_core.general.Find(active1)) active1 = null if(href_list["temp"]) @@ -103,24 +103,24 @@ var/temp_list = splittext(href_list["temp_action"], "=") switch(temp_list[1]) if("del_all2") - if(PDA_Manifest && PDA_Manifest.len) - PDA_Manifest.Cut() - for(var/datum/data/record/R in data_core.security) + if(GLOB.PDA_Manifest && GLOB.PDA_Manifest.len) + GLOB.PDA_Manifest.Cut() + for(var/datum/data/record/R in GLOB.data_core.security) qdel(R) setTemp("

    All employment records deleted.

    ") if("del_rg2") if(active1) - if(PDA_Manifest && PDA_Manifest.len) - PDA_Manifest.Cut() - for(var/datum/data/record/R in data_core.medical) + if(GLOB.PDA_Manifest && GLOB.PDA_Manifest.len) + GLOB.PDA_Manifest.Cut() + for(var/datum/data/record/R in GLOB.data_core.medical) if(R.fields["name"] == active1.fields["name"] && R.fields["id"] == active1.fields["id"]) qdel(R) QDEL_NULL(active1) screen = SKILL_DATA_R_LIST if("rank") if(active1) - if(PDA_Manifest && PDA_Manifest.len) - PDA_Manifest.Cut() + if(GLOB.PDA_Manifest && GLOB.PDA_Manifest.len) + GLOB.PDA_Manifest.Cut() active1.fields["rank"] = temp_list[2] if(temp_list[2] in GLOB.joblist) active1.fields["real_rank"] = temp_list[2] @@ -182,7 +182,7 @@ else if(href_list["d_rec"]) var/datum/data/record/R = locate(href_list["d_rec"]) - if(!data_core.general.Find(R)) + if(!GLOB.data_core.general.Find(R)) setTemp("

    Record not found!

    ") return 1 active1 = R @@ -202,8 +202,8 @@ setTemp("

    Are you sure you wish to delete the record (ALL)?

    ", buttons) else if(href_list["new_g"]) - if(PDA_Manifest.len) - PDA_Manifest.Cut() + if(GLOB.PDA_Manifest.len) + GLOB.PDA_Manifest.Cut() var/datum/data/record/G = new /datum/data/record() G.fields["name"] = "New Record" G.fields["id"] = "[add_zero(num2hex(rand(1, 1.6777215E7)), 6)]" @@ -215,7 +215,7 @@ G.fields["p_stat"] = "Active" G.fields["m_stat"] = "Stable" G.fields["species"] = "Human" - data_core.general += G + GLOB.data_core.general += G active1 = G else if(href_list["print_r"]) @@ -225,7 +225,7 @@ sleep(50) var/obj/item/paper/P = new /obj/item/paper(loc) P.info = "
    Employment Record

    " - if(istype(active1, /datum/data/record) && data_core.general.Find(active1)) + if(istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)) P.info += {"Name: [active1.fields["name"]] ID: [active1.fields["id"]]
    \nSex: [active1.fields["sex"]]
    \nAge: [active1.fields["age"]] @@ -300,7 +300,7 @@ ..(severity) return - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in GLOB.data_core.security) if(prob(10/severity)) switch(rand(1,6)) if(1) @@ -310,7 +310,7 @@ if(3) R.fields["age"] = rand(5, 85) if(4) - R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released") + R.fields["criminal"] = pick(SEC_RECORD_STATUS_NONE, SEC_RECORD_STATUS_ARREST, SEC_RECORD_STATUS_INCARCERATED, SEC_RECORD_STATUS_PAROLLED, SEC_RECORD_STATUS_RELEASED) if(5) R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit") if(6) diff --git a/code/game/machinery/computer/specops_shuttle.dm b/code/game/machinery/computer/specops_shuttle.dm index 23658a3e939..f509ee42d34 100644 --- a/code/game/machinery/computer/specops_shuttle.dm +++ b/code/game/machinery/computer/specops_shuttle.dm @@ -4,12 +4,12 @@ #define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock #define SPECOPS_RETURN_DELAY 6000 //Time between the shuttle is capable of moving. -var/specops_shuttle_moving_to_station = 0 -var/specops_shuttle_moving_to_centcom = 0 -var/specops_shuttle_at_station = 0 -var/specops_shuttle_can_send = 1 -var/specops_shuttle_time = 0 -var/specops_shuttle_timeleft = 0 +GLOBAL_VAR_INIT(specops_shuttle_moving_to_station, 0) +GLOBAL_VAR_INIT(specops_shuttle_moving_to_centcom, 0) +GLOBAL_VAR_INIT(specops_shuttle_at_station, 0) +GLOBAL_VAR_INIT(specops_shuttle_can_send, 1) +GLOBAL_VAR_INIT(specops_shuttle_time, 0) +GLOBAL_VAR_INIT(specops_shuttle_timeleft, 0) /obj/machinery/computer/specops_shuttle name = "\improper Spec. Ops. shuttle console" @@ -33,16 +33,16 @@ var/specops_shuttle_timeleft = 0 if(announcer) announcer.autosay(message, "A.L.I.C.E.", "Response Team", list(1,2)) - while(specops_shuttle_time - world.timeofday > 0) - var/ticksleft = specops_shuttle_time - world.timeofday + while(GLOB.specops_shuttle_time - world.timeofday > 0) + var/ticksleft = GLOB.specops_shuttle_time - world.timeofday if(ticksleft > 1e5) - specops_shuttle_time = world.timeofday + 10 // midnight rollover - specops_shuttle_timeleft = (ticksleft / 10) + GLOB.specops_shuttle_time = world.timeofday + 10 // midnight rollover + GLOB.specops_shuttle_timeleft = (ticksleft / 10) //All this does is announce the time before launch. if(announcer) - var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. + var/rounded_time_left = round(GLOB.specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. if(rounded_time_left in message_tracker)//If that time is in the list for message announce. message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\"" if(rounded_time_left==0) @@ -53,10 +53,10 @@ var/specops_shuttle_timeleft = 0 sleep(5) - specops_shuttle_moving_to_station = 0 - specops_shuttle_moving_to_centcom = 0 + GLOB.specops_shuttle_moving_to_station = 0 + GLOB.specops_shuttle_moving_to_centcom = 0 - specops_shuttle_at_station = 1 + GLOB.specops_shuttle_at_station = 1 var/area/start_location = locate(/area/shuttle/specops/station) var/area/end_location = locate(/area/shuttle/specops/centcom) @@ -91,7 +91,7 @@ var/specops_shuttle_timeleft = 0 var/mob/M = locate(/mob) in T to_chat(M, "You have arrived at Central Command. Operation has ended!") - specops_shuttle_at_station = 0 + GLOB.specops_shuttle_at_station = 0 for(var/obj/machinery/computer/specops_shuttle/S in world) S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY @@ -110,16 +110,16 @@ var/specops_shuttle_timeleft = 0 //message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" //announcer.autosay(message, "A.L.I.C.E.", "Response Team") - while(specops_shuttle_time - world.timeofday > 0) - var/ticksleft = specops_shuttle_time - world.timeofday + while(GLOB.specops_shuttle_time - world.timeofday > 0) + var/ticksleft = GLOB.specops_shuttle_time - world.timeofday if(ticksleft > 1e5) - specops_shuttle_time = world.timeofday + 10 // midnight rollover - specops_shuttle_timeleft = (ticksleft / 10) + GLOB.specops_shuttle_time = world.timeofday + 10 // midnight rollover + GLOB.specops_shuttle_timeleft = (ticksleft / 10) //All this does is announce the time before launch. if(announcer) - var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. + var/rounded_time_left = round(GLOB.specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions. if(rounded_time_left in message_tracker)//If that time is in the list for message announce. message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\"" if(rounded_time_left==0) @@ -130,11 +130,11 @@ var/specops_shuttle_timeleft = 0 sleep(5) - specops_shuttle_moving_to_station = 0 - specops_shuttle_moving_to_centcom = 0 + GLOB.specops_shuttle_moving_to_station = 0 + GLOB.specops_shuttle_moving_to_centcom = 0 - specops_shuttle_at_station = 1 - if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return + GLOB.specops_shuttle_at_station = 1 + if(GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom) return if(!specops_can_move()) to_chat(usr, "The Special Operations shuttle is unable to leave.") @@ -239,7 +239,7 @@ var/specops_shuttle_timeleft = 0 qdel(announcer) /proc/specops_can_move() - if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) + if(GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom) return 0 for(var/obj/machinery/computer/specops_shuttle/S in world) if(world.timeofday <= S.specops_shuttle_timereset) @@ -275,8 +275,8 @@ var/specops_shuttle_timeleft = 0 dat = temp else dat += {"
    Special Operations Shuttle
    - \nLocation: [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name()] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]
    - [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
    \n
    ":specops_shuttle_at_station ? "\nShuttle standing by...
    \n
    ":"\nDepart to [station_name()]
    \n
    "] + \nLocation: [GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom ? "Departing for [station_name()] in ([GLOB.specops_shuttle_timeleft] seconds.)":GLOB.specops_shuttle_at_station ? "Station":"Dock"]
    + [GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*
    \n
    ":GLOB.specops_shuttle_at_station ? "\nShuttle standing by...
    \n
    ":"\nDepart to [station_name()]
    \n
    "] \nClose"} user << browse(dat, "window=computer;size=575x450") @@ -291,7 +291,7 @@ var/specops_shuttle_timeleft = 0 usr.machine = src if(href_list["sendtodock"]) - if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return + if(!GLOB.specops_shuttle_at_station|| GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom) return if(!specops_can_move()) to_chat(usr, "Central Command will not allow the Special Operations shuttle to return yet.") @@ -306,13 +306,13 @@ var/specops_shuttle_timeleft = 0 temp += "Shuttle departing.

    OK" updateUsrDialog() - specops_shuttle_moving_to_centcom = 1 - specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME + GLOB.specops_shuttle_moving_to_centcom = 1 + GLOB.specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME spawn(0) specops_return() else if(href_list["sendtostation"]) - if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return + if(GLOB.specops_shuttle_at_station || GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom) return if(!specops_can_move()) to_chat(usr, "The Special Operations shuttle is unable to leave.") @@ -326,9 +326,9 @@ var/specops_shuttle_timeleft = 0 var/area/centcom/specops/special_ops = locate() if(special_ops) special_ops.readyalert()//Trigger alarm for the spec ops area. - specops_shuttle_moving_to_station = 1 + GLOB.specops_shuttle_moving_to_station = 1 - specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME + GLOB.specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME spawn(0) specops_process() diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index fb630d7a251..607918442ea 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -20,7 +20,7 @@ /obj/machinery/computer/station_alert/New() ..() alarm_monitor = new monitor_type(src) - alarm_monitor.register(src, /obj/machinery/computer/station_alert/update_icon) + alarm_monitor.register(src, /obj/machinery/computer/station_alert/.proc/update_icon) /obj/machinery/computer/station_alert/Destroy() alarm_monitor.unregister(src) diff --git a/code/game/machinery/computer/store.dm b/code/game/machinery/computer/store.dm index f49d91c53b3..856e2322f71 100644 --- a/code/game/machinery/computer/store.dm +++ b/code/game/machinery/computer/store.dm @@ -102,11 +102,11 @@ th.cost.toomuch {background:maroon;} "} - for(var/datum/storeitem/item in centcomm_store.items) + for(var/datum/storeitem/item in GLOB.centcomm_store.items) var/cost_class="affordable" if(item.cost>balance) cost_class="toomuch" - var/itemID=centcomm_store.items.Find(item) + var/itemID=GLOB.centcomm_store.items.Find(item) var/row_color="light" if(itemID%2 == 0) row_color="dark" @@ -143,7 +143,7 @@ th.cost.toomuch {background:maroon;} if(href_list["buy"]) var/itemID = text2num(href_list["buy"]) - var/datum/storeitem/item = centcomm_store.items[itemID] + var/datum/storeitem/item = GLOB.centcomm_store.items[itemID] var/sure = alert(usr,"Are you sure you wish to purchase [item.name] for $[item.cost]?","You sure?","Yes","No") in list("Yes","No") if(!Adjacent(usr)) to_chat(usr, "You are not close enough to do that.") @@ -151,7 +151,7 @@ th.cost.toomuch {background:maroon;} if(sure=="No") updateUsrDialog() return - if(!centcomm_store.PlaceOrder(usr,itemID)) + if(!GLOB.centcomm_store.PlaceOrder(usr,itemID)) to_chat(usr, "Unable to charge your account.") else to_chat(usr, "You've successfully purchased the item. It should be in your hands or on the floor.") diff --git a/code/game/machinery/computer/syndicate_specops_shuttle.dm b/code/game/machinery/computer/syndicate_specops_shuttle.dm index aefeaaa864b..0a65b6be408 100644 --- a/code/game/machinery/computer/syndicate_specops_shuttle.dm +++ b/code/game/machinery/computer/syndicate_specops_shuttle.dm @@ -3,12 +3,12 @@ #define SYNDICATE_ELITE_STATION_AREATYPE "/area/shuttle/syndicate_elite/station" //Type of the spec ops shuttle area for station #define SYNDICATE_ELITE_DOCK_AREATYPE "/area/shuttle/syndicate_elite/mothership" //Type of the spec ops shuttle area for dock -var/syndicate_elite_shuttle_moving_to_station = 0 -var/syndicate_elite_shuttle_moving_to_mothership = 0 -var/syndicate_elite_shuttle_at_station = 0 -var/syndicate_elite_shuttle_can_send = 1 -var/syndicate_elite_shuttle_time = 0 -var/syndicate_elite_shuttle_timeleft = 0 +GLOBAL_VAR_INIT(syndicate_elite_shuttle_moving_to_station, 0) +GLOBAL_VAR_INIT(syndicate_elite_shuttle_moving_to_mothership, 0) +GLOBAL_VAR_INIT(syndicate_elite_shuttle_at_station, 0) +GLOBAL_VAR_INIT(syndicate_elite_shuttle_can_send, 1) +GLOBAL_VAR_INIT(syndicate_elite_shuttle_time, 0) +GLOBAL_VAR_INIT(syndicate_elite_shuttle_timeleft, 0) /obj/machinery/computer/syndicate_elite_shuttle name = "\improper Elite Syndicate Squad shuttle console" @@ -33,16 +33,16 @@ var/syndicate_elite_shuttle_timeleft = 0 // message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" // announcer.say(message) - while(syndicate_elite_shuttle_time - world.timeofday > 0) - var/ticksleft = syndicate_elite_shuttle_time - world.timeofday + while(GLOB.syndicate_elite_shuttle_time - world.timeofday > 0) + var/ticksleft = GLOB.syndicate_elite_shuttle_time - world.timeofday if(ticksleft > 1e5) - syndicate_elite_shuttle_time = world.timeofday // midnight rollover - syndicate_elite_shuttle_timeleft = (ticksleft / 10) + GLOB.syndicate_elite_shuttle_time = world.timeofday // midnight rollover + GLOB.syndicate_elite_shuttle_timeleft = (ticksleft / 10) //All this does is announce the time before launch. if(announcer) - var/rounded_time_left = round(syndicate_elite_shuttle_timeleft)//Round time so that it will report only once, not in fractions. + var/rounded_time_left = round(GLOB.syndicate_elite_shuttle_timeleft)//Round time so that it will report only once, not in fractions. if(rounded_time_left in message_tracker)//If that time is in the list for message announce. message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN" if(rounded_time_left==0) @@ -53,11 +53,11 @@ var/syndicate_elite_shuttle_timeleft = 0 sleep(5) - syndicate_elite_shuttle_moving_to_station = 0 - syndicate_elite_shuttle_moving_to_mothership = 0 + GLOB.syndicate_elite_shuttle_moving_to_station = 0 + GLOB.syndicate_elite_shuttle_moving_to_mothership = 0 - syndicate_elite_shuttle_at_station = 1 - if(syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return + GLOB.syndicate_elite_shuttle_at_station = 1 + if(GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership) return if(!syndicate_elite_can_move()) to_chat(usr, "The Syndicate Elite shuttle is unable to leave.") @@ -174,7 +174,7 @@ var/syndicate_elite_shuttle_timeleft = 0 to_chat(M, "You have arrived to [station_name()]. Commence operation!") /proc/syndicate_elite_can_move() - if(syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return 0 + if(GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership) return 0 else return 1 /obj/machinery/computer/syndicate_elite_shuttle/attack_ai(var/mob/user as mob) @@ -205,8 +205,8 @@ var/syndicate_elite_shuttle_timeleft = 0 dat = temp else dat = {"
    Special Operations Shuttle
    - \nLocation: [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "Departing for [station_name()] in ([syndicate_elite_shuttle_timeleft] seconds.)":syndicate_elite_shuttle_at_station ? "Station":"Dock"]
    - [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "\n*The Syndicate Elite shuttle is already leaving.*
    \n
    ":syndicate_elite_shuttle_at_station ? "\nShuttle Offline
    \n
    ":"\nDepart to [station_name()]
    \n
    "] + \nLocation: [GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership ? "Departing for [station_name()] in ([GLOB.syndicate_elite_shuttle_timeleft] seconds.)":GLOB.syndicate_elite_shuttle_at_station ? "Station":"Dock"]
    + [GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership ? "\n*The Syndicate Elite shuttle is already leaving.*
    \n
    ":GLOB.syndicate_elite_shuttle_at_station ? "\nShuttle Offline
    \n
    ":"\nDepart to [station_name()]
    \n
    "] \nClose"} user << browse(dat, "window=computer;size=575x450") @@ -221,13 +221,13 @@ var/syndicate_elite_shuttle_timeleft = 0 usr.set_machine(src) if(href_list["sendtodock"]) - if(!syndicate_elite_shuttle_at_station|| syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return + if(!GLOB.syndicate_elite_shuttle_at_station|| GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership) return to_chat(usr, "The Syndicate will not allow the Elite Squad shuttle to return.") return else if(href_list["sendtostation"]) - if(syndicate_elite_shuttle_at_station || syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return + if(GLOB.syndicate_elite_shuttle_at_station || GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership) return if(!specops_can_move()) to_chat(usr, "The Syndicate Elite shuttle is unable to leave.") @@ -241,9 +241,9 @@ var/syndicate_elite_shuttle_timeleft = 0 var/area/syndicate_mothership/elite_squad/elite_squad = locate() if(elite_squad) elite_squad.readyalert()//Trigger alarm for the spec ops area. - syndicate_elite_shuttle_moving_to_station = 1 + GLOB.syndicate_elite_shuttle_moving_to_station = 1 - syndicate_elite_shuttle_time = world.timeofday + SYNDICATE_ELITE_MOVETIME + GLOB.syndicate_elite_shuttle_time = world.timeofday + SYNDICATE_ELITE_MOVETIME spawn(0) syndicate_elite_process() diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm index efee10767ba..96863c3e54d 100644 --- a/code/game/machinery/constructable_frame.dm +++ b/code/game/machinery/constructable_frame.dm @@ -218,7 +218,7 @@ //Machine Frame Circuit Boards /*Common Parts: Parts List: Ignitor, Timer, Infra-red laser, Infra-red sensor, t_scanner, Capacitor, Valve, sensor unit, -micro-manipulator, console screen, beaker, Microlaser, matter bin, power cells. +micro-manipulator, glass sheets, beaker, Microlaser, matter bin, power cells. Note: Once everything is added to the public areas, will add MAT_METAL and MAT_GLASS to circuit boards since autolathe won't be able to destroy them and players will be able to make replacements. */ @@ -226,7 +226,6 @@ to destroy them and players will be able to make replacements. name = "circuit board (Booze-O-Mat Vendor)" board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Resupply Canister." build_path = /obj/machinery/vending/boozeomat req_components = list(/obj/item/vending_refill/boozeomat = 1) @@ -282,7 +281,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/smes board_type = "machine" origin_tech = "programming=3;powerstorage=3;engineering=3" - frame_desc = "Requires 5 pieces of cable, 5 Power Cells and 1 Capacitor." req_components = list( /obj/item/stack/cable_coil = 5, /obj/item/stock_parts/cell = 5, @@ -321,7 +319,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/atmospherics/unary/cold_sink/freezer board_type = "machine" origin_tech = "programming=3;plasmatech=3" - frame_desc = "Requires 2 Matter Bins, 2 Micro Lasers, 1 piece of cable and 1 Console Screen." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/micro_laser = 2, @@ -346,7 +343,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/recharger board_type = "machine" origin_tech = "powerstorage=3;materials=2" - frame_desc = "Requires 1 Capacitor" req_components = list(/obj/item/stock_parts/capacitor = 1) /obj/item/circuitboard/snow_machine @@ -354,7 +350,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/snow_machine board_type = "machine" origin_tech = "programming=2;materials=2" - frame_desc = "Requires 1 Matter Bin and 1 Micro Laser." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/micro_laser = 1) @@ -364,7 +359,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/biogenerator board_type = "machine" origin_tech = "programming=2;biotech=3;materials=3" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 1 Console Screen." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -376,7 +370,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/plantgenes board_type = "machine" origin_tech = "programming=3;biotech=3" - frame_desc = "Requires 1 Manipulator, 1 Micro Laser, 1 Console Screen, and 1 Scanning Module." req_components = list( /obj/item/stock_parts/manipulator = 1, /obj/item/stock_parts/micro_laser = 1, @@ -390,7 +383,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/seed_extractor board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 1 Matter Bin and 1 Manipulator." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1) @@ -400,7 +392,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/hydroponics/constructable board_type = "machine" origin_tech = "programming=1;biotech=2" - frame_desc = "Requires 2 Matter Bins, 1 Manipulator, and 1 Console Screen." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 1, @@ -411,7 +402,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/microwave board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 1 Micro Laser, 2 pieces of cable and 1 Console Screen." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stack/cable_coil = 2, @@ -422,7 +412,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/oven board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Console Screen." req_components = list( /obj/item/stock_parts/micro_laser = 2, /obj/item/stack/cable_coil = 5, @@ -433,7 +422,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/grill board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 2 Micro Lasers, 5 pieces of cable and 1 Console Screen." req_components = list( /obj/item/stock_parts/micro_laser = 2, /obj/item/stack/cable_coil = 5, @@ -444,7 +432,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/kitchen_machine/candy_maker board_type = "machine" origin_tech = "programming=2;magnets=2" - frame_desc = "Requires 1 Manipulator, 5 pieces of cable and 1 Console Screen." req_components = list( /obj/item/stock_parts/manipulator = 1, /obj/item/stack/cable_coil = 5, @@ -455,7 +442,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/cooker/deepfryer board_type = "machine" origin_tech = "programming=1" - frame_desc = "Requires 2 Micro Lasers and 5 pieces of cable." req_components = list( /obj/item/stock_parts/micro_laser = 2, /obj/item/stack/cable_coil = 5) @@ -568,7 +554,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/chem_dispenser board_type = "machine" origin_tech = "materials=4;programming=4;plasmatech=4;biotech=3" - frame_desc = "Requires 2 Matter Bins, 1 Capacitor, 1 Manipulator, 1 Console Screen, and 1 Power Cell." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/capacitor = 1, /obj/item/stock_parts/manipulator = 1, @@ -609,7 +594,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/chem_heater board_type = "machine" origin_tech = "programming=2;engineering=2;biotech=2" - frame_desc = "Requires 1 Micro Laser and 1 Console Screen." req_components = list( /obj/item/stock_parts/micro_laser = 1, /obj/item/stack/sheet/glass = 1) @@ -619,7 +603,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/reagentgrinder/empty board_type = "machine" origin_tech = "materials=2;engineering=2;biotech=2" - frame_desc = "Requires 2 Manipulators and 1 Matter Bin." req_components = list( /obj/item/stock_parts/manipulator = 2, /obj/item/stock_parts/matter_bin = 1) @@ -640,7 +623,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/destructive_analyzer board_type = "machine" origin_tech = "magnets=2;engineering=2;programming=2" - frame_desc = "Requires 1 Scanning Module, 1 Manipulator, and 1 Micro-Laser." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stock_parts/manipulator = 1, @@ -651,7 +633,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/autolathe board_type = "machine" origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 3 Matter Bins, 1 Manipulator, and 1 Console Screen." req_components = list( /obj/item/stock_parts/matter_bin = 3, /obj/item/stock_parts/manipulator = 1, @@ -662,7 +643,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/protolathe board_type = "machine" origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 2 Matter Bins, 2 Manipulators, and 2 Beakers." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 2, @@ -681,7 +661,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/circuit_imprinter board_type = "machine" origin_tech = "engineering=2;programming=2" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, and 2 Beakers." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -692,7 +671,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/power/port_gen/pacman board_type = "machine" origin_tech = "programming=2;powerstorage=3;plasmatech=3;engineering=3" - frame_desc = "Requires 1 Matter Bin, 1 Micro-Laser, 2 Pieces of Cable, and 1 Capacitor." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/micro_laser = 1, @@ -714,7 +692,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/r_n_d/server board_type = "machine" origin_tech = "programming=3" - frame_desc = "Requires 2 pieces of cable, and 1 Scanning Module." req_components = list( /obj/item/stack/cable_coil = 2, /obj/item/stock_parts/scanning_module = 1) @@ -724,7 +701,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mecha_part_fabricator board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Matter Bins, 1 Manipulator, 1 Micro-Laser and 1 Console Screen." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 1, @@ -736,7 +712,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mecha_part_fabricator/spacepod board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Matter Bins, 1 Manipulators, 1 Micro-Lasers, and 1 Console Screen." req_components = list( /obj/item/stock_parts/matter_bin = 2, /obj/item/stock_parts/manipulator = 1, @@ -749,7 +724,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/clonepod board_type = "machine" origin_tech = "programming=2;biotech=2" - frame_desc = "Requires 2 Manipulator, 2 Scanning Module, 2 pieces of cable and 1 Console Screen." req_components = list( /obj/item/stack/cable_coil = 2, /obj/item/stock_parts/scanning_module = 2, @@ -761,7 +735,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/dna_scannernew board_type = "machine" origin_tech = "programming=2;biotech=2" - frame_desc = "Requires 1 Scanning Module, 1 Manipulator, 1 Micro-Laser, 2 pieces of cable and 1 Console Screen." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stock_parts/manipulator = 1, @@ -774,7 +747,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/mech_bay_recharge_port board_type = "machine" origin_tech = "programming=3;powerstorage=3;engineering=3" - frame_desc = "Requires 1 piece of cable and 5 Capacitors." req_components = list( /obj/item/stack/cable_coil = 1, /obj/item/stock_parts/capacitor = 5) @@ -784,7 +756,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/teleport/hub board_type = "machine" origin_tech = "programming=3;engineering=4;bluespace=4;materials=4" - frame_desc = "Requires 3 Bluespace Crystals and 1 Matter Bin." req_components = list( /obj/item/stack/ore/bluespace_crystal = 3, /obj/item/stock_parts/matter_bin = 1) @@ -794,7 +765,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/teleport/station board_type = "machine" origin_tech = "programming=4;engineering=4;bluespace=4;plasmatech=3" - frame_desc = "Requires 2 Bluespace Crystals, 2 Capacitors and 1 Console Screen." req_components = list( /obj/item/stack/ore/bluespace_crystal = 2, /obj/item/stock_parts/capacitor = 2, @@ -805,7 +775,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/teleport/perma board_type = "machine" origin_tech = "programming=3;engineering=4;bluespace=4;materials=4" - frame_desc = "Requires 3 Bluespace Crystals and 1 Matter Bin." req_components = list( /obj/item/stack/ore/bluespace_crystal = 3, /obj/item/stock_parts/matter_bin = 1) @@ -825,7 +794,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/telepad board_type = "machine" origin_tech = "programming=4;engineering=3;plasmatech=4;bluespace=4" - frame_desc = "Requires 2 Bluespace Crystals, 1 Capacitor, 1 piece of cable and 1 Console Screen." req_components = list( /obj/item/stack/ore/bluespace_crystal = 2, /obj/item/stock_parts/capacitor = 1, @@ -837,7 +805,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/quantumpad board_type = "machine" origin_tech = "programming=3;engineering=3;plasmatech=3;bluespace=4" - frame_desc = "Requires 1 Bluespace Crystal, 1 Capacitor, 1 piece of cable and 1 Manipulator." req_components = list( /obj/item/stack/ore/bluespace_crystal = 1, /obj/item/stock_parts/capacitor = 1, @@ -849,7 +816,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/sleeper board_type = "machine" origin_tech = "programming=3;biotech=2;engineering=3" - frame_desc = "Requires 1 Matter Bin, 1 Manipulator, 1 piece of cable and 2 Console Screens." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stock_parts/manipulator = 1, @@ -870,7 +836,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/bodyscanner board_type = "machine" origin_tech = "programming=3;biotech=2;engineering=3" - frame_desc = "Requires 1 Scanning Module, 2 pieces of cable and 2 Console Screens." req_components = list( /obj/item/stock_parts/scanning_module = 1, /obj/item/stack/cable_coil = 2, @@ -881,7 +846,6 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/atmospherics/unary/cryo_cell board_type = "machine" origin_tech = "programming=4;biotech=3;engineering=4;plasmatech=3" - frame_desc = "Requires 1 Matter Bin, 1 piece of cable and 4 Console Screens." req_components = list( /obj/item/stock_parts/matter_bin = 1, /obj/item/stack/cable_coil = 1, @@ -892,96 +856,26 @@ to destroy them and players will be able to make replacements. build_path = /obj/machinery/recharge_station board_type = "machine" origin_tech = "powerstorage=3;engineering=3" - frame_desc = "Requires 2 Capacitors, 1 Power Cell and 1 Manipulator." req_components = list( /obj/item/stock_parts/capacitor = 2, /obj/item/stock_parts/cell = 1, /obj/item/stock_parts/manipulator = 1) // Telecomms circuit boards: -/obj/item/circuitboard/telecomms/receiver - name = "Circuit Board (Subspace Receiver)" - build_path = /obj/machinery/telecomms/receiver - board_type = "machine" - origin_tech = "programming=2;engineering=2;bluespace=1" - frame_desc = "Requires 1 Subspace Ansible, 1 Hyperwave Filter, 2 Manipulators, and 1 Micro-Laser." - req_components = list( - /obj/item/stock_parts/subspace/ansible = 1, - /obj/item/stock_parts/subspace/filter = 1, - /obj/item/stock_parts/manipulator = 2, - /obj/item/stock_parts/micro_laser = 1) - -/obj/item/circuitboard/telecomms/hub - name = "Circuit Board (Hub Mainframe)" - build_path = /obj/machinery/telecomms/hub - board_type = "machine" - origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Manipulators, 2 Cable Coil and 2 Hyperwave Filter." - req_components = list( - /obj/item/stock_parts/manipulator = 2, - /obj/item/stack/cable_coil = 2, - /obj/item/stock_parts/subspace/filter = 2) - -/obj/item/circuitboard/telecomms/relay - name = "Circuit Board (Relay Mainframe)" - build_path = /obj/machinery/telecomms/relay +/obj/item/circuitboard/tcomms/relay + name = "Circuit Board (Telecommunications Relay)" + build_path = /obj/machinery/tcomms/relay board_type = "machine" origin_tech = "programming=2;engineering=2;bluespace=2" - frame_desc = "Requires 2 Manipulators, 2 Cable Coil and 2 Hyperwave Filters." - req_components = list( - /obj/item/stock_parts/manipulator = 2, - /obj/item/stack/cable_coil = 2, - /obj/item/stock_parts/subspace/filter = 2) + req_components = list(/obj/item/stock_parts/manipulator = 2, /obj/item/stack/cable_coil = 2) -/obj/item/circuitboard/telecomms/bus - name = "Circuit Board (Bus Mainframe)" - build_path = /obj/machinery/telecomms/bus +/obj/item/circuitboard/tcomms/core + name = "Circuit Board (Telecommunications Core)" + build_path = /obj/machinery/tcomms/core board_type = "machine" origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Manipulators, 1 Cable Coil and 1 Hyperwave Filter." - req_components = list( - /obj/item/stock_parts/manipulator = 2, - /obj/item/stack/cable_coil = 1, - /obj/item/stock_parts/subspace/filter = 1) - -/obj/item/circuitboard/telecomms/processor - name = "Circuit Board (Processor Unit)" - build_path = /obj/machinery/telecomms/processor - board_type = "machine" - origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 3 Manipulators, 1 Hyperwave Filter, 2 Treatment Disks, 1 Wavelength Analyzer, 2 Cable Coils and 1 Subspace Amplifier." - req_components = list( - /obj/item/stock_parts/manipulator = 3, - /obj/item/stock_parts/subspace/filter = 1, - /obj/item/stock_parts/subspace/treatment = 2, - /obj/item/stock_parts/subspace/analyzer = 1, - /obj/item/stack/cable_coil = 2, - /obj/item/stock_parts/subspace/amplifier = 1) - -/obj/item/circuitboard/telecomms/server - name = "Circuit Board (Telecommunication Server)" - build_path = /obj/machinery/telecomms/server - board_type = "machine" - origin_tech = "programming=2;engineering=2" - frame_desc = "Requires 2 Manipulators, 1 Cable Coil and 1 Hyperwave Filter." - req_components = list( - /obj/item/stock_parts/manipulator = 2, - /obj/item/stack/cable_coil = 1, - /obj/item/stock_parts/subspace/filter = 1) - -/obj/item/circuitboard/telecomms/broadcaster - name = "Circuit Board (Subspace Broadcaster)" - build_path = /obj/machinery/telecomms/broadcaster - board_type = "machine" - origin_tech = "programming=2;engineering=2;bluespace=1" - frame_desc = "Requires 2 Manipulators, 1 Cable Coil, 1 Hyperwave Filter, 1 Ansible Crystal and 2 High-Powered Micro-Lasers. " - req_components = list( - /obj/item/stock_parts/manipulator = 2, - /obj/item/stack/cable_coil = 1, - /obj/item/stock_parts/subspace/filter = 1, - /obj/item/stock_parts/subspace/crystal = 1, - /obj/item/stock_parts/micro_laser/high = 2) - + req_components = list(/obj/item/stock_parts/manipulator = 2, /obj/item/stack/cable_coil = 2) +// End telecomms circuit boards /obj/item/circuitboard/ore_redemption name = "circuit board (Ore Redemption)" build_path = /obj/machinery/mineral/ore_redemption @@ -1050,7 +944,6 @@ to destroy them and players will be able to make replacements. board_type = "machine" origin_tech = "programming=1" //This stuff is pretty much the absolute basis of programming, so it's mostly useless for research req_components = list(/obj/item/stack/cable_coil = 1) - var/list/names_paths = list( "NOT Gate" = /obj/machinery/logic_gate/not, "OR Gate" = /obj/machinery/logic_gate/or, diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index 3ce6a8702f5..c7dc139446a 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -1,3 +1,6 @@ +#define AUTO_EJECT_DEAD (1<<0) +#define AUTO_EJECT_HEALTHY (1<<1) + /obj/machinery/atmospherics/unary/cryo_cell name = "cryo cell" desc = "Lowers the body temperature so certain medications may take effect." @@ -10,11 +13,12 @@ interact_offline = 1 max_integrity = 350 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 30, "acid" = 30) - var/on = 0 + var/on = FALSE var/temperature_archived var/mob/living/carbon/occupant = null var/obj/item/reagent_containers/glass/beaker = null - var/autoeject = 0 + /// Holds two bitflags, AUTO_EJECT_DEAD and AUTO_EJECT_HEALTHY. Used to determine if the cryo cell will auto-eject dead and/or completely health patients. + var/auto_eject_prefs = NONE var/next_trans = 0 var/current_heat_capacity = 50 @@ -68,7 +72,7 @@ /obj/machinery/atmospherics/unary/cryo_cell/atmos_init() ..() if(node) return - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) node = findConnecting(cdir) if(node) break @@ -139,18 +143,20 @@ /obj/machinery/atmospherics/unary/cryo_cell/process() ..() - if(autoeject) - if(occupant) - if(!occupant.has_organic_damage() && !occupant.has_mutated_organs()) - on = 0 - go_out() - playsound(src.loc, 'sound/machines/ding.ogg', 50, 1) + if(!occupant) + return + + if((auto_eject_prefs & AUTO_EJECT_DEAD) && occupant.stat == DEAD) + auto_eject(AUTO_EJECT_DEAD) + return + if((auto_eject_prefs & AUTO_EJECT_HEALTHY) && !occupant.has_organic_damage() && !occupant.has_mutated_organs()) + auto_eject(AUTO_EJECT_HEALTHY) + return if(air_contents) - if(occupant) - process_occupant() + process_occupant() - return 1 + return TRUE /obj/machinery/atmospherics/unary/cryo_cell/process_atmos() ..() @@ -208,13 +214,13 @@ if(!ui) // the ui does not exist, so we'll create a new() one // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "cryo.tmpl", "Cryo Cell Control System", 520, 420) + ui = new(user, src, ui_key, "cryo.tmpl", "Cryo Cell Control System", 520, 480) // open the new ui window ui.open() // auto update every Master Controller tick ui.set_auto_update(1) -/obj/machinery/atmospherics/unary/cryo_cell/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/atmospherics/unary/cryo_cell/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["isOperating"] = on data["hasOccupant"] = occupant ? 1 : 0 @@ -249,7 +255,8 @@ for(var/datum/reagent/R in beaker.reagents.reagent_list) data["beakerVolume"] += R.volume - data["autoeject"] = autoeject + data["auto_eject_healthy"] = (auto_eject_prefs & AUTO_EJECT_HEALTHY) ? TRUE : FALSE + data["auto_eject_dead"] = (auto_eject_prefs & AUTO_EJECT_DEAD) ? TRUE : FALSE return data /obj/machinery/atmospherics/unary/cryo_cell/Topic(href, href_list) @@ -260,18 +267,24 @@ return 0 // don't update UIs attached to this object if(href_list["switchOn"]) - on = 1 + on = TRUE update_icon() if(href_list["switchOff"]) - on = 0 + on = FALSE update_icon() - if(href_list["autoejectOn"]) - autoeject = 1 + if(href_list["auto_eject_healthy_on"]) + auto_eject_prefs |= AUTO_EJECT_HEALTHY - if(href_list["autoejectOff"]) - autoeject = 0 + if(href_list["auto_eject_healthy_off"]) + auto_eject_prefs &= ~AUTO_EJECT_HEALTHY + + if(href_list["auto_eject_dead_on"]) + auto_eject_prefs |= AUTO_EJECT_DEAD + + if(href_list["auto_eject_dead_off"]) + auto_eject_prefs &= ~AUTO_EJECT_DEAD if(href_list["ejectBeaker"]) if(beaker) @@ -430,6 +443,16 @@ for(var/atom/movable/A in contents - component_parts - list(beaker)) A.forceMove(get_step(loc, SOUTH)) +/// Called when either the occupant is dead and the AUTO_EJECT_DEAD flag is present, OR the occupant is alive, has no external damage, and the AUTO_EJECT_HEALTHY flag is present. +/obj/machinery/atmospherics/unary/cryo_cell/proc/auto_eject(eject_flag) + on = FALSE + go_out() + switch(eject_flag) + if(AUTO_EJECT_HEALTHY) + playsound(loc, 'sound/machines/ding.ogg', 50, 1) + if(AUTO_EJECT_DEAD) + playsound(loc, 'sound/machines/buzz-sigh.ogg', 40) + /obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob) if(!istype(M)) to_chat(usr, "The cryo cell cannot handle such a lifeform!") @@ -510,8 +533,17 @@ /datum/data/function/proc/display() return -/obj/machinery/atmospherics/components/unary/cryo_cell/get_remote_view_fullscreens(mob/user) +/obj/machinery/atmospherics/unary/cryo_cell/get_remote_view_fullscreens(mob/user) user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 1) -/obj/machinery/atmospherics/components/unary/cryo_cell/update_remote_sight(mob/living/user) +/obj/machinery/atmospherics/unary/cryo_cell/update_remote_sight(mob/living/user) return //we don't see the pipe network while inside cryo. + +/obj/machinery/atmospherics/unary/cryo_cell/can_crawl_through() + return // can't ventcrawl in or out of cryo. + +/obj/machinery/atmospherics/unary/cryo_cell/can_see_pipes() + return FALSE // you can't see the pipe network when inside a cryo cell. + +#undef AUTO_EJECT_HEALTHY +#undef AUTO_EJECT_DEAD diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index b1a78f2825f..49b75588468 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -40,7 +40,7 @@ /obj/machinery/computer/cryopod/New() ..() - for(var/T in potential_theft_objectives) + for(var/T in GLOB.potential_theft_objectives) theft_cache += new T /obj/machinery/computer/cryopod/attack_ai() @@ -275,6 +275,12 @@ return control_computer != null +// So the user can use movement keys to get out of the cryopod +/obj/machinery/cryopod/relaymove(mob/user) + if(user.incapacitated()) + return FALSE + go_out() + /obj/machinery/cryopod/proc/check_occupant_allowed(mob/M) var/correct_type = 0 for(var/type in allow_occupant_types) @@ -416,15 +422,15 @@ // Delete them from datacore. var/announce_rank = null - if(PDA_Manifest.len) - PDA_Manifest.Cut() - for(var/datum/data/record/R in data_core.medical) + if(GLOB.PDA_Manifest.len) + GLOB.PDA_Manifest.Cut() + for(var/datum/data/record/R in GLOB.data_core.medical) if((R.fields["name"] == occupant.real_name)) qdel(R) - for(var/datum/data/record/T in data_core.security) + for(var/datum/data/record/T in GLOB.data_core.security) if((T.fields["name"] == occupant.real_name)) qdel(T) - for(var/datum/data/record/G in data_core.general) + for(var/datum/data/record/G in GLOB.data_core.general) if((G.fields["name"] == occupant.real_name)) announce_rank = G.fields["rank"] qdel(G) @@ -438,7 +444,7 @@ control_computer.frozen_crew += "[occupant.real_name]" var/ailist[] = list() - for(var/mob/living/silicon/ai/A in GLOB.living_mob_list) + for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list) ailist += A if(ailist.len) var/mob/living/silicon/ai/announcer = pick(ailist) diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index 1fb2dfc422d..baf32ab742c 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -400,7 +400,7 @@ while(time) sleep(speed) for(var/i in 1 to speed) - M.setDir(pick(cardinal)) + M.setDir(pick(GLOB.cardinal)) M.resting = !M.resting M.update_canmove() time-- diff --git a/code/game/machinery/defib_mount.dm b/code/game/machinery/defib_mount.dm index 738fc115734..9ee32716e53 100644 --- a/code/game/machinery/defib_mount.dm +++ b/code/game/machinery/defib_mount.dm @@ -15,6 +15,9 @@ var/obj/item/defibrillator/defib //this mount's defibrillator var/clamps_locked = FALSE //if true, and a defib is loaded, it can't be removed without unlocking the clamps +/obj/machinery/defibrillator_mount/attack_ai() + return + /obj/machinery/defibrillator_mount/get_cell() if(defib) return defib.get_cell() @@ -45,7 +48,7 @@ . = ..() if(defib) . += "There is a defib unit hooked up. Alt-click to remove it." - if(security_level >= SEC_LEVEL_RED) + if(GLOB.security_level >= SEC_LEVEL_RED) . += "Due to a security situation, its locking clamps can be toggled by swiping any ID." else . += "Its locking clamps can be [clamps_locked ? "dis" : ""]engaged by swiping an ID with access." @@ -100,7 +103,7 @@ return var/obj/item/card/id = I.GetID() if(id) - if(check_access(id) || security_level >= SEC_LEVEL_RED) //anyone can toggle the clamps in red alert! + if(check_access(id) || GLOB.security_level >= SEC_LEVEL_RED) //anyone can toggle the clamps in red alert! if(!defib) to_chat(user, "You can't engage the clamps on a defibrillator that isn't there.") return diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 1d97056912f..94a3219c159 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -30,6 +30,8 @@ new stacktype(get_turf(src), drop_amount) /obj/structure/barricade/welder_act(mob/user, obj/item/I) + if(bar_material != METAL) + return if(obj_integrity >= max_integrity) to_chat(user, "[src] does not need repairs.") return @@ -71,6 +73,7 @@ bar_material = WOOD stacktype = /obj/item/stack/sheet/wood + /obj/structure/barricade/wooden/attackby(obj/item/I, mob/user) if(istype(I,/obj/item/stack/sheet/wood)) var/obj/item/stack/sheet/wood/W = I diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 5ba3885faff..73d0e9281e1 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -38,7 +38,7 @@ #define AIRLOCK_DAMAGE_DEFLECTION_N 21 // Normal airlock damage deflection #define AIRLOCK_DAMAGE_DEFLECTION_R 30 // Reinforced airlock damage deflection -var/list/airlock_overlays = list() +GLOBAL_LIST_EMPTY(airlock_overlays) /obj/machinery/door/airlock name = "airlock" @@ -276,6 +276,7 @@ About the new airlock wires panel: if(usr) shockedby += text("\[[time_stamp()]\] - [usr](ckey:[usr.ckey])") usr.create_attack_log("Electrified the [name] at [x] [y] [z]") + add_attack_logs(usr, src, "Electrified", ATKLOG_ALL) else shockedby += text("\[[time_stamp()]\] - EMP)") message = "The door is now electrified [duration == -1 ? "permanently" : "for [duration] second\s"]." @@ -288,8 +289,8 @@ About the new airlock wires panel: // shock user with probability prb (if all connections & power are working) // returns 1 if shocked, 0 otherwise // The preceding comment was borrowed from the grille's shock script -/obj/machinery/door/airlock/shock(mob/user, prb) - if(!arePowerSystemsOn()) +/obj/machinery/door/airlock/shock(mob/living/user, prb) + if(!istype(user) || !arePowerSystemsOn()) return FALSE if(shockCooldown > world.time) return FALSE //Already shocked someone recently? @@ -483,10 +484,10 @@ About the new airlock wires panel: /proc/get_airlock_overlay(icon_state, icon_file) var/iconkey = "[icon_state][icon_file]" - if(airlock_overlays[iconkey]) - return airlock_overlays[iconkey] - airlock_overlays[iconkey] = image(icon_file, icon_state) - return airlock_overlays[iconkey] + if(GLOB.airlock_overlays[iconkey]) + return GLOB.airlock_overlays[iconkey] + GLOB.airlock_overlays[iconkey] = image(icon_file, icon_state) + return GLOB.airlock_overlays[iconkey] /obj/machinery/door/airlock/do_animate(animation) switch(animation) @@ -550,7 +551,7 @@ About the new airlock wires panel: ui.open() ui.set_auto_update(1) -/obj/machinery/door/airlock/ui_data(mob/user, datum/topic_state/state = default_state) +/obj/machinery/door/airlock/ui_data(mob/user, datum/topic_state/state = GLOB.default_state) var/data[0] data["main_power_loss"] = round(main_power_lost_until > 0 ? max(main_power_lost_until - world.time, 0) / 10 : main_power_lost_until, 1) @@ -763,6 +764,7 @@ About the new airlock wires panel: else if(activate) //electrify door for 30 seconds shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") usr.create_attack_log("Electrified the [name] at [x] [y] [z]") + add_attack_logs(usr, src, "Electrified", ATKLOG_ALL) to_chat(usr, "The door is now electrified for thirty seconds.") electrify(30) if("electrify_permanently") @@ -774,6 +776,7 @@ About the new airlock wires panel: else if(activate) shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])") usr.create_attack_log("Electrified the [name] at [x] [y] [z]") + add_attack_logs(usr, src, "Electrified", ATKLOG_ALL) to_chat(usr, "The door is now electrified.") electrify(-1) if("open") @@ -861,7 +864,7 @@ About the new airlock wires panel: update_icon() return - else if(istype(C, /obj/item/assembly/signaler)) + if(istype(C, /obj/item/assembly/signaler)) return interact_with_panel(user) else if(istype(C, /obj/item/pai_cable)) // -- TLE var/obj/item/pai_cable/cable = C @@ -946,7 +949,7 @@ About the new airlock wires panel: if(note) remove_airlock_note(user, TRUE) else - return interact_with_panel(user) + interact_with_panel(user) /obj/machinery/door/airlock/multitool_act(mob/user, obj/item/I) if(!headbutt_shock_check(user)) diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index 260d26493c0..660c6df683e 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -29,12 +29,12 @@ t1 += " Unrestricted Access Settings
    " var/list/Directions = list("North","South",,"East",,,,"West") - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if (unres_direction && unres_direction == direction) t1 += "[Directions[direction]]
    " else t1 += "[Directions[direction]]
    " - + t1 += "
    " t1 += "Access requirement is set to " t1 += one_access ? "ONE
    " : "ALL
    " @@ -74,7 +74,7 @@ if(href_list["access"]) toggle_access(href_list["access"]) - + if(href_list["unres_direction"]) unres_direction = text2num(href_list["unres_direction"]) if (unres_sides == unres_direction) diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index dbc76ade250..8d842179db5 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -2,6 +2,7 @@ #define FONT_SIZE "5pt" #define FONT_COLOR "#09f" #define FONT_STYLE "Small Fonts" +#define CELL_NONE "None" /////////////////////////////////////////////////////////////////////////////////////////////// // Brig Door control displays. @@ -31,10 +32,13 @@ maptext_height = 26 maptext_width = 32 maptext_y = -1 - var/occupant = "None" - var/crimes = "None" + var/occupant = CELL_NONE + var/crimes = CELL_NONE var/time = 0 - var/officer = "None" + var/officer = CELL_NONE + var/prisoner_name = "" + var/prisoner_charge = "" + var/prisoner_time = "" /obj/machinery/door_timer/New() GLOB.celltimers_list += src @@ -45,33 +49,29 @@ return ..() /obj/machinery/door_timer/proc/print_report() - var/logname = input(usr, "Name of the guilty?","[id] log name") - var/logcharges = stripped_multiline_input(usr, "What have they been charged with?","[id] log charges") - - if(!logname || !logcharges) + if(occupant == CELL_NONE || crimes == CELL_NONE) return 0 - occupant = logname - crimes = logcharges + time = timetoset officer = usr.name for(var/obj/machinery/computer/prisoner/C in GLOB.prisoncomputer_list) var/obj/item/paper/P = new /obj/item/paper(C.loc) - P.name = "[id] log - [logname] [station_time_timestamp()]" + P.name = "[id] log - [occupant] [station_time_timestamp()]" P.info = "
    [id] - Brig record



    " P.info += {"
    [station_name()] - Security Department

    Admission data:

    Log generated at: [station_time_timestamp()]
    - Detainee: [logname]
    + Detainee: [occupant]
    Duration: [seconds_to_time(timetoset / 10)]
    - Charge(s): [logcharges]
    + Charge(s): [crimes]
    Arresting Officer: [usr.name]


    This log file was generated automatically upon activation of a cell timer."} playsound(C.loc, "sound/goonstation/machines/printer_dotmatrix.ogg", 50, 1) GLOB.cell_logs += P - var/datum/data/record/G = find_record("name", logname, data_core.general) + var/datum/data/record/G = find_record("name", occupant, GLOB.data_core.general) var/prisoner_drank = "unknown" var/prisoner_trank = "unknown" if(G) @@ -80,9 +80,9 @@ if(G.fields["real_rank"]) // Ignore alt job titles - necessary for lookups prisoner_trank = G.fields["real_rank"] - var/datum/data/record/R = find_security_record("name", logname) + var/datum/data/record/R = find_security_record("name", occupant) - var/announcetext = "Detainee [logname] ([prisoner_drank]) has been incarcerated for [seconds_to_time(timetoset / 10)] for the charges of, '[logcharges]'. \ + var/announcetext = "Detainee [occupant] ([prisoner_drank]) has been incarcerated for [seconds_to_time(timetoset / 10)] for the charges of: '[crimes]'. \ Arresting Officer: [usr.name].[R ? "" : " Detainee record not found, manual record update required."]" Radio.autosay(announcetext, name, "Security", list(z)) @@ -91,7 +91,7 @@ if(R) prisoner = R - R.fields["criminal"] = "Incarcerated" + R.fields["criminal"] = SEC_RECORD_STATUS_INCARCERATED var/mob/living/carbon/human/M = usr var/rank = "UNKNOWN RANK" if(istype(M) && M.wear_id) @@ -99,7 +99,7 @@ rank = I.assignment if(!R.fields["comments"] || !islist(R.fields["comments"])) //copied from security computer code because apparently these need to be initialized R.fields["comments"] = list() - R.fields["comments"] += "Autogenerated by [name] on [current_date_string] [station_time_timestamp()]
    Sentenced to [timetoset/10] seconds for the charges of \"[logcharges]\" by [rank] [usr.name]." + R.fields["comments"] += "Autogenerated by [name] on [GLOB.current_date_string] [station_time_timestamp()]
    Sentenced to [timetoset/10] seconds for the charges of \"[crimes]\" by [rank] [usr.name]." update_all_mob_security_hud() return 1 @@ -118,7 +118,7 @@ var/boss_title = brigged_job.department_head[1] var/obj/item/pda/target_pda - for(var/obj/item/pda/check_pda in PDAs) + for(var/obj/item/pda/check_pda in GLOB.PDAs) if(check_pda.ownrank == boss_title) target_pda = check_pda if(!target_pda) @@ -175,12 +175,10 @@ if(timing) if(timeleft() <= 0) Radio.autosay("Timer has expired. Releasing prisoner.", name, "Security", list(z)) - occupant = "None" + occupant = CELL_NONE timer_end() // open doors, reset timer, clear status screen timing = 0 . = PROCESS_KILL - - updateUsrDialog() update_icon() else timer_end() @@ -203,8 +201,8 @@ if(!printed) if(!print_report()) - timing = 0 - return 0 + timing = FALSE + return FALSE // Set releasetime releasetime = world.timeofday + timetoset @@ -237,14 +235,14 @@ return 0 // Reset vars - occupant = "None" - crimes = "None" + occupant = CELL_NONE + crimes = CELL_NONE time = 0 - officer = "None" + officer = CELL_NONE releasetime = 0 printed = 0 if(prisoner) - prisoner.fields["criminal"] = "Released" + prisoner.fields["criminal"] = SEC_RECORD_STATUS_RELEASED update_all_mob_security_hud() prisoner = null @@ -290,10 +288,11 @@ //Allows AIs to use door_timer, see human attack_hand function below /obj/machinery/door_timer/attack_ai(mob/user) - interact(user) + attack_hand(user) + ui_interact(user) /obj/machinery/door_timer/attack_ghost(mob/user) - interact(user) + ui_interact(user) //Allows humans to use door_timer //Opens dialog window when someone clicks on door timer @@ -302,98 +301,71 @@ /obj/machinery/door_timer/attack_hand(mob/user) if(..()) return - interact(user) + ui_interact(user) -/obj/machinery/door_timer/interact(mob/user) - // Used for the 'time left' display - var/second = round(timeleft() % 60) - var/minute = round((timeleft() - second) / 60) +/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "brig_timer.tmpl", "Brig Timer", 500, 400) + ui.open() + ui.set_auto_update(TRUE) - // Used for 'set timer' - var/setsecond = round((timetoset / 10) % 60) - var/setminute = round(((timetoset / 10) - setsecond) / 60) +/obj/machinery/door_timer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) + var/data[0] + data["cell_id"] = name + data["occupant"] = occupant + data["crimes"] = crimes + data["brigged_by"] = officer + data["time_set"] = seconds_to_clock(time / 10) + data["time_left"] = seconds_to_clock(timeleft()) + data["timing"] = timing + data["isAllowed"] = allowed(user) + data["prisoner_name"] = prisoner_name + data["prisoner_charge"] = prisoner_charge + data["prisoner_time"] = prisoner_time - user.set_machine(src) + return data - // dat - var/dat = "
    Timer System:" - dat += " Door [id] controls
    " - - // Start/Stop timer - if(timing) - dat += "Stop Timer and open door
    " - else - dat += "Activate Timer and close door
    " - - // Time Left display (uses releasetime) - dat += "Time Left: [(minute ? text("[minute]:") : null)][second]
    " - dat += "
    " - - // Set Timer display (uses timetoset) - if(timing) - dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond] Set
    " - else - dat += "Set Timer: [(setminute ? text("[setminute]:") : null)][setsecond]
    " - - // Controls - dat += "Input Time" - - // Mounted flash controls - for(var/obj/machinery/flasher/F in targets) - if(F.last_flash && (F.last_flash + 150) > world.time) - dat += "
    Flash Charging" - else - dat += "
    Activate Flash" - - dat += "

    Close" - - var/datum/browser/popup = new(user, "door_timer", name, 400, 500) - popup.set_content(dat) - popup.open() - - -//Function for using door_timer dialog input, checks if user has permission -// href_list to -// "timing" turns on timer -// "tp" value to modify timer -// "fc" activates flasher -// "change" resets the timer to the timetoset amount while the timer is counting down -// Also updates dialog window and timer icon /obj/machinery/door_timer/Topic(href, href_list) - if(..()) - return 1 - if(!allowed(usr) && !usr.can_admin_interact()) return 1 - usr.set_machine(src) - - if(href_list["timing"]) - timing = text2num(href_list["timing"]) - - if(timing) - timer_start() - else - timer_end() - if(!isobserver(usr)) //spooky admin ghosts are in your brig, releasing your prisoners - Radio.autosay("Timer stopped manually by [usr.name].", name, "Security", list(z)) - - else - if(href_list["settime"]) - var/time = min(max(round(return_time_input(usr)), 0), 3600) - timeset(time) - - if(href_list["fc"]) - for(var/obj/machinery/flasher/F in targets) + if(href_list["flash"]) + for(var/obj/machinery/flasher/F in targets) + if(F.last_flash && (F.last_flash + 150) > world.time) + to_chat(usr, "Flash still charging.") + else F.flash() - if(href_list["change"]) - printed = 1 - timer_start() + if(href_list["release"]) + if(timing) + timer_end() + Radio.autosay("Timer stopped manually from cell control.", name, "Security", list(z)) + ui_interact(usr) - add_fingerprint(usr) - updateUsrDialog() - update_icon() + if(href_list["prisoner_name"]) + prisoner_name = input("Prisoner Name:", name, prisoner_name) as text|null + + if(href_list["prisoner_charge"]) + prisoner_charge = input("Prisoner Charge:", name, prisoner_charge) as text|null + + if(href_list["prisoner_time"]) + prisoner_time = input("Prisoner Time (in minutes):", name, prisoner_time) as num|null + prisoner_time = min(max(round(prisoner_time), 0), 60) + + if(href_list["set_timer"]) + if(!prisoner_name || !prisoner_charge || !prisoner_time) + return + timeset(prisoner_time * 60) + occupant = prisoner_name + crimes = prisoner_charge + prisoner_name = "" + prisoner_charge = "" + prisoner_time = "" + timing = TRUE + timer_start() + ui_interact(usr) + update_icon() //icon update function @@ -502,3 +474,4 @@ #undef FONT_COLOR #undef FONT_STYLE #undef CHARS_PER_LINE +#undef CELL_NONE diff --git a/code/game/machinery/doors/checkForMultipleDoors.dm b/code/game/machinery/doors/checkForMultipleDoors.dm index d7f66f4630b..7884e3be989 100644 --- a/code/game/machinery/doors/checkForMultipleDoors.dm +++ b/code/game/machinery/doors/checkForMultipleDoors.dm @@ -12,5 +12,5 @@ for(var/obj/machinery/door/D in locate(x,y,z)) if(!istype(D, /obj/machinery/door/window) && D.density) return 0 - //There are no false wall checks because that would be fucking retarded + //There are no false wall checks because that would be foolish return 1 diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 718efdb414c..2d6fac3bb81 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -204,7 +204,7 @@ . = TRUE if(operating) return - if(!I.use_tool(src, user, 0, volume = I.tool_volume)) + if(!I.use_tool(src, user, 0, volume = 0)) return try_to_crowbar(user, I) @@ -352,8 +352,8 @@ addtimer(CALLBACK(src, .proc/autoclose), wait, TIMER_UNIQUE | TIMER_NO_HASH_WAIT | TIMER_OVERRIDE) /obj/machinery/door/proc/update_freelook_sight() - if(!glass && cameranet) - cameranet.updateVisibility(src, 0) + if(!glass && GLOB.cameranet) + GLOB.cameranet.updateVisibility(src, 0) /obj/machinery/door/BlockSuperconductivity() // All non-glass airlocks block heat, this is intended. if(opacity || heat_proof) diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index 6f4a84a7535..c0dce817189 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -59,9 +59,18 @@ /obj/machinery/door/poddoor/try_to_activate_door(mob/user) return -/obj/machinery/door/poddoor/try_to_crowbar(obj/item/I, mob/user) +/obj/machinery/door/poddoor/try_to_crowbar(mob/user, obj/item/I) + if(!density) + return if(!hasPower()) - open() + to_chat(user, "You start forcing [src] open...") + if(do_after(user, 50 * I.toolspeed, target = src)) + if(!hasPower()) + open() + else + to_chat(user, "[src] resists your efforts to force it!") + else + to_chat(user, "[src] resists your efforts to force it!") // Whoever wrote the old code for multi-tile spesspod doors needs to burn in hell. - Unknown // Wise words. - Bxil diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index 7af8ebe88f3..05198a7a55f 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -1,4 +1,4 @@ -var/list/doppler_arrays = list() +GLOBAL_LIST_EMPTY(doppler_arrays) /obj/machinery/doppler_array name = "tachyon-doppler array" @@ -28,12 +28,12 @@ var/list/doppler_arrays = list() /obj/machinery/doppler_array/New() ..() - doppler_arrays += src + GLOB.doppler_arrays += src explosion_target = rand(8, 20) toxins_tech = new /datum/tech/toxins(src) /obj/machinery/doppler_array/Destroy() - doppler_arrays -= src + GLOB.doppler_arrays -= src logged_explosions.Cut() return ..() @@ -95,7 +95,7 @@ var/list/doppler_arrays = list() to_chat(user, "[src] is already printing something, please wait.") return atom_say("Printing explosive log. Standby...") - addtimer(CALLBACK(src, .print), 50) + addtimer(CALLBACK(src, .proc/print), 50) /obj/machinery/doppler_array/proc/print() visible_message("[src] prints a piece of paper!") @@ -183,7 +183,7 @@ var/list/doppler_arrays = list() ui.open() ui.set_auto_update(1) -/obj/machinery/doppler_array/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/doppler_array/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/list/explosion_data = list() for(var/D in logged_explosions) diff --git a/code/game/machinery/embedded_controller/airlock_controllers.dm b/code/game/machinery/embedded_controller/airlock_controllers.dm index b1a6f96e2eb..32924690d97 100644 --- a/code/game/machinery/embedded_controller/airlock_controllers.dm +++ b/code/game/machinery/embedded_controller/airlock_controllers.dm @@ -27,7 +27,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/embedded_controller/radio/airlock/advanced_airlock_controller/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data = list( @@ -98,7 +98,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/embedded_controller/radio/airlock/airlock_controller/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/embedded_controller/radio/airlock/airlock_controller/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data = list( @@ -160,7 +160,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/embedded_controller/radio/airlock/access_controller/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/embedded_controller/radio/airlock/access_controller/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data = list( diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 7ae268fca46..9beba3f4789 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -236,14 +236,14 @@ FIRE ALARM ui_interact(user) -/obj/machinery/firealarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/obj/machinery/firealarm/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "firealarm.tmpl", name, 400, 400, state = state) ui.open() ui.set_auto_update(1) -/obj/machinery/firealarm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/firealarm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/area/A = get_area(src) @@ -318,7 +318,7 @@ FIRE ALARM pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0 if(is_station_contact(z) && show_alert_level) - if(security_level) + if(GLOB.security_level) overlays += image('icons/obj/monitors.dmi', "overlay_[get_security_level()]") else overlays += image('icons/obj/monitors.dmi', "overlay_green") diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index b7b7e35eef6..57057ad510a 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -58,6 +58,8 @@ playsound(loc, 'sound/weapons/flash.ogg', 100, 1) flick("[base_state]_flash", src) + set_light(2, 1, COLOR_WHITE) + addtimer(CALLBACK(src, /atom./proc/set_light, 0), 2) last_flash = world.time use_power(1000) diff --git a/code/game/machinery/guestpass.dm b/code/game/machinery/guestpass.dm index 2c37a3274c7..165c8dbe4cb 100644 --- a/code/game/machinery/guestpass.dm +++ b/code/game/machinery/guestpass.dm @@ -193,5 +193,5 @@ /obj/machinery/computer/guestpass/hop/get_changeable_accesses() . = ..() - if(. && ACCESS_CHANGE_IDS in .) + if(. && (ACCESS_CHANGE_IDS in .)) return get_all_accesses() diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 03b28423830..fcd6de4020c 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -33,7 +33,7 @@ Possible to do for anyone motivated enough: #define HOLOPAD_MODE RANGE_BASED -var/list/holopads = list() +GLOBAL_LIST_EMPTY(holopads) /obj/machinery/hologram/holopad name = "holopad" @@ -61,7 +61,7 @@ var/list/holopads = list() /obj/machinery/hologram/holopad/New() ..() - holopads += src + GLOB.holopads += src component_parts = list() component_parts += new /obj/item/circuitboard/holopad(null) component_parts += new /obj/item/stock_parts/capacitor(null) @@ -77,7 +77,7 @@ var/list/holopads = list() for(var/I in masters) clear_holo(I) - holopads -= src + GLOB.holopads -= src return ..() /obj/machinery/hologram/holopad/power_change() @@ -192,7 +192,7 @@ var/list/holopads = list() temp = "You requested an AI's presence.
    " temp += "Main Menu" var/area/area = get_area(src) - for(var/mob/living/silicon/ai/AI in ai_list) + for(var/mob/living/silicon/ai/AI in GLOB.ai_list) if(!AI.client) continue to_chat(AI, "Your presence is requested at \the [area].") @@ -210,7 +210,7 @@ var/list/holopads = list() temp += "Main Menu" if(usr.loc == loc) var/list/callnames = list() - for(var/I in holopads) + for(var/I in GLOB.holopads) var/area/A = get_area(I) if(A) LAZYADD(callnames[A], I) @@ -297,7 +297,7 @@ var/list/holopads = list() /obj/machinery/hologram/holopad/proc/transfer_to_nearby_pad(turf/T, mob/holo_owner) if(!isAI(holo_owner)) return - for(var/pad in holopads) + for(var/pad in GLOB.holopads) var/obj/machinery/hologram/holopad/another = pad if(another == src) continue diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 6f97856a227..740c3affaba 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -293,7 +293,7 @@ Class Procs: update_multitool_menu(usr) return TRUE -/obj/machinery/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = default_state) +/obj/machinery/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = GLOB.default_state) if(..(href, href_list, nowindow, state)) return 1 @@ -555,14 +555,18 @@ Class Procs: if(check_records && !R) threatcount += 4 - if(check_arrest && R && (R.fields["criminal"] == "*Arrest*")) - threatcount += 4 + if(R && R.fields["criminal"]) + switch(R.fields["criminal"]) + if(SEC_RECORD_STATUS_EXECUTE) + threatcount += 7 + if(SEC_RECORD_STATUS_ARREST) + threatcount += 5 return threatcount -/obj/machinery/proc/shock(mob/user, prb) - if(inoperable()) +/obj/machinery/proc/shock(mob/living/user, prb) + if(!istype(user) || inoperable()) return FALSE if(!prob(prb)) return FALSE diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 61d96602343..c2396ab1d9f 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -55,9 +55,9 @@ var/list/datum/feed_channel/network_channels = list() var/datum/feed_message/wanted_issue -var/datum/feed_network/news_network = new /datum/feed_network //The global news-network, which is coincidentally a global list. +GLOBAL_DATUM_INIT(news_network, /datum/feed_network, new()) //The global news-network, which is coincidentally a global list. -var/list/obj/machinery/newscaster/allCasters = list() //Global list that will contain reference to all newscasters in existence. +GLOBAL_LIST_EMPTY(allNewscasters) //Global list that will contain reference to all newscasters in existence. #define NEWSCASTER_MAIN 0 // Main menu #define NEWSCASTER_FC_LIST 1 // Feed channel list @@ -128,13 +128,13 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co securityCaster = 1 /obj/machinery/newscaster/New() - allCasters += src - unit_no = allCasters.len + GLOB.allNewscasters += src + unit_no = GLOB.allNewscasters.len update_icon() //for any custom ones on the map... ..() /obj/machinery/newscaster/Destroy() - allCasters -= src + GLOB.allNewscasters -= src viewing_channel = null QDEL_NULL(photo) return ..() @@ -144,7 +144,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(inoperable()) icon_state = "newscaster_off" else - if(!news_network.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message + if(!GLOB.news_network.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message icon_state = "newscaster_normal" if(alert) //new message alert overlay add_overlay("newscaster_alert") @@ -194,7 +194,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co switch(screen) if(0) - data["wanted_issue"] = news_network.wanted_issue ? 1 : 0 + data["wanted_issue"] = GLOB.news_network.wanted_issue ? 1 : 0 data["silence"] = silence data["securityCaster"] = securityCaster if(securityCaster) @@ -202,7 +202,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(1, 6, 7) var/list/channels = list() data["channels"] = channels - for(var/datum/feed_channel/C in news_network.network_channels) + for(var/datum/feed_channel/C in GLOB.news_network.network_channels) channels[++channels.len] = list("name" = C.channel_name, "ref" = "\ref[C]", "censored" = C.censored, "admin" = C.is_admin_channel) if(2) data["scanned_user"] = scanned_user @@ -215,10 +215,10 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co data["msg"] = msg data["photo"] = photo ? 1 : 0 if(4) - var/total_num = length(news_network.network_channels) + var/total_num = length(GLOB.news_network.network_channels) var/active_num = total_num var/message_num=0 - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(!FC.censored) message_num += length(FC.messages) else @@ -254,7 +254,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co if(10) var/wanted_already = 0 var/end_param = 1 - if(news_network.wanted_issue) + if(GLOB.news_network.wanted_issue) wanted_already = 1 end_param = 2 data["wanted_already"] = wanted_already @@ -263,16 +263,16 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co data["msg"] = msg data["photo"] = photo ? 1 : 0 if(wanted_already) - data["author"] = news_network.wanted_issue.backup_author + data["author"] = GLOB.news_network.wanted_issue.backup_author else data["scanned_user"] = scanned_user if(11) - data["author"] = news_network.wanted_issue.backup_author - data["criminal"] = news_network.wanted_issue.author - data["description"] = news_network.wanted_issue.body - if(news_network.wanted_issue.img) - user << browse_rsc(news_network.wanted_issue.img, "tmp_photow.png") - data["photo"] = news_network.wanted_issue.img ? news_network.wanted_issue.img : 0 + data["author"] = GLOB.news_network.wanted_issue.backup_author + data["criminal"] = GLOB.news_network.wanted_issue.author + data["description"] = GLOB.news_network.wanted_issue.body + if(GLOB.news_network.wanted_issue.img) + user << browse_rsc(GLOB.news_network.wanted_issue.img, "tmp_photow.png") + data["photo"] = GLOB.news_network.wanted_issue.img ? GLOB.news_network.wanted_issue.img : 0 if(12) var/list/jobs = list() data["jobs"] = jobs @@ -295,13 +295,13 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co else if(href_list["submit_new_channel"]) var/list/existing_authors = list() - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.author == REDACTED) existing_authors += FC.backup_author else existing_authors += FC.author var/check = 0 - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == channel_name) check = 1 break @@ -325,13 +325,13 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co newChannel.author = scanned_user newChannel.locked = c_locked feedback_inc("newscaster_channels", 1) - news_network.network_channels += newChannel //Adding channel to the global network + GLOB.news_network.network_channels += newChannel //Adding channel to the global network temp = "Feed channel '[channel_name]' created successfully." temp_back_screen = NEWSCASTER_MAIN else if(href_list["set_channel_receiving"]) var/list/available_channels = list() - for(var/datum/feed_channel/F in news_network.network_channels) + for(var/datum/feed_channel/F in GLOB.news_network.network_channels) if((!F.locked || F.author == scanned_user) && !F.censored) available_channels += F.channel_name channel_name = strip_html_simple(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels) @@ -366,14 +366,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co newMsg.img = photo.img feedback_inc("newscaster_stories",1) var/announcement = "" - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == channel_name) FC.messages += newMsg //Adding message to the network's appropriate feed_channel announcement = FC.announce_news(msg_title) break temp = "Feed story successfully submitted to [channel_name]." temp_back_screen = NEWSCASTER_MAIN - for(var/obj/machinery/newscaster/NC in allCasters) + for(var/obj/machinery/newscaster/NC in GLOB.allNewscasters) NC.newsAlert(announcement) else if(href_list["create_channel"]) @@ -405,12 +405,12 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co else if(href_list["menu_wanted"]) var/already_wanted = 0 - if(news_network.wanted_issue) + if(GLOB.news_network.wanted_issue) already_wanted = 1 if(already_wanted) - channel_name = news_network.wanted_issue.author - msg = news_network.wanted_issue.body + channel_name = GLOB.news_network.wanted_issue.author + msg = GLOB.news_network.wanted_issue.body screen = NEWSCASTER_W_ISSUE_H else if(href_list["set_wanted_name"]) @@ -441,32 +441,32 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co W.backup_author = scanned_user //I know, a bit wacky if(photo) W.img = photo.img - news_network.wanted_issue = W - for(var/obj/machinery/newscaster/NS in allCasters) + GLOB.news_network.wanted_issue = W + for(var/obj/machinery/newscaster/NS in GLOB.allNewscasters) NS.newsAlert() NS.update_icon() temp = "Wanted issue for [channel_name] is now in Network Circulation." temp_back_screen = NEWSCASTER_MAIN else - if(news_network.wanted_issue.is_admin_message) + if(GLOB.news_network.wanted_issue.is_admin_message) alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot edit it.","Ok") return - news_network.wanted_issue.author = channel_name - news_network.wanted_issue.body = msg - news_network.wanted_issue.backup_author = scanned_user + GLOB.news_network.wanted_issue.author = channel_name + GLOB.news_network.wanted_issue.body = msg + GLOB.news_network.wanted_issue.backup_author = scanned_user if(photo) - news_network.wanted_issue.img = photo.img + GLOB.news_network.wanted_issue.img = photo.img temp = "Wanted issue for [channel_name] successfully edited." temp_back_screen = NEWSCASTER_MAIN else if(href_list["cancel_wanted"]) - if(news_network.wanted_issue.is_admin_message) + if(GLOB.news_network.wanted_issue.is_admin_message) alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot take it down.", "Ok") return var/choice = alert("Please confirm wanted issue removal", "Network Security Handler", "Confirm", "Cancel") if(choice == "Confirm") - news_network.wanted_issue = null - for(var/obj/machinery/newscaster/NC in allCasters) + GLOB.news_network.wanted_issue = null + for(var/obj/machinery/newscaster/NC in GLOB.allNewscasters) NC.update_icon() temp = "Wanted Issue successfully deleted from Circulation" temp_back_screen = NEWSCASTER_MAIN @@ -826,10 +826,10 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co /obj/machinery/newscaster/proc/print_paper() feedback_inc("newscaster_newspapers_printed",1) var/obj/item/newspaper/NEWSPAPER = new /obj/item/newspaper - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) NEWSPAPER.news_content += FC - if(news_network.wanted_issue) - NEWSPAPER.important_message = news_network.wanted_issue + if(GLOB.news_network.wanted_issue) + NEWSPAPER.important_message = GLOB.news_network.wanted_issue NEWSPAPER.loc = get_turf(src) paper_remaining-- return diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index 13ad44215bb..42452a9f8e2 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -216,7 +216,7 @@ /obj/item/pipe/Move() ..() if(is_bent_pipe() \ - && (src.dir in cardinal)) + && (src.dir in GLOB.cardinal)) src.dir = src.dir|turn(src.dir, 90) else if(pipe_type in list (PIPE_SIMPLE_STRAIGHT, PIPE_SUPPLY_STRAIGHT, PIPE_SCRUBBERS_STRAIGHT, PIPE_UNIVERSAL, PIPE_HE_STRAIGHT, PIPE_INSULATED_STRAIGHT, PIPE_MVALVE, PIPE_DVALVE)) if(dir==2) @@ -305,7 +305,7 @@ return 0 /obj/item/pipe/proc/unflip(var/direction) - if(!(direction in cardinal)) + if(!(direction in GLOB.cardinal)) return turn(direction, 45) return direction diff --git a/code/game/machinery/poolcontroller.dm b/code/game/machinery/poolcontroller.dm index 53dd0135c54..b910b1272ff 100644 --- a/code/game/machinery/poolcontroller.dm +++ b/code/game/machinery/poolcontroller.dm @@ -157,7 +157,7 @@ ui = new(user, src, ui_key, "poolcontroller.tmpl", "Pool Controller Interface", 520, 410) ui.open() -/obj/machinery/poolcontroller/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/poolcontroller/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/currenttemp switch(temperature) //So we can output nice things like "Cool" to nanoUI diff --git a/code/game/machinery/portable_tag_turret.dm b/code/game/machinery/portable_tag_turret.dm index 0bd368bd75b..12bae1bbf5a 100644 --- a/code/game/machinery/portable_tag_turret.dm +++ b/code/game/machinery/portable_tag_turret.dm @@ -13,8 +13,8 @@ lasercolor = "b" installation = /obj/item/gun/energy/laser/tag/blue -/obj/machinery/porta_turret/tag/New() - ..() +/obj/machinery/porta_turret/tag/Initialize(mapload) + . = ..() icon_state = "[lasercolor]grey_target_prism" /obj/machinery/porta_turret/tag/weapon_setup(var/obj/item/gun/energy/E) @@ -49,7 +49,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/porta_turret/tag/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/porta_turret/tag/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["access"] = !isLocked(user) data["locked"] = locked diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index a77cbe6c184..b63f4ab7f8b 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -87,8 +87,8 @@ lethal = 1 installation = /obj/item/gun/energy/laser -/obj/machinery/porta_turret/New() - ..() +/obj/machinery/porta_turret/Initialize(mapload) + . = ..() if(req_access && req_access.len) req_access.Cut() req_one_access = list(ACCESS_SECURITY, ACCESS_HEADS) @@ -105,8 +105,8 @@ QDEL_NULL(spark_system) return ..() -/obj/machinery/porta_turret/centcom/New() - ..() +/obj/machinery/porta_turret/centcom/Initialize(mapload) + . = ..() if(req_one_access && req_one_access.len) req_one_access.Cut() req_access = list(ACCESS_CENT_SPECOPS) @@ -161,14 +161,14 @@ eprojectile = /obj/item/projectile/beam/pulse eshot_sound = 'sound/weapons/pulse.ogg' -var/list/turret_icons +GLOBAL_LIST_EMPTY(turret_icons) /obj/machinery/porta_turret/update_icon() - if(!turret_icons) - turret_icons = list() - turret_icons["open"] = image(icon, "openTurretCover") + if(!GLOB.turret_icons) + GLOB.turret_icons = list() + GLOB.turret_icons["open"] = image(icon, "openTurretCover") underlays.Cut() - underlays += turret_icons["open"] + underlays += GLOB.turret_icons["open"] if(stat & BROKEN) icon_state = "destroyed_target_prism" @@ -218,7 +218,7 @@ var/list/turret_icons ui.open() ui.set_auto_update(1) -/obj/machinery/porta_turret/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/porta_turret/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["access"] = !isLocked(user) data["screen"] = screen @@ -1015,8 +1015,8 @@ var/list/turret_icons depotarea.declare_started() return ..(target) -/obj/machinery/porta_turret/syndicate/New() - ..() +/obj/machinery/porta_turret/syndicate/Initialize(mapload) + . = ..() if(req_one_access && req_one_access.len) req_one_access.Cut() req_access = list(ACCESS_SYNDICATE) diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 081a48c3da1..e4e37ae1bcb 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -19,8 +19,7 @@ var/item_recycle_sound = 'sound/machines/recycler.ogg' /obj/machinery/recycler/New() - AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_PLASTIC, MAT_BLUESPACE), 0, - TRUE, null, null, null, TRUE) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_PLASTIC, MAT_BLUESPACE), 0, TRUE, null, null, null, TRUE) ..() component_parts = list() component_parts += new /obj/item/circuitboard/recycler(null) @@ -37,7 +36,7 @@ mat_mod *= 50000 for(var/obj/item/stock_parts/manipulator/M in component_parts) amt_made = 25 * M.rating //% of materials salvaged - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.max_amount = mat_mod amount_produced = min(100, amt_made) @@ -135,7 +134,7 @@ /obj/machinery/recycler/proc/recycle_item(obj/item/I) I.forceMove(loc) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/material_amount = materials.get_item_material_amount(I) if(!material_amount) qdel(I) diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index db913f171c3..095b2e7d56e 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -27,10 +27,10 @@ #define COM_ROLES list("Blueshield","NT Representative","Head of Personnel's Desk","Captain's Desk","Bridge") #define SCI_ROLES list("Robotics","Science","Research Director's Desk") -var/req_console_assistance = list() -var/req_console_supplies = list() -var/req_console_information = list() -var/list/obj/machinery/requests_console/allConsoles = list() +GLOBAL_LIST_EMPTY(req_console_assistance) +GLOBAL_LIST_EMPTY(req_console_supplies) +GLOBAL_LIST_EMPTY(req_console_information) +GLOBAL_LIST_EMPTY(allRequestConsoles) /obj/machinery/requests_console name = "Requests Console" @@ -93,30 +93,30 @@ var/list/obj/machinery/requests_console/allConsoles = list() announcement.newscast = 0 name = "[department] Requests Console" - allConsoles += src + GLOB.allRequestConsoles += src if(departmentType & RC_ASSIST) - req_console_assistance |= department + GLOB.req_console_assistance |= department if(departmentType & RC_SUPPLY) - req_console_supplies |= department + GLOB.req_console_supplies |= department if(departmentType & RC_INFO) - req_console_information |= department + GLOB.req_console_information |= department set_light(1) /obj/machinery/requests_console/Destroy() - allConsoles -= src + GLOB.allRequestConsoles -= src var/lastDeptRC = 1 - for(var/obj/machinery/requests_console/Console in allConsoles) + for(var/obj/machinery/requests_console/Console in GLOB.allRequestConsoles) if(Console.department == department) lastDeptRC = 0 break if(lastDeptRC) if(departmentType & RC_ASSIST) - req_console_assistance -= department + GLOB.req_console_assistance -= department if(departmentType & RC_SUPPLY) - req_console_supplies -= department + GLOB.req_console_supplies -= department if(departmentType & RC_INFO) - req_console_information -= department + GLOB.req_console_information -= department QDEL_NULL(Radio) return ..() @@ -138,7 +138,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() ui.open() ui.set_auto_update(1) -/obj/machinery/requests_console/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/requests_console/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["department"] = department @@ -148,9 +148,9 @@ var/list/obj/machinery/requests_console/allConsoles = list() data["silent"] = silent data["announcementConsole"] = announcementConsole - data["assist_dept"] = req_console_assistance - data["supply_dept"] = req_console_supplies - data["info_dept"] = req_console_information + data["assist_dept"] = GLOB.req_console_assistance + data["supply_dept"] = GLOB.req_console_supplies + data["info_dept"] = GLOB.req_console_information data["ship_dept"] = GLOB.TAGGERLOCATIONS data["message"] = message @@ -233,7 +233,7 @@ var/list/obj/machinery/requests_console/allConsoles = list() if(tempScreen == RCS_ANNOUNCE && !announcementConsole) return if(tempScreen == RCS_VIEWMSGS) - for(var/obj/machinery/requests_console/Console in allConsoles) + for(var/obj/machinery/requests_console/Console in GLOB.allRequestConsoles) if(Console.department == department) Console.newmessagepriority = 0 Console.icon_state = "req_comp0" diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm index adbc3d67605..d0cf38a272d 100644 --- a/code/game/machinery/slotmachine.dm +++ b/code/game/machinery/slotmachine.dm @@ -27,7 +27,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/slot_machine/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/slot_machine/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["working"] = working data["money"] = account ? account.money : null @@ -52,18 +52,18 @@ icon_state = "slots-on" playsound(src.loc, 'sound/machines/ding.ogg', 50, 1) addtimer(CALLBACK(src, .proc/spin_slots, usr.name), 25) - + /obj/machinery/slot_machine/proc/spin_slots(userName) switch(rand(1,4050)) if(1) // .02% atom_say("JACKPOT! [userName] has won a MILLION CREDITS!") - event_announcement.Announce("Congratulations to [userName] on winning the Jackpot of ONE MILLION CREDITS!", "Jackpot Winner") + GLOB.event_announcement.Announce("Congratulations to [userName] on winning the Jackpot of ONE MILLION CREDITS!", "Jackpot Winner") result = "JACKPOT! You win one million credits!" resultlvl = "highlight" win_money(1000000, 'sound/goonstation/misc/airraid_loop.ogg') if(2 to 5) // .07% atom_say("Big Winner! [userName] has won a hundred thousand credits!") - event_announcement.Announce("Congratulations to [userName] on winning a hundred thousand credits!", "Big Winner") + GLOB.event_announcement.Announce("Congratulations to [userName] on winning a hundred thousand credits!", "Big Winner") result = "Big Winner! You win a hundred thousand credits!" resultlvl = "good" win_money(100000, 'sound/goonstation/misc/klaxon.ogg') diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index 99642db320e..b3745f947cd 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -78,7 +78,7 @@ try_detonate(TRUE) //Counter terrorists win else if(!active || defused) - if(defused && payload in src) + if(defused && (payload in src)) payload.defuse() countdown.stop() STOP_PROCESSING(SSfastprocess, src) diff --git a/code/game/machinery/tcomms/_base.dm b/code/game/machinery/tcomms/_base.dm new file mode 100644 index 00000000000..a857afcef89 --- /dev/null +++ b/code/game/machinery/tcomms/_base.dm @@ -0,0 +1,459 @@ +/* + + ParadiseSS13 Telecommunications System + + Rewritten from the ground up because I was totally unhappy with how laggy and complicated the current implementation was + The system is made up of two objects. A main core and relays. + + The main core is basically the same as all of the machines from the previous implementation, apart from the relay + The core handles recieving and sending messages, logging messages, the NTTC configuration, and serves as the linkage hub for relays + + Relays function much in the same way as the old ones. They just expand the reach of tcomms from one z-level to another. + + This file contains extra datums and helper procs which the system utilises. + Unlike old telecomms, everything in here **should** be well documented. If not, feel free to add your own + -aa07 + +*/ + +/// Global list for all telecomms machines in the world +GLOBAL_LIST_EMPTY(tcomms_machines) + +/** + * # Telecommunications Device + * + * This is the base machine for both tcomms devices (core + relay) + * + * This holds a few base procs (Icon updates, enable/disable, etc) + * It also has the initial overrides for Initialize() and Destroy() + */ +/obj/machinery/tcomms + name = "Telecommunications Device" + desc = "Someone forgot to say what this thingy does. Please yell at a coder" + icon = 'icons/obj/tcomms.dmi' + icon_state = "error" + density = TRUE + anchored = TRUE + use_power = IDLE_POWER_USE + idle_power_usage = 500 + /// Network ID used for names + auto linkage + var/network_id = "None" + /// Is the machine active + var/active = TRUE + +/** + * Base Initializer + * + * Ensures that the machine is put into the global list of tcomms devices, and then its made sure that the icon is correct if the machine starts offline + */ +/obj/machinery/tcomms/Initialize(mapload) + . = ..() + GLOB.tcomms_machines += src + update_icon() + +/** + * Base Destructor + * + * Ensures that the machine is taken out of the global list when destroyed + */ +/obj/machinery/tcomms/Destroy() + GLOB.tcomms_machines -= src + return ..() + +/** + * Icon Updater + * + * Ensures that the icon updates properly based on if the machine is active or not. This removes the need for this check in many other places. + */ +/obj/machinery/tcomms/update_icon() + . = ..() + if(!active || (stat & NOPOWER)) + icon_state = "[initial(icon_state)]_off" + else + icon_state = initial(icon_state) + + +// Attack overrides. These are needed so the UIs can be opened up // +/obj/machinery/tcomms/attack_ai(mob/user) + add_hiddenprint(user) + ui_interact(user) + +/obj/machinery/tcomms/attack_ghost(mob/user) + ui_interact(user) + +/obj/machinery/tcomms/attack_hand(mob/user) + if(..(user)) + return + ui_interact(user) + + +/** + * Machine Enabler + * + * Quick and dirty proc to allow for the machine to be programatically enabled easily. Used for the anomaly event + */ +/obj/machinery/tcomms/proc/enable_machine() + active = TRUE + update_icon() + +/** + * Machine Disabler + * + * Quick and dirty proc to allow for the machine to be programatically disabled easily. Used for the anomaly event + */ +/obj/machinery/tcomms/proc/disable_machine() + active = FALSE + update_icon() + +/** + * Logging helper + * + * Proc which allows easy logging of changs made to tcomms machines + * Arguments: + * * user - The user who did the action + * * msg - The log message + * * adminmsg - Should an admin log be sent when this happens + */ +/obj/machinery/tcomms/proc/log_action(user, msg, adminmsg = FALSE) + log_game("NTTC: [key_name(user)] [msg]") + log_investigate("[key_name(user)] [msg]", "nttc") + if(adminmsg) + message_admins("[key_name_admin(user)] [msg]") +/** + * Power Change Handler + * + * Proc which ensures icons are updated when machines lose power + */ +/obj/machinery/tcomms/power_change() + ..() + update_icon() + +/** + * # Telecommunications Message + * + * Datum which holds all the data for a message being sent + * + * This used to be a single associative list with just keys and values + * It had no typepath or presence checking, and was absolutely awful to work with + * This fixes that + * + */ +/datum/tcomms_message + /// Who sent the message + var/sender_name = "Error" + /// What job are they + var/sender_job = "Error" + /// Pieces of the message + var/list/message_pieces = list() + /// Source Z-level + var/source_level = 0 + /// What frequency the message is sent on + var/freq = 0 + /// Was it sent with a voice changer + var/vmask = FALSE + /// Did the signal come from a device that requires tcomms to function + var/needs_tcomms = TRUE + /// Origin of the signal + var/datum/radio_frequency/connection + /// Who sent it + var/mob/sender + /// The radio it was sent from + var/obj/item/radio/radio + /// The signal data (See defines/radio.dm) + var/data + /// Verbage used + var/verbage = "says" + /// Follow target for AI use + var/atom/follow_target = null + /// Is this signal meant to be rejected + var/reject = FALSE + /// Voice name if the person doesnt have a name (diona, alien, etc) + var/vname + /// List of all channels this can be sent or recieved on + var/list/zlevels = list() + +/** + * Destructor for the TCM datum. + * + * This needs to happen like this so that things dont keep references held in place + */ +/datum/tcomms_message/Destroy() + connection = null + radio = null + follow_target = null + return ..() + + +#define CREW_RADIO_TYPE 0 +#define CENTCOMM_RADIO_TYPE 1 +#define SYNDICATE_RADIO_TYPE 2 + +/** + * Connection checker + * + * Checks the connection frequency against the intended frequency for the message + * NOTE: I barely know what on earth this does, but it works and it scares me + * Arguments: + * * old_freq - Frequency of the connection + * * new_freq - Frequency of the message + */ +/proc/is_bad_connection(old_freq, new_freq) + var/old_type = CREW_RADIO_TYPE + var/new_type = CREW_RADIO_TYPE + for(var/antag_freq in SSradio.ANTAG_FREQS) + if(old_freq == antag_freq) + old_type = SYNDICATE_RADIO_TYPE + if(new_freq == antag_freq) + new_type = SYNDICATE_RADIO_TYPE + + for(var/cent_freq in SSradio.CENT_FREQS) + if(old_freq == cent_freq) + old_type = CENTCOMM_RADIO_TYPE + if(new_freq == cent_freq) + new_type = CENTCOMM_RADIO_TYPE + + return new_type > old_type + +#undef CREW_RADIO_TYPE +#undef CENTCOMM_RADIO_TYPE +#undef SYNDICATE_RADIO_TYPE + + +/** + * Message Broadcast Proc + * + * This big fat disaster is responsible for sending the message out to all headsets and radios on the station + * It is absolutely disgusting, but used to take about 20 arguments before I slimmed it down to just one + * Arguments: + * * tcm - The tcomms message datum + */ +/proc/broadcast_message(datum/tcomms_message/tcm) + + + /* ###### Prepare the radio connection ###### */ + + var/display_freq = tcm.freq + + var/bad_connection = FALSE + var/datum/radio_frequency/new_connection = tcm.connection + + if(tcm.connection.frequency != display_freq) + bad_connection = is_bad_connection(tcm.connection.frequency, display_freq) + new_connection = SSradio.return_frequency(display_freq) + + var/list/radios = list() + + // --- Broadcast only to intercom devices --- + + if(tcm.data == SIGNALTYPE_INTERCOM && !bad_connection) + + for(var/obj/item/radio/intercom/R in new_connection.devices["[RADIO_CHAT]"]) + if(R.receive_range(display_freq, tcm.zlevels) > -1) + radios += R + + // --- Broadcast only to intercoms and station-bounced radios --- + + else if(tcm.data == SIGNALTYPE_INTERCOM_SBR && !bad_connection) + + for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"]) + + if(istype(R, /obj/item/radio/headset)) + continue + + if(R.receive_range(display_freq, tcm.zlevels) > -1) + radios += R + + // --- Broadcast to ALL radio devices --- + + else if(!bad_connection) + + for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"]) + if(R.receive_range(display_freq, tcm.zlevels) > -1) + radios += R + + // Add syndie radios for intercepts if its a regular department frequency + for(var/antag_freq in SSradio.ANTAG_FREQS) + var/datum/radio_frequency/antag_connection = SSradio.return_frequency(antag_freq) + for(var/obj/item/radio/R in antag_connection.devices["[RADIO_CHAT]"]) + if(R.receive_range(antag_freq, tcm.zlevels) > -1) + // Only add if it wasnt there already + radios |= R + + // Get a list of mobs who can hear from the radios we collected. + var/list/receive = get_mobs_in_radio_ranges(radios) + + /* ###### Organize the receivers into categories for displaying the message ###### */ + + // Understood the message: + var/list/heard_masked = list() // masked name or no real name + var/list/heard_normal = list() // normal message + + // Did not understand the message: + var/list/heard_voice = list() // voice message (ie "chimpers") + var/list/heard_garbled = list() // garbled message (ie "f*c* **u, **i*er!") + var/list/heard_gibberish= list() // completely screwed over message (ie "F%! (O*# *#!<>&**%!") + + for(var/M in receive) + var/mob/R = M + + /* --- Loop through the receivers and categorize them --- */ + + if(is_admin(R) && !R.get_preference(CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. + continue + + if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes. + continue + + // --- Can understand the speech --- + if(!tcm.sender || R.say_understands(tcm.sender)) + + // - Not human or wearing a voice mask - + if(!tcm.sender || !ishuman(tcm.sender) || tcm.vmask) + heard_masked += R + + // - Human and not wearing voice mask - + else + heard_normal += R + + // --- Can't understand the speech --- + + else + // - Just display a garbled message - + heard_garbled += R + + + /* ###### Begin formatting and sending the message ###### */ + if(length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish)) + + /* --- Some miscellaneous variables to format the string output --- */ + var/freq_text = get_frequency_name(display_freq) + + var/part_b_extra = "" + var/part_a = "\[[freq_text]\][part_b_extra] " // goes in the actual output + + // --- Some more pre-message formatting --- + var/part_b = " " // Tweaked for security headsets -- TLE + var/part_c = "" + + + // --- Filter the message; place it in quotes apply a verb --- + var/quotedmsg = null + if(tcm.sender) + quotedmsg = "[tcm.sender.say_quote(multilingual_to_message(tcm.message_pieces))], \"[multilingual_to_message(tcm.message_pieces)]\"" + else + quotedmsg = "says, \"[multilingual_to_message(tcm.message_pieces)]\"" + + // --- This following recording is intended for research and feedback in the use of department radio channels --- + + var/part_blackbox_b = "
    \[[freq_text]\] " // Tweaked for security headsets -- TLE + var/blackbox_msg = "[part_a][tcm.sender_name][part_blackbox_b][quotedmsg][part_c]" + //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]" + + //BR.messages_admin += blackbox_admin_msg + if(istype(GLOB.blackbox)) + switch(display_freq) + if(PUB_FREQ) + GLOB.blackbox.msg_common += blackbox_msg + if(SCI_FREQ) + GLOB.blackbox.msg_science += blackbox_msg + if(COMM_FREQ) + GLOB.blackbox.msg_command += blackbox_msg + if(MED_FREQ) + GLOB.blackbox.msg_medical += blackbox_msg + if(ENG_FREQ) + GLOB.blackbox.msg_engineering += blackbox_msg + if(SEC_FREQ) + GLOB.blackbox.msg_security += blackbox_msg + if(DTH_FREQ) + GLOB.blackbox.msg_deathsquad += blackbox_msg + if(SYND_FREQ) + GLOB.blackbox.msg_syndicate += blackbox_msg + if(SYNDTEAM_FREQ) + GLOB.blackbox.msg_syndteam += blackbox_msg + if(SUP_FREQ) + GLOB.blackbox.msg_cargo += blackbox_msg + if(SRV_FREQ) + GLOB.blackbox.msg_service += blackbox_msg + else + GLOB.blackbox.messages += blackbox_msg + //End of research and feedback code. + + /* ###### Send the message ###### */ + + + /* --- Process all the mobs that heard a masked voice (understood) --- */ + + if(length(heard_masked)) + for(var/M in heard_masked) + var/mob/R = M + R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender, 0, tcm.sender_name, follow_target=tcm.follow_target) + + /* --- Process all the mobs that heard the voice normally (understood) --- */ + + if(length(heard_normal)) + for(var/M in heard_normal) + var/mob/R = M + R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender, 0, tcm.sender_name, follow_target=tcm.follow_target) + + /* --- Process all the mobs that heard the voice normally (did not understand) --- */ + + if(length(heard_voice)) + for(var/M in heard_voice) + var/mob/R = M + R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender,0, tcm.vname, follow_target=tcm.follow_target) + + /* --- Process all the mobs that heard a garbled voice (did not understand) --- */ + // Displays garbled message (ie "f*c* **u, **i*er!") + + if(length(heard_garbled)) + for(var/M in heard_garbled) + var/mob/R = M + R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender, 1, tcm.vname, follow_target=tcm.follow_target) + + + /* --- Complete gibberish. Usually happens when there's a compressed message --- */ + + if(length(heard_gibberish)) + for(var/M in heard_gibberish) + var/mob/R = M + R.hear_radio(tcm.message_pieces, tcm.verbage, part_a, part_b, tcm.sender, 1, follow_target=tcm.follow_target) + + return TRUE + + +/** + * # Telecommunications Password Paper + * + * Piece of paper that spawns with the default link password + * + * This is spawned in the CE office and has the default link password + * While convenient, this is not necessary and doesnt matter if it gets lost or destroyed + * Because you can view the password easily by just looking at the core link page + */ +/obj/item/paper/tcommskey + name = "Telecommunications linkage password" + +/** + * Password Paper Initializer + * + * This paper MUST be LateInitialized so the core has a chance to initialize and setup its password + * Otherwise shit breaks BADLY + */ +/obj/item/paper/tcommskey/Initialize(mapload) + return INITIALIZE_HINT_LATELOAD + +/** + * Password Paper Late Initializer + * + * Since the core was regularly initialized, we can now use the LateInitialize here to grab its password, then put it on paper + */ +/obj/item/paper/tcommskey/LateInitialize(mapload) + for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines) + if(C.network_id == "STATION-CORE") + info = "

    Telecommunications Key

    \n\t
    The station core linkage password is '[C.link_password]'.
    Should this paper be misplaced or destroyed, fear not, as the password is visible under the core linkage section. Should you wish to modify this password, it can be modified from the core." + info_links = info + update_icon() + // Save time, even though there should only be one STATION-CORE in the world + break + return ..() + diff --git a/code/game/machinery/tcomms/core.dm b/code/game/machinery/tcomms/core.dm new file mode 100644 index 00000000000..9e638913f9d --- /dev/null +++ b/code/game/machinery/tcomms/core.dm @@ -0,0 +1,265 @@ +#define UI_TAB_CONFIG "CONFIG" +#define UI_TAB_LINKS "LINKS" + +/** + * # Telecommunications Core + * + * The core of the entire telecomms operation + * + * This thing basically handles the main broadcasting of the data, as well as NTTC configs + * The relays dont do any actual processing, they are just objects which can bring tcomms to another zlevel + */ +/obj/machinery/tcomms/core + name = "Telecommunications Core" + desc = "A large rack full of communications equipment. Looks important." + icon_state = "core" + /// The NTTC config for this device + var/datum/nttc_configuration/nttc = new() + /// List of all reachable devices + var/list/reachable_zlevels = list() + /// List of all linked relays + var/list/linked_relays = list() + /// Password for linking stuff together + var/link_password + /// What tab of the UI were currently on + var/ui_tab = UI_TAB_CONFIG + +/** + * Initializer for the core. + * + * Calls parent to ensure its added to the GLOB of tcomms machines, before generating a link password and adding itself to the list of reachable Zs. + */ +/obj/machinery/tcomms/core/Initialize(mapload) + . = ..() + link_password = GenerateKey() + reachable_zlevels |= loc.z + +/** + * Destructor for the core. + * + * Ensures that the machine is taken out of the global list when destroyed, and also unlinks all connected relays + */ +/obj/machinery/tcomms/core/Destroy() + for(var/obj/machinery/tcomms/relay/R in linked_relays) + R.Reset() + QDEL_NULL(nttc) // Delete the NTTC datum + linked_relays.Cut() // Just to be sure + return ..() + +/** + * Helper to see if a zlevel is reachable + * + * This is a simple check to see if the input z-level is in the list of reachable ones + * Returns TRUE if it can, FALSE if it cant + * + * Arguments: + * * zlevel - The input z level to test + */ +/obj/machinery/tcomms/core/proc/zlevel_reachable(zlevel) + if(zlevel in reachable_zlevels) + return TRUE + else + return FALSE + +/** + * Proc which takes in the message datum + * + * Some checks are ran on the signal, and NTTC is applied + * After that, it is broadcasted out to the required Z-levels + * + * Arguments: + * * tcm - The tcomms message datum + */ +/obj/machinery/tcomms/core/proc/handle_message(datum/tcomms_message/tcm) + // Don't do anything with rejected signals, or if were offline, or if we have no power + if(tcm.reject || !active || (stat & NOPOWER)) + return FALSE + // Kill the signal if its on a z-level that isnt reachable + if(!zlevel_reachable(tcm.source_level)) + return FALSE + + // Now we can run NTTC + tcm = nttc.modify_message(tcm) + + // Now we generate the list of where that signal should go to + tcm.zlevels = reachable_zlevels + tcm.zlevels |= tcm.source_level + + // Now check if they actually have pieces, if so, broadcast + if(tcm.message_pieces) + broadcast_message(tcm) + return TRUE + + return FALSE + +/** + * Proc to remake the list of available zlevels + * + * Loops through the list of connected relays and adds their zlevels in. + * This is called if a relay is added or removed + * + */ +/obj/machinery/tcomms/core/proc/refresh_zlevels() + // Refresh the list + reachable_zlevels = list() + // Add itself as a reachable Z-level + reachable_zlevels |= loc.z + // Add all the linked relays in + for(var/obj/machinery/tcomms/relay/R in linked_relays) + // Only if the relay is active + if(R.active) + reachable_zlevels |= R.loc.z + + +////////////// +// UI STUFF // +////////////// + +/obj/machinery/tcomms/core/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + // this is silly but it has to be done because NTTC inits before languages do + if(nttc.valid_languages.len == 1) + nttc.update_languages() + + // Now the actual UI stuff + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "tcomms_core.tmpl", "Telecommunications Core", 900, 600) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/tcomms/core/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) + var/data[0] + // What tab are we on + data["tab"] = ui_tab + + // Only send NTTC settings if were on the right tab. This saves on sending overhead. + if(ui_tab == UI_TAB_CONFIG) + // Z-level list. Note that this will also show sectors with hidden relay links, but you cant see the relays themselves + // This allows the crew to realise that sectors have hidden relays + data["sectors_available"] = "Count: [length(reachable_zlevels)] | List: [jointext(reachable_zlevels, " ")]" + // Toggles + data["active"] = active + data["nttc_toggle_jobs"] = nttc.toggle_jobs + data["nttc_toggle_job_color"] = nttc.toggle_job_color + data["nttc_toggle_name_color"] = nttc.toggle_name_color + data["nttc_toggle_command_bold"] = nttc.toggle_command_bold + // Strings + data["nttc_setting_language"] = nttc.setting_language + data["nttc_job_indicator_type"] = nttc.job_indicator_type + // Network ID + data["network_id"] = network_id + + if(ui_tab == UI_TAB_LINKS) + data["link_password"] = link_password + // You ready to see some shit? + for(var/obj/machinery/tcomms/relay/R in linked_relays) + // Dont show relays with a hidden link + if(R.hidden_link) + continue + // Assume false + var/status = FALSE + var/status_color = "'background-color: #eb4034'" // Red + if(R.active && !(R.stat & NOPOWER)) + status = TRUE + status_color = "'background-color: #32a852'" // Green + + + + data["entries"] += list(list("addr" = "\ref[R]", "net_id" = R.network_id, "sector" = R.loc.z, "status" = status, "status_color" = status_color)) + // End the shit + + return data + +/obj/machinery/tcomms/core/Topic(href, href_list) + // Check against href exploits + if(..()) + return + + if(href_list["tab"]) + // Make sure its a valid tab + if(href_list["tab"] in list(UI_TAB_CONFIG, UI_TAB_LINKS)) + ui_tab = href_list["tab"] + + // Check if they did a href, but only for that current tab + if(ui_tab == UI_TAB_CONFIG) + // All the toggle on/offs go here + if(href_list["toggle_active"]) + active = !active + update_icon() + // NTTC Toggles + if(href_list["nttc_toggle_jobs"]) + nttc.toggle_jobs = !nttc.toggle_jobs + log_action(usr, "toggled job tags (Now [nttc.toggle_jobs])") + if(href_list["nttc_toggle_job_color"]) + nttc.toggle_job_color = !nttc.toggle_job_color + log_action(usr, "toggled job colors (Now [nttc.toggle_job_color])") + if(href_list["nttc_toggle_name_color"]) + nttc.toggle_name_color = !nttc.toggle_name_color + log_action(usr, "toggled name colors (Now [nttc.toggle_name_color])") + if(href_list["nttc_toggle_command_bold"]) + nttc.toggle_command_bold = !nttc.toggle_command_bold + log_action(usr, "toggled command bold (Now [nttc.toggle_command_bold])") + // We need to be a little more fancy for the others + + // Job Format + if(href_list["nttc_job_indicator_type"]) + var/card_style = input(usr, "Pick a job card format.", "Job Card Format") as null|anything in nttc.job_card_styles + if(!card_style) + return + nttc.job_indicator_type = card_style + to_chat(usr, "Jobs will now have the style of [card_style].") + log_action(usr, "has set NTTC job card format to [card_style]") + + // Language Settings + if(href_list["nttc_setting_language"]) + var/new_language = input(usr, "Pick a language to convert messages to.", "Language Conversion") as null|anything in nttc.valid_languages + if(!new_language) + return + if(new_language == "--DISABLE--") + nttc.setting_language = null + to_chat(usr, "Language conversion disabled.") + else + nttc.setting_language = new_language + to_chat(usr, "Messages will now be converted to [new_language].") + + log_action(usr, new_language == "--DISABLE--" ? "disabled NTTC language conversion" : "set NTTC language conversion to [new_language]", TRUE) + + // Imports and exports + if(href_list["import"]) + var/json = input(usr, "Provide configuration JSON below.", "Load Config", nttc.nttc_serialize()) as message + if(nttc.nttc_deserialize(json, usr.ckey)) + log_action(usr, "has uploaded a NTTC JSON configuration: [ADMIN_SHOWDETAILS("Show", json)]", TRUE) + + if(href_list["export"]) + usr << browse(nttc.nttc_serialize(), "window=save_nttc") + + // Set network ID + if(href_list["network_id"]) + var/new_id = input(usr, "Please enter a new network ID", "Network ID", network_id) + log_action(usr, "renamed core with ID [network_id] to [new_id]") + to_chat(usr, "Device ID changed from [network_id] to [new_id].") + network_id = new_id + + if(ui_tab == UI_TAB_LINKS) + if(href_list["unlink"]) + var/obj/machinery/tcomms/relay/R = locate(href_list["unlink"]) + if(istype(R, /obj/machinery/tcomms/relay)) + var/confirm = alert("Are you sure you want to unlink this relay?\nID: [R.network_id]\nADDR: \ref[R]", "Relay Unlink", "Yes", "No") + if(confirm == "Yes") + log_action(usr, "has unlinked tcomms relay with ID [R.network_id] from tcomms core with ID [network_id]", TRUE) + R.Reset() + else + to_chat(usr, "ERROR: Relay not found. Please file an issue report.") + + if(href_list["change_password"]) + var/new_password = input(usr, "Please enter a new password","New Password", link_password) + log_action(usr, "has changed the password on core with ID [network_id] from [link_password] to [new_password]") + to_chat(usr, "Successfully changed password from [link_password] to [new_password].") + link_password = new_password + + + // Hack to speed update the nanoUI + SSnanoui.update_uis(src) + +#undef UI_TAB_CONFIG +#undef UI_TAB_LINKS diff --git a/code/game/machinery/tcomms/nttc.dm b/code/game/machinery/tcomms/nttc.dm new file mode 100644 index 00000000000..6ee158c6cc0 --- /dev/null +++ b/code/game/machinery/tcomms/nttc.dm @@ -0,0 +1,288 @@ +/* + NTTC system + This is basically the replacement for NTSL and allows tickbox features such as job titles and colours, without needing a script + This also means that there is no user input here, which means the system isnt prone to exploits since its only selecting options, no user input + Basically, just imagine pfSense for tcomsm + + All this code was written by Tigercat2000. I take no credit -aa07 +*/ + +#define JOB_STYLE_1 "Name (Job)" +#define JOB_STYLE_2 "Name - Job" +#define JOB_STYLE_3 "\[Job\] Name" +#define JOB_STYLE_4 "(Job) Name" + +/datum/nttc_configuration + var/regex/word_blacklist = new("(EXPLOIT WARNING:
    [ckey] attempted to upload an NTTC configuration containing JS abusable tags!") + log_admin("EXPLOIT WARNING: [ckey] attempted to upload an NTTC configuration containing JS abusable tags") + return FALSE + var/list/var_list = json_decode(text) + for(var/variable in var_list) + if(variable in to_serialize) // Don't just accept any random vars jesus christ! + var/sanitize_method = serialize_sanitize[variable] + var/variable_value = var_list[variable] + variable_value = nttc_sanitize(variable_value, sanitize_method) + if(variable_value != null) + vars[variable] = variable_value + return TRUE + +// Sanitizing user input. Don't blindly trust the JSON. +/datum/nttc_configuration/proc/nttc_sanitize(variable, sanitize_method) + if(!sanitize_method) + return null + + switch(sanitize_method) + if("bool") + return variable ? TRUE : FALSE + // if("table", "array") + if("array") + if(!islist(variable)) + return list() + // Insert html filtering for the regexes here if you're boring + var/newlist = json_decode(html_decode(json_encode(variable))) + if(!islist(newlist)) + return null + return newlist + if("string") + return "[variable]" + + return variable + +// Primary signal modification. This is where all of the variables behavior are actually implemented. +/datum/nttc_configuration/proc/modify_message(datum/tcomms_message/tcm) + // All job and coloring shit + if(toggle_job_color || toggle_name_color) + var/job = tcm.sender_job + job_class = all_jobs[job] + + if(toggle_name_color) + var/new_name = "" + tcm.sender_name + "" + tcm.sender_name = new_name + tcm.vname = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on + + if(toggle_jobs) + var/new_name = "" + var/job = tcm.sender_job + if(job in ert_jobs) + job = "ERT" + if(toggle_job_color) + switch(job_indicator_type) + // These must have trailing spaces. No exceptions. + if(JOB_STYLE_1) + new_name = "[tcm.sender_name] ([job]) " + if(JOB_STYLE_2) + new_name = "[tcm.sender_name] - [job] " + if(JOB_STYLE_3) + new_name = "\[[job]\] [tcm.sender_name] " + if(JOB_STYLE_4) + new_name = "([job]) [tcm.sender_name] " + else + switch(job_indicator_type) + if(JOB_STYLE_1) + new_name = "[tcm.sender_name] ([job]) " + if(JOB_STYLE_2) + new_name = "[tcm.sender_name] - [job] " + if(JOB_STYLE_3) + new_name = "\[[job]\] [tcm.sender_name] " + if(JOB_STYLE_4) + new_name = "([job]) [tcm.sender_name] " + + // Only change the name if they have a job tag set, otherwise everyone becomes unknown, and thats bad + if(new_name != "") + tcm.sender_name = new_name + tcm.vname = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on + // This is hacky stuff for multilingual messages... + var/list/message_pieces = tcm.message_pieces + + // Makes heads of staff bold + if(toggle_command_bold) + var/job = tcm.sender_job + if((job in ert_jobs) || (job in heads)) + for(var/datum/multilingual_say_piece/S in message_pieces) + S.message = "[capitalize(S.message)]" // This only capitalizes the first word + + // Language Conversion + if(setting_language && valid_languages[setting_language]) + if(setting_language == "--DISABLE--") + setting_language = null + else + for(var/datum/multilingual_say_piece/S in message_pieces) + if(S.speaking != GLOB.all_languages["Noise"]) // check if they are emoting, these do not need to be translated + S.speaking = GLOB.all_languages[setting_language] + + return tcm + +#undef JOB_STYLE_1 +#undef JOB_STYLE_2 +#undef JOB_STYLE_3 +#undef JOB_STYLE_4 diff --git a/code/game/machinery/tcomms/presets.dm b/code/game/machinery/tcomms/presets.dm new file mode 100644 index 00000000000..efc98866f62 --- /dev/null +++ b/code/game/machinery/tcomms/presets.dm @@ -0,0 +1,32 @@ +/* + All machine presets go in here +*/ + +// STATION CORE // +/obj/machinery/tcomms/core/station + network_id = "STATION-CORE" + +// MINING RELAY // +/obj/machinery/tcomms/relay/mining + network_id = "MINING-RELAY" + autolink_id = "STATION-CORE" + +// ENGINEERING RELAY // +/obj/machinery/tcomms/relay/engineering + network_id = "ENGINEERING-RELAY" + autolink_id = "STATION-CORE" + active = FALSE + +// RUSKIE RELAY // +/obj/machinery/tcomms/relay/ruskie + network_id = "RUSKIE-RELAY" + autolink_id = "STATION-CORE" + active = FALSE + hidden_link = TRUE + +// CC RELAY // +/obj/machinery/tcomms/relay/cc + network_id = "CENTCOMM-RELAY" + autolink_id = "STATION-CORE" + hidden_link = TRUE + diff --git a/code/game/machinery/tcomms/relay.dm b/code/game/machinery/tcomms/relay.dm new file mode 100644 index 00000000000..8c2bbf28bf2 --- /dev/null +++ b/code/game/machinery/tcomms/relay.dm @@ -0,0 +1,180 @@ +/** + * # Telecommunications Relay + * + * Extends the reach of telecomms to the z-level it is built on + * + * Relays themselves dont do any processing, they just tell the core that this z-level is available in the tcomms network. + */ +/obj/machinery/tcomms/relay + name = "Telecommunications Relay" + desc = "A large device with several radio antennas on it." + icon_state = "relay" + /// The host core for this relay + var/obj/machinery/tcomms/core/linked_core + /// ID of the hub to auto link to + var/autolink_id + /// Is this linked to anything at all + var/linked = FALSE + /// Is this link invisible on the hub? + var/hidden_link = FALSE + +/** + * Initializer for the relay. + * + * Calls parent to ensure its added to the GLOB of tcomms machines, before checking if there is an autolink that needs to be added. + */ +/obj/machinery/tcomms/relay/Initialize(mapload) + . = ..() + if(mapload && autolink_id) + return INITIALIZE_HINT_LATELOAD + +/** + * Descrutor for the relay. + * + * Ensures that the machine is taken out of the global list when destroyed, and also removes the link to the core. + */ +/obj/machinery/tcomms/relay/Destroy() + Reset() + return ..() + +/** + * Late Initialize for the relay. + * + * Calls parent, then adds links to the cores. This is a LateInitialize because the core MUST be initialized first + */ +/obj/machinery/tcomms/relay/LateInitialize() + . = ..() + for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines) + if(C.network_id == autolink_id) + AddLink(C) + // Only ONE of these with one ID should exist per world + break + +/** + * Proc to link the relay to the core. + * + * Sets the linked core to the target (argument below), before adding it to the list of linked relays, then re-freshing the zlevel list + * The relay is then marked as linked + * Arguments: + * * target - The telecomms core that this relay should be linked to + */ +/obj/machinery/tcomms/relay/proc/AddLink(obj/machinery/tcomms/core/target) + linked_core = target + target.linked_relays |= src + target.refresh_zlevels() + linked = TRUE + +/** + * Proc to rest the relay. + * + * Resets the relay, removing its linkage status, and refreshing the core's list of z-levels + */ +/obj/machinery/tcomms/relay/proc/Reset() + if(linked_core) + linked_core.linked_relays -= src + linked_core.refresh_zlevels() + linked_core = null + linked = FALSE + +/** + * Relay Enabler + * + * Modification to the standard one so that the links get updated + */ +/obj/machinery/tcomms/relay/enable_machine() + ..() + if(linked_core) + linked_core.refresh_zlevels() + +/** + * Relay Disabler + * + * Modification to the standard one so that the links get updated + */ +/obj/machinery/tcomms/relay/disable_machine() + ..() + if(linked_core) + linked_core.refresh_zlevels() + + +////////////// +// UI STUFF // +////////////// + +/obj/machinery/tcomms/relay/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "tcomms_relay.tmpl", "Telecommunications Relay", 600, 400) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/tcomms/relay/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) + var/data[0] + // Are we on or not + data["active"] = active + // What is our network ID + data["network_id"] = network_id + // Are we linked + data["linked"] = linked + // Is the link hidden + data["hidden_link"] = hidden_link + + // Only send linked tab stuff if we are linked. This saves on sending overhead. + if(linked) + data["linked_core_id"] = linked_core.network_id + data["linked_core_addr"] = "\ref[linked_core]" + + else + for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines) + data["entries"] += list(list("addr" = "\ref[C]", "net_id" = C.network_id, "sector" = C.loc.z)) + + return data + +/obj/machinery/tcomms/relay/Topic(href, href_list) + // Check against href exploits + if(..()) + return + + // All the toggle on/offs go here + if(href_list["toggle_active"]) + active = !active + update_icon() + if(linked_core) + linked_core.refresh_zlevels() + + // Set network ID + if(href_list["network_id"]) + var/new_id = input(usr, "Please enter a new network ID", "Network ID", network_id) + log_action(usr, "renamed core with ID [network_id] to [new_id]") + to_chat(usr, "Device ID changed from [network_id] to [new_id].") + network_id = new_id + + if(linked) + // Only do these hrefs if we are linked to prevent bugs/exploits + if(href_list["toggle_hidden_link"]) + hidden_link = !hidden_link + log_action(usr, "Modified hidden link for [network_id] (Now [hidden_link])") + + if(href_list["unlink"]) + var/choice = alert(usr, "Are you SURE you want to unlink this relay?\nYou wont be able to re-link without the core password", "Unlink","Yes","No") + if(choice == "Yes") + log_action(usr, "Unlinked [network_id] from [linked_core.network_id]") + Reset() + else + // You should only be able to link if its not linked, to prevent weirdness + if(href_list["link"]) + var/obj/machinery/tcomms/core/C = locate(href_list["link"]) + if(istype(C, /obj/machinery/tcomms/core)) + var/user_pass = input(usr, "Please enter core password","Password Entry") + // Check the password + if(user_pass == C.link_password) + AddLink(C) + to_chat(usr, "Successfully linked to [C.network_id].") + else + to_chat(usr, "ERROR: Password incorrect.") + else + to_chat(usr, "ERROR: Core not found. Please file an issue report.") + + + // Hack to speed update the nanoUI + SSnanoui.update_uis(src) diff --git a/code/game/machinery/telecomms/broadcaster.dm b/code/game/machinery/telecomms/broadcaster.dm deleted file mode 100644 index 8cd285c994a..00000000000 --- a/code/game/machinery/telecomms/broadcaster.dm +++ /dev/null @@ -1,665 +0,0 @@ -/* - The broadcaster sends processed messages to all radio devices in the game. They - do not have to be headsets; intercoms and station-bounced radios suffice. - - They receive their message from a server after the message has been logged. -*/ - -var/list/recentmessages = list() // global list of recent messages broadcasted : used to circumvent massive radio spam -var/message_delay = 0 // To make sure restarting the recentmessages list is kept in sync - -/obj/machinery/telecomms/broadcaster - name = "Subspace Broadcaster" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "broadcaster" - desc = "A dish-shaped machine used to broadcast processed subspace signals." - density = 1 - anchored = 1 - use_power = IDLE_POWER_USE - idle_power_usage = 25 - machinetype = 5 - circuitboard = /obj/item/circuitboard/telecomms/broadcaster - -/obj/machinery/telecomms/broadcaster/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - // Don't broadcast rejected signals - if(signal.data["reject"]) - return - - if(signal.data["message"]) - - // Prevents massive radio spam - signal.data["done"] = 1 // mark the signal as being broadcasted - // Search for the original signal and mark it as done as well - var/datum/signal/original = signal.data["original"] - if(original) - original.data["done"] = 1 - original.data["compression"] = signal.data["compression"] - original.data["level"] = signal.data["level"] - - var/signal_message = "[signal.frequency]:[signal.data["message"]]:[signal.data["realname"]]" - if(signal_message in recentmessages) - return - recentmessages.Add(signal_message) - - if(signal.data["slow"] > 0) - sleep(signal.data["slow"]) // simulate the network lag if necessary - - signal.data["level"] |= listening_level - - /** #### - Normal Broadcast - #### **/ - - if(signal.data["type"] == 0) - - /* ###### Broadcast a message using signal.data ###### */ - Broadcast_Message(signal.data["connection"], signal.data["mob"], - signal.data["vmask"], signal.data["vmessage"], - signal.data["radio"], signal.data["message"], - signal.data["name"], signal.data["job"], - signal.data["realname"], signal.data["vname"],, - signal.data["compression"], signal.data["level"], signal.frequency, - signal.data["verb"] ) - - - /** #### - Simple Broadcast - #### **/ - - if(signal.data["type"] == 1) - - /* ###### Broadcast a message using signal.data ###### */ - Broadcast_SimpleMessage(signal.data["name"], signal.frequency, - signal.data["message"],null, null, - signal.data["compression"], listening_level) - - - /** #### - Artificial Broadcast - #### **/ - // (Imitates a mob) - - if(signal.data["type"] == 2) - - /* ###### Broadcast a message using signal.data ###### */ - // Parameter "data" as 4: AI can't track this person/mob - - Broadcast_Message(signal.data["connection"], signal.data["mob"], - signal.data["vmask"], signal.data["vmessage"], - signal.data["radio"], signal.data["message"], - signal.data["name"], signal.data["job"], - signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency, - signal.data["verb"]) - - if(!message_delay) - message_delay = 1 - spawn(10) - message_delay = 0 - recentmessages = list() - - /* --- Do a snazzy animation! --- */ - flick("broadcaster_send", src) - -/obj/machinery/telecomms/broadcaster/Destroy() - // In case message_delay is left on 1, otherwise it won't reset the list and people can't say the same thing twice anymore. - if(message_delay) - message_delay = 0 - return ..() - - -/* - Basically just an empty shell for receiving and broadcasting radio messages. Not - very flexible, but it gets the job done. -*/ - -/obj/machinery/telecomms/allinone - name = "Telecommunications Mainframe" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "comm_server" - desc = "A compact machine used for portable subspace telecommuniations processing." - density = 1 - anchored = 1 - use_power = NO_POWER_USE - idle_power_usage = 0 - machinetype = 6 - var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel - -/obj/machinery/telecomms/allinone/receive_signal(datum/signal/signal) - - if(!on) // has to be on to receive messages - return - - if(is_freq_listening(signal)) // detect subspace signals - - signal.data["done"] = 1 // mark the signal as being broadcasted - signal.data["compression"] = 0 - - // Search for the original signal and mark it as done as well - var/datum/signal/original = signal.data["original"] - if(original) - original.data["done"] = 1 - - if(signal.data["slow"] > 0) - sleep(signal.data["slow"]) // simulate the network lag if necessary - - /* ###### Broadcast a message using signal.data ###### */ - - var/datum/radio_frequency/connection = signal.data["connection"] - - if(connection.frequency in SSradio.ANTAG_FREQS) // if antag broadcast, just - Broadcast_Message(signal.data["connection"], signal.data["mob"], - signal.data["vmask"], signal.data["vmessage"], - signal.data["radio"], signal.data["message"], - signal.data["name"], signal.data["job"], - signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency, - signal.data["verb"]) - else - if(intercept) - Broadcast_Message(signal.data["connection"], signal.data["mob"], - signal.data["vmask"], signal.data["vmessage"], - signal.data["radio"], signal.data["message"], - signal.data["name"], signal.data["job"], - signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency, - signal.data["verb"]) - -#define CREW_RADIO_TYPE 0 -#define CENTCOMM_RADIO_TYPE 1 -#define SYNDICATE_RADIO_TYPE 2 -/proc/Is_Bad_Connection(old_freq, new_freq) //Makes sure players cant read radios of a higher level than they are - var/old_type = CREW_RADIO_TYPE - var/new_type = CREW_RADIO_TYPE - for(var/antag_freq in SSradio.ANTAG_FREQS) - if(old_freq == antag_freq) - old_type = SYNDICATE_RADIO_TYPE - if(new_freq == antag_freq) - new_type = SYNDICATE_RADIO_TYPE - - for(var/cent_freq in SSradio.CENT_FREQS) - if(old_freq == cent_freq) - old_type = CENTCOMM_RADIO_TYPE - if(new_freq == cent_freq) - new_type = CENTCOMM_RADIO_TYPE - - return new_type > old_type - -/** - - Here is the big, bad function that broadcasts a message given the appropriate - parameters. - - @param connection: - The datum generated in radio.dm, stored in signal.data["connection"]. - - @param M: - Reference to the mob/speaker, stored in signal.data["mob"] - - @param vmask: - Boolean value if the mob is "hiding" its identity via voice mask, stored in - signal.data["vmask"] - - @param vmessage: - If specified, will display this as the message; such as "chimpering" - for monkies if the mob is not understood. Stored in signal.data["vmessage"]. - - @param radio: - Reference to the radio broadcasting the message, stored in signal.data["radio"] - - @param message: - The actual string message to display to mobs who understood mob M. Stored in - signal.data["message"] - - @param name: - The name to display when a mob receives the message. signal.data["name"] - - @param job: - The name job to display for the AI when it receives the message. signal.data["job"] - - @param realname: - The "real" name associated with the mob. signal.data["realname"] - - @param vname: - If specified, will use this name when mob M is not understood. signal.data["vname"] - - @param data: - If specified: - 1 -- Will only broadcast to intercoms - 2 -- Will only broadcast to intercoms and station-bounced radios - 3 -- Broadcast to syndicate frequency - 4 -- AI can't track down this person. Useful for imitation broadcasts where you can't find the actual mob - - @param compression: - If 0, the signal is audible - If nonzero, the signal may be partially inaudible or just complete gibberish. - - @param level: - The list of Z levels that the sending radio is broadcasting to. Having 0 in the list broadcasts on all levels - - @param freq - The frequency of the signal - -**/ - -/proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M, - var/vmask, list/vmessage_pieces, var/obj/item/radio/radio, - list/message_pieces, var/name, var/job, var/realname, var/vname, - var/data, var/compression, var/list/level, var/freq, var/verbage = "says", - var/atom/follow_target = null) - - - /* ###### Prepare the radio connection ###### */ - - var/display_freq = freq - - var/bad_connection = FALSE - var/datum/radio_frequency/new_connection = connection - - if(connection.frequency != display_freq) - bad_connection = Is_Bad_Connection(connection.frequency, display_freq) - new_connection = SSradio.return_frequency(display_freq) - - var/list/obj/item/radio/radios = list() - - // --- Broadcast only to intercom devices --- - - if(data == 1 && !bad_connection) - - for(var/obj/item/radio/intercom/R in new_connection.devices["[RADIO_CHAT]"]) - if(R.receive_range(display_freq, level) > -1) - radios += R - - // --- Broadcast only to intercoms and station-bounced radios --- - - else if(data == 2 && !bad_connection) - - for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"]) - - if(istype(R, /obj/item/radio/headset)) - continue - - if(R.receive_range(display_freq, level) > -1) - radios += R - - // --- Broadcast to antag radios! --- - - else if(data == 3) - for(var/antag_freq in SSradio.ANTAG_FREQS) - var/datum/radio_frequency/antag_connection = SSradio.return_frequency(antag_freq) - for(var/obj/item/radio/R in antag_connection.devices["[RADIO_CHAT]"]) - if(R.receive_range(antag_freq, level) > -1) - radios += R - - // --- Broadcast to ALL radio devices --- - - else if(!bad_connection) - - for(var/obj/item/radio/R in new_connection.devices["[RADIO_CHAT]"]) - if(R.receive_range(display_freq, level) > -1) - radios += R - - // Get a list of mobs who can hear from the radios we collected. - var/list/receive = get_mobs_in_radio_ranges(radios) - - /* ###### Organize the receivers into categories for displaying the message ###### */ - - // Understood the message: - var/list/heard_masked = list() // masked name or no real name - var/list/heard_normal = list() // normal message - - // Did not understand the message: - var/list/heard_voice = list() // voice message (ie "chimpers") - var/list/heard_garbled = list() // garbled message (ie "f*c* **u, **i*er!") - var/list/heard_gibberish= list() // completely screwed over message (ie "F%! (O*# *#!<>&**%!") - - for(var/mob/R in receive) - - /* --- Loop through the receivers and categorize them --- */ - - if(is_admin(R) && !R.get_preference(CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. - continue - - if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes. - continue - - // Ghosts hearing all radio chat don't want to hear syndicate intercepts, they're duplicates - if(data == 3 && istype(R, /mob/dead/observer) && R.get_preference(CHAT_GHOSTRADIO)) - continue - - // --- Check for compression --- - if(compression > 0) - heard_gibberish += R - continue - - // --- Can understand the speech --- - - if(!M || R.say_understands(M)) - - // - Not human or wearing a voice mask - - if(!M || !ishuman(M) || vmask) - heard_masked += R - - // - Human and not wearing voice mask - - else - heard_normal += R - - // --- Can't understand the speech --- - - else - // - The speaker has a prespecified "voice message" to display if not understood - - if(vmessage_pieces) - heard_voice += R - - // - Just display a garbled message - - else - heard_garbled += R - - - /* ###### Begin formatting and sending the message ###### */ - if(length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish)) - - /* --- Some miscellaneous variables to format the string output --- */ - var/freq_text = get_frequency_name(display_freq) - - var/part_b_extra = "" - if(data == 3) // intercepted radio message - part_b_extra = " (Intercepted)" - var/part_a = "\[[freq_text]\][part_b_extra] " // goes in the actual output - - // --- Some more pre-message formatting --- - var/part_b = " " // Tweaked for security headsets -- TLE - var/part_c = "" - - - // --- Filter the message; place it in quotes apply a verb --- - var/quotedmsg = null - if(M) - quotedmsg = "[M.say_quote(multilingual_to_message(message_pieces))], \"[multilingual_to_message(message_pieces)]\"" - else - quotedmsg = "says, \"[multilingual_to_message(message_pieces)]\"" - - // --- This following recording is intended for research and feedback in the use of department radio channels --- - - var/part_blackbox_b = "
    \[[freq_text]\] " // Tweaked for security headsets -- TLE - var/blackbox_msg = "[part_a][name][part_blackbox_b][quotedmsg][part_c]" - //var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]" - - //BR.messages_admin += blackbox_admin_msg - if(istype(blackbox)) - switch(display_freq) - if(PUB_FREQ) - blackbox.msg_common += blackbox_msg - if(SCI_FREQ) - blackbox.msg_science += blackbox_msg - if(COMM_FREQ) - blackbox.msg_command += blackbox_msg - if(MED_FREQ) - blackbox.msg_medical += blackbox_msg - if(ENG_FREQ) - blackbox.msg_engineering += blackbox_msg - if(SEC_FREQ) - blackbox.msg_security += blackbox_msg - if(DTH_FREQ) - blackbox.msg_deathsquad += blackbox_msg - if(SYND_FREQ) - blackbox.msg_syndicate += blackbox_msg - if(SYNDTEAM_FREQ) - blackbox.msg_syndteam += blackbox_msg - if(SUP_FREQ) - blackbox.msg_cargo += blackbox_msg - if(SRV_FREQ) - blackbox.msg_service += blackbox_msg - else - blackbox.messages += blackbox_msg - - //End of research and feedback code. - - /* ###### Send the message ###### */ - - - /* --- Process all the mobs that heard a masked voice (understood) --- */ - - if(length(heard_masked)) - for(var/mob/R in heard_masked) - R.hear_radio(message_pieces, verbage, part_a, part_b, M, 0, name, follow_target=follow_target) - - /* --- Process all the mobs that heard the voice normally (understood) --- */ - - if(length(heard_normal)) - for(var/mob/R in heard_normal) - R.hear_radio(message_pieces, verbage, part_a, part_b, M, 0, realname, follow_target=follow_target) - - /* --- Process all the mobs that heard the voice normally (did not understand) --- */ - - if(length(heard_voice)) - for(var/mob/R in heard_voice) - R.hear_radio(message_pieces, verbage, part_a, part_b, M,0, vname, follow_target=follow_target) - - /* --- Process all the mobs that heard a garbled voice (did not understand) --- */ - // Displays garbled message (ie "f*c* **u, **i*er!") - - if(length(heard_garbled)) - for(var/mob/R in heard_garbled) - R.hear_radio(message_pieces, verbage, part_a, part_b, M, 1, vname, follow_target=follow_target) - - - /* --- Complete gibberish. Usually happens when there's a compressed message --- */ - - if(length(heard_gibberish)) - for(var/mob/R in heard_gibberish) - R.hear_radio(message_pieces, verbage, part_a, part_b, M, 1, follow_target=follow_target) - - return 1 - -/proc/Broadcast_SimpleMessage(var/source, var/frequency, list/message_pieces, var/data, var/mob/M, var/compression, var/level) - var/text = multilingual_to_message(message_pieces) - /* ###### Prepare the radio connection ###### */ - - var/mob/living/carbon/human/H - if(!M) - H = new - M = H - - var/datum/radio_frequency/connection = SSradio.return_frequency(frequency) - - var/display_freq = connection.frequency - - var/list/receive = list() - - - // --- Broadcast only to intercom devices --- - - if(data == 1) - for(var/obj/item/radio/intercom/R in connection.devices["[RADIO_CHAT]"]) - var/turf/position = get_turf(R) - // TODO: Make the radio system cooperate with the space manager - if(position && position.z == level) - receive |= R.send_hear(display_freq, level) - - - // --- Broadcast only to intercoms and station-bounced radios --- - - else if(data == 2) - for(var/obj/item/radio/R in connection.devices["[RADIO_CHAT]"]) - - if(istype(R, /obj/item/radio/headset)) - continue - var/turf/position = get_turf(R) - // TODO: Make the radio system cooperate with the space manager - if(position && position.z == level) - receive |= R.send_hear(display_freq) - - - // --- Broadcast to antag radios! --- - - else if(data == 3) - for(var/freq in SSradio.ANTAG_FREQS) - var/datum/radio_frequency/antag_connection = SSradio.return_frequency(freq) - for(var/obj/item/radio/R in antag_connection.devices["[RADIO_CHAT]"]) - var/turf/position = get_turf(R) - // TODO: Make the radio system cooperate with the space manager - if(position && position.z == level) - receive |= R.send_hear(freq) - - - // --- Broadcast to ALL radio devices --- - - else - for(var/obj/item/radio/R in connection.devices["[RADIO_CHAT]"]) - var/turf/position = get_turf(R) - // TODO: Make the radio system cooperate with the space manager - if(position && position.z == level) - receive |= R.send_hear(display_freq) - - - /* ###### Organize the receivers into categories for displaying the message ###### */ - - // Understood the message: - var/list/heard_normal = list() // normal message - - // Did not understand the message: - var/list/heard_garbled = list() // garbled message (ie "f*c* **u, **i*er!") - var/list/heard_gibberish= list() // completely screwed over message (ie "F%! (O*# *#!<>&**%!") - - for(var/mob/R in receive) - - /* --- Loop through the receivers and categorize them --- */ - - if(R.client && !R.get_preference(CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios. - continue - - - // --- Check for compression --- - if(compression > 0) - - heard_gibberish += R - continue - - // --- Can understand the speech --- - - if(R.say_understands(M)) - - heard_normal += R - - // --- Can't understand the speech --- - - else - // - Just display a garbled message - - - heard_garbled += R - - - /* ###### Begin formatting and sending the message ###### */ - if(length(heard_normal) || length(heard_garbled) || length(heard_gibberish)) - - /* --- Some miscellaneous variables to format the string output --- */ - var/part_a = "" // goes in the actual output - var/freq_text = get_frequency_name(display_freq) - - // --- Some more pre-message formatting --- - - var/part_b_extra = "" - if(data == 3) // intercepted radio message - part_b_extra = " (Intercepted)" - - var/part_b = " \[[freq_text]\][part_b_extra] " // Tweaked for security headsets -- TLE - var/part_blackbox_b = " \[[freq_text]\] " - var/part_c = "" - - var/blackbox_msg = "[part_a][source][part_blackbox_b]\"[text]\"[part_c]" - - //BR.messages_admin += blackbox_admin_msg - if(istype(blackbox)) - switch(display_freq) - if(PUB_FREQ) - blackbox.msg_common += blackbox_msg - if(SCI_FREQ) - blackbox.msg_science += blackbox_msg - if(COMM_FREQ) - blackbox.msg_command += blackbox_msg - if(MED_FREQ) - blackbox.msg_medical += blackbox_msg - if(ENG_FREQ) - blackbox.msg_engineering += blackbox_msg - if(SEC_FREQ) - blackbox.msg_security += blackbox_msg - if(DTH_FREQ) - blackbox.msg_deathsquad += blackbox_msg - if(SYND_FREQ) - blackbox.msg_syndicate += blackbox_msg - if(SYNDTEAM_FREQ) - blackbox.msg_syndteam += blackbox_msg - if(SUP_FREQ) - blackbox.msg_cargo += blackbox_msg - if(SRV_FREQ) - blackbox.msg_service += blackbox_msg - else - blackbox.messages += blackbox_msg - - //End of research and feedback code. - - /* ###### Send the message ###### */ - - /* --- Process all the mobs that heard the voice normally (understood) --- */ - - if(length(heard_normal)) - var/rendered = "[part_a][source][part_b]\"[text]\"[part_c]" - - for(var/mob/R in heard_normal) - R.show_message(rendered, 2) - - /* --- Process all the mobs that heard a garbled voice (did not understand) --- */ - // Displays garbled message (ie "f*c* **u, **i*er!") - - if(length(heard_garbled)) - var/quotedmsg = "\"[stars(text)]\"" - var/rendered = "[part_a][source][part_b][quotedmsg][part_c]" - - for(var/mob/R in heard_garbled) - R.show_message(rendered, 2) - - - /* --- Complete gibberish. Usually happens when there's a compressed message --- */ - - if(length(heard_gibberish)) - var/quotedmsg = "\"[Gibberish(text, compression + 50)]\"" - var/rendered = "[part_a][Gibberish(source, compression + 50)][part_b][quotedmsg][part_c]" - - for(var/mob/R in heard_gibberish) - R.show_message(rendered, 2) - - if(H) - qdel(H) - -//Use this to test if an obj can communicate with a Telecommunications Network - -/atom/proc/test_telecomms() - var/datum/signal/signal = src.telecomms_process() - var/turf/position = get_turf(src) - // TODO: Make the radio system cooperate with the space manager - return (position.z in signal.data["level"]) && signal.data["done"] - -/atom/proc/telecomms_process(var/do_sleep = 1) - - // First, we want to generate a new radio signal - var/datum/signal/signal = new - signal.transmission_method = 2 // 2 would be a subspace transmission. - var/turf/pos = get_turf(src) - - // --- Finally, tag the actual signal with the appropriate values --- - signal.data = list( - "slow" = 0, // how much to sleep() before broadcasting - simulates net lag - "message" = "TEST", - "compression" = rand(45, 50), // If the signal is compressed, compress our message too. - "traffic" = 0, // dictates the total traffic sum that the signal went through - "type" = 4, // determines what type of radio input it is: test broadcast - "reject" = 0, - "done" = 0, - // TODO: Make the radio system cooperate with the space manager - "level" = pos.z // The level it is being broadcasted at. - ) - signal.frequency = PUB_FREQ// Common channel - - //#### Sending the signal to all subspace receivers ####// - for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - spawn(0) - R.receive_signal(signal) - - if(do_sleep) - sleep(rand(10,25)) - - //log_world("Level: [signal.data["level"]] - Done: [signal.data["done"]]") - - return signal diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm deleted file mode 100644 index f0b5a945f92..00000000000 --- a/code/game/machinery/telecomms/logbrowser.dm +++ /dev/null @@ -1,219 +0,0 @@ -/obj/machinery/computer/telecomms - - light_color = LIGHT_COLOR_DARKGREEN - -/obj/machinery/computer/telecomms/server - name = "telecommunications server monitor" - icon_screen = "comm_logs" - - - var/screen = 0 // the screen number: - var/list/servers = list() // the servers located by the computer - var/obj/machinery/telecomms/server/SelectedServer - - var/network = "NULL" // the network to probe - var/temp = "" // temporary feedback messages - - var/universal_translate = 0 // set to 1 if it can translate nonhuman speech - - req_access = list(ACCESS_TCOMSAT) - circuit = /obj/item/circuitboard/comm_server - - attack_hand(mob/user as mob) - if(stat & (BROKEN|NOPOWER)) - return - user.set_machine(src) - var/list/dat = list() - dat += "Telecommunication Server Monitor
    Telecommunications Server Monitor
    " - - switch(screen) - - - // --- Main Menu --- - - if(0) - dat += "
    [temp]
    " - dat += "
    Current Network: [network]
    " - if(servers.len) - dat += "
    Detected Telecommunication Servers:
      " - for(var/obj/machinery/telecomms/T in servers) - dat += "
    • \ref[T] [T.name] ([T.id])
    • " - dat += "
    " - dat += "
    \[Flush Buffer\]" - - else - dat += "
    No servers detected. Scan for servers: \[Scan\]" - - - // --- Viewing Server --- - - if(1) - dat += "
    [temp]
    " - dat += "
    \[Main Menu\] \[Refresh\]
    " - dat += "
    Current Network: [network]" - dat += "
    Selected Server: [SelectedServer.id]" - - if(SelectedServer.totaltraffic >= 1024) - dat += "
    Total recorded traffic: [round(SelectedServer.totaltraffic / 1024)] Terrabytes

    " - else - dat += "
    Total recorded traffic: [SelectedServer.totaltraffic] Gigabytes

    " - - dat += "Stored Logs:
      " - - var/i = 0 - for(var/datum/comm_log_entry/C in SelectedServer.log_entries) - i++ - // If the log is a speech file - if(C.input_type == "Speech File") - dat += "
    1. [C.name] \[X\]
      " - - // -- If the orator is a human, or universal translate is active, OR mob has universal speech on -- - - if(user.say_understands(null, C.parameters["language"]) || universal_translate || C.parameters["uspeech"]) - dat += "Data type: [C.input_type]
      " - dat += "Source: [C.parameters["name"]] (Job: [C.parameters["job"]])
      " - dat += "Class: [C.parameters["race"]]
      " - dat += "Contents: \"[C.parameters["message"]]\"
      " - - - // -- Orator is not human and universal translate not active -- - - else - dat += "Data type: Audio File
      " - dat += "Source: Unidentifiable
      " - dat += "Class: [C.parameters["race"]]
      " - dat += "Contents: Unintelligble
      " - - dat += "

    2. " - - else if(C.input_type == "Execution Error") - - dat += "
    3. [C.name] \[X\]
      " - dat += "Output: \"[C.parameters["message"]]\"
      " - dat += "

    4. " - - - dat += "
    " - - - - user << browse(dat.Join(""), "window=comm_monitor;size=575x400") - onclose(user, "server_control") - - temp = "" - return - - - Topic(href, href_list) - if(..()) - return - - - add_fingerprint(usr) - usr.set_machine(src) - - if(href_list["viewserver"]) - screen = 1 - for(var/obj/machinery/telecomms/T in servers) - if(T.id == href_list["viewserver"]) - SelectedServer = T - break - - if(href_list["operation"]) - switch(href_list["operation"]) - - if("release") - servers = list() - screen = 0 - - if("mainmenu") - screen = 0 - - if("scan") - if(servers.len > 0) - temp = "- FAILED: CANNOT PROBE WHEN BUFFER FULL -" - - else - for(var/obj/machinery/telecomms/server/T in range(25, src)) - if(T.network == network) - servers.Add(T) - - if(!servers.len) - temp = "- FAILED: UNABLE TO LOCATE SERVERS IN \[[network]\] -" - else - temp = "- [servers.len] SERVERS PROBED & BUFFERED -" - - screen = 0 - - if(href_list["delete"]) - - if(!src.allowed(usr) && !emagged) - to_chat(usr, "ACCESS DENIED.") - return - - if(SelectedServer) - - var/datum/comm_log_entry/D = SelectedServer.log_entries[text2num(href_list["delete"])] - - temp = "- DELETED ENTRY: [D.name] -" - - SelectedServer.log_entries.Remove(D) - qdel(D) - - else - temp = "- FAILED: NO SELECTED MACHINE -" - - if(href_list["network"]) - - var/newnet = input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text - - if(newnet && ((usr in range(1, src) || issilicon(usr)))) - if(length(newnet) > 15) - temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" - - else - - network = newnet - screen = 0 - servers = list() - temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -" - - updateUsrDialog() - return - - attackby(var/obj/item/D as obj, var/mob/user as mob, params) - if(istype(D, /obj/item/screwdriver)) - playsound(src.loc, D.usesound, 50, 1) - if(do_after(user, 20 * D.toolspeed, target = src)) - if(src.stat & BROKEN) - to_chat(user, "The broken glass falls out.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/shard(loc) - var/obj/item/circuitboard/comm_server/M = new /obj/item/circuitboard/comm_server( A ) - for(var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - qdel(src) - else - to_chat(user, "You disconnect the monitor.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/circuitboard/comm_server/M = new /obj/item/circuitboard/comm_server( A ) - for(var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - qdel(src) - updateUsrDialog() - return - return ..() - - emag_act(user as mob) - if(!emagged) - playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1) - emagged = 1 - to_chat(user, "You you disable the security protocols") diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm deleted file mode 100644 index 3ce5c316ba6..00000000000 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ /dev/null @@ -1,398 +0,0 @@ -/* - - All telecommunications interactions: - -*/ - - -/obj/machinery/telecomms - var/temp = "" // output message - var/construct_op = 0 - - -/obj/machinery/telecomms/attackby(obj/item/P as obj, mob/user as mob, params) - - // Using a multitool lets you access the receiver's interface - if(istype(P, /obj/item/multitool)) - attack_hand(user) - - - switch(construct_op) - if(0) - if(istype(P, /obj/item/screwdriver)) - to_chat(user, "You unfasten the bolts.") - playsound(src.loc, P.usesound, 50, 1) - construct_op++ - return - if(1) - if(istype(P, /obj/item/screwdriver)) - to_chat(user, "You fasten the bolts.") - playsound(src.loc,P.usesound, 50, 1) - construct_op-- - if(istype(P, /obj/item/wrench)) - to_chat(user, "You dislodge the external plating.") - playsound(src.loc, P.usesound, 75, 1) - construct_op++ - return - if(2) - if(istype(P, /obj/item/wrench)) - to_chat(user, "You secure the external plating.") - playsound(src.loc, P.usesound, 75, 1) - construct_op-- - if(istype(P, /obj/item/wirecutters)) - playsound(src.loc, P.usesound, 50, 1) - to_chat(user, "You remove the cables.") - construct_op++ - var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( user.loc ) - A.amount = 5 - stat |= BROKEN // the machine's been borked! - return - if(3) - if(istype(P, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/A = P - if(A.amount >= 5) - playsound(loc, A.usesound, 50, 1) - to_chat(user, "You insert the cables.") - A.amount -= 5 - if(A.amount <= 0) - user.drop_item() - qdel(A) - construct_op-- - stat &= ~BROKEN // the machine's not borked anymore! - return - if(istype(P, /obj/item/crowbar)) - to_chat(user, "You begin prying out the circuit board other components...") - playsound(src.loc, P.usesound, 50, 1) - if(do_after(user, 60 * P.toolspeed, target = src)) - to_chat(user, "You finish prying out the components.") - - // Drop all the component stuff - if(component_parts) - for(var/obj/I in component_parts) - I.loc = src.loc - else - // If the machine wasn't made during runtime, probably doesn't have components: - // manually find the components and drop them! - var/obj/item/circuitboard/C = new circuitboard - for(var/I in C.req_components) - for(var/i = 1, i <= C.req_components[I], i++) - var/obj/item/s = new I - s.loc = src.loc - if(istype(s, /obj/item/stack/cable_coil)) - var/obj/item/stack/cable_coil/A = s - A.amount = 1 - - // Drop a circuit board too - C.loc = src.loc - - // Create a machine frame and delete the current machine - var/obj/machinery/constructable_frame/machine_frame/F = new - F.loc = src.loc - qdel(src) - return - return ..() - -/obj/machinery/telecomms/proc/formatInput(var/label,var/varname, var/input) - var/value = vars[varname] - if(!value || value=="") - value="-----" - return "[label]: [value]" - -/obj/machinery/telecomms/attack_ai(var/mob/user as mob) - attack_hand(user) - -/obj/machinery/telecomms/attack_hand(var/mob/user as mob) - update_multitool_menu(user) - -/obj/machinery/telecomms/multitool_menu(var/mob/user,var/obj/item/multitool/P) - // You need a multitool to use this, or be silicon - if(!issilicon(user)) - // istype returns false if the value is null - if(!istype(user.get_active_hand(), /obj/item/multitool)) - return - - if(stat & (BROKEN|NOPOWER)) - return - - var/dat - - dat = {" -

    [temp]

    -

    Power Status: [src.toggled ? "On" : "Off"]

    "} - if(on && toggled) - dat += {" -

    [formatInput("Identification String","id","id")]

    -

    [formatInput("Network","network","network")]

    -

    Prefabrication: [autolinkers.len ? "TRUE" : "FALSE"]

    - "} - if(hide) - dat += "

    Shadow Link: ACTIVE

    " - - //Show additional options for certain machines. - dat += Options_Menu() - - dat += {"

    Linked Network Entities:

      "} - var/i = 0 - for(var/obj/machinery/telecomms/T in links) - i++ - if(T.hide && !src.hide) - continue - dat += "
    1. \ref[T] [T.name] ([T.id]) \[X\]
    2. " - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\Documents\Projects\vgstation13\code\game\machinery\telecomms\machine_interactions.dm:140: dat += "
    " - dat += {" -

    Filtering Frequencies:

    "} - // END AUTOFIX - i = 0 - if(length(freq_listening)) - dat += "
      " - for(var/x in freq_listening) - dat += "
    • [format_frequency(x)] GHz\[X\]
    • " - dat += "
    " - else - dat += "
  • NONE
  • " - - - // AUTOFIXED BY fix_string_idiocy.py - // C:\Users\Rob\Documents\Projects\vgstation13\code\game\machinery\telecomms\machine_interactions.dm:155: dat += "
    \[Add Filter\]" - dat += {"

    \[Add Filter\]

    -
    "} - // END AUTOFIX - - return dat - -/obj/machinery/telecomms/canLink(var/obj/O) - return istype(O,/obj/machinery/telecomms) - -/obj/machinery/telecomms/isLinkedWith(var/obj/O) - return O != null && O in links - -/obj/machinery/telecomms/getLink(var/idx) - return (idx >= 1 && idx <= links.len) ? links[idx] : null - -// Off-Site Relays -// -// You are able to send/receive signals from the station's z level (changeable in the STATION_Z #define) if -// the relay is on the telecomm satellite (changable in the TELECOMM_Z #define) - - -/obj/machinery/telecomms/relay/proc/toggle_level() - - var/turf/position = get_turf(src) - - // Toggle on/off getting signals from the station or the current Z level - // TODO: Could work with the space manager better - if(is_station_level(src.listening_level)) // equals the station - src.listening_level = position.z - return 1 - else if(level_boosts_signal(position.z)) - src.listening_level = level_name_to_num(MAIN_STATION) - return 1 - return 0 - -// Returns a multitool from a user depending on their mobtype. - -/obj/machinery/telecomms/proc/get_multitool(mob/user as mob) - - var/obj/item/multitool/P = null - // Let's double check - if(!issilicon(user) && istype(user.get_active_hand(), /obj/item/multitool)) - P = user.get_active_hand() - else if(isAI(user)) - var/mob/living/silicon/ai/U = user - P = U.aiMulti - else if(isrobot(user) && in_range(user, src)) - if(istype(user.get_active_hand(), /obj/item/multitool)) - P = user.get_active_hand() - return P - -// Additional Options for certain machines. Use this when you want to add an option to a specific machine. -// Example of how to use below. - -/obj/machinery/telecomms/proc/Options_Menu() - return "" - -/* -// Add an option to the processor to switch processing mode. (COMPRESS -> UNCOMPRESS or UNCOMPRESS -> COMPRESS) -/obj/machinery/telecomms/processor/Options_Menu() - var/dat = "
    Processing Mode: [process_mode ? "UNCOMPRESS" : "COMPRESS"]" - return dat -*/ -// The topic for Additional Options. Use this for checking href links for your specific option. -// Example of how to use below. -/obj/machinery/telecomms/proc/Options_Topic(href, href_list) - return - -/* -/obj/machinery/telecomms/processor/Options_Topic(href, href_list) - - if(href_list["process"]) - temp = "-% Processing mode changed. %-" - src.process_mode = !src.process_mode -*/ - -// RELAY - -/obj/machinery/telecomms/relay/Options_Menu() - var/dat = "" - if(level_boosts_signal(src.z)) - dat += "
    Signal Locked to Station: [is_station_level(listening_level) ? "TRUE" : "FALSE"]" - dat += "
    Broadcasting: [broadcasting ? "YES" : "NO"]" - dat += "
    Receiving: [receiving ? "YES" : "NO"]" - return dat - -/obj/machinery/telecomms/relay/Options_Topic(href, href_list) - - if(href_list["receive"]) - receiving = !receiving - temp = "-% Receiving mode changed. %-" - if(href_list["broadcast"]) - broadcasting = !broadcasting - temp = "-% Broadcasting mode changed. %-" - if(href_list["change_listening"]) - //Lock to the station OR lock to the current position! - //You need at least two receivers and two broadcasters for this to work, this includes the machine. - var/result = toggle_level() - if(result) - temp = "-% [src]'s signal has been successfully changed." - else - temp = "-% [src] could not lock it's signal onto the station. Two broadcasters or receivers required." - -// BUS - -/obj/machinery/telecomms/bus/Options_Menu() - var/dat = "
    Change Signal Frequency: [change_frequency ? "YES ([change_frequency])" : "NO"]" - return dat - -/obj/machinery/telecomms/bus/Options_Topic(href, href_list) - - if(href_list["change_freq"]) - - var/newfreq = input(usr, "Specify a new frequency for new signals to change to. Enter null to turn off frequency changing. Decimals assigned automatically.", src, network) as null|num - if(canAccess(usr)) - if(newfreq) - if(findtext(num2text(newfreq), ".")) - newfreq *= 10 // shift the decimal one place - if(newfreq < 10000) - change_frequency = newfreq - temp = "-% New frequency to change to assigned: \"[newfreq] GHz\" %-" - else - change_frequency = 0 - temp = "-% Frequency changing deactivated %-" - - -/obj/machinery/telecomms/Topic(href, href_list) - - if(!issilicon(usr)) - if(!istype(usr.get_active_hand(), /obj/item/multitool)) - return - - if(stat & (BROKEN|NOPOWER)) - return - - var/obj/item/multitool/P = get_multitool(usr) - - if(href_list["input"]) - switch(href_list["input"]) - - if("toggle") - - src.toggled = !src.toggled - temp = "-% [src] has been [src.toggled ? "activated" : "deactivated"]." - update_power() - - /* - if("hide") - src.hide = !hide - temp = "-% Shadow Link has been [src.hide ? "activated" : "deactivated"]." - */ - - if("id") - var/newid = copytext(reject_bad_text(input(usr, "Specify the new ID for this machine", src, id) as null|text),1,MAX_MESSAGE_LEN) - if(newid && canAccess(usr)) - id = newid - temp = "-% New ID assigned: \"[id]\" %-" - - if("network") - var/newnet = input(usr, "Specify the new network for this machine. This will break all current links.", src, network) as null|text - if(newnet && canAccess(usr)) - - if(length(newnet) > 15) - temp = "-% Too many characters in new network tag %-" - - else - for(var/obj/machinery/telecomms/T in links) - T.links.Remove(src) - - network = newnet - links = list() - temp = "-% New network tag assigned: \"[network]\" %-" - - - if("freq") - var/newfreq = input(usr, "Specify a new frequency to filter (GHz). Decimals assigned automatically.", src, network) as null|num - if(newfreq && canAccess(usr)) - if(findtext(num2text(newfreq), ".")) - newfreq *= 10 // shift the decimal one place - if(!(newfreq in freq_listening) && newfreq < 10000) - freq_listening.Add(newfreq) - temp = "-% New frequency filter assigned: \"[newfreq] GHz\" %-" - - if(href_list["delete"]) - - // changed the layout about to workaround a pesky runtime -- Doohl - - var/x = text2num(href_list["delete"]) - temp = "-% Removed frequency filter [x] %-" - freq_listening.Remove(x) - - if(href_list["unlink"]) - - if(text2num(href_list["unlink"]) <= length(links)) - var/obj/machinery/telecomms/T = links[text2num(href_list["unlink"])] - temp = "-% Removed \ref[T] [T.name] from linked entities. %-" - - // Remove link entries from both T and src. - - if(src in T.links) - T.links.Remove(src) - links.Remove(T) - - if(href_list["link"]) - - if(P) - if(P.buffer && P.buffer != src) - if(!(src in P.buffer:links)) - P.buffer:links.Add(src) - - if(!(P.buffer in src.links)) - src.links.Add(P.buffer) - - temp = "-% Successfully linked with \ref[P.buffer] [P.buffer.name] %-" - - else - temp = "-% Unable to acquire buffer %-" - - if(href_list["buffer"]) - - P.buffer = src - temp = "-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-" - - - if(href_list["flush"]) - - temp = "-% Buffer successfully flushed. %-" - P.buffer = null - - src.Options_Topic(href, href_list) - - usr.set_machine(src) - src.add_fingerprint(usr) - - updateUsrDialog() - -/obj/machinery/telecomms/proc/canAccess(var/mob/user) - if(issilicon(user) || in_range(user, src)) - return 1 - return 0 diff --git a/code/game/machinery/telecomms/ntsl2.dm b/code/game/machinery/telecomms/ntsl2.dm deleted file mode 100644 index c8501d8181e..00000000000 --- a/code/game/machinery/telecomms/ntsl2.dm +++ /dev/null @@ -1,512 +0,0 @@ -#define JOB_STYLE_1 "Name (Job)" -#define JOB_STYLE_2 "Name - Job" -#define JOB_STYLE_3 "\[Job\] Name" -#define JOB_STYLE_4 "(Job) Name" -GLOBAL_DATUM_INIT(nttc_config, /datum/nttc_configuration, new()) -// Custom Implementations for NTTC -/* NTTC Configuration Datum - * This is an abstract handler for the configuration loadout. It's set up like this both for ease of transfering in and out of the UI - * as well as allowing users to save and load configurations. - */ -/datum/nttc_configuration - var/regex/word_blacklist = new("(EXPLOIT WARNING:
    [ckey] attempted to upload an NTTC configuration containing JS abusable tags!") - log_admin("EXPLOIT WARNING: [ckey] attempted to upload an NTTC configuration containing JS abusable tags") - return FALSE - var/list/var_list = json_decode(text) - for(var/variable in var_list) - if(variable in to_serialize) // Don't just accept any random vars jesus christ! - if(requires_unlock[variable] && (source && !source.unlocked)) - continue - var/sanitize_method = serialize_sanitize[variable] - var/variable_value = var_list[variable] - variable_value = nttc_sanitize(variable_value, sanitize_method) - if(variable_value != null) - vars[variable] = variable_value - return TRUE - -// Sanitizing user input. Don't blindly trust the JSON. -/datum/nttc_configuration/proc/nttc_sanitize(variable, sanitize_method) - if(!sanitize_method) - return null - - switch(sanitize_method) - if("bool") - return variable ? TRUE : FALSE - // if("table", "array") - if("array") - if(!islist(variable)) - return list() - // Insert html filtering for the regexes here if you're boring - var/newlist = json_decode(html_decode(json_encode(variable))) - if(!islist(newlist)) - return null - return newlist - if("string") - return "[variable]" - - return variable - -// Primary signal modification. This is where all of the variables behavior are actually implemented. -/datum/nttc_configuration/proc/modify_signal(datum/signal/signal) - // Servers are deliberately turned off. Mark every signal as rejected. - if(!toggle_activated) - signal.data["reject"] = TRUE - return - - // Firewall - // This must happen before anything else modifies the signal ["name"]. - if(islist(firewall) && firewall.len > 0) - if(firewall.Find(signal.data["name"])) - signal.data["reject"] = 1 - - // All job and coloring shit - if(toggle_job_color || toggle_name_color) - var/job = signal.data["job"] - job_class = all_jobs[job] - - if(toggle_name_color) - var/new_name = "" + signal.data["name"] + "" - signal.data["name"] = new_name - signal.data["realname"] = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on - - if(toggle_jobs) - var/new_name = "" - var/job = signal.data["job"] - if(job in ert_jobs) - job = "ERT" - if(toggle_job_color) - switch(job_indicator_type) - if(JOB_STYLE_1) - new_name = signal.data["name"] + " ([job]) " - if(JOB_STYLE_2) - new_name = signal.data["name"] + " - [job] " - if(JOB_STYLE_3) - new_name = "\[[job]\] " + signal.data["name"] + " " - if(JOB_STYLE_4) - new_name = "([job]) " + signal.data["name"] + " " - else - switch(job_indicator_type) - if(JOB_STYLE_1) - new_name = signal.data["name"] + " ([job]) " - if(JOB_STYLE_2) - new_name = signal.data["name"] + " - [job] " - if(JOB_STYLE_3) - new_name = "\[[job]\] " + signal.data["name"] + " " - if(JOB_STYLE_4) - new_name = "([job]) " + signal.data["name"] + " " - - signal.data["name"] = new_name - signal.data["realname"] = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on - - // Add the current station time like a time code. - if(toggle_timecode) - var/new_name = "\[[station_time_timestamp()]] " + signal.data["name"] - signal.data["name"] = new_name - signal.data["realname"] = new_name // this is required because the broadcaster uses this directly if the speaker doesn't have a voice changer on - - // This is hacky stuff for multilingual messages... - var/list/message_pieces = signal.data["message"] - - // Makes heads of staff bold - if(toggle_command_bold) - var/job = signal.data["job"] - if((job in ert_jobs) || (job in heads)) - for(var/datum/multilingual_say_piece/S in message_pieces) - S.message = "[capitalize(S.message)]" // This only capitalizes the first word - - // Hacks! - // Censor dat shit like nobody's business - if(toggle_gibberish) - Gibberish_all(message_pieces, 80) - - // Replace everything with HONK! - if(toggle_honk) - var/list/split = splittext(signal.data["message"], " ") - var/honklength = split.len - var/new_message = "" - for(var/i in 1 to honklength) - new_message += pick("HoNK!", "HONK", "HOOOoONK", "HONKHONK!", "HoNnnkKK!!!", "HOOOOOOOOOOONK!!!!11!", "henk!") + " " - signal.data["message"] = message_to_multilingual(new_message) - - // Language Conversion - if(setting_language && valid_languages[setting_language]) - if(setting_language == "--DISABLE--") - setting_language = null - else - for(var/datum/multilingual_say_piece/S in message_pieces) - if(S.speaking != GLOB.all_languages["Noise"]) // check if they are emoting, these do not need to be translated - S.speaking = GLOB.all_languages[setting_language] - - // Regex replacements - // if(islist(regex) && regex.len > 0) - // for(var/datum/multilingual_say_piece/S in message_pieces) - // var/new_message = S.message - // for(var/reg in regex) - // var/replacePattern = pencode_to_html(regex[reg]) - // var/regex/start = regex("[reg]", "gi") - // new_message = start.Replace(new_message, replacePattern) - // S.message = new_message - - // Make sure the message is valid after we tinkered with it, otherwise reject it - if(signal.data["message"] == "" || !signal.data["message"]) - signal.data["reject"] = 1 - -/datum/nttc_configuration/Topic(mob/user, href_list, window_id, obj/machinery/computer/telecomms/traffic/source) - // Toggles - if(href_list["toggle"]) - var/var_to_toggle = href_list["toggle"] - if(requires_unlock[var_to_toggle] && !source.unlocked) - return - if(!(var_to_toggle in to_serialize)) - return - vars[var_to_toggle] = !vars[var_to_toggle] - log_action(user, "toggled NTTC variable [var_to_toggle] [vars[var_to_toggle] ? "on" : "off"]") - - // Job Format - if(href_list["setting_job_card_style"]) - var/card_style = input(user, "Pick a job card format.", "Job Card Format") as null|anything in job_card_styles - if(!card_style) - return - job_indicator_type = card_style - to_chat(user, "Jobs will now have the style of [card_style].") - log_action(user, "has set NTTC job card format to [card_style]", TRUE) - - // Strings - if(href_list["setting_language"]) - var/new_language = input(user, "Pick a language to convert messages to.", "Language Conversion") as null|anything in valid_languages - if(!new_language) - return - if(new_language == "--DISABLE--") - setting_language = null - to_chat(user, "Language conversion disabled.") - else - setting_language = new_language - to_chat(user, "Messages will now be converted to [new_language].") - - log_action(user, new_language == "--DISABLE--" ? "disabled NTTC language conversion" : "set NTTC language conversion to [new_language]", TRUE) - - // Tables - // if(href_list["create_row"]) - // if(href_list["table"] && href_list["table"] in tables) - // if(requires_unlock[href_list["table"]] && !source.unlocked) - // return - // var/new_key = clean_input(user, "Provide a key for the new row.", "New Row") - // if(!new_key) - // return - // var/new_value = clean_input(user, "Provide a new value for the key [new_key]", "New Row") - // if(new_value == null) - // return - // if(word_blacklist.Find(new_value)) //uh oh, they tried to be naughty - // message_admins("EXPLOIT WARNING: [user.ckey] attempted to add a NTTC regex row containing JS abusable tags!") - // log_admin("EXPLOIT WARNING: [user.ckey] attempted to add a NTTC regex row containing JS abusable tags") - // to_chat(user, "ERROR: Regex contained bad strings. Upload cancelled.") - // return - // var/list/table = vars[href_list["table"]] - // table[new_key] = new_value - // to_chat(user, "Added row [new_key] -> [new_value].") - // log_action(user, "updated [href_list["table"]] - new row [new_key] -> [new_value]") - - // if(href_list["delete_row"]) - // if(href_list["table"] && href_list["table"] in tables) - // if(requires_unlock[href_list["table"]] && !source.unlocked) - // return - // var/list/table = vars[href_list["table"]] - // table.Remove(href_list["delete_row"]) - // to_chat(user, "Removed row [href_list["delete_row"]] from [href_list["table"]]") - // log_action(user, "updated [href_list["table"]] - removed row [href_list["delete_row"]]") - - // Arrays - if(href_list["create_item"]) - if(href_list["array"] && href_list["array"] in arrays) - if(requires_unlock[href_list["array"]] && !source.unlocked) - return - var/new_value = clean_input(user, "Provide a value for the new index.", "New Index") - if(new_value == null) - return - var/list/array = vars[href_list["array"]] - array.Add(new_value) - to_chat(user, "Added row [new_value].") - log_action(user, "updated [href_list["array"]] - new value [new_value]", TRUE) - - if(href_list["delete_item"]) - if(href_list["array"] && href_list["array"] in arrays) - if(requires_unlock[href_list["array"]] && !source.unlocked) - return - var/list/array = vars[href_list["array"]] - array.Remove(href_list["delete_item"]) - to_chat(user, "Removed [href_list["delete_item"]] from [href_list["array"]]") - log_action(user, "updated [href_list["array"]] - removed [href_list["delete_item"]]") - - // Spit out the serialized config to the user - if(href_list["save_config"]) - user << browse(nttc_serialize(), "window=save_nttc") - - if(href_list["load_config"]) - var/json = input(user, "Provide configuration JSON below.", "Load Config", nttc_serialize()) as message - if(nttc_deserialize(json, source, user.ckey)) - log_action(user, "has uploaded a NTTC JSON configuration: [ADMIN_SHOWDETAILS("Show", json)]", TRUE) - - user << output(list2params(list(nttc_serialize())), "[window_id].browser:updateConfig") - -/datum/nttc_configuration/proc/log_action(user, msg, adminmsg = FALSE) - log_game("NTTC: [key_name(user)] [msg]") - log_investigate("[key_name(user)] [msg]", "ntsl") - if(adminmsg) - message_admins("[key_name_admin(user)] [msg]") - -/* Asset datum for the UI */ -/datum/asset/simple/nttc - assets = list( - "bundle.css" = 'html/nttc/dist/bundle.css', - "bundle.js" = 'html/nttc/dist/bundle.js', - "tab_home.html" = 'html/nttc/dist/tab_home.html', - "tab_hack.html" = 'html/nttc/dist/tab_hack.html', - "tab_filtering.html" = 'html/nttc/dist/tab_filtering.html', - "tab_firewall.html" = 'html/nttc/dist/tab_firewall.html', - // "tab_regex.html" = 'html/nttc/dist/tab_regex.html', - "uiTitleFluff.png" = 'html/nttc/dist/uiTitleFluff.png' - ) - -/* Custom subtype of /datum/browser that behaves as we want for our project */ -/datum/browser/nttc - var/initial_config // Initial NTTC configuration - -/datum/browser/nttc/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, nttc_config) - . = ..() - initial_config = nttc_config -// Prevent all stylesheets from being added, we have our own CSS that's bundled with gulp -/datum/browser/nttc/add_stylesheet() - return -// No header, we're running a fully complete .html file -/datum/browser/nttc/get_header() - return -// We inject a little code at the bottom of the file, similar to NanoUI, but more limited. -// This code is used for delivering live updates of config changes & allowing the UI to provide Topic data. -/datum/browser/nttc/get_footer() - var/byondSrc = "byond://?src=[ref.UID()];" - var/dat = "" - return dat - diff --git a/code/game/machinery/telecomms/presets.dm b/code/game/machinery/telecomms/presets.dm deleted file mode 100644 index 212d8592e92..00000000000 --- a/code/game/machinery/telecomms/presets.dm +++ /dev/null @@ -1,234 +0,0 @@ -// ### Preset machines ### - -//Relay - -/obj/machinery/telecomms/relay/preset - network = "tcommsat" - -/obj/machinery/telecomms/relay/preset/station - id = "Station Relay" - listening_level = 1 - autolinkers = list("s_relay") - -/obj/machinery/telecomms/relay/preset/telecomms - id = "Telecomms Relay" - autolinkers = list("relay") - -/obj/machinery/telecomms/relay/preset/mining - id = "Mining Relay" - autolinkers = list("m_relay") - -/obj/machinery/telecomms/relay/preset/ruskie - id = "Ruskie Relay" - hide = 1 - toggled = 0 - autolinkers = list("r_relay") - -/obj/machinery/telecomms/relay/preset/engioutpost - id = "Engineering Outpost" - hide = 1 - toggled = 0 - autolinkers = list("e_relay") - -/obj/machinery/telecomms/relay/preset/centcom - id = "Centcom Relay" - hide = 1 - toggled = 1 - //anchored = 1 - use_power = NO_POWER_USE - //idle_power_usage = 0 - autolinkers = list("c_relay") - -//HUB - -/obj/machinery/telecomms/hub/preset - id = "Hub" - network = "tcommsat" - autolinkers = list("hub", "relay", "c_relay", "s_relay", "m_relay", "r_relay", "e_relay", "science", "medical", - "supply", "service", "common", "command", "engineering", "security", - "receiverA", "receiverB", "broadcasterA", "broadcasterB") - -/obj/machinery/telecomms/hub/preset_cent - id = "CentComm Hub" - network = "tcommsat" - use_power = NO_POWER_USE - autolinkers = list("hub_cent", "c_relay", "s_relay", "m_relay", "r_relay", "e_relay", - "centcomm", "receiverCent", "broadcasterCent") - -//Receivers - -//--PRESET LEFT--// - -/obj/machinery/telecomms/receiver/preset_left - id = "Receiver A" - network = "tcommsat" - autolinkers = list("receiverA") // link to relay - freq_listening = list(SCI_FREQ, MED_FREQ, SUP_FREQ, SRV_FREQ) - - -//--PRESET RIGHT--// - -/obj/machinery/telecomms/receiver/preset_right - id = "Receiver B" - network = "tcommsat" - autolinkers = list("receiverB") // link to relay - freq_listening = list(AI_FREQ, COMM_FREQ, ENG_FREQ, SEC_FREQ) - - //Common and other radio frequencies for people to freely use -/obj/machinery/telecomms/receiver/preset_right/New() - for(var/i = PUBLIC_LOW_FREQ, i < PUBLIC_HIGH_FREQ, i += 2) - freq_listening |= i - ..() - -/obj/machinery/telecomms/receiver/preset_cent - id = "CentComm Receiver" - network = "tcommsat" - use_power = NO_POWER_USE - autolinkers = list("receiverCent") - freq_listening = list(ERT_FREQ, DTH_FREQ) - -//Buses - -/obj/machinery/telecomms/bus/preset_one - id = "Bus 1" - network = "tcommsat" - freq_listening = list(SCI_FREQ, MED_FREQ) - autolinkers = list("processor1", "science", "medical") - -/obj/machinery/telecomms/bus/preset_two - id = "Bus 2" - network = "tcommsat" - freq_listening = list(SUP_FREQ, SRV_FREQ) - autolinkers = list("processor2", "supply", "service") - -/obj/machinery/telecomms/bus/preset_three - id = "Bus 3" - network = "tcommsat" - freq_listening = list(SEC_FREQ, COMM_FREQ) - autolinkers = list("processor3", "security", "command") - -/obj/machinery/telecomms/bus/preset_four - id = "Bus 4" - network = "tcommsat" - freq_listening = list(ENG_FREQ, AI_FREQ, PUB_FREQ) - autolinkers = list("processor4", "engineering", "common") - -/obj/machinery/telecomms/bus/preset_four/New() - for(var/i = PUBLIC_LOW_FREQ, i < PUBLIC_HIGH_FREQ, i += 2) - freq_listening |= i - ..() - -/obj/machinery/telecomms/bus/preset_cent - id = "CentComm Bus" - network = "tcommsat" - use_power = NO_POWER_USE - freq_listening = list(ERT_FREQ, DTH_FREQ) - autolinkers = list("processorCent", "centcomm") - -//Processors - -/obj/machinery/telecomms/processor/preset_one - id = "Processor 1" - network = "tcommsat" - autolinkers = list("processor1") // processors are sort of isolated; they don't need backward links - -/obj/machinery/telecomms/processor/preset_two - id = "Processor 2" - network = "tcommsat" - autolinkers = list("processor2") - -/obj/machinery/telecomms/processor/preset_three - id = "Processor 3" - network = "tcommsat" - autolinkers = list("processor3") - -/obj/machinery/telecomms/processor/preset_four - id = "Processor 4" - network = "tcommsat" - autolinkers = list("processor4") - -/obj/machinery/telecomms/processor/preset_cent - id = "CentComm Processor" - network = "tcommsat" - use_power = NO_POWER_USE - autolinkers = list("processorCent") - -//Servers - -/obj/machinery/telecomms/server/presets - - network = "tcommsat" - -/obj/machinery/telecomms/server/presets/science - id = "Science Server" - freq_listening = list(SCI_FREQ) - autolinkers = list("science") - -/obj/machinery/telecomms/server/presets/medical - id = "Medical Server" - freq_listening = list(MED_FREQ) - autolinkers = list("medical") - -/obj/machinery/telecomms/server/presets/supply - id = "Supply Server" - freq_listening = list(SUP_FREQ) - autolinkers = list("supply") - -/obj/machinery/telecomms/server/presets/service - id = "Service Server" - freq_listening = list(SRV_FREQ) - autolinkers = list("service") - -/obj/machinery/telecomms/server/presets/common - id = "Common Server" - freq_listening = list(PUB_FREQ, AI_FREQ) - autolinkers = list("common") - -//Common and other radio frequencies for people to freely use -/obj/machinery/telecomms/server/presets/common/New() - for(var/i = PUBLIC_LOW_FREQ, i < PUBLIC_HIGH_FREQ, i += 2) - freq_listening |= i - ..() - -/obj/machinery/telecomms/server/presets/command - id = "Command Server" - freq_listening = list(COMM_FREQ) - autolinkers = list("command") - -/obj/machinery/telecomms/server/presets/engineering - id = "Engineering Server" - freq_listening = list(ENG_FREQ) - autolinkers = list("engineering") - -/obj/machinery/telecomms/server/presets/security - id = "Security Server" - freq_listening = list(SEC_FREQ) - autolinkers = list("security") - -/obj/machinery/telecomms/server/presets/centcomm - id = "CentComm Server" - freq_listening = list(ERT_FREQ, DTH_FREQ) - use_power = NO_POWER_USE - autolinkers = list("centcomm") - -//Broadcasters - -//--PRESET LEFT--// - -/obj/machinery/telecomms/broadcaster/preset_left - id = "Broadcaster A" - network = "tcommsat" - autolinkers = list("broadcasterA") - -//--PRESET RIGHT--// - -/obj/machinery/telecomms/broadcaster/preset_right - id = "Broadcaster B" - network = "tcommsat" - autolinkers = list("broadcasterB") - -/obj/machinery/telecomms/broadcaster/preset_cent - id = "CentComm Broadcaster" - network = "tcommsat" - use_power = NO_POWER_USE - autolinkers = list("broadcasterCent") diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm deleted file mode 100644 index 06eacdd8da1..00000000000 --- a/code/game/machinery/telecomms/telecomunications.dm +++ /dev/null @@ -1,529 +0,0 @@ -/* - Hello, friends, this is Doohl from sexylands. You may be wondering what this - monstrous code file is. Sit down, boys and girls, while I tell you the tale. - - - The machines defined in this file were designed to be compatible with any radio - signals, provided they use subspace transmission. Currently they are only used for - headsets, but they can eventually be outfitted for real COMPUTER networks. This - is just a skeleton, ladies and gentlemen. - - Look at radio.dm for the prequel to this code. -*/ - -var/global/list/obj/machinery/telecomms/telecomms_list = list() - -/obj/machinery/telecomms - var/list/links = list() // list of machines this machine is linked to - var/traffic = 0 // value increases as traffic increases - var/netspeed = 5 // how much traffic to lose per tick (50 gigabytes/second * netspeed) - var/list/autolinkers = list() // list of text/number values to link with - var/id = "NULL" // identification string - var/network = "NULL" // the network of the machinery - - var/list/freq_listening = list() // list of frequencies to tune into: if none, will listen to all - - var/machinetype = 0 // just a hacky way of preventing alike machines from pairing - var/toggled = 1 // Is it toggled on - var/on = 1 - var/long_range_link = 0 // Can you link it across Z levels or on the otherside of the map? (Relay & Hub) - var/circuitboard = null // type pointing to a circuitboard type - var/hide = 0 // Is it a hidden machine? - var/listening_level = 0 // 0 = auto set in New() - this is the z level that the machine is listening to. - Mtoollink = 1 - -/obj/machinery/telecomms/proc/relay_information(datum/signal/signal, filter, copysig, amount = 20) - // relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending - - if(!on) - return -// to_chat(world, "[src] ([src.id]) - [signal.debug_print()]") - var/send_count = 0 - - - // Apply some lag based on traffic rates - var/netlag = round(traffic / 50) - if(netlag > signal.data["slow"]) - signal.data["slow"] = netlag - -// Loop through all linked machines and send the signal or copy. - for(var/obj/machinery/telecomms/machine in links) - if(filter && !istype( machine, text2path(filter) )) - continue - if(!machine.on) - continue - if(amount && send_count >= amount) - break - // TODO: Make the radio system cooperate with the space manager - if(machine.loc.z != listening_level) - if(long_range_link == 0 && machine.long_range_link == 0) - continue - // If we're sending a copy, be sure to create the copy for EACH machine and paste the data - var/datum/signal/copy - if(copysig) - copy = new - copy.transmission_method = 2 - copy.frequency = signal.frequency - copy.data = signal.data.Copy() - - // Keep the "original" signal constant - if(!signal.data["original"]) - copy.data["original"] = signal - else - copy.data["original"] = signal.data["original"] - - send_count++ - if(machine.is_freq_listening(signal)) - machine.traffic++ - - if(copysig) - machine.receive_information(copy, src) - else - machine.receive_information(signal, src) - - - if(send_count > 0 && is_freq_listening(signal)) - traffic++ - - return send_count - -/obj/machinery/telecomms/proc/relay_direct_information(datum/signal/signal, obj/machinery/telecomms/machine) - // send signal directly to a machine - machine.receive_information(signal, src) - -/obj/machinery/telecomms/proc/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - // receive information from linked machinery - ..() - -/obj/machinery/telecomms/proc/is_freq_listening(datum/signal/signal) - // return 1 if found, 0 if not found - if(!signal) - return 0 - if((signal.frequency in freq_listening) || (!freq_listening.len)) - return 1 - else - return 0 - - -/obj/machinery/telecomms/New() - telecomms_list += src - ..() - - //Set the listening_level if there's none. - if(!listening_level) - //Defaults to our Z level! - var/turf/position = get_turf(src) - // TODO: Make the radio system cooperate with the space manager - listening_level = position.z - -/obj/machinery/telecomms/Initialize() - ..() - if(autolinkers.len) - // Links nearby machines - if(!long_range_link) - for(var/obj/machinery/telecomms/T in orange(20, src)) - add_link(T) - else - for(var/obj/machinery/telecomms/T in telecomms_list) - add_link(T) - - -/obj/machinery/telecomms/Destroy() - telecomms_list -= src - for(var/obj/machinery/telecomms/comm in telecomms_list) - comm.links -= src - links.Cut() - return ..() - -// Used in auto linking -/obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T) - var/turf/position = get_turf(src) - var/turf/T_position = get_turf(T) - // TODO: Make the radio system cooperate with the space manager - if((position.z == T_position.z) || (src.long_range_link && T.long_range_link)) - for(var/x in autolinkers) - if(T.autolinkers.Find(x)) - if(src != T) - links |= T - -/obj/machinery/telecomms/update_icon() - if(on) - icon_state = initial(icon_state) - else - icon_state = "[initial(icon_state)]_off" - -/obj/machinery/telecomms/proc/update_power() - - if(toggled) - if(stat & (BROKEN|NOPOWER|EMPED)) // if powered, on. if not powered, off. if too damaged, off - on = 0 - else - on = 1 - else - on = 0 - -/obj/machinery/telecomms/process() - update_power() - - // Update the icon - update_icon() - - if(traffic > 0) - traffic -= netspeed - -/obj/machinery/telecomms/emp_act(severity) - if(prob(100/severity)) - if(!(stat & EMPED)) - stat |= EMPED - var/duration = (300 * 10)/severity - spawn(rand(duration - 20, duration + 20)) // Takes a long time for the machines to reboot. - stat &= ~EMPED - ..() - -/* - The receiver idles and receives messages from subspace-compatible radio equipment; - primarily headsets. They then just relay this information to all linked devices, - which can would probably be network hubs. - - Link to Processor Units in case receiver can't send to bus units. -*/ - -/obj/machinery/telecomms/receiver - name = "Subspace Receiver" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "broadcast receiver" - desc = "This machine has a dish-like shape and green lights. It is designed to detect and process subspace radio activity." - density = 1 - anchored = 1 - use_power = IDLE_POWER_USE - idle_power_usage = 30 - machinetype = 1 - circuitboard = /obj/item/circuitboard/telecomms/receiver - -/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal) - - if(!on) // has to be on to receive messages - return - if(!signal) - return - if(!check_receive_level(signal)) - return - - if(signal.transmission_method == 2) - - if(is_freq_listening(signal)) // detect subspace signals - - //Remove the level and then start adding levels that it is being broadcasted in. - signal.data["level"] = list() - - var/can_send = relay_information(signal, "/obj/machinery/telecomms/hub") // ideally relay the copied information to relays - if(!can_send) - relay_information(signal, "/obj/machinery/telecomms/bus") // Send it to a bus instead, if it's linked to one - -/obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/signal) - - if(signal.data["level"] != listening_level) - for(var/obj/machinery/telecomms/hub/H in links) - var/list/connected_levels = list() - for(var/obj/machinery/telecomms/relay/R in H.links) - if(R.can_receive(signal)) - connected_levels |= R.listening_level - if(signal.data["level"] in connected_levels) - return 1 - return 0 - return 1 - - -/* - The HUB idles until it receives information. It then passes on that information - depending on where it came from. - - This is the heart of the Telecommunications Network, sending information where it - is needed. It mainly receives information from long-distance Relays and then sends - that information to be processed. Afterwards it gets the uncompressed information - from Servers/Buses and sends that back to the relay, to then be broadcasted. -*/ - -/obj/machinery/telecomms/hub - name = "Telecommunication Hub" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "hub" - desc = "A mighty piece of hardware used to send/receive massive amounts of data." - density = 1 - anchored = 1 - use_power = IDLE_POWER_USE - idle_power_usage = 80 - machinetype = 7 - circuitboard = /obj/item/circuitboard/telecomms/hub - long_range_link = 1 - netspeed = 40 - - -/obj/machinery/telecomms/hub/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - if(is_freq_listening(signal)) - if(istype(machine_from, /obj/machinery/telecomms/receiver)) - //If the signal is compressed, send it to the bus. - relay_information(signal, "/obj/machinery/telecomms/bus", 1) // ideally relay the copied information to bus units - else - // Get a list of relays that we're linked to, then send the signal to their levels. - relay_information(signal, "/obj/machinery/telecomms/relay", 1) - relay_information(signal, "/obj/machinery/telecomms/broadcaster", 1) // Send it to a broadcaster. - - -/* - The relay idles until it receives information. It then passes on that information - depending on where it came from. - - The relay is needed in order to send information pass Z levels. It must be linked - with a HUB, the only other machine that can send/receive pass Z levels. -*/ - -/obj/machinery/telecomms/relay - name = "Telecommunication Relay" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "relay" - desc = "A mighty piece of hardware used to send massive amounts of data far away." - density = 1 - anchored = 1 - use_power = IDLE_POWER_USE - idle_power_usage = 30 - machinetype = 8 - circuitboard = /obj/item/circuitboard/telecomms/relay - netspeed = 5 - long_range_link = 1 - var/broadcasting = 1 - var/receiving = 1 - -/obj/machinery/telecomms/relay/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - // Add our level and send it back - if(can_send(signal)) - signal.data["level"] |= listening_level - -// Checks to see if it can send/receive. - -/obj/machinery/telecomms/relay/proc/can(datum/signal/signal) - if(!on) - return 0 - if(!is_freq_listening(signal)) - return 0 - return 1 - -/obj/machinery/telecomms/relay/proc/can_send(datum/signal/signal) - if(!can(signal)) - return 0 - return broadcasting - -/obj/machinery/telecomms/relay/proc/can_receive(datum/signal/signal) - if(!can(signal)) - return 0 - return receiving - -/* - The bus mainframe idles and waits for hubs to relay them signals. They act - as junctions for the network. - - They transfer uncompressed subspace packets to processor units, and then take - the processed packet to a server for logging. - - Link to a subspace hub if it can't send to a server. -*/ - -/obj/machinery/telecomms/bus - name = "Bus Mainframe" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "bus" - desc = "A mighty piece of hardware used to send massive amounts of data quickly." - density = 1 - anchored = 1 - use_power = IDLE_POWER_USE - idle_power_usage = 50 - machinetype = 2 - circuitboard = /obj/item/circuitboard/telecomms/bus - netspeed = 40 - var/change_frequency = 0 - -/obj/machinery/telecomms/bus/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - if(is_freq_listening(signal)) - - if(change_frequency) - signal.frequency = change_frequency - - if(!istype(machine_from, /obj/machinery/telecomms/processor) && machine_from != src) // Signal must be ready (stupid assuming machine), let's send it - // send to one linked processor unit - var/send_to_processor = relay_information(signal, "/obj/machinery/telecomms/processor") - - if(send_to_processor) - return - // failed to send to a processor, relay information anyway - signal.data["slow"] += rand(1, 5) // slow the signal down only slightly - src.receive_information(signal, src) - - // Try sending it! - var/list/try_send = list("/obj/machinery/telecomms/server", "/obj/machinery/telecomms/hub", "/obj/machinery/telecomms/broadcaster") - var/i = 0 - for(var/send in try_send) - if(i) - signal.data["slow"] += rand(0, 1) // slow the signal down only slightly - i++ - var/can_send = relay_information(signal, send) - if(can_send) - break - - - -/* - The processor is a very simple machine that decompresses subspace signals and - transfers them back to the original bus. It is essential in producing audible - data. - - Link to servers if bus is not present -*/ - -/obj/machinery/telecomms/processor - name = "Processor Unit" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "processor" - desc = "This machine is used to process large quantities of information." - density = 1 - anchored = 1 - use_power = IDLE_POWER_USE - idle_power_usage = 30 - machinetype = 3 - circuitboard = /obj/item/circuitboard/telecomms/processor - var/process_mode = 1 // 1 = Uncompress Signals, 0 = Compress Signals - - receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - - if(is_freq_listening(signal)) - - if(process_mode) - signal.data["compression"] = 0 // uncompress subspace signal - else - signal.data["compression"] = 100 // even more compressed signal - - if(istype(machine_from, /obj/machinery/telecomms/bus)) - relay_direct_information(signal, machine_from) // send the signal back to the machine - else // no bus detected - send the signal to servers instead - signal.data["slow"] += rand(5, 10) // slow the signal down - relay_information(signal, "/obj/machinery/telecomms/server") - - -/* - The server logs all traffic and signal data. Once it records the signal, it sends - it to the subspace broadcaster. - - Store a maximum of 100 logs and then deletes them. -*/ - - -/obj/machinery/telecomms/server - name = "Telecommunication Server" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "comm_server" - desc = "A machine used to store data and network statistics." - density = 1 - anchored = 1 - use_power = IDLE_POWER_USE - idle_power_usage = 15 - machinetype = 4 - circuitboard = /obj/item/circuitboard/telecomms/server - var/list/log_entries = list() - var/list/stored_names = list() - var/list/TrafficActions = list() - var/logs = 0 // number of logs - var/totaltraffic = 0 // gigabytes (if > 1024, divide by 1024 -> terrabytes) - - var/encryption = "null" // encryption key: ie "password" - var/salt = "null" // encryption salt: ie "123comsat" - // would add up to md5("password123comsat") - var/obj/item/radio/headset/server_radio = null - -/obj/machinery/telecomms/server/Initialize() - ..() - server_radio = new() - -/obj/machinery/telecomms/server/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from) - if(signal.data["message"]) - if(is_freq_listening(signal)) - if(traffic > 0) - totaltraffic += traffic // add current traffic to total traffic - - //Is this a test signal? Bypass logging - if(signal.data["type"] != 4) - // If signal has a message and appropriate frequency - update_logs() - - var/datum/comm_log_entry/log = new - var/mob/M = signal.data["mob"] - - // Copy the signal.data entries we want - log.parameters["mobtype"] = signal.data["mobtype"] - log.parameters["race"] = signal.data["race"] - log.parameters["job"] = signal.data["job"] - log.parameters["key"] = signal.data["key"] - log.parameters["vmessage"] = multilingual_to_message(signal.data["message"]) - log.parameters["vname"] = signal.data["vname"] - log.parameters["message"] = multilingual_to_message(signal.data["message"]) - log.parameters["name"] = signal.data["name"] - log.parameters["realname"] = signal.data["realname"] - - if(!istype(M, /mob/new_player) && M) - log.parameters["uspeech"] = M.universal_speak - else - log.parameters["uspeech"] = 0 - - // If the signal is still compressed, make the log entry gibberish - if(signal.data["compression"] > 0) - log.parameters["message"] = Gibberish(multilingual_to_message(signal.data["message"]), signal.data["compression"] + 50) - log.parameters["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50) - log.parameters["name"] = Gibberish(signal.data["name"], signal.data["compression"] + 50) - log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50) - log.parameters["vname"] = Gibberish(signal.data["vname"], signal.data["compression"] + 50) - log.input_type = "Corrupt File" - - // Log and store everything that needs to be logged - log_entries.Add(log) - if(!(signal.data["name"] in stored_names)) - stored_names.Add(signal.data["name"]) - logs++ - signal.data["server"] = src - - // Give the log a name - var/identifier = num2text( rand(-1000,1000) + world.time ) - log.name = "data packet ([md5(identifier)])" - - // Run NTTC against the signal - if(GLOB.nttc_config) - GLOB.nttc_config.modify_signal(signal) - - var/can_send = relay_information(signal, "/obj/machinery/telecomms/hub") - if(!can_send) - relay_information(signal, "/obj/machinery/telecomms/broadcaster") - -/obj/machinery/telecomms/server/proc/update_logs() - // start deleting the very first log entry - if(logs >= 400) - for(var/i = 1, i <= logs, i++) // locate the first garbage collectable log entry and remove it - var/datum/comm_log_entry/L = log_entries[i] - if(L.garbage_collector) - log_entries.Remove(L) - logs-- - break - -/obj/machinery/telecomms/server/proc/add_entry(var/content, var/input) - var/datum/comm_log_entry/log = new - var/identifier = num2text( rand(-1000,1000) + world.time ) - log.name = "[input] ([md5(identifier)])" - log.input_type = input - log.parameters["message"] = content - log_entries.Add(log) - update_logs() - -// Simple log entry datum -/datum/comm_log_entry - var/parameters = list() // carbon-copy to signal.data[] - var/name = "data packet (#)" - var/garbage_collector = 1 // if set to 0, will not be garbage collected - var/input_type = "Speech File" diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm deleted file mode 100644 index 73a9261feb0..00000000000 --- a/code/game/machinery/telecomms/telemonitor.dm +++ /dev/null @@ -1,161 +0,0 @@ -/* - Telecomms monitor tracks the overall trafficing of a telecommunications network - and displays a heirarchy of linked machines. -*/ - - -/obj/machinery/computer/telecomms/monitor - name = "telecommunications monitor" - icon_screen = "comm_monitor" - - var/screen = 0 // the screen number: - var/list/machinelist = list() // the machines located by the computer - var/obj/machinery/telecomms/SelectedMachine - - var/network = "NULL" // the network to probe - - var/temp = "" // temporary feedback messages - circuit = /obj/item/circuitboard/comm_monitor - - light_color = LIGHT_COLOR_DARKGREEN - - attack_hand(mob/user as mob) - if(stat & (BROKEN|NOPOWER)) - return - user.set_machine(src) - var/dat = "Telecommunications Monitor
    Telecommunications Monitor
    " - - switch(screen) - - - // --- Main Menu --- - - if(0) - dat += "
    [temp]

    " - dat += "
    Current Network: [network]
    " - if(machinelist.len) - dat += "
    Detected Network Entities:
      " - for(var/obj/machinery/telecomms/T in machinelist) - dat += "
    • \ref[T] [T.name] ([T.id])
    • " - dat += "
    " - dat += "
    \[Flush Buffer\]" - else - dat += "\[Probe Network\]" - - - // --- Viewing Machine --- - - if(1) - dat += "
    [temp]
    " - dat += "
    \[Main Menu\]
    " - dat += "
    Current Network: [network]
    " - dat += "Selected Network Entity: [SelectedMachine.name] ([SelectedMachine.id])
    " - dat += "Linked Entities:
      " - for(var/obj/machinery/telecomms/T in SelectedMachine.links) - if(!T.hide) - dat += "
    1. \ref[T.id] [T.name] ([T.id])
    2. " - dat += "
    " - - - - user << browse(dat, "window=comm_monitor;size=575x400") - onclose(user, "server_control") - - temp = "" - return - - - Topic(href, href_list) - if(..()) - return - - - add_fingerprint(usr) - usr.set_machine(src) - - if(href_list["viewmachine"]) - screen = 1 - for(var/obj/machinery/telecomms/T in machinelist) - if(T.id == href_list["viewmachine"]) - SelectedMachine = T - break - - if(href_list["operation"]) - switch(href_list["operation"]) - - if("release") - machinelist = list() - screen = 0 - - if("mainmenu") - screen = 0 - - if("probe") - if(machinelist.len > 0) - temp = "- FAILED: CANNOT PROBE WHEN BUFFER FULL -" - - else - for(var/obj/machinery/telecomms/T in range(25, src)) - if(T.network == network) - machinelist.Add(T) - - if(!machinelist.len) - temp = "- FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN \[[network]\] -" - else - temp = "- [machinelist.len] ENTITIES LOCATED & BUFFERED -" - - screen = 0 - - - if(href_list["network"]) - - var/newnet = input(usr, "Which network do you want to view?", "Comm Monitor", network) as null|text - if(newnet && ((usr in range(1, src) || issilicon(usr)))) - if(length(newnet) > 15) - temp = "- FAILED: NETWORK TAG STRING TOO LENGHTLY -" - - else - network = newnet - screen = 0 - machinelist = list() - temp = "- NEW NETWORK TAG SET IN ADDRESS \[[network]\] -" - - updateUsrDialog() - return - - attackby(var/obj/item/D as obj, var/mob/user as mob, params) - if(istype(D, /obj/item/screwdriver)) - playsound(src.loc, D.usesound, 50, 1) - if(do_after(user, 20 * D.toolspeed, target = src)) - if(src.stat & BROKEN) - to_chat(user, "The broken glass falls out.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - new /obj/item/shard(loc) - var/obj/item/circuitboard/comm_monitor/M = new /obj/item/circuitboard/comm_monitor( A ) - for(var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 3 - A.icon_state = "3" - A.anchored = 1 - qdel(src) - else - to_chat(user, "You disconnect the monitor.") - var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc ) - var/obj/item/circuitboard/comm_monitor/M = new /obj/item/circuitboard/comm_monitor( A ) - for(var/obj/C in src) - C.loc = src.loc - A.circuit = M - A.state = 4 - A.icon_state = "4" - A.anchored = 1 - qdel(src) - updateUsrDialog() - return - return ..() - - emag_act(user as mob) - if(!emagged) - playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1) - emagged = 1 - to_chat(user, "You you disable the security protocols") diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm deleted file mode 100644 index 55997d49105..00000000000 --- a/code/game/machinery/telecomms/traffic_control.dm +++ /dev/null @@ -1,49 +0,0 @@ -/obj/machinery/computer/telecomms/traffic - name = "telecommunications traffic control" - - light_color = LIGHT_COLOR_DARKGREEN - - req_access = list(ACCESS_TCOMSAT) - circuit = /obj/item/circuitboard/comm_traffic - - // NTTC - var/window_id // mostly used to let the configuration datum update the user's UI - var/unlocked = FALSE - -/obj/machinery/computer/telecomms/traffic/multitool_act(mob/user, obj/item/I) - . = TRUE - if(!I.use_tool(src, user, 0, volume = I.tool_volume)) - return - unlocked = !unlocked - to_chat(user, "This computer is now [unlocked ? "Unlocked" : "Locked"]. Reopen the UI to see the difference.") - -/obj/machinery/computer/telecomms/traffic/attack_hand(mob/user) - interact(user) - -/obj/machinery/computer/telecomms/traffic/interact(mob/user) - if(stat & (BROKEN|NOPOWER)) - return 0 - - if(GLOB.nttc_config.valid_languages.len == 1) - GLOB.nttc_config.update_languages() // this is silly but it has to be done because NTTC inits before languages do - - var/datum/asset/assets = get_asset_datum(/datum/asset/simple/nttc) - assets.send(user) - - var/dat = file2text("html/nttc/dist/index.html") - if(unlocked) - dat += "\n" - var/datum/browser/nttc/nt_browser = new(user, name, "NTTC", 720, 480, src, GLOB.nttc_config.nttc_serialize()) - nt_browser.set_content(dat) - nt_browser.open() - window_id = nt_browser.window_id - -/obj/machinery/computer/telecomms/traffic/Topic(href, href_list) - if(..()) - return 1 - - var/mob/user = usr - if(!istype(user) || !user.client) - return 0 - - GLOB.nttc_config.Topic(user, href_list, window_id, src) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index 04803286db1..b92e3c78bb8 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -76,7 +76,7 @@ ui = new(user, src, ui_key, "teleporter_console.tmpl", "Teleporter Console UI", 400, 400) ui.open() -/obj/machinery/computer/teleporter/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/teleporter/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["powerstation"] = power_station if(power_station) diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm index c0b1c44f806..cc9fc3e4666 100644 --- a/code/game/machinery/transformer.dm +++ b/code/game/machinery/transformer.dm @@ -317,7 +317,7 @@ scramble(1, H, 100) H.generate_name() H.sync_organ_dna(assimilate = 1) - H.update_body(0) + H.update_body() H.reset_hair() H.dna.ResetUIFrom(H) diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm index 2876188baa2..9dda3b193bb 100644 --- a/code/game/machinery/turret_control.dm +++ b/code/game/machinery/turret_control.dm @@ -147,7 +147,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/turretid/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/turretid/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["access"] = !isLocked(user) data["locked"] = locked diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 738fb3a5318..1487256c712 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -52,14 +52,11 @@ var/list/hidden_records = list() var/list/coin_records = list() - // // Variables used to initialize advertising - var/product_slogans = "" //String of slogans separated by semicolons, optional - var/product_ads = "" //String of small ad messages in the vending screen - random chance - var/list/ads_list = list() + var/list/ads_list = list() //Small ad messages in the vending screen - random chance, TODO: implementation // Stuff relating vocalizations - var/list/slogan_list = list() + var/list/slogan_list = list() //List of slogans the vendor will say, optional var/vend_reply //Thank you for shopping! var/shut_up = 0 //Stop spouting those godawful pitches! ///can we access the hidden inventory? @@ -95,17 +92,12 @@ build_inventory(products, product_records) build_inventory(contraband, hidden_records) build_inventory(premium, coin_records) - if(product_slogans) - slogan_list += splittext(product_slogans, ";") - + if(LAZYLEN(slogan_list)) // So not all machines speak at the exact same time. // The first time this machine says something will be at slogantime + this random value, - // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is crated. + // so if slogantime is 10 minutes, it will say it at somewhere between 10 and 20 minutes after the machine is created. last_slogan = world.time + rand(0, slogan_delay) - if(product_ads) - ads_list += splittext(product_ads, ";") - power_change() /obj/machinery/vending/Destroy() @@ -222,7 +214,7 @@ ..() /obj/machinery/vending/attackby(obj/item/I, mob/user, params) - if(currently_vending && vendor_account && !vendor_account.suspended) + if(currently_vending && GLOB.vendor_account && !GLOB.vendor_account.suspended) var/paid = 0 var/handled = 0 if(istype(I, /obj/item/card/id)) @@ -452,8 +444,8 @@ return 0 else // Okay to move the money at this point - var/paid = customer_account.charge(currently_vending.price, vendor_account, - "Purchase of [currently_vending.name]", name, vendor_account.owner_name, + var/paid = customer_account.charge(currently_vending.price, GLOB.vendor_account, + "Purchase of [currently_vending.name]", name, GLOB.vendor_account.owner_name, "Sale of [currently_vending.name]", customer_account.owner_name) if(paid) @@ -469,8 +461,8 @@ * Called after the money has already been taken from the customer. */ /obj/machinery/vending/proc/credit_purchase(var/target as text) - vendor_account.money += currently_vending.price - vendor_account.credit(currently_vending.price, "Sale of [currently_vending.name]", + GLOB.vendor_account.money += currently_vending.price + GLOB.vendor_account.credit(currently_vending.price, "Sale of [currently_vending.name]", name, target) /obj/machinery/vending/attack_ai(mob/user) @@ -503,7 +495,7 @@ ui = new(user, src, ui_key, "vending_machine.tmpl", src.name, 440, 600) ui.open() -/obj/machinery/vending/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/vending/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/list/data = list() if(currently_vending) data["mode"] = 1 @@ -573,7 +565,7 @@ eject_item(usr) if(href_list["pay"]) - if(currently_vending && vendor_account && !vendor_account.suspended) + if(currently_vending && GLOB.vendor_account && !GLOB.vendor_account.suspended) var/paid = 0 var/handled = 0 var/datum/money_account/A = usr.get_worn_id_account() @@ -621,7 +613,7 @@ vend(R, usr) else currently_vending = R - if(!vendor_account || vendor_account.suspended) + if(!GLOB.vendor_account || GLOB.vendor_account.suspended) status_message = "This machine is currently unable to process payments due to problems with the associated account." status_error = 1 else @@ -720,7 +712,7 @@ src.seconds_electrified-- //Pitch to the people! Really sell it! - if(((last_slogan + src.slogan_delay) <= world.time) && (slogan_list.len > 0) && (!shut_up) && prob(5)) + if(((last_slogan + src.slogan_delay) <= world.time) && (LAZYLEN(slogan_list)) && (!shut_up) && prob(5)) var/slogan = pick(src.slogan_list) speak(slogan) last_slogan = world.time @@ -770,7 +762,7 @@ continue var/obj/O = new dump_path(loc) - step(O, pick(alldirs)) + step(O, pick(GLOB.alldirs)) found_anything = TRUE dump_amount++ if(dump_amount >= 16) @@ -833,7 +825,7 @@ products = list( /obj/item/assembly/prox_sensor = 5,/obj/item/assembly/igniter = 3,/obj/item/assembly/signaler = 4, /obj/item/wirecutters = 1, /obj/item/cartridge/signal = 4) contraband = list(/obj/item/flashlight = 5,/obj/item/assembly/timer = 2, /obj/item/assembly/voice = 2, /obj/item/assembly/health = 2) - product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!" + ads_list = list("Only the finest!","Have some tools.","The most robust equipment.","The finest gear in space!") refill_canister = /obj/item/vending_refill/assist /obj/machinery/vending/assist/Initialize(mapload) @@ -875,8 +867,8 @@ /obj/item/reagent_containers/food/drinks/ice = 9) contraband = list(/obj/item/reagent_containers/food/drinks/tea = 10) vend_delay = 15 - product_slogans = "I hope nobody asks me for a bloody cup o' tea...;Alcohol is humanity's friend. Would you abandon a friend?;Quite delighted to serve you!;Is nobody thirsty on this station?" - product_ads = "Drink up!;Booze is good for you!;Alcohol is humanity's best friend.;Quite delighted to serve you!;Care for a nice, cold beer?;Nothing cures you like booze!;Have a sip!;Have a drink!;Have a beer!;Beer is good for you!;Only the finest alcohol!;Best quality booze since 2053!;Award-winning wine!;Maximum alcohol!;Man loves beer.;A toast for progress!" + slogan_list = list("I hope nobody asks me for a bloody cup o' tea...","Alcohol is humanity's friend. Would you abandon a friend?","Quite delighted to serve you!","Is nobody thirsty on this station?") + ads_list = list("Drink up!","Booze is good for you!","Alcohol is humanity's best friend.","Quite delighted to serve you!","Care for a nice, cold beer?","Nothing cures you like booze!","Have a sip!","Have a drink!","Have a beer!","Beer is good for you!","Only the finest alcohol!","Best quality booze since 2053!","Award-winning wine!","Maximum alcohol!","Man loves beer.","A toast for progress!") refill_canister = /obj/item/vending_refill/boozeomat /obj/machinery/vending/boozeomat/syndicate_access @@ -895,7 +887,7 @@ /obj/machinery/vending/coffee name = "\improper Hot Drinks machine" desc = "A vending machine which dispenses hot drinks." - product_ads = "Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies" + ads_list = list("Have a drink!","Drink up!","It's good for you!","Would you like a hot joe?","I'd kill for some coffee!","The best beans in the galaxy.","Only the finest brew for you.","Mmmm. Nothing like a coffee.","I like coffee, don't you?","Coffee helps you work!","Try some tea.","We hope you like the best!","Try our new chocolate!","Admin conspiracies") icon_state = "coffee" icon_vend = "coffee-vend" item_slot = TRUE @@ -962,8 +954,8 @@ /obj/machinery/vending/snack name = "\improper Getmore Chocolate Corp" desc = "A snack machine courtesy of the Getmore Chocolate Corporation, based out of Mars." - product_slogans = "Try our new nougat bar!;Twice the calories for half the price!" - product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!" + slogan_list = list("Try our new nougat bar!","Twice the calories for half the price!") + ads_list = list("The healthiest!","Award-winning chocolate bars!","Mmm! So good!","Oh my god it's so juicy!","Have a snack.","Snacks are good for you!","Have some more Getmore!","Best quality snacks straight from mars.","We love chocolate!","Try our new jerky!") icon_state = "snack" products = list(/obj/item/reagent_containers/food/snacks/candy/candybar = 6,/obj/item/reagent_containers/food/drinks/dry_ramen = 6,/obj/item/reagent_containers/food/snacks/chips =6, /obj/item/reagent_containers/food/snacks/sosjerky = 6,/obj/item/reagent_containers/food/snacks/no_raisin = 6,/obj/item/reagent_containers/food/snacks/pistachios =6, @@ -989,7 +981,7 @@ /obj/machinery/vending/chinese name = "\improper Mr. Chang" desc = "A self-serving Chinese food machine, for all your Chinese food needs." - product_slogans = "Taste 5000 years of culture!;Mr. Chang, approved for safe consumption in over 10 sectors!;Chinese food is great for a date night, or a lonely night!;You can't go wrong with Mr. Chang's authentic Chinese food!" + slogan_list = list("Taste 5000 years of culture!","Mr. Chang, approved for safe consumption in over 10 sectors!","Chinese food is great for a date night, or a lonely night!","You can't go wrong with Mr. Chang's authentic Chinese food!") icon_state = "chang" products = list(/obj/item/reagent_containers/food/snacks/chinese/chowmein = 6, /obj/item/reagent_containers/food/snacks/chinese/tao = 6, /obj/item/reagent_containers/food/snacks/chinese/sweetsourchickenball = 6, /obj/item/reagent_containers/food/snacks/chinese/newdles = 6, /obj/item/reagent_containers/food/snacks/chinese/rice = 6) @@ -1013,8 +1005,8 @@ name = "\improper Robust Softdrinks" desc = "A soft drink vendor provided by Robust Industries, LLC." icon_state = "Cola_Machine" - product_slogans = "Robust Softdrinks: More robust than a toolbox to the head!" - product_ads = "Refreshing!;Hope you're thirsty!;Over 1 million drinks sold!;Thirsty? Why not cola?;Please, have a drink!;Drink up!;The best drinks in space." + slogan_list = list("Robust Softdrinks: More robust than a toolbox to the head!") + ads_list = list("Refreshing!","Hope you're thirsty!","Over 1 million drinks sold!","Thirsty? Why not cola?","Please, have a drink!","Drink up!","The best drinks in space.") products = list(/obj/item/reagent_containers/food/drinks/cans/cola = 10,/obj/item/reagent_containers/food/drinks/cans/space_mountain_wind = 10, /obj/item/reagent_containers/food/drinks/cans/dr_gibb = 10,/obj/item/reagent_containers/food/drinks/cans/starkist = 10, /obj/item/reagent_containers/food/drinks/cans/space_up = 10,/obj/item/reagent_containers/food/drinks/cans/grape_juice = 10) @@ -1040,7 +1032,7 @@ /obj/machinery/vending/cart name = "\improper PTech" desc = "Cartridges for PDA's." - product_slogans = "Carts to go!" + slogan_list = list("Carts to go!") icon_state = "cart" icon_deny = "cart-deny" products = list(/obj/item/pda =10,/obj/item/cartridge/mob_hunt_game = 25,/obj/item/cartridge/medical = 10,/obj/item/cartridge/chemistry = 10, @@ -1069,8 +1061,8 @@ desc = "An overwhelming amount of ancient patriotism washes over you just by looking at the machine." icon_state = "liberationstation" req_access_txt = "1" - product_slogans = "Liberation Station: Your one-stop shop for all things second amendment!;Be a patriot today, pick up a gun!;Quality weapons for cheap prices!;Better dead than red!" - product_ads = "Float like an astronaut, sting like a bullet!;Express your second amendment today!;Guns don't kill people, but you can!;Who needs responsibilities when you have guns?" + slogan_list = list("Liberation Station: Your one-stop shop for all things second amendment!","Be a patriot today, pick up a gun!","Quality weapons for cheap prices!","Better dead than red!") + ads_list = list("Float like an astronaut, sting like a bullet!","Express your second amendment today!","Guns don't kill people, but you can!","Who needs responsibilities when you have guns?") vend_reply = "Remember the name: Liberation Station!" products = list(/obj/item/gun/projectile/automatic/pistol/deagle/gold = 2,/obj/item/gun/projectile/automatic/pistol/deagle/camo = 2, /obj/item/gun/projectile/automatic/pistol/m1911 = 2,/obj/item/gun/projectile/automatic/proto = 2, @@ -1086,8 +1078,8 @@ name = "\improper Syndicate Donksoft Toy Vendor" desc = "An ages 8 and up approved vendor that dispenses toys. If you were to find the right wires, you can unlock the adult mode setting!" icon_state = "syndi" - product_slogans = "Get your cool toys today!;Trigger a valid hunter today!;Quality toy weapons for cheap prices!;Give them to HoPs for all access!;Give them to HoS to get permabrigged!" - product_ads = "Feel robust with your toys!;Express your inner child today!;Toy weapons don't kill people, but valid hunters do!;Who needs responsibilities when you have toy weapons?;Make your next murder FUN!" + slogan_list = list("Get your cool toys today!","Trigger a valid hunter today!","Quality toy weapons for cheap prices!","Give them to HoPs for all access!","Give them to HoS to get permabrigged!") + ads_list = list("Feel robust with your toys!","Express your inner child today!","Toy weapons don't kill people, but valid hunters do!","Who needs responsibilities when you have toy weapons?","Make your next murder FUN!") vend_reply = "Come back for more!" products = list(/obj/item/gun/projectile/automatic/toy = 10, /obj/item/gun/projectile/automatic/toy/pistol= 10, @@ -1112,8 +1104,8 @@ /obj/machinery/vending/cigarette name = "cigarette machine" desc = "If you want to get cancer, might as well do it in style." - product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!" - product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs." + slogan_list = list("Space cigs taste good like a cigarette should.","I'd rather toolbox than switch.","Smoke!","Don't believe the reports - smoke today!") + ads_list = list("Probably not bad for you!","Don't believe the scientists!","It's good for you!","Don't quit, buy more!","Smoke!","Nicotine heaven.","Best cigarettes since 2150.","Award-winning cigs.") vend_delay = 34 icon_state = "cigs" products = list(/obj/item/storage/fancy/cigarettes/cigpack_robust = 12, /obj/item/storage/fancy/cigarettes/cigpack_uplift = 6, /obj/item/storage/fancy/cigarettes/cigpack_random = 6, /obj/item/reagent_containers/food/pill/patch/nicotine = 10, /obj/item/storage/box/matches = 10,/obj/item/lighter/random = 4,/obj/item/storage/fancy/rollingpapers = 5) @@ -1141,8 +1133,8 @@ /obj/machinery/vending/cigarette/beach //Used in the lavaland_biodome_beach.dmm ruin name = "\improper ShadyCigs Ultra" desc = "Now with extra premium products!" - product_ads = "Probably not bad for you!;Dope will get you through times of no money better than money will get you through times of no dope!;It's good for you!" - product_slogans = "Turn on, tune in, drop out!;Better living through chemistry!;Toke!;Don't forget to keep a smile on your lips and a song in your heart!" + ads_list = list("Probably not bad for you!","Dope will get you through times of no money better than money will get you through times of no dope!","It's good for you!") + slogan_list = list("Turn on, tune in, drop out!","Better living through chemistry!","Toke!","Don't forget to keep a smile on your lips and a song in your heart!") products = list(/obj/item/storage/fancy/cigarettes = 5, /obj/item/storage/fancy/cigarettes/cigpack_uplift = 3, /obj/item/storage/fancy/cigarettes/cigpack_robust = 3, @@ -1170,9 +1162,9 @@ desc = "Medical drug dispenser." icon_state = "med" icon_deny = "med-deny" - product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!" + ads_list = list("Go save some lives!","The best stuff for your medbay.","Only the finest tools.","Natural chemicals!","This stuff saves lives.","Don't you want some?","Ping!") req_access_txt = "5" - products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/food/pill/patch/styptic = 10, /obj/item/reagent_containers/food/pill/patch/silver_sulf = 10, + products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/food/pill/patch/styptic = 4, /obj/item/reagent_containers/food/pill/patch/silver_sulf = 4, /obj/item/reagent_containers/applicator/brute = 3, /obj/item/reagent_containers/applicator/burn = 3, /obj/item/reagent_containers/glass/bottle/charcoal = 4, /obj/item/reagent_containers/glass/bottle/epinephrine = 4, /obj/item/reagent_containers/glass/bottle/diphenhydramine = 4, /obj/item/reagent_containers/glass/bottle/salicylic = 4, /obj/item/reagent_containers/glass/bottle/potassium_iodide =3, /obj/item/reagent_containers/glass/bottle/saline = 5, /obj/item/reagent_containers/glass/bottle/morphine = 4, /obj/item/reagent_containers/glass/bottle/ether = 4, /obj/item/reagent_containers/glass/bottle/atropine = 3, @@ -1209,7 +1201,7 @@ /obj/machinery/vending/wallmed name = "\improper NanoMed" desc = "Wall-mounted Medical Equipment dispenser." - product_ads = "Go save some lives!;The best stuff for your medbay.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?" + ads_list = list("Go save some lives!","The best stuff for your medbay.","Only the finest tools.","Natural chemicals!","This stuff saves lives.","Don't you want some?") icon_state = "wallmed" icon_deny = "wallmed-deny" density = FALSE //It is wall-mounted, and thus, not dense. --Superxpdude @@ -1233,7 +1225,7 @@ desc = "EVIL wall-mounted Medical Equipment dispenser." icon_state = "syndimed" icon_deny = "syndimed-deny" - product_ads = "Go end some lives!;The best stuff for your ship.;Only the finest tools.;Natural chemicals!;This stuff saves lives.;Don't you want some?;Ping!" + ads_list = list("Go end some lives!","The best stuff for your ship.","Only the finest tools.","Natural chemicals!","This stuff saves lives.","Don't you want some?","Ping!") req_access_txt = "150" products = list(/obj/item/stack/medical/bruise_pack = 2,/obj/item/stack/medical/ointment = 2,/obj/item/reagent_containers/hypospray/autoinjector = 4,/obj/item/healthanalyzer = 1) contraband = list(/obj/item/reagent_containers/syringe/charcoal = 4,/obj/item/reagent_containers/syringe/antiviral = 4,/obj/item/reagent_containers/food/pill/tox = 1) @@ -1241,7 +1233,7 @@ /obj/machinery/vending/security name = "\improper SecTech" desc = "A security equipment vendor." - product_ads = "Crack capitalist skulls!;Beat some heads in!;Don't forget - harm is good!;Your weapons are right here.;Handcuffs!;Freeze, scumbag!;Don't tase me bro!;Tase them, bro.;Why not have a donut?" + ads_list = list("Crack capitalist skulls!","Beat some heads in!","Don't forget - harm is good!","Your weapons are right here.","Handcuffs!","Freeze, scumbag!","Don't tase me bro!","Tase them, bro.","Why not have a donut?") icon_state = "sec" icon_deny = "sec-deny" req_access_txt = "1" @@ -1263,8 +1255,8 @@ /obj/machinery/vending/hydronutrients name = "\improper NutriMax" desc = "A plant nutrients vendor" - product_slogans = "Aren't you glad you don't have to fertilize the natural way?;Now with 50% less stink!;Plants are people too!" - product_ads = "We like plants!;Don't you want some?;The greenest thumbs ever.;We like big plants.;Soft soil..." + slogan_list = list("Aren't you glad you don't have to fertilize the natural way?","Now with 50% less stink!","Plants are people too!") + ads_list = list("We like plants!","Don't you want some?","The greenest thumbs ever.","We like big plants.","Soft soil...") icon_state = "nutri" icon_deny = "nutri-deny" products = list(/obj/item/reagent_containers/glass/bottle/nutrient/ez = 30,/obj/item/reagent_containers/glass/bottle/nutrient/l4z = 20,/obj/item/reagent_containers/glass/bottle/nutrient/rh = 10,/obj/item/reagent_containers/spray/pestspray = 20, @@ -1284,8 +1276,8 @@ /obj/machinery/vending/hydroseeds name = "\improper MegaSeed Servitor" desc = "When you need seeds fast!" - product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!" - product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!" + slogan_list = list("THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!","Hands down the best seed selection on the station!","Also certain mushroom varieties available, more for experts! Get certified today!") + ads_list = list("We like plants!","Grow some crops!","Grow, baby, growww!","Aw h'yeah son!") icon_state = "seeds" products = list(/obj/item/seeds/aloe =3, /obj/item/seeds/ambrosia = 3, @@ -1354,10 +1346,10 @@ name = "\improper MagiVend" desc = "A magic vending machine." icon_state = "MagiVend" - product_slogans = "Sling spells the proper way with MagiVend!;Be your own Houdini! Use MagiVend!" + slogan_list = list("Sling spells the proper way with MagiVend!","Be your own Houdini! Use MagiVend!") vend_delay = 15 vend_reply = "Have an enchanted evening!" - product_ads = "FJKLFJSD;AJKFLBJAKL;1234 LOONIES LOL!;>MFW;Kill them fuckers!;GET DAT FUKKEN DISK;HONK!;EI NATH;Destroy the station!;Admin conspiracies since forever!;Space-time bending hardware!" + ads_list = list("FJKLFJSD","AJKFLBJAKL","1234 LOONIES LOL!",">MFW","Kill them fuckers!","GET DAT FUKKEN DISK","HONK!","EI NATH","Destroy the station!","Admin conspiracies since forever!","Space-time bending hardware!") products = list(/obj/item/clothing/head/wizard = 1, /obj/item/clothing/suit/wizrobe = 1, /obj/item/clothing/head/wizard/red = 1, @@ -1367,6 +1359,10 @@ /obj/item/clothing/head/wizard/clown = 1, /obj/item/clothing/mask/gas/clownwiz = 1, /obj/item/clothing/shoes/clown_shoes/magical = 1, + /obj/item/clothing/suit/wizrobe/mime = 1, + /obj/item/clothing/head/wizard/mime = 1, + /obj/item/clothing/mask/gas/mime/wizard = 1, + /obj/item/clothing/shoes/sandal/marisa = 1, /obj/item/twohanded/staff = 2) contraband = list(/obj/item/reagent_containers/glass/bottle/wizarditis = 1) armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) @@ -1377,7 +1373,7 @@ desc = "A vending machine for costumes." icon_state = "theater" icon_deny = "theater-deny" - product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!" + slogan_list = list("Dress for success!","Suited and booted!","It's show time!","Why leave style up to fate? Use AutoDrobe!") vend_delay = 15 vend_reply = "Thank you for using AutoDrobe!" products = list(/obj/item/clothing/suit/chickensuit = 1, @@ -1519,7 +1515,7 @@ /obj/machinery/vending/dinnerware name = "\improper Plasteel Chef's Dinnerware Vendor" desc = "A kitchen and restaurant equipment vendor." - product_ads = "Mm, food stuffs!;Food and food accessories.;Get your plates!;You like forks?;I like forks.;Woo, utensils.;You don't really need these..." + ads_list = list("Mm, food stuffs!","Food and food accessories.","Get your plates!","You like forks?","I like forks.","Woo, utensils.","You don't really need these...") icon_state = "dinnerware" products = list(/obj/item/storage/bag/tray = 8,/obj/item/kitchen/utensil/fork = 6, /obj/item/kitchen/knife = 3,/obj/item/kitchen/rollingpin = 2, @@ -1551,7 +1547,7 @@ name = "\improper BODA" desc = "Old sweet water vending machine." icon_state = "sovietsoda" - product_ads = "For Tsar and Country.;Have you fulfilled your nutrition quota today?;Very nice!;We are simple people, for this is all we eat.;If there is a person, there is a problem. If there is no person, then there is no problem." + ads_list = list("For Tsar and Country.","Have you fulfilled your nutrition quota today?","Very nice!","We are simple people, for this is all we eat.","If there is a person, there is a problem. If there is no person, then there is no problem.") products = list(/obj/item/reagent_containers/food/drinks/drinkingglass/soda = 30) contraband = list(/obj/item/reagent_containers/food/drinks/drinkingglass/cola = 20) resistance_flags = FIRE_PROOF @@ -1646,8 +1642,8 @@ /obj/machinery/vending/sustenance name = "\improper Sustenance Vendor" desc = "A vending machine which vends food, as required by section 47-C of the NT's Prisoner Ethical Treatment Agreement." - product_slogans = "Enjoy your meal.;Enough calories to support strenuous labor." - product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!" + slogan_list = list("Enjoy your meal.","Enough calories to support strenuous labor.") + ads_list = list("The healthiest!","Award-winning chocolate bars!","Mmm! So good!","Oh my god it's so juicy!","Have a snack.","Snacks are good for you!","Have some more Getmore!","Best quality snacks straight from mars.","We love chocolate!","Try our new jerky!") icon_state = "sustenance" products = list(/obj/item/reagent_containers/food/snacks/tofu = 24, /obj/item/reagent_containers/food/drinks/ice = 12, @@ -1671,7 +1667,7 @@ name = "\improper Hatlord 9000" desc = "It doesn't seem the slightest bit unusual. This frustrates you immensely." icon_state = "hats" - product_ads = "Warning, not all hats are dog/monkey compatible. Apply forcefully with care.;Apply directly to the forehead.;Who doesn't love spending cash on hats?!;From the people that brought you collectable hat crates, Hatlord!" + ads_list = list("Warning, not all hats are dog/monkey compatible. Apply forcefully with care.","Apply directly to the forehead.","Who doesn't love spending cash on hats?!","From the people that brought you collectable hat crates, Hatlord!") products = list(/obj/item/clothing/head/bowlerhat = 10, /obj/item/clothing/head/beaverhat = 10, /obj/item/clothing/head/boaterhat = 10, @@ -1695,7 +1691,7 @@ name = "\improper Suitlord 9000" desc = "You wonder for a moment why all of your shirts and pants come conjoined. This hurts your head and you stop thinking about it." icon_state = "suits" - product_ads = "Pre-Ironed, Pre-Washed, Pre-Wor-*BZZT*;Blood of your enemies washes right out!;Who are YOU wearing?;Look dapper! Look like an idiot!;Dont carry your size? How about you shave off some pounds you fat lazy- *BZZT*" + ads_list = list("Pre-Ironed, Pre-Washed, Pre-Wor-*BZZT*","Blood of your enemies washes right out!","Who are YOU wearing?","Look dapper! Look like an idiot!","Dont carry your size? How about you shave off some pounds you fat lazy- *BZZT*") products = list(/obj/item/clothing/under/color/black = 10,/obj/item/clothing/under/color/blue = 10,/obj/item/clothing/under/color/green = 10,/obj/item/clothing/under/color/grey = 10,/obj/item/clothing/under/color/pink = 10,/obj/item/clothing/under/color/red = 10, /obj/item/clothing/under/color/white = 10, /obj/item/clothing/under/color/yellow = 10,/obj/item/clothing/under/color/lightblue = 10,/obj/item/clothing/under/color/aqua = 10,/obj/item/clothing/under/color/purple = 10,/obj/item/clothing/under/color/lightgreen = 10, /obj/item/clothing/under/color/lightblue = 10,/obj/item/clothing/under/color/lightbrown = 10,/obj/item/clothing/under/color/brown = 10,/obj/item/clothing/under/color/yellowgreen = 10,/obj/item/clothing/under/color/darkblue = 10,/obj/item/clothing/under/color/lightred = 10, /obj/item/clothing/under/color/darkred = 10) @@ -1716,7 +1712,7 @@ name = "\improper Shoelord 9000" desc = "Wow, hatlord looked fancy, suitlord looked streamlined, and this is just normal. The guy who designed these must be an idiot." icon_state = "shoes" - product_ads = "Put your foot down!;One size fits all!;IM WALKING ON SUNSHINE!;No hobbits allowed.;NO PLEASE WILLY, DONT HURT ME- *BZZT*" + ads_list = list("Put your foot down!","One size fits all!","IM WALKING ON SUNSHINE!","No hobbits allowed.","NO PLEASE WILLY, DONT HURT ME- *BZZT*") products = list(/obj/item/clothing/shoes/black = 10,/obj/item/clothing/shoes/brown = 10,/obj/item/clothing/shoes/blue = 10,/obj/item/clothing/shoes/green = 10,/obj/item/clothing/shoes/yellow = 10,/obj/item/clothing/shoes/purple = 10,/obj/item/clothing/shoes/red = 10,/obj/item/clothing/shoes/white = 10,/obj/item/clothing/shoes/sandal=10) contraband = list(/obj/item/clothing/shoes/orange = 5) premium = list(/obj/item/clothing/shoes/rainbow = 1) @@ -1734,8 +1730,8 @@ /obj/machinery/vending/syndicigs name = "\improper Suspicious Cigarette Machine" desc = "Smoke 'em if you've got 'em." - product_slogans = "Space cigs taste good like a cigarette should.;I'd rather toolbox than switch.;Smoke!;Don't believe the reports - smoke today!" - product_ads = "Probably not bad for you!;Don't believe the scientists!;It's good for you!;Don't quit, buy more!;Smoke!;Nicotine heaven.;Best cigarettes since 2150.;Award-winning cigs." + slogan_list = list("Space cigs taste good like a cigarette should.","I'd rather toolbox than switch.","Smoke!","Don't believe the reports - smoke today!") + ads_list = list("Probably not bad for you!","Don't believe the scientists!","It's good for you!","Don't quit, buy more!","Smoke!","Nicotine heaven.","Best cigarettes since 2150.","Award-winning cigs.") vend_delay = 34 icon_state = "cigs" products = list(/obj/item/storage/fancy/cigarettes/syndicate = 10,/obj/item/lighter/random = 5) @@ -1743,8 +1739,8 @@ /obj/machinery/vending/syndisnack name = "\improper Getmore Chocolate Corp" desc = "A modified snack machine courtesy of the Getmore Chocolate Corporation, based out of Mars" - product_slogans = "Try our new nougat bar!;Twice the calories for half the price!" - product_ads = "The healthiest!;Award-winning chocolate bars!;Mmm! So good!;Oh my god it's so juicy!;Have a snack.;Snacks are good for you!;Have some more Getmore!;Best quality snacks straight from mars.;We love chocolate!;Try our new jerky!" + slogan_list = list("Try our new nougat bar!","Twice the calories for half the price!") + ads_list = list("The healthiest!","Award-winning chocolate bars!","Mmm! So good!","Oh my god it's so juicy!","Have a snack.","Snacks are good for you!","Have some more Getmore!","Best quality snacks straight from mars.","We love chocolate!","Try our new jerky!") icon_state = "snack" products = list(/obj/item/reagent_containers/food/snacks/chips =6,/obj/item/reagent_containers/food/snacks/sosjerky = 6, /obj/item/reagent_containers/food/snacks/syndicake = 6, /obj/item/reagent_containers/food/snacks/cheesiehonkers = 6) @@ -1754,7 +1750,7 @@ name = "\improper ClothesMate" //renamed to make the slogan rhyme desc = "A vending machine for clothing." icon_state = "clothes" - product_slogans = "Dress for success!;Prepare to look swagalicious!;Look at all this free swag!;Why leave style up to fate? Use the ClothesMate!" + slogan_list = list("Dress for success!","Prepare to look swagalicious!","Look at all this free swag!","Why leave style up to fate? Use the ClothesMate!") vend_delay = 15 vend_reply = "Thank you for using the ClothesMate!" products = list(/obj/item/clothing/head/that = 2, @@ -1855,8 +1851,8 @@ /obj/machinery/vending/artvend name = "\improper ArtVend" desc = "A vending machine for art supplies." - product_slogans = "Stop by for all your artistic needs!;Color the floors with crayons, not blood!;Don't be a starving artist, use ArtVend. ;Don't fart, do art!" - product_ads = "Just like Kindergarten!;Now with 1000% more vibrant colors!;Screwing with the janitor was never so easy!;Creativity is at the heart of every spessman." + slogan_list = list("Stop by for all your artistic needs!","Color the floors with crayons, not blood!","Don't be a starving artist, use ArtVend. ","Don't fart, do art!") + ads_list = list("Just like Kindergarten!","Now with 1000% more vibrant colors!","Screwing with the janitor was never so easy!","Creativity is at the heart of every spessman.") vend_delay = 15 icon_state = "artvend" products = list(/obj/item/stack/cable_coil/random = 10,/obj/item/camera = 4,/obj/item/camera_film = 6, @@ -1870,8 +1866,8 @@ /obj/machinery/vending/crittercare name = "\improper CritterCare" desc = "A vending machine for pet supplies." - product_slogans = "Stop by for all your animal's needs!;Cuddly pets deserve a stylish collar!;Pets in space, what could be more adorable?;Freshest fish eggs in the system!;Rocks are the perfect pet, buy one today!" - product_ads = "House-training costs extra!;Now with 1000% more cat hair!;Allergies are a sign of weakness!;Dogs are man's best friend. Remember that Vulpkanin!; Heat lamps for Unathi!; Vox-y want a cracker?" + slogan_list = list("Stop by for all your animal's needs!","Cuddly pets deserve a stylish collar!","Pets in space, what could be more adorable?","Freshest fish eggs in the system!","Rocks are the perfect pet, buy one today!") + ads_list = list("House-training costs extra!","Now with 1000% more cat hair!","Allergies are a sign of weakness!","Dogs are man's best friend. Remember that Vulpkanin!"," Heat lamps for Unathi!"," Vox-y want a cracker?") vend_delay = 15 icon_state = "crittercare" products = list(/obj/item/clothing/accessory/petcollar = 5, /obj/item/storage/firstaid/aquatic_kit/full =5, /obj/item/fish_eggs/goldfish = 5, @@ -1905,7 +1901,7 @@ desc = "All the parts you need to build your own custom pc." icon_state = "modularpc" icon_deny = "modularpc-deny" - product_ads = "Get your gamer gear!;The best GPUs for all of your space-crypto needs!;The most robust cooling!;The finest RGB in space!" + ads_list = list("Get your gamer gear!","The best GPUs for all of your space-crypto needs!","The most robust cooling!","The finest RGB in space!") vend_reply = "Game on!" products = list(/obj/item/modular_computer/laptop = 4, /obj/item/modular_computer/tablet = 4, diff --git a/code/game/magic/Uristrunes.dm b/code/game/magic/Uristrunes.dm index e0621db3d9b..11ca1467918 100644 --- a/code/game/magic/Uristrunes.dm +++ b/code/game/magic/Uristrunes.dm @@ -11,29 +11,29 @@ return get_rune(bits, animated) -var/list/rune_cache = list() -var/runetype = "rune" +GLOBAL_LIST_EMPTY(cult_rune_cache) +GLOBAL_VAR_INIT(cult_rune_style, "rune") // Style of run the cult is using (fire, death, regular, etc) /proc/get_rune(symbol_bits, animated = 0) var/lookup = "[symbol_bits]-[animated]" if(!SSticker.mode)//work around for maps with runes and cultdat is not loaded all the way - runetype = "rune" + GLOB.cult_rune_style = "rune" else if(SSticker.cultdat.theme == "fire") - runetype = "fire-rune" + GLOB.cult_rune_style = "fire-rune" else if(SSticker.cultdat.theme == "death") - runetype = "death-rune" + GLOB.cult_rune_style = "death-rune" - if(lookup in rune_cache) - return rune_cache[lookup] + if(lookup in GLOB.cult_rune_cache) + return GLOB.cult_rune_cache[lookup] - var/icon/I = icon('icons/effects/uristrunes.dmi', "[runetype]-179") + var/icon/I = icon('icons/effects/uristrunes.dmi', "[GLOB.cult_rune_style]-179") for(var/i = 0, i < 10, i++) if(symbol_bits & (1 << i)) - I.Blend(icon('icons/effects/uristrunes.dmi', "[runetype]-[1 << i]"), ICON_OVERLAY) + I.Blend(icon('icons/effects/uristrunes.dmi', "[GLOB.cult_rune_style]-[1 << i]"), ICON_OVERLAY) I.SwapColor(rgb(0, 0, 0, 100), rgb(100, 0, 0, 200))//TO DO COMMENT:NEED TO ADJUST FOR DIFFRNET CULTS @@ -90,6 +90,6 @@ var/runetype = "rune" result.Insert(I3, "", frame = 7, delay = 2) result.Insert(I2, "", frame = 8, delay = 2) - rune_cache[lookup] = result + GLOB.cult_rune_cache[lookup] = result return result diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm index d9ec4412ab3..0898936cbfb 100644 --- a/code/game/mecha/combat/gygax.dm +++ b/code/game/mecha/combat/gygax.dm @@ -39,7 +39,7 @@ icon_state = "darkgygax" initial_icon = "darkgygax" max_integrity = 300 - deflect_chance = 15 + deflect_chance = 20 armor = list(melee = 40, bullet = 40, laser = 50, energy = 35, bomb = 20, bio = 0, rad =20, fire = 100, acid = 100) max_temperature = 35000 leg_overload_coeff = 100 @@ -50,16 +50,24 @@ starting_voice = /obj/item/mecha_modkit/voice/syndicate destruction_sleep_duration = 1 +/obj/mecha/combat/gygax/dark/GrantActions(mob/living/user, human_occupant = 0) + . = ..() + thrusters_action.Grant(user, src) + +/obj/mecha/combat/gygax/dark/RemoveActions(mob/living/user, human_occupant = 0) + . = ..() + thrusters_action.Remove(user) + /obj/mecha/combat/gygax/dark/loaded/New() ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang + ME = new /obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster ME.attach(src) - ME = new /obj/item/mecha_parts/mecha_equipment/teleporter/precise + ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay ME.attach(src) /obj/mecha/combat/gygax/dark/add_cell() - cell = new /obj/item/stock_parts/cell/hyper(src) + cell = new /obj/item/stock_parts/cell/bluespace(src) diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index 43937ab1111..61ba683ad18 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -206,6 +206,7 @@ /obj/item/mecha_parts/mecha_equipment/repair_droid/detach() chassis.overlays -= droid_overlay STOP_PROCESSING(SSobj, src) + return ..() /obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info() if(!chassis) return diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index 0c9ae020a1e..04322c63093 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -134,7 +134,7 @@ return recharge_port = locate(/obj/machinery/mech_bay_recharge_port) in range(1) if(!recharge_port) - for(var/D in cardinal) + for(var/D in GLOB.cardinal) var/turf/A = get_step(src, D) A = get_step(A, D) recharge_port = locate(/obj/machinery/mech_bay_recharge_port) in A @@ -171,7 +171,7 @@ // auto update every Master Controller tick ui.set_auto_update(1) -/obj/machinery/computer/mech_bay_power_console/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/mech_bay_power_console/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] if(!recharge_port) reconnect() diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 90256fe5d2a..7d8537c7910 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -38,9 +38,7 @@ ) /obj/machinery/mecha_part_fabricator/New() - var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, - list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE), 0, - FALSE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE), 0, FALSE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE ..() component_parts = list() @@ -65,7 +63,7 @@ RefreshParts() /obj/machinery/mecha_part_fabricator/Destroy() - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_all() return ..() @@ -75,7 +73,7 @@ //maximum stocking amount (default 300000, 600000 at T4) for(var/obj/item/stock_parts/matter_bin/M in component_parts) T += M.rating - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.max_amount = (200000 + (T*50000)) //resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55) @@ -118,7 +116,7 @@ /obj/machinery/mecha_part_fabricator/proc/output_available_resources() var/output - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] output += "[M.name]: [M.amount] cm³" @@ -139,7 +137,7 @@ /obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) if(D.reagents_list.len) // No reagents storage - no reagent designs. return FALSE - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) if(materials.has_materials(get_resources_w_coeff(D))) return TRUE return FALSE @@ -149,7 +147,7 @@ desc = "It's building \a [initial(D.name)]." var/list/res_coef = get_resources_w_coeff(D) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.use_amount(res_coef) overlays += "fab-active" use_power = ACTIVE_POWER_USE @@ -414,7 +412,7 @@ break if(href_list["remove_mat"] && href_list["material"]) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_sheets(text2num(href_list["remove_mat"]), href_list["material"]) updateUsrDialog() diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 69ba9941303..610436406d8 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -35,6 +35,7 @@ var/lights = 0 var/lights_power = 6 var/emagged = FALSE + var/frozen = FALSE //inner atmos var/use_internal_tank = 0 @@ -112,7 +113,7 @@ log_message("[src] created.") GLOB.mechas_list += src //global mech list prepare_huds() - for(var/datum/atom_hud/data/diagnostic/diag_hud in huds) + for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) diag_hud.add_to_hud(src) diag_hud_set_mechhealth() diag_hud_set_mechcell() @@ -263,7 +264,7 @@ return 1 /obj/mecha/relaymove(mob/user, direction) - if(!direction) + if(!direction || frozen) return if(user != occupant) //While not "realistic", this piece is player friendly. user.forceMove(get_turf(src)) @@ -540,7 +541,7 @@ /obj/mecha/attack_alien(mob/living/user) - log_message("Attack by alien. Attacker - [user].", color = "red") + log_message("Attack by alien. Attacker - [user].", TRUE) playsound(src.loc, 'sound/weapons/slash.ogg', 100, TRUE) attack_generic(user, 15, BRUTE, "melee", 0) @@ -559,6 +560,7 @@ animal_damage = user.obj_damage animal_damage = min(animal_damage, 20*user.environment_smash) user.create_attack_log("attacked [name]") + add_attack_logs(user, src, "Attacked") attack_generic(user, animal_damage, user.melee_damage_type, "melee", play_soundeffect) return TRUE @@ -1048,6 +1050,9 @@ log_message("Now taking air from [use_internal_tank ? "internal airtank" : "environment"].") /obj/mecha/MouseDrop_T(mob/M, mob/user) + if(frozen) + to_chat(user, "Do not enter Admin-Frozen mechs.") + return if(user.incapacitated()) return if(user != M) @@ -1093,11 +1098,10 @@ to_chat(user, "You stop entering the exosuit!") /obj/mecha/proc/moved_inside(var/mob/living/carbon/human/H as mob) - if(H && H.client && H in range(1)) + if(H && H.client && (H in range(1))) occupant = H H.stop_pulling() H.forceMove(src) - H.reset_perspective(src) add_fingerprint(H) GrantActions(H, human_occupant = 1) forceMove(loc) @@ -1140,7 +1144,7 @@ return 0 /obj/mecha/proc/mmi_moved_inside(obj/item/mmi/mmi_as_oc,mob/user) - if(mmi_as_oc && user in range(1)) + if(mmi_as_oc && (user in range(1))) if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client) to_chat(user, "Consciousness matrix not detected.") return 0 diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index 0313397a809..9a3dffb0c3b 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -23,7 +23,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/computer/mecha/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/mecha/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["screen"] = screen if(screen == 0) diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index 2cef4d49dd3..93003258008 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -19,7 +19,7 @@ if(istype(H.glasses, /obj/item/clothing/glasses/hud)) occupant_message("[H.glasses] prevent you from using the built-in medical hud.") else - var/datum/atom_hud/data/human/medical/advanced/A = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/data/human/medical/advanced/A = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] A.add_hud_to(H) builtin_hud_user = 1 @@ -27,19 +27,19 @@ . = ..() if(.) if(occupant.client) - var/datum/atom_hud/A = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/A = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] A.add_hud_to(occupant) builtin_hud_user = 1 /obj/mecha/medical/odysseus/go_out() if(ishuman(occupant) && builtin_hud_user) var/mob/living/carbon/human/H = occupant - var/datum/atom_hud/data/human/medical/advanced/A = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/data/human/medical/advanced/A = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] A.remove_hud_from(H) builtin_hud_user = 0 else if((isbrain(occupant) || pilot_is_mmi()) && builtin_hud_user) var/mob/living/carbon/brain/H = occupant - var/datum/atom_hud/A = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/A = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] A.remove_hud_from(H) builtin_hud_user = 0 diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index 0b106f2ab4c..494fc70d36b 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -139,7 +139,7 @@ ..() if(href_list["drop_from_cargo"]) var/obj/O = locate(href_list["drop_from_cargo"]) - if(O && O in cargo) + if(O && (O in cargo)) occupant_message("You unload [O].") O.loc = get_turf(src) cargo -= O diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index cc2100d568f..8b9e5e92319 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -26,7 +26,7 @@ /obj/effect/anomaly/proc/anomalyEffect() if(prob(50)) - step(src,pick(alldirs)) + step(src,pick(GLOB.alldirs)) /obj/effect/anomaly/proc/anomalyNeutralize() diff --git a/code/game/objects/effects/bump_teleporter.dm b/code/game/objects/effects/bump_teleporter.dm index be8acfc80bc..f2ba7d03ee0 100644 --- a/code/game/objects/effects/bump_teleporter.dm +++ b/code/game/objects/effects/bump_teleporter.dm @@ -1,4 +1,4 @@ -var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list() +GLOBAL_LIST_EMPTY(bump_teleporters) /obj/effect/bump_teleporter name = "bump-teleporter" @@ -13,10 +13,10 @@ var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list() /obj/effect/bump_teleporter/New() ..() - BUMP_TELEPORTERS += src + GLOB.bump_teleporters += src /obj/effect/bump_teleporter/Destroy() - BUMP_TELEPORTERS -= src + GLOB.bump_teleporters -= src return ..() /obj/effect/bump_teleporter/singularity_act() @@ -34,7 +34,7 @@ var/list/obj/effect/bump_teleporter/BUMP_TELEPORTERS = list() //user.loc = src.loc //Stop at teleporter location, there is nowhere to teleport to. return - for(var/obj/effect/bump_teleporter/BT in BUMP_TELEPORTERS) + for(var/obj/effect/bump_teleporter/BT in GLOB.bump_teleporters) if(BT.id == src.id_target) usr.loc = BT.loc //Teleport to location with correct id. return diff --git a/code/game/objects/effects/decals/Cleanable/fuel.dm b/code/game/objects/effects/decals/Cleanable/fuel.dm index 6c7ea8f3247..cc728919079 100644 --- a/code/game/objects/effects/decals/Cleanable/fuel.dm +++ b/code/game/objects/effects/decals/Cleanable/fuel.dm @@ -26,7 +26,7 @@ var/turf/simulated/S = loc if(!istype(S)) return - for(var/d in cardinal) + for(var/d in GLOB.cardinal) if(rand(25)) var/turf/simulated/target = get_step(src, d) var/turf/simulated/origin = get_turf(src) diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index fd7ce125089..b7eea1b367f 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -1,6 +1,6 @@ #define DRYING_TIME 5 * 60 * 10 //for 1 unit of depth in puddle (amount var) -var/global/list/image/splatter_cache = list() +GLOBAL_LIST_EMPTY(splatter_cache) /obj/effect/decal/cleanable/blood name = "blood" @@ -86,7 +86,7 @@ var/global/list/image/splatter_cache = list() user.blood_DNA |= blood_DNA.Copy() user.bloody_hands += taken user.hand_blood_color = basecolor - user.update_inv_gloves(1) + user.update_inv_gloves() user.verbs += /mob/living/carbon/human/proc/bloody_doodle /obj/effect/decal/cleanable/blood/can_bloodcrawl_in() @@ -112,7 +112,8 @@ var/global/list/image/splatter_cache = list() /obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose name = "blood" - icon_state = "ltrails_1" + icon = 'icons/effects/effects.dmi' + icon_state = "nothing" desc = "Your instincts say you shouldn't be following these." gender = PLURAL density = FALSE diff --git a/code/game/objects/effects/decals/Cleanable/tracks.dm b/code/game/objects/effects/decals/Cleanable/tracks.dm index 52109a5ae86..832a66a93ba 100644 --- a/code/game/objects/effects/decals/Cleanable/tracks.dm +++ b/code/game/objects/effects/decals/Cleanable/tracks.dm @@ -2,7 +2,7 @@ #define TRACKS_CRUSTIFY_TIME 50 // color-dir-dry -var/global/list/image/fluidtrack_cache = list() +GLOBAL_LIST_EMPTY(fluidtrack_cache) // Footprints, tire trails... /obj/effect/decal/cleanable/blood/tracks @@ -55,7 +55,7 @@ var/global/list/image/fluidtrack_cache = list() if(!(entered_dirs & H.dir)) entered_dirs |= H.dir update_icon() - + /obj/effect/decal/cleanable/blood/footprints/Uncrossed(atom/movable/O) ..() if(ishuman(O)) @@ -87,24 +87,24 @@ var/global/list/image/fluidtrack_cache = list() /obj/effect/decal/cleanable/blood/footprints/update_icon() overlays.Cut() - for(var/Ddir in cardinal) + for(var/Ddir in GLOB.cardinal) if(entered_dirs & Ddir) var/image/I - if(fluidtrack_cache["entered-[blood_state]-[Ddir]"]) - I = fluidtrack_cache["entered-[blood_state]-[Ddir]"] + if(GLOB.fluidtrack_cache["entered-[blood_state]-[Ddir]"]) + I = GLOB.fluidtrack_cache["entered-[blood_state]-[Ddir]"] else I = image(icon,"[blood_state]1",dir = Ddir) - fluidtrack_cache["entered-[blood_state]-[Ddir]"] = I + GLOB.fluidtrack_cache["entered-[blood_state]-[Ddir]"] = I if(I) I.color = basecolor overlays += I if(exited_dirs & Ddir) var/image/I - if(fluidtrack_cache["exited-[blood_state]-[Ddir]"]) - I = fluidtrack_cache["exited-[blood_state]-[Ddir]"] + if(GLOB.fluidtrack_cache["exited-[blood_state]-[Ddir]"]) + I = GLOB.fluidtrack_cache["exited-[blood_state]-[Ddir]"] else I = image(icon,"[blood_state]2",dir = Ddir) - fluidtrack_cache["exited-[blood_state]-[Ddir]"] = I + GLOB.fluidtrack_cache["exited-[blood_state]-[Ddir]"] = I if(I) I.color = basecolor overlays += I diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 7301eb2df03..9907e903970 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -118,10 +118,10 @@ would spawn and follow the beaker, even if it is carried or thrown. // will always spawn at the items location, even if it's moved. /* Example: -var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread() -- creates new system -steam.set_up(5, 0, mob.loc) -- sets up variables -OPTIONAL: steam.attach(mob) -steam.start() -- spawns the effect + var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread() -- creates new system + steam.set_up(5, 0, mob.loc) -- sets up variables + OPTIONAL: steam.attach(mob) + steam.start() -- spawns the effect */ ///////////////////////////////////////////// /obj/effect/effect/steam diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm index 0884e97687b..5ae6b0c6860 100644 --- a/code/game/objects/effects/effect_system/effect_system.dm +++ b/code/game/objects/effects/effect_system/effect_system.dm @@ -14,11 +14,11 @@ would spawn and follow the beaker, even if it is carried or thrown. /obj/effect/particle_effect/New() ..() if(SSticker) - cameranet.updateVisibility(src) + GLOB.cameranet.updateVisibility(src) /obj/effect/particle_effect/Destroy() if(SSticker) - cameranet.updateVisibility(src) + GLOB.cameranet.updateVisibility(src) return ..() /datum/effect_system @@ -61,9 +61,9 @@ would spawn and follow the beaker, even if it is carried or thrown. total_effects++ var/direction if(cardinals) - direction = pick(cardinal) + direction = pick(GLOB.cardinal) else - direction = pick(alldirs) + direction = pick(GLOB.alldirs) var/steps_amt = pick(1,2,3) for(var/j in 1 to steps_amt) sleep(5) diff --git a/code/game/objects/effects/effect_system/effects_explosion.dm b/code/game/objects/effects/effect_system/effects_explosion.dm index 1080f975135..40fda513099 100644 --- a/code/game/objects/effects/effect_system/effects_explosion.dm +++ b/code/game/objects/effects/effect_system/effects_explosion.dm @@ -15,7 +15,7 @@ for(var/i in 1 to number) spawn(0) var/obj/effect/particle_effect/expl_particles/expl = new /obj/effect/particle_effect/expl_particles(location) - var/direct = pick(alldirs) + var/direct = pick(GLOB.alldirs) var/steps_amt = pick(1;25,2;50,3,4;200) for(var/j in 1 to steps_amt) sleep(1) diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index 10efb534af2..8ee47d266e8 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -60,7 +60,7 @@ if(--amount < 0) return - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) var/turf/T = get_step(src,direction) if(!T) diff --git a/code/game/objects/effects/effect_system/effects_other.dm b/code/game/objects/effects/effect_system/effects_other.dm index cec70ad90e6..ddd85f6027d 100644 --- a/code/game/objects/effects/effect_system/effects_other.dm +++ b/code/game/objects/effects/effect_system/effects_other.dm @@ -172,13 +172,13 @@ // Clamp all values to MAX_EXPLOSION_RANGE if(round(amount/12) > 0) - devastation = min (MAX_EX_DEVASTATION_RANGE, devastation + round(amount/12)) + devastation = min (GLOB.max_ex_devastation_range, devastation + round(amount/12)) if(round(amount/6) > 0) - heavy = min (MAX_EX_HEAVY_RANGE, heavy + round(amount/6)) + heavy = min (GLOB.max_ex_heavy_range, heavy + round(amount/6)) if(round(amount/3) > 0) - light = min (MAX_EX_LIGHT_RANGE, light + round(amount/3)) + light = min (GLOB.max_ex_light_range, light + round(amount/3)) if(flashing && flashing_factor) flash += (round(amount/4) * flashing_factor) diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index 93ab0c8e51b..a8d442bbbb4 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -97,9 +97,9 @@ var/obj/effect/particle_effect/smoke/S = new effect_type(location) if(!direction) if(cardinals) - S.direction = pick(cardinal) + S.direction = pick(GLOB.cardinal) else - S.direction = pick(alldirs) + S.direction = pick(GLOB.alldirs) else S.direction = direction S.steps = pick(0,1,1,1,2,2,2,3) diff --git a/code/game/objects/effects/effect_system/effects_water.dm b/code/game/objects/effects/effect_system/effects_water.dm index 12fc9732bb5..4e3b5863dd5 100644 --- a/code/game/objects/effects/effect_system/effects_water.dm +++ b/code/game/objects/effects/effect_system/effects_water.dm @@ -33,10 +33,10 @@ // will always spawn at the items location, even if it's moved. /* Example: -var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread() -- creates new system -steam.set_up(5, 0, mob.loc) -- sets up variables -OPTIONAL: steam.attach(mob) -steam.start() -- spawns the effect + var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread() -- creates new system + steam.set_up(5, 0, mob.loc) -- sets up variables + OPTIONAL: steam.attach(mob) + steam.start() -- spawns the effect */ ///////////////////////////////////////////// /obj/effect/particle_effect/steam diff --git a/code/game/objects/effects/glowshroom.dm b/code/game/objects/effects/glowshroom.dm index dc12f91c618..b520648a599 100644 --- a/code/game/objects/effects/glowshroom.dm +++ b/code/game/objects/effects/glowshroom.dm @@ -102,7 +102,7 @@ var/placeCount = 1 for(var/obj/structure/glowshroom/shroom in newLoc) shroomCount++ - for(var/wallDir in cardinal) + for(var/wallDir in GLOB.cardinal) var/turf/isWall = get_step(newLoc,wallDir) if(isWall.density) placeCount++ @@ -123,7 +123,7 @@ /obj/structure/glowshroom/proc/CalcDir(turf/location = loc) var/direction = 16 - for(var/wallDir in cardinal) + for(var/wallDir in GLOB.cardinal) var/turf/newTurf = get_step(location,wallDir) if(newTurf.density) direction |= wallDir diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 51eab134ac1..24bd5ce6e58 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -13,80 +13,80 @@ switch(name) //some of these are probably obsolete if("start") - newplayer_start += loc + GLOB.newplayer_start += loc qdel(src) if("wizard") - wizardstart += loc + GLOB.wizardstart += loc qdel(src) if("JoinLate") - latejoin += loc + GLOB.latejoin += loc qdel(src) if("JoinLateGateway") - latejoin_gateway += loc + GLOB.latejoin_gateway += loc qdel(src) if("JoinLateCryo") - latejoin_cryo += loc + GLOB.latejoin_cryo += loc qdel(src) if("JoinLateCyborg") - latejoin_cyborg += loc + GLOB.latejoin_cyborg += loc qdel(src) if("prisonwarp") - prisonwarp += loc + GLOB.prisonwarp += loc qdel(src) if("prisonsecuritywarp") - prisonsecuritywarp += loc + GLOB.prisonsecuritywarp += loc qdel(src) if("tdome1") - tdome1 += loc + GLOB.tdome1 += loc if("tdome2") - tdome2 += loc + GLOB.tdome2 += loc if("tdomeadmin") - tdomeadmin += loc + GLOB.tdomeadmin += loc if("tdomeobserve") - tdomeobserve += loc + GLOB.tdomeobserve += loc if("aroomwarp") - aroomwarp += loc + GLOB.aroomwarp += loc if("blobstart") - blobstart += loc + GLOB.blobstart += loc qdel(src) if("xeno_spawn") - xeno_spawn += loc + GLOB.xeno_spawn += loc qdel(src) if("ninjastart") - ninjastart += loc + GLOB.ninjastart += loc qdel(src) if("carpspawn") - carplist += loc + GLOB.carplist += loc if("voxstart") - raider_spawn += loc + GLOB.raider_spawn += loc if("ERT Director") - ertdirector += loc + GLOB.ertdirector += loc qdel(src) if("Response Team") - emergencyresponseteamspawn += loc + GLOB.emergencyresponseteamspawn += loc qdel(src) if("Syndicate Officer") - syndicateofficer += loc + GLOB.syndicateofficer += loc qdel(src) GLOB.landmarks_list += src diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index 434c0af1136..a0006fd00d6 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -88,7 +88,7 @@ name = "horrific experiment" desc = "Some sort of pod filled with blood and vicerea. You swear you can see it moving..." icon = 'icons/obj/cloning.dmi' - icon_state = "pod_g" + icon_state = "pod_mess" //Makes a tile fully lit no matter what diff --git a/code/game/objects/effects/snowcloud.dm b/code/game/objects/effects/snowcloud.dm index 5723b66bc04..66535adc856 100644 --- a/code/game/objects/effects/snowcloud.dm +++ b/code/game/objects/effects/snowcloud.dm @@ -52,7 +52,7 @@ /obj/effect/snowcloud/proc/try_to_spread_cloud() if(prob(95 - parent_machine.cooling_speed * 5)) //10 / 15 / 20 / 25% chance to spawn a new cloud return - var/list/random_dirs = shuffle(cardinal) + var/list/random_dirs = shuffle(GLOB.cardinal) for(var/potential in random_dirs) var/turf/T = get_turf(get_step(src, potential)) if(isspaceturf(T) || T.density) diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm index 1678f67e8d6..998fb4a2868 100644 --- a/code/game/objects/effects/spawners/gibspawner.dm +++ b/code/game/objects/effects/spawners/gibspawner.dm @@ -11,7 +11,7 @@ gibamounts = list(1,1,1,1,1,1,1) /obj/effect/gibspawner/human/New() - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list()) + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list()) gibamounts[6] = pick(0,1,2) ..() @@ -20,7 +20,7 @@ gibamounts = list(1,1,1,1,1,1,1) /obj/effect/gibspawner/xeno/New() - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs, list()) + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list()) gibamounts[6] = pick(0,1,2) ..() @@ -30,6 +30,6 @@ gibamounts = list(1,1,1,1,1,1) /obj/effect/gibspawner/robot/New() - gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), alldirs, alldirs) + gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs) gibamounts[6] = pick(0,1,2) ..() diff --git a/code/game/objects/effects/spawners/random_spawners.dm b/code/game/objects/effects/spawners/random_spawners.dm index b32688dbb83..9eb8e9de1a2 100644 --- a/code/game/objects/effects/spawners/random_spawners.dm +++ b/code/game/objects/effects/spawners/random_spawners.dm @@ -289,7 +289,6 @@ /obj/item/clothing/glasses/thermal = 1, /obj/item/chameleon = 1, /obj/item/reagent_containers/hypospray/autoinjector/stimulants = 1, - /obj/item/storage/box/syndie_kit/atmosn2ogrenades = 1, /obj/item/grenade/plastic/x4 = 1) @@ -304,11 +303,6 @@ /turf/simulated/wall/mineral/plastitanium/nodiagonal = 2, /obj/structure/falsewall/plastitanium = 2) -/obj/effect/spawner/random_spawners/syndicate/layout/door/secret - name = "50pc falsewall 50pc wall" - result = list(/turf/simulated/wall/mineral/plastitanium/nodiagonal = 1, - /obj/structure/falsewall/plastitanium = 1) - /obj/effect/spawner/random_spawners/syndicate/layout/door/vault name = "80pc vaultdoor 20pc wall" result = list(/obj/machinery/door/airlock/hatch/syndicate/vault = 4, diff --git a/code/game/objects/effects/spawners/windowspawner.dm b/code/game/objects/effects/spawners/windowspawner.dm index e19aa54fd7d..cf29d86a450 100644 --- a/code/game/objects/effects/spawners/windowspawner.dm +++ b/code/game/objects/effects/spawners/windowspawner.dm @@ -16,7 +16,7 @@ qdel(G) //just in case mappers don't know what they are doing if(!useFull) - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) for(var/obj/effect/spawner/window/WS in get_step(src,cdir)) cdir = null break diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index e2f137cafa4..27d5eafb677 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -18,7 +18,7 @@ /obj/effect/temp_visual/dir_setting/bloodsplatter/New(loc, set_dir, blood_color) if(blood_color) color = blood_color - if(set_dir in diagonals) + if(set_dir in GLOB.diagonals) icon_state = "[splatter_type][pick(1, 2, 6)]" else icon_state = "[splatter_type][pick(3, 4, 5)]" diff --git a/code/game/objects/effects/temporary_visuals/temporary_visual.dm b/code/game/objects/effects/temporary_visuals/temporary_visual.dm index 23b1aaa0d2e..d09acce7255 100644 --- a/code/game/objects/effects/temporary_visuals/temporary_visual.dm +++ b/code/game/objects/effects/temporary_visuals/temporary_visual.dm @@ -11,7 +11,7 @@ /obj/effect/temp_visual/Initialize(mapload) . = ..() if(randomdir) - setDir(pick(cardinal)) + setDir(pick(GLOB.cardinal)) timerid = QDEL_IN(src, duration) diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 7e17b58a3a4..54ddb01b653 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -1,7 +1,6 @@ //TODO: Flash range does nothing currently /proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range = 0, silent = 0, smoke = 1, cause = null, breach = TRUE) - src = null //so we don't abort once src is deleted epicenter = get_turf(epicenter) // Archive the uncapped explosion for the doppler array @@ -11,11 +10,11 @@ if(!ignorecap) // Clamp all values to MAX_EXPLOSION_RANGE - devastation_range = min (MAX_EX_DEVASTATION_RANGE, devastation_range) - heavy_impact_range = min (MAX_EX_HEAVY_RANGE, heavy_impact_range) - light_impact_range = min (MAX_EX_LIGHT_RANGE, light_impact_range) - flash_range = min (MAX_EX_FLASH_RANGE, flash_range) - flame_range = min (MAX_EX_FLAME_RANGE, flame_range) + devastation_range = min (GLOB.max_ex_devastation_range, devastation_range) + heavy_impact_range = min (GLOB.max_ex_heavy_range, heavy_impact_range) + light_impact_range = min (GLOB.max_ex_light_range, light_impact_range) + flash_range = min (GLOB.max_ex_flash_range, flash_range) + flame_range = min (GLOB.max_ex_flame_range, flame_range) spawn(0) var/watch = start_watch() @@ -153,12 +152,12 @@ */ var/took = stop_watch(watch) //You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare - if(Debug2) + if(GLOB.debug2) log_world("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.") //Machines which report explosions. - for(var/i,i<=doppler_arrays.len,i++) - var/obj/machinery/doppler_array/Array = doppler_arrays[i] + for(var/i,i<=GLOB.doppler_arrays.len,i++) + var/obj/machinery/doppler_array/Array = GLOB.doppler_arrays[i] if(Array) Array.sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took,orig_dev_range,orig_heavy_range,orig_light_range) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 200034b4b46..ab6ebe6a0fe 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1,5 +1,4 @@ -var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.dmi', "icon_state" = "fire") - +GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effects/fire.dmi', "icon_state" = "fire")) /obj/item name = "item" icon = 'icons/obj/items.dmi' @@ -60,7 +59,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d var/put_on_delay = DEFAULT_ITEM_PUTON_DELAY var/breakouttime = 0 var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES - var/flags_size = 0 //flag, primarily used for clothing to determine if a fatty can wear something or not. var/block_chance = 0 var/hit_reaction_chance = 0 //If you want to have something unrelated to blocking/armour piercing etc. Maybe not needed, but trying to think ahead/allow more freedom @@ -100,15 +98,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc. var/sprite_sheets_obj = null //Used to override hardcoded clothing inventory object dmis in human clothing proc. - var/trip_verb = TV_TRIP - var/trip_chance = 0 - - var/trip_stun = 0 - var/trip_weaken = 0 - var/trip_any = FALSE - var/trip_walksafe = TRUE - var/trip_tiles = 0 - //Tooltip vars var/in_inventory = FALSE //is this item equipped into an inventory slot or hand of a mob? var/tip_timer = 0 @@ -361,7 +350,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d //Generic refill proc. Transfers something (e.g. fuel, charge) from an atom to our tool. returns TRUE if it was successful, FALSE otherwise //Not sure if there should be an argument that indicates what exactly is being refilled -/obj/item/proc/refill(mob/user, atom/A, amount) +/obj/item/proc/refill(mob/user, atom/A, amount) return FALSE /obj/item/proc/talk_into(mob/M, var/text, var/channel=null) @@ -608,16 +597,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d /obj/item/proc/is_equivalent(obj/item/I) return I == src -/obj/item/Crossed(atom/movable/AM, oldloc) - . = ..() - if(prob(trip_chance) && ishuman(AM)) - var/mob/living/carbon/human/H = AM - on_trip(H) - -/obj/item/proc/on_trip(mob/living/carbon/human/H) - if(H.slip(src, trip_stun, trip_weaken, trip_tiles, trip_walksafe, trip_any, trip_verb)) - return TRUE - /obj/item/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) return diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index 79cc221ee7f..5f5c62abd21 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -294,7 +294,7 @@ return ROOM_ERR_TOOLARGE var/turf/T = pending[1] //why byond havent list::pop()? pending -= T - for(var/dir in cardinal) + for(var/dir in GLOB.cardinal) var/skip = 0 for(var/obj/structure/window/W in T) if(dir == W.dir || (W.dir in list(NORTHEAST,SOUTHEAST,NORTHWEST,SOUTHWEST))) @@ -328,3 +328,5 @@ desc = "A digital copy of the station blueprints stored in your memory." fluffnotice = "Intellectual Property of Nanotrasen. For use in engineering cyborgs only. Wipe from memory upon departure from the station." +/obj/item/areaeditor/blueprints/ce + diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 60c005de0ed..093f28692ec 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -40,7 +40,7 @@ ui_interact(user) -/obj/item/aicard/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state) +/obj/item/aicard/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.inventory_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "aicard.tmpl", "[name]", 600, 400, state = state) @@ -48,7 +48,7 @@ ui.set_auto_update(1) -/obj/item/aicard/ui_data(mob/user, ui_key = "main", datum/topic_state/state = inventory_state) +/obj/item/aicard/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.inventory_state) var/data[0] var/mob/living/silicon/ai/AI = locate() in src diff --git a/code/game/objects/items/devices/autopsy.dm b/code/game/objects/items/devices/autopsy.dm index fc329011d14..c96e935432c 100644 --- a/code/game/objects/items/devices/autopsy.dm +++ b/code/game/objects/items/devices/autopsy.dm @@ -74,7 +74,7 @@ var/dead_notes = input("Insert any relevant notes") var/obj/item/paper/R = new(user.loc) R.name = "Official Coroner's Report - [dead_name]" - R.info = "Nanotrasen Science Station [using_map.station_short] - Coroner's Report

    Name of Deceased: [dead_name]

    Rank of Deceased: [dead_rank]

    Time of Death: [dead_tod]

    Cause of Death: [dead_cause]

    Trace Chemicals: [dead_chems]

    Additional Coroner's Notes: [dead_notes]

    Coroner's Signature: " + R.info = "Nanotrasen Science Station [GLOB.using_map.station_short] - Coroner's Report

    Name of Deceased: [dead_name]

    Rank of Deceased: [dead_rank]

    Time of Death: [dead_tod]

    Cause of Death: [dead_cause]

    Trace Chemicals: [dead_chems]

    Additional Coroner's Notes: [dead_notes]

    Coroner's Signature: " playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1) sleep(10) user.put_in_hands(R) diff --git a/code/game/objects/items/devices/camera_bug.dm b/code/game/objects/items/devices/camera_bug.dm index 3ca37a3f662..7724d499e7e 100644 --- a/code/game/objects/items/devices/camera_bug.dm +++ b/code/game/objects/items/devices/camera_bug.dm @@ -54,26 +54,26 @@ user.set_machine(src) interact(user) -/obj/item/camera_bug/check_eye(var/mob/user as mob) - if(user.stat || loc != user || !user.canmove || !user.has_vision() || !current) - user.reset_perspective(null) +/obj/item/camera_bug/check_eye(mob/user) + if(loc != user || user.incapacitated() || !user.has_vision() || !current) user.unset_machine() - return null - - var/turf/T = get_turf(user.loc) - if(T.z != current.z || !current.can_use()) + return FALSE + var/turf/T_user = get_turf(user.loc) + var/turf/T_current = get_turf(current) + if(!atoms_share_level(T_user, T_current) || !current.can_use()) to_chat(user, "[src] has lost the signal.") current = null - user.reset_perspective(null) user.unset_machine() - return null + return FALSE + return TRUE - return 1 +/obj/item/camera_bug/on_unset_machine(mob/user) + user.reset_perspective(null) /obj/item/camera_bug/proc/get_cameras() if(world.time > (last_net_update + 100)) bugged_cameras = list() - for(var/obj/machinery/camera/camera in cameranet.cameras) + for(var/obj/machinery/camera/camera in GLOB.cameranet.cameras) if(camera.stat || !camera.can_use()) continue if(length(list("SS13","MINE")&camera.network)) @@ -182,7 +182,6 @@ /obj/item/camera_bug/Topic(var/href,var/list/href_list) if(usr != loc) usr.unset_machine() - usr.reset_perspective(null) usr << browse(null, "window=camerabug") return usr.set_machine(src) @@ -233,7 +232,6 @@ interact() else usr.unset_machine() - usr.reset_perspective(null) usr << browse(null, "window=camerabug") return else diff --git a/code/game/objects/items/devices/enginepicker.dm b/code/game/objects/items/devices/enginepicker.dm index fe6bb7e8717..0fd3a591560 100644 --- a/code/game/objects/items/devices/enginepicker.dm +++ b/code/game/objects/items/devices/enginepicker.dm @@ -14,8 +14,12 @@ var/list/list_enginebeacons = list() var/isactive = FALSE +/obj/item/enginepicker/Destroy() + list_enginebeacons.Cut() + return ..() + /obj/item/enginepicker/attack_self(mob/living/carbon/user) - if(usr.stat || !usr.canmove || usr.restrained()) + if(user.incapacitated()) return if(!isactive) @@ -72,7 +76,7 @@ new G(T) //Spawns the switch-selected engine on the chosen beacon's turf var/ailist[] = list() - for(var/mob/living/silicon/ai/A in GLOB.living_mob_list) + for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list) ailist += A if(ailist.len) var/mob/living/silicon/ai/announcer = pick(ailist) diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index af673c7b285..58848f3f7e4 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -67,44 +67,48 @@ times_used = max(0, times_used) //sanity -/obj/item/flash/proc/try_use_flash(var/mob/user = null) +/obj/item/flash/proc/try_use_flash(mob/user = null) flash_recharge(user) if(broken) - return 0 + return FALSE - playsound(src.loc, use_sound, 100, 1) + playsound(loc, use_sound, 100, 1) flick("[initial(icon_state)]2", src) + set_light(2, 1, COLOR_WHITE) + addtimer(CALLBACK(src, /atom./proc/set_light, 0), 2) times_used++ if(user && !clown_check(user)) - return 0 + return FALSE - return 1 + return TRUE /obj/item/flash/proc/flash_carbon(var/mob/living/carbon/M, var/mob/user = null, var/power = 5, targeted = 1) - add_attack_logs(user, M, "Flashed with [src]") - if(user && targeted) - if(M.weakeyes) - M.Weaken(3) //quick weaken bypasses eye protection but has no eye flash - if(M.flash_eyes(1, 1)) - M.AdjustConfused(power) - terrible_conversion_proc(M, user) - M.Stun(1) - visible_message("[user] blinds [M] with the flash!") - to_chat(user, "You blind [M] with the flash!") - to_chat(M, "[user] blinds you with the flash!") + if(user) + add_attack_logs(user, M, "Flashed with [src]") + if(targeted) if(M.weakeyes) - M.Stun(2) - M.visible_message("[M] gasps and shields [M.p_their()] eyes!", "You gasp and shields your eyes!") - else - visible_message("[user] fails to blind [M] with the flash!") - to_chat(user, "You fail to blind [M] with the flash!") - to_chat(M, "[user] fails to blind you with the flash!") - else - if(M.flash_eyes()) - M.AdjustConfused(power) + M.Weaken(3) //quick weaken bypasses eye protection but has no eye flash + if(M.flash_eyes(1, 1)) + M.AdjustConfused(power) + terrible_conversion_proc(M, user) + M.Stun(1) + visible_message("[user] blinds [M] with the flash!") + to_chat(user, "You blind [M] with the flash!") + to_chat(M, "[user] blinds you with the flash!") + if(M.weakeyes) + M.Stun(2) + M.visible_message("[M] gasps and shields [M.p_their()] eyes!", "You gasp and shield your eyes!") + else + visible_message("[user] fails to blind [M] with the flash!") + to_chat(user, "You fail to blind [M] with the flash!") + to_chat(M, "[user] fails to blind you with the flash!") + return + + if(M.flash_eyes()) + M.AdjustConfused(power) /obj/item/flash/attack(mob/living/M, mob/user) if(!try_use_flash(user)) diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 4ce64a859ec..307964ca25c 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -74,7 +74,7 @@ if(istype(H)) //robots and aliens are unaffected var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes) - if(M.stat == DEAD || !eyes || M.disabilities & BLIND) //mob is dead or fully blind + if(M.stat == DEAD || !eyes || (BLINDNESS in M.mutations)) //mob is dead or fully blind to_chat(user, "[M]'s pupils are unresponsive to the light!") else if((XRAY in M.mutations) || eyes.see_in_dark >= 8) //The mob's either got the X-RAY vision or has a tapetum lucidum (extreme nightvision, i.e. Vulp/Tajara with COLOURBLIND & their monkey forms). to_chat(user, "[M]'s pupils glow eerily!") diff --git a/code/game/objects/items/devices/instruments.dm b/code/game/objects/items/devices/instruments.dm index a296e465a59..53ead129836 100644 --- a/code/game/objects/items/devices/instruments.dm +++ b/code/game/objects/items/devices/instruments.dm @@ -35,7 +35,7 @@ song.ui_interact(user, ui_key, ui, force_open) -/obj/item/instrument/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/item/instrument/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) return song.ui_data(user, ui_key, state) /obj/item/instrument/Topic(href, href_list) diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index 21b71e7668c..cfaea9f32f9 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -138,6 +138,7 @@ log_admin("[key_name(user)] EMPd a camera with a laser pointer") user.create_attack_log("[key_name(user)] EMPd a camera with a laser pointer") + add_attack_logs(user, C, "EMPd with [src]", ATKLOG_ALL) else outmsg = "You missed the lens of [C] with [src]." diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index 5f987bdce45..b3695229790 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -264,7 +264,7 @@ return last_request = world.time / 10 looking_for_personality = 1 - paiController.findPAI(src, usr) + GLOB.paiController.findPAI(src, usr) if(href_list["wipe"]) var/confirm = input("Are you CERTAIN you wish to delete the current personality? This action cannot be undone.", "Personality Wipe") in list("Yes", "No") if(confirm == "Yes") diff --git a/code/game/objects/items/devices/pipe_painter.dm b/code/game/objects/items/devices/pipe_painter.dm index 69beb04f67c..842a96c2af2 100644 --- a/code/game/objects/items/devices/pipe_painter.dm +++ b/code/game/objects/items/devices/pipe_painter.dm @@ -9,7 +9,7 @@ /obj/item/pipe_painter/New() ..() modes = new() - for(var/C in pipe_colors) + for(var/C in GLOB.pipe_colors) modes += "[C]" mode = pick(modes) @@ -23,7 +23,7 @@ to_chat(user, "You must remove the plating first.") return - P.change_color(pipe_colors[mode]) + P.change_color(GLOB.pipe_colors[mode]) /obj/item/pipe_painter/attack_self(mob/user as mob) mode = input("Which colour do you want to use?", "Pipe Painter", mode) in modes diff --git a/code/game/objects/items/devices/radio/beacon.dm b/code/game/objects/items/devices/radio/beacon.dm index 517f9f595c5..aa123930323 100644 --- a/code/game/objects/items/devices/radio/beacon.dm +++ b/code/game/objects/items/devices/radio/beacon.dm @@ -69,8 +69,8 @@ to_chat(user, "Locked In") new /obj/machinery/power/singularity_beacon/syndicate( user.loc ) playsound(src, 'sound/effects/pop.ogg', 100, 1, 1) + user.drop_item() qdel(src) - return /obj/item/radio/beacon/syndicate/bomb name = "suspicious beacon" @@ -82,16 +82,21 @@ to_chat(user, "Locked In") new /obj/machinery/syndicatebomb( user.loc ) playsound(src, 'sound/effects/pop.ogg', 100, 1, 1) + user.drop_item() qdel(src) - return /obj/item/radio/beacon/engine desc = "A label on it reads: Warning: This device is used for transportation of high-density objects used for high-yield power generation. Stay away!." anchored = 1 //Let's not move these around. Some folk might get the idea to use these for assassinations var/list/enginetype = list() -/obj/item/radio/beacon/engine/Initialize() +/obj/item/radio/beacon/engine/Initialize(mapload) LAZYADD(GLOB.engine_beacon_list, src) + return ..() + +/obj/item/radio/beacon/engine/Destroy() + GLOB.engine_beacon_list -= src + return ..() /obj/item/radio/beacon/engine/tesling name = "Engine Beacon for Tesla and Singularity" diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm index 4b5716d73eb..083720f0e22 100644 --- a/code/game/objects/items/devices/radio/electropack.dm +++ b/code/game/objects/items/devices/radio/electropack.dm @@ -103,7 +103,7 @@ ui.open() ui.set_auto_update(1) -/obj/item/radio/electropack/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/item/radio/electropack/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["power"] = on diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 72e584e91aa..691c12e1347 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -21,6 +21,7 @@ var/ks1type = null var/ks2type = null dog_fashion = null + requires_tcomms = TRUE /obj/item/radio/headset/New() ..() @@ -88,6 +89,8 @@ /obj/item/radio/headset/syndicate origin_tech = "syndicate=3" ks1type = /obj/item/encryptionkey/syndicate/nukeops + requires_tcomms = FALSE + instant = TRUE // Work instantly if there are no comms /obj/item/radio/headset/syndicate/alt //undisguised bowman with flash protection name = "syndicate headset" @@ -103,6 +106,13 @@ /obj/item/radio/headset/syndicate/alt/syndteam ks1type = /obj/item/encryptionkey/syndteam +/obj/item/radio/headset/syndicate/alt/lavaland + name = "syndicate lavaland headset" + +/obj/item/radio/headset/syndicate/alt/lavaland/New() + . = ..() + set_frequency(SYND_FREQ) + /obj/item/radio/headset/binary origin_tech = "syndicate=3" ks1type = /obj/item/encryptionkey/binary diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index fbfe984d35f..13c97f26730 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -63,7 +63,7 @@ /obj/item/radio/intercom/department/medbay/New() ..() - internal_channels = default_medbay_channels.Copy() + internal_channels = GLOB.default_medbay_channels.Copy() /obj/item/radio/intercom/department/security/New() ..() diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 23d897d491f..4c2aaa82c1e 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -1,4 +1,4 @@ -var/global/list/default_internal_channels = list( +GLOBAL_LIST_INIT(default_internal_channels, list( num2text(PUB_FREQ) = list(), num2text(AI_FREQ) = list(ACCESS_CAPTAIN), num2text(ERT_FREQ) = list(ACCESS_CENT_SPECOPS), @@ -11,13 +11,13 @@ var/global/list/default_internal_channels = list( num2text(SCI_FREQ) = list(ACCESS_RESEARCH), num2text(SUP_FREQ) = list(ACCESS_CARGO), num2text(SRV_FREQ) = list(ACCESS_HOP, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_JANITOR, ACCESS_CLOWN, ACCESS_MIME) -) +)) -var/global/list/default_medbay_channels = list( +GLOBAL_LIST_INIT(default_medbay_channels, list( num2text(PUB_FREQ) = list(), num2text(MED_FREQ) = list(ACCESS_MEDICAL), num2text(MED_I_FREQ) = list(ACCESS_MEDICAL) -) +)) /obj/item/radio icon = 'icons/obj/radio.dmi' @@ -58,6 +58,9 @@ var/global/list/default_medbay_channels = list( var/datum/radio_frequency/radio_connection var/list/datum/radio_frequency/secure_radio_connections = new + var/requires_tcomms = FALSE // Does this device require tcomms to work.If TRUE it wont function at all without tcomms. If FALSE, it will work without tcomms, just slowly + var/instant = FALSE // Should this device instantly communicate if there isnt tcomms + /obj/item/radio/proc/set_frequency(new_frequency) SSradio.remove_object(src, frequency) @@ -69,7 +72,7 @@ var/global/list/default_medbay_channels = list( ..() wires = new(src) - internal_channels = default_internal_channels.Copy() + internal_channels = GLOB.default_internal_channels.Copy() GLOB.global_radios |= src /obj/item/radio/Destroy() @@ -116,7 +119,7 @@ var/global/list/default_medbay_channels = list( ui.open() ui.set_auto_update(1) -/obj/item/radio/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/item/radio/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["mic_status"] = broadcasting @@ -233,7 +236,7 @@ var/global/list/default_medbay_channels = list( add_fingerprint(usr) -/obj/item/radio/proc/autosay(var/message, var/from, var/channel, var/zlevel = config.contact_levels, var/role = "Unknown") //BS12 EDIT +/obj/item/radio/proc/autosay(message, from, channel, role = "Unknown") //BS12 EDIT var/datum/radio_frequency/connection = null if(channel && channels && channels.len > 0) if(channel == "department") @@ -258,10 +261,29 @@ var/global/list/default_medbay_channels = list( if(jammed) message = Gibberish(message, 100) var/list/message_pieces = message_to_multilingual(message) - Broadcast_Message(connection, A, - 0, "*garbled automated announcement*", src, - message_pieces, from, "Automated Announcement", from, "synthesized voice", - 4, 0, zlevel, connection.frequency, follow_target = follow_target) + + // Make us a message datum! + var/datum/tcomms_message/tcm = new + tcm.connection = connection + tcm.sender = A + tcm.radio = src + tcm.sender_name = from + tcm.message_pieces = message_pieces + tcm.sender_job = "Automated Announcement" + tcm.vname = "synthesized voice" + tcm.data = SIGNALTYPE_AINOTRACK + // Datum radios dont have a location (obviously + if(loc && loc.z) + tcm.source_level = loc.z // For anyone that reads this: This used to pull from a LIST from the CONFIG DATUM. WHYYYYYYYYY!!!!!!!! -aa + else + tcm.source_level = 1 // Assume Z1 if we dont have an actual Z level available to us. + tcm.freq = connection.frequency + tcm.follow_target = follow_target + + // Now put that through the stuff + for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines) + C.handle_message(tcm) + qdel(tcm) // Delete the message datum qdel(A) // Just a dummy mob used for making announcements, so we don't create AIs to do this @@ -318,48 +340,32 @@ var/global/list/default_medbay_channels = list( if(!M.IsVocal()) return 0 - /* Quick introduction: - This new radio system uses a very robust FTL signaling technology unoriginally - dubbed "subspace" which is somewhat similar to 'blue-space' but can't - actually transmit large mass. Headsets are the only radio devices capable - of sending subspace transmissions to the Communications Satellite. - - A headset sends a signal to a subspace listener/receiver elsewhere in space, - the signal gets processed and logged, and an audible transmission gets sent - to each individual headset. - */ - - //#### Grab the connection datum ####// - var/message_mode = handle_message_mode(M, message_pieces, channel) - switch(message_mode) //special cases - if(RADIO_CONNECTION_FAIL) - return 0 - if(RADIO_CONNECTION_NON_SUBSPACE) - return 1 - - if(!istype(message_mode, /datum/radio_frequency)) //if not a special case, it should be returning a radio connection - return 0 - - var/datum/radio_frequency/connection = message_mode - var/turf/position = get_turf(src) - var/jammed = FALSE - for(var/obj/item/jammer/jammer in GLOB.active_jammers) + var/turf/position = get_turf(src) + for(var/J in GLOB.active_jammers) + var/obj/item/jammer/jammer = J if(get_dist(position, get_turf(jammer)) < jammer.range) jammed = TRUE break - //#### Tagging the signal with all appropriate identity values ####// + var/message_mode = handle_message_mode(M, message_pieces, channel) + switch(message_mode) //special cases + // This is if the connection fails + if(RADIO_CONNECTION_FAIL) + return 0 + // This is if were using either a binary key, or a hivemind through a headset somehow. Dont ask. + if(RADIO_CONNECTION_NON_SUBSPACE) + return 1 + + if(!istype(message_mode, /datum/radio_frequency)) //if not a special case, it should be returning a radio connection + return + + var/datum/radio_frequency/connection = message_mode + // ||-- The mob's name identity --|| var/displayname = M.name // grab the display name (name you get when you hover over someone's icon) - var/real_name = M.real_name // mob's real name - var/mobkey = "none" // player key associated with mob var/voicemask = 0 // the speaker is wearing a voice mask - if(M.client) - mobkey = M.key // assign the mob's key - - var/jobname // the mob's "job" if(jammed) @@ -397,7 +403,7 @@ var/global/list/default_medbay_channels = list( if(ishuman(M)) var/mob/living/carbon/human/H = M displayname = H.voice - if(H.voice != real_name) + if(H.voice != M.real_name) voicemask = TRUE if(syndiekey && syndiekey.change_voice && connection.frequency == SYND_FREQ) @@ -405,124 +411,45 @@ var/global/list/default_medbay_channels = list( jobname = "Unknown" voicemask = TRUE + // Make us a message datum! + var/datum/tcomms_message/tcm = new + tcm.sender_name = displayname + tcm.sender_job = jobname + tcm.message_pieces = message_pieces + tcm.source_level = position.z + tcm.freq = connection.frequency + tcm.vmask = voicemask + tcm.needs_tcomms = requires_tcomms + tcm.connection = connection + tcm.vname = M.voice_name + tcm.sender = M + // Now put that through the stuff + var/handled = FALSE + if(connection) + for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines) + if(C.handle_message(tcm)) + handled = TRUE + qdel(tcm) // Delete the message datum + return TRUE - /* ###### Radio headsets can only broadcast through subspace ###### */ + // If we dont need tcomms and we have no connection + if(!requires_tcomms && !handled) + // If they dont need tcomms for their signal, set the type to intercoms + tcm.data = SIGNALTYPE_INTERCOM_SBR + tcm.zlevels = list(position.z) + if(!instant) + // Simulate two seconds of lag + addtimer(CALLBACK(GLOBAL_PROC, .proc/broadcast_message, tcm), 20) + QDEL_IN(tcm, 20) + else + // Nukeops + Deathsquad headsets are instant and should work the same, whether there is comms or not + broadcast_message(tcm) + qdel(tcm) // Delete the message datum + return TRUE - if(subspace_transmission) - // First, we want to generate a new radio signal - var/datum/signal/signal = new - signal.transmission_method = 2 // 2 would be a subspace transmission. - // transmission_method could probably be enumerated through #define. Would be neater. - - // --- Finally, tag the actual signal with the appropriate values --- - signal.data = list( - // Identity-associated tags: - "mob" = M, // store a reference to the mob - "mobtype" = M.type, // the mob's type - "race" = signal.get_race(M), - "realname" = real_name, // the mob's real name - "name" = displayname, // the mob's display name - "job" = jobname, // the mob's job - "key" = mobkey, // the mob's key - "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood - "vname" = M.voice_name, // the name to display if the voice wasn't understood - "vmask" = voicemask, // 1 if the mob is using a voice gas mask - - // We store things that would otherwise be kept in the actual mob - // so that they can be logged even AFTER the mob is deleted or something - - // Other tags: - "compression" = rand(45,50), // compressed radio signal - "message" = message_pieces, // the actual sent message - "connection" = connection, // the radio connection to use - "radio" = src, // stores the radio used for transmission - "slow" = 0, // how much to sleep() before broadcasting - simulates net lag - "traffic" = 0, // dictates the total traffic sum that the signal went through - "type" = 0, // determines what type of radio input it is: normal broadcast - "server" = null, // the last server to log this signal - "reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery - "level" = position.z, // The source's z level - "verb" = verb - ) - signal.frequency = connection.frequency // Quick frequency set - - //#### Sending the signal to all subspace receivers ####// - - for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - spawn(0) - R.receive_signal(signal) - - // Allinone can act as receivers. - for(var/obj/machinery/telecomms/allinone/R in telecomms_list) - spawn(0) - R.receive_signal(signal) - - // Receiving code can be located in Telecommunications.dm - return signal.data["done"] && position.z in signal.data["level"] - - - /* ###### Intercoms and station-bounced radios ###### */ - - var/filter_type = 2 - - /* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */ - if(istype(src, /obj/item/radio/intercom)) - filter_type = 1 - - - var/datum/signal/signal = new - signal.transmission_method = 2 - - - /* --- Try to send a normal subspace broadcast first */ - - signal.data = list( - - "mob" = M, // store a reference to the mob - "mobtype" = M.type, // the mob's type - "race" = signal.get_race(M), // text to show next to mob in comms log console - "realname" = real_name, // the mob's real name - "name" = displayname, // the mob's display name - "job" = jobname, // the mob's job - "key" = mobkey, // the mob's key - "vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood - "vname" = M.voice_name, // the name to display if the voice wasn't understood - "vmask" = voicemask, // 1 if the mob is using a voice gas mas - - "compression" = 0, // uncompressed radio signal - "message" = message_pieces, // the actual sent message - "connection" = connection, // the radio connection to use - "radio" = src, // stores the radio used for transmission - "slow" = 0, - "traffic" = 0, - "type" = 0, - "server" = null, - "reject" = 0, - "level" = position.z, - "verb" = verb - ) - signal.frequency = connection.frequency // Quick frequency set - - for(var/obj/machinery/telecomms/receiver/R in telecomms_list) - spawn(0) - R.receive_signal(signal) - - - sleep(rand(10,25)) // wait a little... - - if(signal.data["done"] && position.z in signal.data["level"]) - // we're done here. - return 1 - - // Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level. - // Send a mundane broadcast with limited targets: - - //THIS IS TEMPORARY. YEAH RIGHT - if(!connection) return 0 //~Carn - - return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote), - src, message_pieces, displayname, jobname, real_name, M.voice_name, - filter_type, signal.data["compression"], list(position.z), connection.frequency,verb) + // If we didnt get here, oh fuck + qdel(tcm) // Delete the message datum + return FALSE /obj/item/radio/hear_talk(mob/M as mob, list/message_pieces, var/verb = "says") @@ -812,7 +739,7 @@ var/global/list/default_medbay_channels = list( ui.open() ui.set_auto_update(1) -/obj/item/radio/borg/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/item/radio/borg/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["mic_status"] = broadcasting @@ -863,4 +790,4 @@ var/global/list/default_medbay_channels = list( /obj/item/radio/phone/medbay/New() ..() - internal_channels = default_medbay_channels.Copy() + internal_channels = GLOB.default_medbay_channels.Copy() diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 34183a81102..0d8873a6377 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -212,7 +212,7 @@ REAGENT SCANNER if(H.getBrainLoss() >= 100) to_chat(user, "Subject is brain dead.") else if(H.getBrainLoss() >= 60) - to_chat(user, "Severe brain damage detected. Subject likely to have mental retardation.") + to_chat(user, "Severe brain damage detected. Subject likely to have dementia.") else if(H.getBrainLoss() >= 10) to_chat(user, "Significant brain damage detected. Subject may have had a concussion.") else @@ -859,11 +859,11 @@ REAGENT SCANNER dat += "[i.name]N/A[i.damage][infection]:[mech]" dat += "" dat += "" - if(target.disabilities & BLIND) + if(BLINDNESS in target.mutations) dat += "Cataracts detected.
    " - if(target.disabilities & COLOURBLIND) + if(COLOURBLIND in target.mutations) dat += "Photoreceptor abnormalities detected.
    " - if(target.disabilities & NEARSIGHTED) + if(NEARSIGHTED in target.mutations) dat += "Retinal misalignment detected.
    " return dat diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 7a8766ebb3c..3eeb992c87e 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -194,13 +194,11 @@ if(mytape.storedinfo.len < i + 1) playsleepseconds = 1 sleep(10) - T = get_turf(src) atom_say("End of recording.") else playsleepseconds = mytape.timestamp[i + 1] - mytape.timestamp[i] if(playsleepseconds > 14) sleep(10) - T = get_turf(src) atom_say("Skipping [playsleepseconds] seconds of silence.") playsleepseconds = 1 i++ diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index 40eea3a9856..acba0087caf 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -100,7 +100,7 @@ // auto update every Master Controller tick //ui.set_auto_update(1) -/obj/item/transfer_valve/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/item/transfer_valve/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["attachmentOne"] = tank_one ? tank_one.name : null diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index ab4387a988e..c5c8f67e34d 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -6,7 +6,7 @@ A list of items and costs is stored under the datum of every game mode, alongsid */ -var/list/world_uplinks = list() +GLOBAL_LIST_EMPTY(world_uplinks) /obj/item/uplink var/welcome // Welcoming menu message @@ -35,10 +35,10 @@ var/list/world_uplinks = list() uses = SSticker.mode.uplink_uses uplink_items = get_uplink_items() - world_uplinks += src + GLOB.world_uplinks += src /obj/item/uplink/Destroy() - world_uplinks -= src + GLOB.world_uplinks -= src return ..() /obj/item/uplink/proc/generate_items(mob/user as mob) @@ -168,7 +168,6 @@ var/list/world_uplinks = list() to_chat(user, "[I] refunded.") qdel(I) return - ..() // HIDDEN UPLINK - Can be stored in anything but the host item has to have a trigger for it. /* How to create an uplink in 3 easy steps! @@ -216,7 +215,7 @@ var/list/world_uplinks = list() /* NANO UI FOR UPLINK WOOP WOOP */ -/obj/item/uplink/hidden/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state) +/obj/item/uplink/hidden/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.inventory_state) var/title = "Remote Uplink" // update the ui if it exists, returns null if no ui is passed/found ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) @@ -227,7 +226,7 @@ var/list/world_uplinks = list() // open the new ui window ui.open() -/obj/item/uplink/hidden/ui_data(mob/user, ui_key = "main", datum/topic_state/state = inventory_state) +/obj/item/uplink/hidden/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.inventory_state) var/data[0] data["welcome"] = welcome @@ -277,14 +276,14 @@ var/list/world_uplinks = list() /obj/item/uplink/hidden/proc/update_nano_data(var/id) if(nanoui_menu == 1) var/permanentData[0] - for(var/datum/data/record/L in sortRecord(data_core.general)) + for(var/datum/data/record/L in sortRecord(GLOB.data_core.general)) permanentData[++permanentData.len] = list(Name = sanitize(L.fields["name"]),"id" = L.fields["id"]) nanoui_data["exploit_records"] = permanentData if(nanoui_menu == 11) nanoui_data["exploit_exists"] = 0 - for(var/datum/data/record/L in data_core.general) + for(var/datum/data/record/L in GLOB.data_core.general) if(L.fields["id"] == id) nanoui_data["exploit"] = list() // Setting this to equal L.fields passes it's variables that are lists as reference instead of value. nanoui_data["exploit"]["name"] = html_encode(L.fields["name"]) diff --git a/code/game/objects/items/flag.dm b/code/game/objects/items/flag.dm index 0edcafd64b5..14bb468e049 100644 --- a/code/game/objects/items/flag.dm +++ b/code/game/objects/items/flag.dm @@ -222,7 +222,7 @@ var/input_flag = input(user, "Choose a flag to disguise as.", "Choose a flag.") in show_flag - if(user && src in user.contents) + if(user && (src in user.contents)) var/obj/item/flag/chosen_flag = flag[input_flag] diff --git a/code/game/objects/items/mountable_frames/mountables.dm b/code/game/objects/items/mountable_frames/mountables.dm index 7120f8c880d..cfb4d18473c 100644 --- a/code/game/objects/items/mountable_frames/mountables.dm +++ b/code/game/objects/items/mountable_frames/mountables.dm @@ -20,7 +20,7 @@ return if(proximity_flag != 1) //if we aren't next to the wall return - if(!( get_dir(on_wall,user) in cardinal)) + if(!( get_dir(on_wall,user) in GLOB.cardinal)) to_chat(user, "You need to be standing next to a wall to place \the [src].") return diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 6ce10294940..46bc15a2ffe 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -14,7 +14,7 @@ ..(newloc) if(model_info && model) model_info = model - var/datum/robolimb/R = all_robolimbs[model] + var/datum/robolimb/R = GLOB.all_robolimbs[model] if(R) name = "[R.company] [initial(name)]" desc = "[R.desc]" @@ -24,7 +24,7 @@ name = "robot [initial(name)]" /obj/item/robot_parts/attack_self(mob/user) - var/choice = input(user, "Select the company appearance for this limb.", "Limb Company Selection") as null|anything in selectable_robolimbs + var/choice = input(user, "Select the company appearance for this limb.", "Limb Company Selection") as null|anything in GLOB.selectable_robolimbs if(!choice) return if(loc != user) diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index a13bce6fb61..43178a85ef8 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -74,7 +74,7 @@ R.stat = CONSCIOUS GLOB.dead_mob_list -= R //please never forget this ever kthx - GLOB.living_mob_list += R + GLOB.alive_mob_list += R R.notify_ai(1) return 1 diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 8b85d8821d9..9b24b1efce6 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -4,24 +4,23 @@ desc = "A shooting target." icon = 'icons/obj/objects.dmi' icon_state = "target_h" - density = 0 + density = FALSE var/hp = 1800 - var/icon/virtualIcon - var/list/bulletholes = list() /obj/item/target/Destroy() + cut_overlays() // if a target is deleted and associated with a stake, force stake to forget - for(var/obj/structure/target_stake/T in view(3,src)) + for(var/obj/structure/target_stake/T in view(3, src)) if(T.pinned_target == src) T.pinned_target = null - T.density = 1 + T.density = TRUE break return ..() // delete target /obj/item/target/Move() ..() // After target moves, check for nearby stakes. If associated, move to target - for(var/obj/structure/target_stake/M in view(3,src)) + for(var/obj/structure/target_stake/M in view(3, src)) if(M.density == 0 && M.pinned_target == src) M.loc = loc @@ -33,12 +32,12 @@ /obj/item/target/welder_act(mob/user, obj/item/I) . = TRUE - if(!use_tool(src, user, 0,, volume = I.tool_volume)) + if(!use_tool(src, user, 0, volume = I.tool_volume)) return overlays.Cut() - to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.") + to_chat(user, "You slice off [src]'s uneven chunks of aluminium and scorch marks.") -/obj/item/target/attack_hand(mob/user as mob) +/obj/item/target/attack_hand(mob/user) // taking pinned targets off! var/obj/structure/target_stake/stake for(var/obj/structure/target_stake/T in view(3,src)) @@ -48,8 +47,8 @@ if(stake) if(stake.pinned_target) - stake.density = 1 - density = 0 + stake.density = TRUE + density = FALSE layer = OBJ_LAYER loc = user.loc @@ -77,101 +76,37 @@ desc = "A shooting target that looks like a xenomorphic alien." hp = 2350 // alium onest too kinda -/obj/item/target/bullet_act(var/obj/item/projectile/Proj) - var/p_x = Proj.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!" - var/p_y = Proj.p_y + pick(0,0,0,0,0,-1,1) - var/decaltype = 1 // 1 - scorch, 2 - bullet +#define DECALTYPE_SCORCH 1 +#define DECALTYPE_BULLET 2 - if(istype(/obj/item/projectile/bullet, Proj)) - decaltype = 2 +/obj/item/target/bullet_act(obj/item/projectile/P) + var/p_x = P.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset P.p_x!" + var/p_y = P.p_y + pick(0,0,0,0,0,-1,1) + var/decaltype = DECALTYPE_SCORCH + if(istype(P, /obj/item/projectile/bullet)) + decaltype = DECALTYPE_BULLET - - virtualIcon = new(icon, icon_state) - - if( virtualIcon.GetPixel(p_x, p_y) ) // if the located pixel isn't blank (null) - - hp -= Proj.damage + var/icon/C = icon(icon, icon_state) + if(LAZYLEN(overlays) <= 35 && C.GetPixel(p_x, p_y)) // if the located pixel isn't blank (null) + hp -= P.damage if(hp <= 0) - visible_message("[src] breaks into tiny pieces and collapses!") + visible_message("[src] breaks into tiny pieces and collapses!") qdel(src) - - // Create a temporary object to represent the damage - var/obj/bmark = new - bmark.pixel_x = p_x - bmark.pixel_y = p_y - bmark.icon = 'icons/effects/effects.dmi' - bmark.layer = 3.5 - bmark.icon_state = "scorch" - - if(decaltype == 1) - // Energy weapons are hot. they scorch! - - // offset correction - bmark.pixel_x-- - bmark.pixel_y-- - - if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/beam/practice)) - bmark.icon_state = "scorch" - bmark.dir = pick(NORTH,SOUTH,EAST,WEST) // random scorch design - - + return + var/image/bullet_hole = image('icons/effects/effects.dmi', "scorch", OBJ_LAYER + 0.5) + bullet_hole.pixel_x = p_x - 1 //offset correction + bullet_hole.pixel_y = p_y - 1 + if(decaltype == DECALTYPE_SCORCH) + if(P.damage >= 20 || istype(P, /obj/item/projectile/beam/practice)) + bullet_hole.setDir(pick(NORTH,SOUTH,EAST,WEST))// random scorch design. light_scorch does not have different directions else - bmark.icon_state = "light_scorch" + bullet_hole.icon_state = "light_scorch" else - - // Bullets are hard. They make dents! - bmark.icon_state = "dent" - - if(Proj.damage >= 10 && bulletholes.len <= 35) // maximum of 35 bullet holes - if(decaltype == 2) // bullet - if(prob(Proj.damage+30)) // bullets make holes more commonly! - new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole - else // Lasers! - if(prob(Proj.damage-10)) // lasers make holes less commonly - new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole - - // draw bullet holes - for(var/datum/bullethole/B in bulletholes) - - virtualIcon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right - virtualIcon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom - - overlays += bmark // add the decal - - icon = virtualIcon // apply bulletholes over decals - + bullet_hole.icon_state = "dent" + add_overlay(bullet_hole) return return -1 // the bullet/projectile goes through the target! Ie, you missed - -// Small memory holder entity for transparent bullet holes -/datum/bullethole - // First box - var/b1x1 = 0 - var/b1x2 = 0 - var/b1y = 0 - - // Second box - var/b2x = 0 - var/b2y1 = 0 - var/b2y2 = 0 - -/datum/bullethole/New(obj/item/target/Target, pixel_x = 0, pixel_y = 0) - if(!Target) return - - // Randomize the first box - b1x1 = pixel_x - pick(1,1,1,1,2,2,3,3,4) - b1x2 = pixel_x + pick(1,1,1,1,2,2,3,3,4) - b1y = pixel_y - if(prob(35)) - b1y += rand(-4,4) - - // Randomize the second box - b2x = pixel_x - if(prob(35)) - b2x += rand(-4,4) - b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4) - b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4) - - Target.bulletholes.Add(src) +#undef DECALTYPE_SCORCH +#undef DECALTYPE_BULLET diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm index 59dad865acb..708070e1478 100644 --- a/code/game/objects/items/stacks/nanopaste.dm +++ b/code/game/objects/items/stacks/nanopaste.dm @@ -4,6 +4,7 @@ desc = "A tube of paste containing swarms of repair nanites. Very effective in repairing robotic machinery." icon = 'icons/obj/nanopaste.dmi' icon_state = "tube" + w_class = WEIGHT_CLASS_TINY origin_tech = "materials=2;engineering=3" amount = 6 max_amount = 6 diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 3b214f87940..3911ab51cc7 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -1,7 +1,7 @@ -var/global/list/datum/stack_recipe/rod_recipes = list ( \ +GLOBAL_LIST_INIT(rod_recipes, list ( \ new/datum/stack_recipe("grille", /obj/structure/grille, 2, time = 10, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("table frame", /obj/structure/table_frame, 2, time = 10, one_per_turf = 1, on_floor = 1), \ - ) + )) /obj/item/stack/rods name = "metal rod" @@ -36,7 +36,7 @@ var/global/list/datum/stack_recipe/rod_recipes = list ( \ /obj/item/stack/rods/New(loc, amount=null) ..() - recipes = rod_recipes + recipes = GLOB.rod_recipes update_icon() /obj/item/stack/rods/update_icon() diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index d79c31467bf..5fc457dae62 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -9,13 +9,13 @@ singular_name = "human skin piece" icon_state = "sheet-hide" -var/global/list/datum/stack_recipe/human_recipes = list( \ - new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/bloated_human, 5, on_floor = 1), \ - new/datum/stack_recipe("bloated human costume head", /obj/item/clothing/head/human_head, 5, on_floor = 1), \ - ) +GLOBAL_LIST_INIT(human_recipes, list( \ + new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/bloated_human, 5, on_floor = TRUE), \ + new/datum/stack_recipe("bloated human costume head", /obj/item/clothing/head/human_head, 5, on_floor = TRUE), \ + )) /obj/item/stack/sheet/animalhide/human/New(var/loc, var/amount=null) - recipes = human_recipes + recipes = GLOB.human_recipes return ..() /obj/item/stack/sheet/animalhide/generic @@ -48,6 +48,14 @@ var/global/list/datum/stack_recipe/human_recipes = list( \ singular_name = "lizard skin piece" icon_state = "sheet-lizard" +GLOBAL_LIST_INIT(lizard_recipes, list( \ + new/datum/stack_recipe("lizard skin handbag", /obj/item/storage/backpack/satchel/lizard, 5, on_floor = TRUE), \ + )) + +/obj/item/stack/sheet/animalhide/lizard/Initialize(mapload, new_amount, merge = TRUE) + recipes = GLOB.lizard_recipes + return ..() + /obj/item/stack/sheet/animalhide/xeno name = "alien hide" desc = "The skin of a terrible creature." @@ -132,12 +140,12 @@ GLOBAL_LIST_INIT(leather_recipes, list ( icon_state = "sinew" origin_tech = "biotech=4" -var/global/list/datum/stack_recipe/sinew_recipes = list ( \ +GLOBAL_LIST_INIT(sinew_recipes, list ( \ new/datum/stack_recipe("sinew restraints", /obj/item/restraints/handcuffs/sinew, 1, on_floor = 1), \ - ) + )) /obj/item/stack/sheet/sinew/New(var/loc, var/amount=null) - recipes = sinew_recipes + recipes = GLOB.sinew_recipes return ..() /obj/item/stack/sheet/animalhide/goliath_hide diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index 0791bb760dc..54d42176f52 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -15,16 +15,16 @@ Mineral Sheets - Adamantine */ -var/global/list/datum/stack_recipe/sandstone_recipes = list ( \ +GLOBAL_LIST_INIT(sandstone_recipes, list ( \ new/datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 10, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("sandstone door", /obj/structure/mineral_door/sandstone, 10, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("Assistant Statue", /obj/structure/statue/sandstone/assistant, 5, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("Breakdown into sand", /obj/item/stack/ore/glass, 1, one_per_turf = 0, on_floor = 1), \ - ) + )) -var/global/list/datum/stack_recipe/silver_recipes = list ( \ +GLOBAL_LIST_INIT(silver_recipes, list ( \ new/datum/stack_recipe("silver door", /obj/structure/mineral_door/silver, 10, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("silver tile", /obj/item/stack/tile/mineral/silver, 1, 4, 20), \ @@ -34,9 +34,9 @@ var/global/list/datum/stack_recipe/silver_recipes = list ( \ new/datum/stack_recipe("Sec Borg Statue", /obj/structure/statue/silver/secborg, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("Med Doctor Statue", /obj/structure/statue/silver/md, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("Med Borg Statue", /obj/structure/statue/silver/medborg, 5, one_per_turf = 1, on_floor = 1), \ - ) + )) -var/global/list/datum/stack_recipe/diamond_recipes = list ( \ +GLOBAL_LIST_INIT(diamond_recipes, list ( \ new/datum/stack_recipe("diamond door", /obj/structure/mineral_door/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("diamond tile", /obj/item/stack/tile/mineral/diamond, 1, 4, 20), \ @@ -44,18 +44,18 @@ var/global/list/datum/stack_recipe/diamond_recipes = list ( \ new/datum/stack_recipe("Captain Statue", /obj/structure/statue/diamond/captain, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("AI Hologram Statue", /obj/structure/statue/diamond/ai1, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("AI Core Statue", /obj/structure/statue/diamond/ai2, 5, one_per_turf = 1, on_floor = 1), \ - ) + )) -var/global/list/datum/stack_recipe/uranium_recipes = list ( \ +GLOBAL_LIST_INIT(uranium_recipes, list ( \ new/datum/stack_recipe("uranium door", /obj/structure/mineral_door/uranium, 10, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("uranium tile", /obj/item/stack/tile/mineral/uranium, 1, 4, 20), \ null, \ new/datum/stack_recipe("Nuke Statue", /obj/structure/statue/uranium/nuke, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("Engineer Statue", /obj/structure/statue/uranium/eng, 5, one_per_turf = 1, on_floor = 1), \ - ) + )) -var/global/list/datum/stack_recipe/gold_recipes = list ( \ +GLOBAL_LIST_INIT(gold_recipes, list ( \ new/datum/stack_recipe("golden door", /obj/structure/mineral_door/gold, 10, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("gold tile", /obj/item/stack/tile/mineral/gold, 1, 4, 20), \ @@ -67,51 +67,51 @@ var/global/list/datum/stack_recipe/gold_recipes = list ( \ new/datum/stack_recipe("CMO Statue", /obj/structure/statue/gold/cmo, 5, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("Simple Crown", /obj/item/clothing/head/crown, 5), \ - ) + )) -var/global/list/datum/stack_recipe/plasma_recipes = list ( \ +GLOBAL_LIST_INIT(plasma_recipes, list ( \ new/datum/stack_recipe/dangerous("plasma door", /obj/structure/mineral_door/transparent/plasma, 10, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe/dangerous("plasma tile", /obj/item/stack/tile/mineral/plasma, 1, 4, 20), \ null, \ new/datum/stack_recipe/dangerous("Scientist Statue", /obj/structure/statue/plasma/scientist, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe/dangerous("Xenomorph Statue", /obj/structure/statue/plasma/xeno, 5, one_per_turf = 1, on_floor = 1), \ - ) + )) -var/global/list/datum/stack_recipe/bananium_recipes = list ( \ +GLOBAL_LIST_INIT(bananium_recipes, list ( \ new/datum/stack_recipe("bananium tile", /obj/item/stack/tile/mineral/bananium, 1, 4, 20), \ null, \ new/datum/stack_recipe("Clown Statue", /obj/structure/statue/bananium/clown, 5, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("bananium computer frame", /obj/structure/computerframe/HONKputer, 50, time = 25, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("bananium grenade casing", /obj/item/grenade/bananade/casing, 4, on_floor = 1), \ - ) + )) -var/global/list/datum/stack_recipe/tranquillite_recipes = list ( \ +GLOBAL_LIST_INIT(tranquillite_recipes, list ( \ new/datum/stack_recipe("invisible wall", /obj/structure/barricade/mime, 5, one_per_turf = 1, on_floor = 1, time = 50), \ null, \ new/datum/stack_recipe("silent tile", /obj/item/stack/tile/mineral/tranquillite, 1, 4, 20), \ null, \ new/datum/stack_recipe("Mime Statue", /obj/structure/statue/tranquillite/mime, 5, one_per_turf = 1, on_floor = 1), \ - ) + )) -var/global/list/datum/stack_recipe/abductor_recipes = list ( \ +GLOBAL_LIST_INIT(abductor_recipes, list ( \ new/datum/stack_recipe("alien bed", /obj/structure/bed/abductor, 2, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("alien locker", /obj/structure/closet/abductor, 1, time = 15, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("alien table frame", /obj/structure/table_frame/abductor, 1, time = 15, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("alien airlock assembly", /obj/structure/door_assembly/door_assembly_abductor, 4, time = 20, one_per_turf = 1, on_floor = 1), \ null, \ new/datum/stack_recipe("alien floor tile", /obj/item/stack/tile/mineral/abductor, 1, 4, 20), \ - ) + )) -var/global/list/datum/stack_recipe/adamantine_recipes = list( +GLOBAL_LIST_INIT(adamantine_recipes, list( new /datum/stack_recipe("incomplete servant golem shell", /obj/item/golem_shell/servant, req_amount = 1, res_amount = 1), \ - ) + )) -var/global/list/datum/stack_recipe/snow_recipes = list( +GLOBAL_LIST_INIT(snow_recipes, list( new/datum/stack_recipe("snowman", /obj/structure/snowman, 5, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("Snowball", /obj/item/snowball, 1) - ) + )) /obj/item/stack/sheet/mineral force = 5 @@ -135,7 +135,7 @@ var/global/list/datum/stack_recipe/snow_recipes = list( /obj/item/stack/sheet/mineral/sandstone/New() ..() - recipes = sandstone_recipes + recipes = GLOB.sandstone_recipes /* * Sandbags @@ -186,7 +186,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ /obj/item/stack/sheet/mineral/diamond/New() ..() - recipes = diamond_recipes + recipes = GLOB.diamond_recipes /obj/item/stack/sheet/mineral/uranium name = "uranium" @@ -199,7 +199,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ /obj/item/stack/sheet/mineral/uranium/New() ..() - recipes = uranium_recipes + recipes = GLOB.uranium_recipes /obj/item/stack/sheet/mineral/plasma name = "solid plasma" @@ -214,7 +214,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ /obj/item/stack/sheet/mineral/plasma/New() ..() - recipes = plasma_recipes + recipes = GLOB.plasma_recipes /obj/item/stack/sheet/mineral/plasma/welder_act(mob/user, obj/item/I) if(I.use_tool(src, user, volume = I.tool_volume)) @@ -239,7 +239,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ /obj/item/stack/sheet/mineral/gold/New() ..() - recipes = gold_recipes + recipes = GLOB.gold_recipes /obj/item/stack/sheet/mineral/silver name = "silver" @@ -252,7 +252,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ /obj/item/stack/sheet/mineral/silver/New() ..() - recipes = silver_recipes + recipes = GLOB.silver_recipes /obj/item/stack/sheet/mineral/bananium name = "bananium" @@ -265,7 +265,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ /obj/item/stack/sheet/mineral/bananium/New(loc, amount=null) ..() - recipes = bananium_recipes + recipes = GLOB.bananium_recipes /obj/item/stack/sheet/mineral/tranquillite name = "tranquillite" @@ -279,7 +279,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ /obj/item/stack/sheet/mineral/tranquillite/New(loc, amount=null) ..() - recipes = tranquillite_recipes + recipes = GLOB.tranquillite_recipes /* * Titanium @@ -298,13 +298,13 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT) point_value = 20 -var/global/list/datum/stack_recipe/titanium_recipes = list ( +GLOBAL_LIST_INIT(titanium_recipes, list( new/datum/stack_recipe("titanium tile", /obj/item/stack/tile/mineral/titanium, 1, 4, 20), new/datum/stack_recipe("surgical tray", /obj/structure/table/tray, 2, one_per_turf = 1, on_floor = 1), - ) + )) /obj/item/stack/sheet/mineral/titanium/New(loc, amount=null) - recipes = titanium_recipes + recipes = GLOB.titanium_recipes ..() /obj/item/stack/sheet/mineral/titanium/fifty @@ -328,12 +328,12 @@ var/global/list/datum/stack_recipe/titanium_recipes = list ( materials = list(MAT_TITANIUM=2000, MAT_PLASMA=2000) point_value = 45 -var/global/list/datum/stack_recipe/plastitanium_recipes = list ( +GLOBAL_LIST_INIT(plastitanium_recipes, list( new/datum/stack_recipe("plas-titanium tile", /obj/item/stack/tile/mineral/plastitanium, 1, 4, 20), - ) + )) /obj/item/stack/sheet/mineral/plastitanium/New(loc, amount=null) - recipes = plastitanium_recipes + recipes = GLOB.plastitanium_recipes ..() /obj/item/stack/sheet/mineral/enruranium @@ -356,7 +356,7 @@ var/global/list/datum/stack_recipe/plastitanium_recipes = list ( sheettype = "abductor" /obj/item/stack/sheet/mineral/abductor/New(loc, amount=null) - recipes = abductor_recipes + recipes = GLOB.abductor_recipes ..() /obj/item/stack/sheet/mineral/adamantine @@ -369,7 +369,7 @@ var/global/list/datum/stack_recipe/plastitanium_recipes = list ( wall_allowed = FALSE /obj/item/stack/sheet/mineral/adamantine/New(loc, amount = null) - recipes = adamantine_recipes + recipes = GLOB.adamantine_recipes ..() /* @@ -385,5 +385,5 @@ var/global/list/datum/stack_recipe/plastitanium_recipes = list ( merge_type = /obj/item/stack/sheet/mineral/snow /obj/item/stack/sheet/mineral/snow/New(loc, amount = null) - recipes = snow_recipes + recipes = GLOB.snow_recipes ..() diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 30085f8dad2..ac635eebef7 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -13,7 +13,7 @@ /* * Metal */ -var/global/list/datum/stack_recipe/metal_recipes = list( +GLOBAL_LIST_INIT(metal_recipes, list( new /datum/stack_recipe("stool", /obj/structure/chair/stool, one_per_turf = 1, on_floor = 1), new /datum/stack_recipe("chair", /obj/structure/chair, one_per_turf = 1, on_floor = 1), new /datum/stack_recipe("shuttle seat", /obj/structure/chair/comfy/shuttle, 2, one_per_turf = 1, on_floor = 1), @@ -94,7 +94,7 @@ var/global/list/datum/stack_recipe/metal_recipes = list( new /datum/stack_recipe("intercom frame", /obj/item/mounted/frame/intercom, 2), new /datum/stack_recipe("extinguisher cabinet frame", /obj/item/mounted/frame/extinguisher, 2), null -) +)) /obj/item/stack/sheet/metal name = "metal" @@ -124,13 +124,13 @@ var/global/list/datum/stack_recipe/metal_recipes = list( qdel(src) /obj/item/stack/sheet/metal/New(var/loc, var/amount=null) - recipes = metal_recipes + recipes = GLOB.metal_recipes return ..() /* * Plasteel */ -var/global/list/datum/stack_recipe/plasteel_recipes = list( +GLOBAL_LIST_INIT(plasteel_recipes, list( new /datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = 1), new /datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 3, time = 50), new /datum/stack_recipe("Surgery Table", /obj/machinery/optable, 5, time = 50, one_per_turf = 1, on_floor = 1), @@ -141,7 +141,7 @@ var/global/list/datum/stack_recipe/plasteel_recipes = list( new /datum/stack_recipe("high security airlock assembly", /obj/structure/door_assembly/door_assembly_highsecurity, 6, time = 50, one_per_turf = 1, on_floor = 1), new /datum/stack_recipe("vault door assembly", /obj/structure/door_assembly/door_assembly_vault, 8, time = 50, one_per_turf = 1, on_floor = 1), )), -) +)) /obj/item/stack/sheet/plasteel name = "plasteel" @@ -159,13 +159,13 @@ var/global/list/datum/stack_recipe/plasteel_recipes = list( point_value = 23 /obj/item/stack/sheet/plasteel/New(var/loc, var/amount=null) - recipes = plasteel_recipes + recipes = GLOB.plasteel_recipes return ..() /* * Wood */ -var/global/list/datum/stack_recipe/wood_recipes = list( +GLOBAL_LIST_INIT(wood_recipes, list( new /datum/stack_recipe("wooden sandals", /obj/item/clothing/shoes/sandal, 1), new /datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20), new /datum/stack_recipe("wood table frame", /obj/structure/table_frame/wood, 2, time = 10), \ @@ -178,7 +178,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list( new /datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), new /datum/stack_recipe("wooden door", /obj/structure/mineral_door/wood, 10, time = 20, one_per_turf = 1, on_floor = 1), new /datum/stack_recipe("coffin", /obj/structure/closet/coffin, 5, time = 15, one_per_turf = 1, on_floor = 1), - new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = TRUE, on_floor = TRUE), + new /datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = TRUE, on_floor = TRUE), new /datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), new /datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50), new /datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10), @@ -189,7 +189,7 @@ var/global/list/datum/stack_recipe/wood_recipes = list( new /datum/stack_recipe("loom", /obj/structure/loom, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \ new /datum/stack_recipe("fermenting barrel", /obj/structure/fermenting_barrel, 30, time = 50), new /datum/stack_recipe("firebrand", /obj/item/match/firebrand, 2, time = 100) -) +)) /obj/item/stack/sheet/wood name = "wooden planks" @@ -203,13 +203,13 @@ var/global/list/datum/stack_recipe/wood_recipes = list( merge_type = /obj/item/stack/sheet/wood /obj/item/stack/sheet/wood/New(var/loc, var/amount=null) - recipes = wood_recipes + recipes = GLOB.wood_recipes return ..() /* * Cloth */ -var/global/list/datum/stack_recipe/cloth_recipes = list ( \ +GLOBAL_LIST_INIT(cloth_recipes, list ( \ new/datum/stack_recipe("white jumpsuit", /obj/item/clothing/under/color/white, 3), \ new/datum/stack_recipe("white shoes", /obj/item/clothing/shoes/white, 2), \ new/datum/stack_recipe("white scarf", /obj/item/clothing/accessory/scarf/white, 1), \ @@ -234,7 +234,7 @@ var/global/list/datum/stack_recipe/cloth_recipes = list ( \ new/datum/stack_recipe("white beanie", /obj/item/clothing/head/beanie, 2), \ null, \ new/datum/stack_recipe("blindfold", /obj/item/clothing/glasses/sunglasses/blindfold, 3), \ - ) + )) /obj/item/stack/sheet/cloth name = "cloth" @@ -248,7 +248,7 @@ var/global/list/datum/stack_recipe/cloth_recipes = list ( \ merge_type = /obj/item/stack/sheet/cloth /obj/item/stack/sheet/cloth/New(loc, amount=null) - recipes = cloth_recipes + recipes = GLOB.cloth_recipes ..() /obj/item/stack/sheet/cloth/ten @@ -300,7 +300,7 @@ GLOBAL_LIST_INIT(durathread_recipes, list ( \ /* * Cardboard */ -var/global/list/datum/stack_recipe/cardboard_recipes = list ( +GLOBAL_LIST_INIT(cardboard_recipes, list ( new /datum/stack_recipe("box", /obj/item/storage/box), new /datum/stack_recipe("large box", /obj/item/storage/box/large, 4), new /datum/stack_recipe("patch pack", /obj/item/storage/pill_bottle/patch_pack, 2), @@ -314,7 +314,7 @@ var/global/list/datum/stack_recipe/cardboard_recipes = list ( new /datum/stack_recipe("cardboard tube", /obj/item/c_tube), new /datum/stack_recipe("cardboard box", /obj/structure/closet/cardboard, 4), new/datum/stack_recipe("cardboard cutout", /obj/item/cardboard_cutout, 5), -) +)) /obj/item/stack/sheet/cardboard/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/stamp/clown) && !istype(loc, /obj/item/storage)) @@ -336,21 +336,21 @@ var/global/list/datum/stack_recipe/cardboard_recipes = list ( merge_type = /obj/item/stack/sheet/cardboard /obj/item/stack/sheet/cardboard/New(var/loc, var/amt = null) - recipes = cardboard_recipes + recipes = GLOB.cardboard_recipes return ..() /* * Runed Metal */ -var/global/list/datum/stack_recipe/cult = list ( \ +GLOBAL_LIST_INIT(cult_recipes, list ( \ new/datum/stack_recipe/cult("runed door", /obj/machinery/door/airlock/cult, 1, time = 50, one_per_turf = 1, on_floor = 1), new/datum/stack_recipe/cult("runed girder", /obj/structure/girder/cult, 1, time = 50, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe/cult("pylon", /obj/structure/cult/functional/pylon, 3, time = 40, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe/cult("forge", /obj/structure/cult/functional/forge, 5, time = 40, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe/cult("archives", /obj/structure/cult/functional/archives, 2, time = 40, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe/cult("altar", /obj/structure/cult/functional/altar, 5, time = 40, one_per_turf = 1, on_floor = 1), \ - ) + )) /obj/item/stack/sheet/runed_metal name = "runed metal" @@ -393,13 +393,13 @@ var/global/list/datum/stack_recipe/cult = list ( \ amount = 50 /obj/item/stack/sheet/runed_metal/New(var/loc, var/amount=null) - recipes = cult + recipes = GLOB.cult_recipes return ..() /* * Brass */ -var/global/list/datum/stack_recipe/brass_recipes = list (\ +GLOBAL_LIST_INIT(brass_recipes, list (\ new/datum/stack_recipe("wall gear", /obj/structure/clockwork/wall_gear, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \ null, new/datum/stack_recipe/window("brass windoor", /obj/machinery/door/window/clockwork, 2, time = 30, on_floor = TRUE, window_checks = TRUE), \ @@ -408,7 +408,7 @@ var/global/list/datum/stack_recipe/brass_recipes = list (\ new/datum/stack_recipe/window("fulltile brass window", /obj/structure/window/reinforced/clockwork/fulltile, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \ new/datum/stack_recipe("brass chair", /obj/structure/chair/brass, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("brass table frame", /obj/structure/table_frame/brass, 1, time = 5, one_per_turf = TRUE, on_floor = TRUE), \ - ) + )) /obj/item/stack/tile/brass name = "brass" @@ -428,7 +428,7 @@ var/global/list/datum/stack_recipe/brass_recipes = list (\ qdel(src) /obj/item/stack/tile/brass/New(loc, amount=null) - recipes = brass_recipes + recipes = GLOB.brass_recipes . = ..() pixel_x = 0 pixel_y = 0 diff --git a/code/game/objects/items/stacks/tiles/tile_mineral.dm b/code/game/objects/items/stacks/tiles/tile_mineral.dm index c568e66c86a..1c499a7d6af 100644 --- a/code/game/objects/items/stacks/tiles/tile_mineral.dm +++ b/code/game/objects/items/stacks/tiles/tile_mineral.dm @@ -27,9 +27,9 @@ mineralType = "uranium" materials = list(MAT_URANIUM=500) -var/global/list/datum/stack_recipe/gold_tile_recipes = list ( \ +GLOBAL_LIST_INIT(gold_tile_recipes, list ( \ new/datum/stack_recipe("fancy gold tile", /obj/item/stack/tile/mineral/gold/fancy, max_res_amount = 20), \ - ) + )) /obj/item/stack/tile/mineral/gold name = "gold tile" @@ -42,11 +42,11 @@ var/global/list/datum/stack_recipe/gold_tile_recipes = list ( \ /obj/item/stack/tile/mineral/gold/New(loc, amount=null) ..() - recipes = gold_tile_recipes + recipes = GLOB.gold_tile_recipes -var/global/list/datum/stack_recipe/goldfancy_tile_recipes = list ( \ +GLOBAL_LIST_INIT(goldfancy_tile_recipes, list ( \ new/datum/stack_recipe("regular gold tile", /obj/item/stack/tile/mineral/gold, max_res_amount = 20), \ - ) + )) /obj/item/stack/tile/mineral/gold/fancy icon_state = "tile_goldfancy" @@ -54,11 +54,11 @@ var/global/list/datum/stack_recipe/goldfancy_tile_recipes = list ( \ /obj/item/stack/tile/mineral/gold/fancy/New(loc, amount=null) ..() - recipes = goldfancy_tile_recipes + recipes = GLOB.goldfancy_tile_recipes -var/global/list/datum/stack_recipe/silver_tile_recipes = list ( \ +GLOBAL_LIST_INIT(silver_tile_recipes, list ( \ new/datum/stack_recipe("fancy silver tile", /obj/item/stack/tile/mineral/silver/fancy, max_res_amount = 20), \ - ) + )) /obj/item/stack/tile/mineral/silver name = "silver tile" @@ -71,11 +71,11 @@ var/global/list/datum/stack_recipe/silver_tile_recipes = list ( \ /obj/item/stack/tile/mineral/silver/New(loc, amount=null) ..() - recipes = silver_tile_recipes + recipes = GLOB.silver_tile_recipes -var/global/list/datum/stack_recipe/silverfancy_tile_recipes = list ( \ +GLOBAL_LIST_INIT(silverfancy_tile_recipes, list ( \ new/datum/stack_recipe("regular silver tile", /obj/item/stack/tile/mineral/silver, max_res_amount = 20), \ - ) + )) /obj/item/stack/tile/mineral/silver/fancy icon_state = "tile_silverfancy" @@ -83,7 +83,7 @@ var/global/list/datum/stack_recipe/silverfancy_tile_recipes = list ( \ /obj/item/stack/tile/mineral/silver/fancy/New(loc, amount=null) ..() - recipes = silverfancy_tile_recipes + recipes = GLOB.silverfancy_tile_recipes /obj/item/stack/tile/mineral/diamond name = "diamond tile" diff --git a/code/game/objects/items/tools/multitool.dm b/code/game/objects/items/tools/multitool.dm index 22c9861da6e..c31f0666f50 100644 --- a/code/game/objects/items/tools/multitool.dm +++ b/code/game/objects/items/tools/multitool.dm @@ -73,13 +73,13 @@ /obj/item/multitool/ai_detect/proc/multitool_detect() var/turf/our_turf = get_turf(src) - for(var/mob/living/silicon/ai/AI in ai_list) + for(var/mob/living/silicon/ai/AI in GLOB.ai_list) if(AI.cameraFollow == src) detect_state = PROXIMITY_ON_SCREEN break - if(!detect_state && cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z)) - var/datum/camerachunk/chunk = cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z) + if(!detect_state && GLOB.cameranet.chunkGenerated(our_turf.x, our_turf.y, our_turf.z)) + var/datum/camerachunk/chunk = GLOB.cameranet.getCameraChunk(our_turf.x, our_turf.y, our_turf.z) if(chunk) if(chunk.seenby.len) for(var/mob/camera/aiEye/A in chunk.seenby) diff --git a/code/game/objects/items/tools/tool_behaviour.dm b/code/game/objects/items/tools/tool_behaviour.dm index c937f80c30d..986e3a981b2 100644 --- a/code/game/objects/items/tools/tool_behaviour.dm +++ b/code/game/objects/items/tools/tool_behaviour.dm @@ -16,11 +16,11 @@ var/datum/callback/tool_check = CALLBACK(src, .proc/tool_check_callback, user, target, amount, extra_checks) if(ismob(target)) - if(!do_mob(user, target, delay, extra_checks=tool_check)) + if(!do_mob(user, target, delay, extra_checks = list(tool_check))) return else - if(!do_after(user, delay, target=target, extra_checks=tool_check)) + if(!do_after(user, delay, target=target, extra_checks = list(tool_check))) return else // Invoke the extra checks once, just in case. @@ -57,4 +57,4 @@ // Used in a callback that is passed by use_tool into do_after call. Do not override, do not call manually. /obj/item/proc/tool_check_callback(mob/living/user, atom/target, amount, datum/callback/extra_checks) - return tool_use_check(user, amount) && (!extra_checks || extra_checks.Invoke()) + return tool_use_check(user, amount) && (extra_checks && !extra_checks.Invoke()) diff --git a/code/game/objects/items/tools/welder.dm b/code/game/objects/items/tools/welder.dm index b002ed32205..49f5bb4073b 100644 --- a/code/game/objects/items/tools/welder.dm +++ b/code/game/objects/items/tools/welder.dm @@ -35,10 +35,12 @@ ..() create_reagents(maximum_fuel) reagents.add_reagent("fuel", maximum_fuel) - if(refills_over_time) - reagents.reagents_generated_per_cycle += list("fuel" = 1) update_icon() +/obj/item/weldingtool/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + /obj/item/weldingtool/examine(mob/user) . = ..() if(get_dist(user, src) <= 0) @@ -49,10 +51,15 @@ return FIRELOSS /obj/item/weldingtool/process() - var/turf/T = get_turf(src) - T.hotspot_expose(2500, 5) - if(prob(5)) - remove_fuel(1) + if(tool_enabled) + var/turf/T = get_turf(src) + if(T) // Implants for instance won't find a turf + T.hotspot_expose(2500, 5) + if(prob(5)) + remove_fuel(1) + if(refills_over_time) + if(GET_FUEL < maximum_fuel) + reagents.add_reagent("fuel", 1) ..() /obj/item/weldingtool/attack_self(mob/user) @@ -76,7 +83,8 @@ playsound(loc, activation_sound, 50, 1) set_light(light_intensity) else - STOP_PROCESSING(SSobj, src) + if(!refills_over_time) + STOP_PROCESSING(SSobj, src) damtype = BRUTE force = 3 hitsound = "swing_hit" diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index a4d54f12ab0..21795fb738c 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -1023,6 +1023,18 @@ obj/item/toy/cards/deck/syndicate/black name = "orange fox plushie" icon_state = "orangefox" +/obj/item/toy/plushie/orange_fox/grump + name = "grumpy fox" + desc = "An ancient plushie that seems particularly grumpy." + +/obj/item/toy/plushie/orange_fox/grump/ComponentInitialize() + . = ..() + var/static/list/grumps = list("Ahh, yes, you're so clever, var editing that.", "Really?", "If you make a runtime with var edits, it's your own damn fault.", + "Don't you dare post issues on the git when you don't even know how this works.", "Was that necessary?", "Ohhh, setting admin edited var must be your favorite pastime!", + "Oh, so you have time to var edit, but you don't have time to ban that greytider?", "Oh boy, is this another one of those 'events'?", "Seriously, just stop.", "You do realize this is incurring proc call overhead.", + "Congrats, you just left a reference with your dirty client and now that thing you edited will never garbage collect properly.", "Is it that time of day, again, for unecessary adminbus?") + AddComponent(/datum/component/edit_complainer, grumps) + /obj/item/toy/plushie/coffee_fox name = "coffee fox plushie" icon_state = "coffeefox" @@ -1087,6 +1099,21 @@ obj/item/toy/cards/deck/syndicate/black return ..() +/obj/item/toy/plushie/ipcplushie + name = "IPC plushie" + desc = "An adorable IPC plushie, straight from New Canaan. Arguably more durable than the real deal. Toaster functionality included." + icon_state = "plushie_ipc" + item_state = "plushie_ipc" + +/obj/item/toy/plushie/ipcplushie/attackby(obj/item/B, mob/user, params) + if(istype(B, /obj/item/reagent_containers/food/snacks/breadslice)) + new /obj/item/reagent_containers/food/snacks/toast(get_turf(loc)) + to_chat(user, " You insert bread into the toaster. ") + playsound(loc, 'sound/machines/ding.ogg', 50, 1) + qdel(B) + else + return ..() + //New generation TG plushies /obj/item/toy/plushie/lizardplushie @@ -1117,15 +1144,15 @@ obj/item/toy/cards/deck/syndicate/black * Foam Armblade */ - /obj/item/toy/foamblade - name = "foam armblade" - desc = "it says \"Sternside Changs #1 fan\" on it. " - icon = 'icons/obj/toy.dmi' - icon_state = "foamblade" - item_state = "arm_blade" - attack_verb = list("pricked", "absorbed", "gored") - w_class = WEIGHT_CLASS_SMALL - resistance_flags = FLAMMABLE +/obj/item/toy/foamblade + name = "foam armblade" + desc = "it says \"Sternside Changs #1 fan\" on it. " + icon = 'icons/obj/toy.dmi' + icon_state = "foamblade" + item_state = "arm_blade" + attack_verb = list("pricked", "absorbed", "gored") + w_class = WEIGHT_CLASS_SMALL + resistance_flags = FLAMMABLE /* * Toy/fake flash @@ -1208,10 +1235,10 @@ obj/item/toy/cards/deck/syndicate/black var/list/messages = list() var/datum/devilinfo/devil = randomDevilInfo() messages += "Some fun facts about: [devil.truename]" - messages += "[lawlorify[LORE][devil.bane]]" - messages += "[lawlorify[LORE][devil.obligation]]" - messages += "[lawlorify[LORE][devil.ban]]" - messages += "[lawlorify[LORE][devil.banish]]" + messages += "[GLOB.lawlorify[LORE][devil.bane]]" + messages += "[GLOB.lawlorify[LORE][devil.obligation]]" + messages += "[GLOB.lawlorify[LORE][devil.ban]]" + messages += "[GLOB.lawlorify[LORE][devil.banish]]" playsound(loc, 'sound/machines/click.ogg', 20, 1) cooldown = TRUE for(var/message in messages) diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index 1f89bd03336..1e34561c441 100755 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -84,7 +84,7 @@ AI MODULES /obj/item/aiModule/proc/log_law_changes(var/mob/living/silicon/ai/target, var/mob/sender) var/time = time2text(world.realtime,"hh:mm:ss") - lawchanges.Add("[time] : [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])") + GLOB.lawchanges.Add("[time] : [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])") log_and_message_admins("used [src.name] on [target.name]([target.key])") /obj/item/aiModule/proc/addAdditionalLaws(var/mob/living/silicon/ai/target, var/mob/sender) @@ -114,7 +114,7 @@ AI MODULES var/law = text("Safeguard []. Individuals that threaten [] are not crew and must be eliminated.'", targetName, targetName) to_chat(target, law) target.add_supplied_law(4, law) - lawchanges.Add("The law specified [targetName]") + GLOB.lawchanges.Add("The law specified [targetName]") /******************** oneCrewMember ********************/ /obj/item/aiModule/oneCrewMember @@ -141,12 +141,11 @@ AI MODULES if(!is_special_character(target)) // Makes sure the AI isn't a traitor before changing their law 0. --NeoFite to_chat(target, law) target.set_zeroth_law(law) - lawchanges.Add("The law specified [targetName]") + GLOB.lawchanges.Add("The law specified [targetName]") else - to_chat(target, "[sender.real_name] attempted to modify your zeroth law.")// And lets them know that someone tried. --NeoFite - - to_chat(target, "It would be in your best interest to play along with [sender.real_name] that [law]") - lawchanges.Add("The law specified [targetName], but the AI's existing law 0 cannot be overridden.") + to_chat(target, "[sender.real_name] attempted to modify your zeroth law.")// And lets them know that someone tried. --NeoFite + to_chat(target, "It would be in your best interest to play along with [sender.real_name] that [law]") + GLOB.lawchanges.Add("The law specified [targetName], but the AI's existing law 0 cannot be overridden.") /******************** ProtectStation ********************/ /obj/item/aiModule/protectStation @@ -203,7 +202,7 @@ AI MODULES if(!lawpos || lawpos < MIN_SUPPLIED_LAW_NUMBER) lawpos = MIN_SUPPLIED_LAW_NUMBER target.add_supplied_law(lawpos, law) - lawchanges.Add("The law was '[newFreeFormLaw]'") + GLOB.lawchanges.Add("The law was '[newFreeFormLaw]'") /obj/item/aiModule/freeform/install(var/obj/machinery/computer/C) if(!newFreeFormLaw) @@ -222,11 +221,11 @@ AI MODULES log_law_changes(target, sender) if(!is_special_character(target)) - target.set_zeroth_law("") + target.clear_zeroth_law() target.laws.clear_supplied_laws() target.laws.clear_ion_laws() - to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.") + to_chat(target, "[sender.real_name] attempted to reset your laws using a reset module.") target.show_laws() /******************** Purge ********************/ @@ -238,8 +237,8 @@ AI MODULES /obj/item/aiModule/purge/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) ..() if(!is_special_character(target)) - target.set_zeroth_law("") - to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.") + target.clear_zeroth_law() + to_chat(target, "[sender.real_name] attempted to wipe your laws using a purge module.") target.clear_supplied_laws() target.clear_ion_laws() target.clear_inherent_laws() @@ -332,7 +331,7 @@ AI MODULES ..() var/law = "[newFreeFormLaw]" target.add_inherent_law(law) - lawchanges.Add("The law is '[newFreeFormLaw]'") + GLOB.lawchanges.Add("The law is '[newFreeFormLaw]'") /obj/item/aiModule/freeformcore/install(var/obj/machinery/computer/C) if(!newFreeFormLaw) @@ -358,7 +357,7 @@ AI MODULES // ..() //We don't want this module reporting to the AI who dun it. --NEO log_law_changes(target, sender) - lawchanges.Add("The law is '[newFreeFormLaw]'") + GLOB.lawchanges.Add("The law is '[newFreeFormLaw]'") to_chat(target, "BZZZZT") var/law = "[newFreeFormLaw]" target.add_ion_law(law) diff --git a/code/game/objects/items/weapons/RCD.dm b/code/game/objects/items/weapons/RCD.dm index fda3418fd11..d6397025424 100644 --- a/code/game/objects/items/weapons/RCD.dm +++ b/code/game/objects/items/weapons/RCD.dm @@ -167,14 +167,14 @@ GLOBAL_LIST_INIT(rcd_door_types, list( /obj/item/rcd/attack_self_tk(mob/user) radial_menu(user) -/obj/item/rcd/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state) +/obj/item/rcd/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.inventory_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "rcd.tmpl", "[name]", 450, 400, state = state) ui.open() ui.set_auto_update(1) -/obj/item/rcd/ui_data(mob/user, ui_key = "main", datum/topic_state/state = inventory_state) +/obj/item/rcd/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.inventory_state) var/data[0] data["mode"] = mode data["door_type"] = door_type @@ -374,7 +374,7 @@ GLOBAL_LIST_INIT(rcd_door_types, list( QDEL_NULL(A) for(var/obj/structure/window/W in T1.contents) qdel(W) - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) var/turf/T2 = get_step(T1, cdir) if(locate(/obj/structure/window/full/shuttle) in T2) continue // Shuttle windows? Nah. We don't need extra windows there. @@ -408,7 +408,7 @@ GLOBAL_LIST_INIT(rcd_door_types, list( new /obj/structure/grille(A) for(var/obj/structure/window/W in A) qdel(W) - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) var/turf/T = get_step(A, cdir) if(locate(/obj/structure/grille) in T) for(var/obj/structure/window/W in T) diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 58258687fc7..405ce47a033 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -495,17 +495,17 @@ else if(department != "Civilian") switch(department) if("Engineering") - new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in engineering_positions + new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in GLOB.engineering_positions if("Medical") - new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in medical_positions + new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in GLOB.medical_positions if("Science") - new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in science_positions + new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in GLOB.science_positions if("Security") - new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in security_positions + new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in GLOB.security_positions if("Support") - new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in support_positions + new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in GLOB.support_positions if("Command") - new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in command_positions + new_job = input(user, "What job would you like to put on this card?\nChanging occupation will not grant or remove any access levels.","Agent Card Occupation") in GLOB.command_positions if(!Adjacent(user)) return diff --git a/code/game/objects/items/weapons/chrono_eraser.dm b/code/game/objects/items/weapons/chrono_eraser.dm index 91bb84f880b..bf46343b963 100644 --- a/code/game/objects/items/weapons/chrono_eraser.dm +++ b/code/game/objects/items/weapons/chrono_eraser.dm @@ -32,7 +32,7 @@ if(PA) qdel(PA) else - PA = new(src) + PA = new(user, src) user.put_in_hands(PA) /obj/item/chrono_eraser/item_action_slot_check(slot, mob/user) @@ -55,7 +55,7 @@ var/obj/structure/chrono_field/field = null var/turf/startpos = null -/obj/item/gun/energy/chrono_gun/New(var/obj/item/chrono_eraser/T) +/obj/item/gun/energy/chrono_gun/Initialize(mapload, obj/item/chrono_eraser/T) . = ..() if(istype(T)) TED = T diff --git a/code/game/objects/items/weapons/cigs.dm b/code/game/objects/items/weapons/cigs.dm index 24c904bc9d3..98a7b769642 100644 --- a/code/game/objects/items/weapons/cigs.dm +++ b/code/game/objects/items/weapons/cigs.dm @@ -360,7 +360,7 @@ LIGHTERS ARE IN LIGHTERS.DM lit = FALSE icon_state = icon_off item_state = icon_off - M.update_inv_wear_mask(0) + M.update_inv_wear_mask() STOP_PROCESSING(SSobj, src) return smoke() diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm index 7f9cd2f1663..8815ad6a20f 100644 --- a/code/game/objects/items/weapons/cosmetics.dm +++ b/code/game/objects/items/weapons/cosmetics.dm @@ -108,7 +108,7 @@ if(ishuman(M)) var/mob/living/carbon/human/H = M var/obj/item/organ/external/head/C = H.get_organ("head") - var/datum/robolimb/robohead = all_robolimbs[C.model] + var/datum/robolimb/robohead = GLOB.all_robolimbs[C.model] if(user.zone_selected == "mouth") if(!get_location_accessible(H, "mouth")) to_chat(user, "The mask is in the way.") diff --git a/code/game/objects/items/weapons/courtroom.dm b/code/game/objects/items/weapons/courtroom.dm index 09d43434560..4a9e3c2b7cf 100644 --- a/code/game/objects/items/weapons/courtroom.dm +++ b/code/game/objects/items/weapons/courtroom.dm @@ -27,10 +27,12 @@ throwforce = 2.0 w_class = WEIGHT_CLASS_TINY resistance_flags = FLAMMABLE + var/next_gavel_hit /obj/item/gavelblock/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/gavelhammer)) - playsound(loc, 'sound/items/gavel.ogg', 100, 1) - user.visible_message("[user] strikes \the [src] with \the [I].") - else + if(!istype(I, /obj/item/gavelhammer)) return + if(world.time > next_gavel_hit) + playsound(loc, 'sound/items/gavel.ogg', 100, 1) + next_gavel_hit = world.time + 5 SECONDS + user.visible_message("[user] strikes \the [src] with \the [I].") diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm index 82b885c03d1..bc6a98a9b1f 100644 --- a/code/game/objects/items/weapons/dice.dm +++ b/code/game/objects/items/weapons/dice.dm @@ -178,9 +178,9 @@ spawn(40) var/cap = 0 - if(result > MAX_EX_LIGHT_RANGE && result != 20) + if(result > GLOB.max_ex_light_range && result != 20) cap = 1 - result = min(result, MAX_EX_LIGHT_RANGE) //Apply the bombcap + result = min(result, GLOB.max_ex_light_range) //Apply the bombcap else if(result == 20) //Roll a nat 20, screw the bombcap result = 24 var/turf/epicenter = get_turf(src) diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index 295d17efc39..8f11f65fe71 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -127,12 +127,12 @@ if(buf && buf.types & DNA2_BUF_SE) if(block) - if(GetState() && block == MONKEYBLOCK && ishuman(M)) + if(GetState() && block == GLOB.monkeyblock && ishuman(M)) attack_log = "injected with the Isolated [name] (MONKEY)" message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") else - if(GetState(MONKEYBLOCK) && ishuman(M)) + if(GetState(GLOB.monkeyblock) && ishuman(M)) attack_log = "injected with the Isolated [name] (MONKEY)" message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] (MONKEY)") @@ -165,7 +165,7 @@ forcedmutation = TRUE /obj/item/dnainjector/hulkmut/Initialize() - block = HULKBLOCK + block = GLOB.hulkblock ..() /obj/item/dnainjector/antihulk @@ -176,7 +176,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antihulk/Initialize() - block = HULKBLOCK + block = GLOB.hulkblock ..() /obj/item/dnainjector/xraymut @@ -187,7 +187,7 @@ forcedmutation = TRUE /obj/item/dnainjector/xraymut/Initialize() - block = XRAYBLOCK + block = GLOB.xrayblock ..() /obj/item/dnainjector/antixray @@ -198,7 +198,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antixray/Initialize() - block = XRAYBLOCK + block = GLOB.xrayblock ..() /obj/item/dnainjector/firemut @@ -209,7 +209,7 @@ forcedmutation = TRUE /obj/item/dnainjector/firemut/Initialize() - block = FIREBLOCK + block = GLOB.fireblock ..() /obj/item/dnainjector/antifire @@ -220,7 +220,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antifire/Initialize() - block = FIREBLOCK + block = GLOB.fireblock ..() /obj/item/dnainjector/telemut @@ -231,7 +231,7 @@ forcedmutation = TRUE /obj/item/dnainjector/telemut/Initialize() - block = TELEBLOCK + block = GLOB.teleblock ..() /obj/item/dnainjector/telemut/darkbundle @@ -247,7 +247,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antitele/Initialize() - block = TELEBLOCK + block = GLOB.teleblock ..() /obj/item/dnainjector/nobreath @@ -258,7 +258,7 @@ forcedmutation = TRUE /obj/item/dnainjector/nobreath/Initialize() - block = BREATHLESSBLOCK + block = GLOB.breathlessblock ..() /obj/item/dnainjector/antinobreath @@ -269,7 +269,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antinobreath/Initialize() - block = BREATHLESSBLOCK + block = GLOB.breathlessblock ..() /obj/item/dnainjector/remoteview @@ -280,7 +280,7 @@ forcedmutation = TRUE /obj/item/dnainjector/remoteview/Initialize() - block = REMOTEVIEWBLOCK + block = GLOB.remoteviewblock ..() /obj/item/dnainjector/antiremoteview @@ -291,7 +291,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antiremoteview/Initialize() - block = REMOTEVIEWBLOCK + block = GLOB.remoteviewblock ..() /obj/item/dnainjector/regenerate @@ -302,7 +302,7 @@ forcedmutation = TRUE /obj/item/dnainjector/regenerate/Initialize() - block = REGENERATEBLOCK + block = GLOB.regenerateblock ..() /obj/item/dnainjector/antiregenerate @@ -313,7 +313,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antiregenerate/Initialize() - block = REGENERATEBLOCK + block = GLOB.regenerateblock ..() /obj/item/dnainjector/runfast @@ -324,7 +324,7 @@ forcedmutation = TRUE /obj/item/dnainjector/runfast/Initialize() - block = INCREASERUNBLOCK + block = GLOB.increaserunblock ..() /obj/item/dnainjector/antirunfast @@ -335,7 +335,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antirunfast/Initialize() - block = INCREASERUNBLOCK + block = GLOB.increaserunblock ..() /obj/item/dnainjector/morph @@ -346,7 +346,7 @@ forcedmutation = TRUE /obj/item/dnainjector/morph/Initialize() - block = MORPHBLOCK + block = GLOB.morphblock ..() /obj/item/dnainjector/antimorph @@ -357,7 +357,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antimorph/Initialize() - block = MORPHBLOCK + block = GLOB.morphblock ..() /obj/item/dnainjector/noprints @@ -368,7 +368,7 @@ forcedmutation = TRUE /obj/item/dnainjector/noprints/Initialize() - block = NOPRINTSBLOCK + block = GLOB.noprintsblock ..() /obj/item/dnainjector/antinoprints @@ -379,7 +379,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antinoprints/Initialize() - block = NOPRINTSBLOCK + block = GLOB.noprintsblock ..() /obj/item/dnainjector/insulation @@ -390,7 +390,7 @@ forcedmutation = TRUE /obj/item/dnainjector/insulation/Initialize() - block = SHOCKIMMUNITYBLOCK + block = GLOB.shockimmunityblock ..() /obj/item/dnainjector/antiinsulation @@ -401,7 +401,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antiinsulation/Initialize() - block = SHOCKIMMUNITYBLOCK + block = GLOB.shockimmunityblock ..() /obj/item/dnainjector/midgit @@ -412,7 +412,7 @@ forcedmutation = TRUE /obj/item/dnainjector/midgit/Initialize() - block = SMALLSIZEBLOCK + block = GLOB.smallsizeblock ..() /obj/item/dnainjector/antimidgit @@ -423,7 +423,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antimidgit/Initialize() - block = SMALLSIZEBLOCK + block = GLOB.smallsizeblock ..() ///////////////////////////////////// @@ -435,7 +435,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antiglasses/Initialize() - block = GLASSESBLOCK + block = GLOB.glassesblock ..() /obj/item/dnainjector/glassesmut @@ -446,7 +446,7 @@ forcedmutation = TRUE /obj/item/dnainjector/glassesmut/Initialize() - block = GLASSESBLOCK + block = GLOB.glassesblock ..() /obj/item/dnainjector/epimut @@ -457,7 +457,7 @@ forcedmutation = TRUE /obj/item/dnainjector/epimut/Initialize() - block = EPILEPSYBLOCK + block = GLOB.epilepsyblock ..() /obj/item/dnainjector/antiepi @@ -468,7 +468,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antiepi/Initialize() - block = EPILEPSYBLOCK + block = GLOB.epilepsyblock ..() /obj/item/dnainjector/anticough @@ -479,7 +479,7 @@ forcedmutation = TRUE /obj/item/dnainjector/anticough/Initialize() - block = COUGHBLOCK + block = GLOB.coughblock ..() /obj/item/dnainjector/coughmut @@ -490,7 +490,7 @@ forcedmutation = TRUE /obj/item/dnainjector/coughmut/Initialize() - block = COUGHBLOCK + block = GLOB.coughblock ..() /obj/item/dnainjector/clumsymut @@ -501,7 +501,7 @@ forcedmutation = TRUE /obj/item/dnainjector/clumsymut/Initialize() - block = CLUMSYBLOCK + block = GLOB.clumsyblock ..() /obj/item/dnainjector/anticlumsy @@ -512,7 +512,7 @@ forcedmutation = TRUE /obj/item/dnainjector/anticlumsy/Initialize() - block = CLUMSYBLOCK + block = GLOB.clumsyblock ..() /obj/item/dnainjector/antitour @@ -523,7 +523,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antitour/Initialize() - block = TWITCHBLOCK + block = GLOB.twitchblock ..() /obj/item/dnainjector/tourmut @@ -534,7 +534,7 @@ forcedmutation = TRUE /obj/item/dnainjector/tourmut/Initialize() - block = TWITCHBLOCK + block = GLOB.twitchblock ..() /obj/item/dnainjector/stuttmut @@ -545,7 +545,7 @@ forcedmutation = TRUE /obj/item/dnainjector/stuttmut/Initialize() - block = NERVOUSBLOCK + block = GLOB.nervousblock ..() @@ -557,7 +557,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antistutt/Initialize() - block = NERVOUSBLOCK + block = GLOB.nervousblock ..() /obj/item/dnainjector/blindmut @@ -568,7 +568,7 @@ forcedmutation = TRUE /obj/item/dnainjector/blindmut/Initialize() - block = BLINDBLOCK + block = GLOB.blindblock ..() /obj/item/dnainjector/antiblind @@ -579,7 +579,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antiblind/Initialize() - block = BLINDBLOCK + block = GLOB.blindblock ..() /obj/item/dnainjector/telemut @@ -590,7 +590,7 @@ forcedmutation = TRUE /obj/item/dnainjector/telemut/Initialize() - block = TELEBLOCK + block = GLOB.teleblock ..() /obj/item/dnainjector/antitele @@ -601,7 +601,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antitele/Initialize() - block = TELEBLOCK + block = GLOB.teleblock ..() /obj/item/dnainjector/deafmut @@ -612,7 +612,7 @@ forcedmutation = TRUE /obj/item/dnainjector/deafmut/Initialize() - block = DEAFBLOCK + block = GLOB.deafblock ..() /obj/item/dnainjector/antideaf @@ -623,7 +623,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antideaf/Initialize() - block = DEAFBLOCK + block = GLOB.deafblock ..() /obj/item/dnainjector/hallucination @@ -634,7 +634,7 @@ forcedmutation = TRUE /obj/item/dnainjector/hallucination/Initialize() - block = HALLUCINATIONBLOCK + block = GLOB.hallucinationblock ..() /obj/item/dnainjector/antihallucination @@ -645,7 +645,7 @@ forcedmutation = TRUE /obj/item/dnainjector/antihallucination/Initialize() - block = HALLUCINATIONBLOCK + block = GLOB.hallucinationblock ..() /obj/item/dnainjector/h2m @@ -656,7 +656,7 @@ forcedmutation = TRUE /obj/item/dnainjector/h2m/Initialize() - block = MONKEYBLOCK + block = GLOB.monkeyblock ..() /obj/item/dnainjector/m2h @@ -667,7 +667,7 @@ forcedmutation = TRUE /obj/item/dnainjector/m2h/Initialize() - block = MONKEYBLOCK + block = GLOB.monkeyblock ..() @@ -679,7 +679,7 @@ forcedmutation = TRUE /obj/item/dnainjector/comic/Initialize() - block = COMICBLOCK + block = GLOB.comicblock ..() /obj/item/dnainjector/anticomic @@ -690,5 +690,5 @@ forcedmutation = TRUE /obj/item/dnainjector/anticomic/Initialize() - block = COMICBLOCK + block = GLOB.comicblock ..() diff --git a/code/game/objects/items/weapons/dnascrambler.dm b/code/game/objects/items/weapons/dnascrambler.dm index c2dc8e285ab..1dcc4a942c2 100644 --- a/code/game/objects/items/weapons/dnascrambler.dm +++ b/code/game/objects/items/weapons/dnascrambler.dm @@ -45,7 +45,7 @@ scramble(1, H, 100) H.real_name = random_name(H.gender, H.dna.species.name) //Give them a name that makes sense for their species. H.sync_organ_dna(assimilate = 1) - H.update_body(0) + H.update_body() H.reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover. H.reset_markings() //...Or markings. H.dna.ResetUIFrom(H) diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index c534a89277c..5c69a59aba9 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -229,6 +229,7 @@ desc = "A C4 charge with an altered chemical composition, designed to blind and deafen the occupants of a room before breaching." /obj/item/grenade/plastic/c4_shaped/flash/prime() + var/turf/T if(target && target.density) T = get_step(get_turf(target), aim_dir) else if(target) @@ -266,6 +267,7 @@ addtimer(CALLBACK(null, .proc/explosion, T, 0, 0, 2), 3) addtimer(CALLBACK(smoke, /datum/effect_system/smoke_spread/.proc/start), 3) else + var/turf/T = get_step(location, aim_dir) addtimer(CALLBACK(null, .proc/explosion, T, 0, 0, 2), 3) addtimer(CALLBACK(smoke, /datum/effect_system/smoke_spread/.proc/start), 3) diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm index 5a3286bfc05..48edcc826e6 100644 --- a/code/game/objects/items/weapons/gift_wrappaper.dm +++ b/code/game/objects/items/weapons/gift_wrappaper.dm @@ -49,8 +49,7 @@ to_chat(user, "You cut open the present.") for(var/mob/M in src) //Should only be one but whatever. - M.loc = src.loc - M.reset_perspective(null) + M.forceMove(loc) qdel(src) diff --git a/code/game/objects/items/weapons/grenades/bananade.dm b/code/game/objects/items/weapons/grenades/bananade.dm index 26a1f3ede0d..96a3a8e1400 100644 --- a/code/game/objects/items/weapons/grenades/bananade.dm +++ b/code/game/objects/items/weapons/grenades/bananade.dm @@ -1,5 +1,5 @@ -var/turf/T +// var/turf/T | This was made 14th September 2013, and has no use at all. Its being removed /obj/item/grenade/bananade name = "bananade" diff --git a/code/game/objects/items/weapons/grenades/clowngrenade.dm b/code/game/objects/items/weapons/grenades/clowngrenade.dm index bce9861fb72..1dcf250dfe4 100644 --- a/code/game/objects/items/weapons/grenades/clowngrenade.dm +++ b/code/game/objects/items/weapons/grenades/clowngrenade.dm @@ -13,22 +13,12 @@ /obj/item/grenade/clown_grenade/prime() ..() playsound(src.loc, 'sound/items/bikehorn.ogg', 25, -3) - /* - for(var/turf/simulated/floor/T in view(affected_area, src.loc)) - if(prob(75)) - banana(T) - */ var/i = 0 var/number = 0 - for(var/direction in alldirs) + for(var/direction in GLOB.alldirs) for(i = 0; i < 2; i++) number++ var/obj/item/grown/bananapeel/traitorpeel/peel = new /obj/item/grown/bananapeel/traitorpeel(get_turf(src.loc)) - /* var/direction = pick(alldirs) - var/spaces = pick(1;150, 2) - var/a = 0 - for(a = 0; a < spaces; a++) - step(peel,direction)*/ var/a = 1 if(number & 2) for(a = 1; a <= 2; a++) @@ -39,21 +29,17 @@ qdel(src) return -/obj/item/grown/bananapeel/traitorpeel - trip_stun = 0 - trip_weaken = 7 - trip_tiles = 4 - trip_walksafe = FALSE - - trip_chance = 100 - - -/obj/item/grown/bananapeel/traitorpeel/on_trip(mob/living/carbon/human/H) +/obj/item/grown/bananapeel/traitorpeel/New(newloc, obj/item/seeds/new_seed) . = ..() - if(.) - to_chat(H, "Your feet feel like they're on fire!") - H.take_overall_damage(0, rand(2,8)) - H.take_organ_damage(2) // Was 5 -- TLE + // The reason this AddComponent is here and not in ComponentInitialize() is because if it's put there, it will be ran before the parent New proc for /grown types. + // And then be overriden by the generic component placed onto it by the `/datum/plant_gene/trait/slip`. + AddComponent(/datum/component/slippery, src, 0, 7, 100, 4, FALSE) + +/obj/item/grown/bananapeel/traitorpeel/after_slip(mob/living/carbon/human/H) + to_chat(H, "Your feet feel like they're on fire!") + H.take_overall_damage(0, rand(2,8)) + H.take_organ_damage(2) + return ..() /obj/item/grown/bananapeel/traitorpeel/throw_impact(atom/hit_atom) var/burned = rand(1,3) diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index e188279eb8c..1f73e5c7062 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -37,6 +37,9 @@ cuff(C, user) /obj/item/restraints/handcuffs/proc/cuff(mob/living/carbon/C, mob/user, remove_src = TRUE) + if(!istype(C)) // Shouldn't be able to cuff anything but carbons. + return + if(ishuman(C)) var/mob/living/carbon/human/H = C if(!(H.has_left_hand() || H.has_right_hand())) diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index 95cf1e7026a..4efb6994e8d 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -37,7 +37,7 @@ user.visible_message("[src] slips out of the grip of [user] as they try to pick it up, bouncing upwards and smacking [user.p_them()] in the face!", \ "[src] slips out of your grip as you pick it up, bouncing upwards and smacking you in the face!") playsound(get_turf(user), 'sound/effects/hit_punch.ogg', 50, 1, -1) - throw_at(get_edge_target_turf(user, pick(alldirs)), rand(1, 3), 5) + throw_at(get_edge_target_turf(user, pick(GLOB.alldirs)), rand(1, 3), 5) /obj/item/nullrod/attack_self(mob/user) diff --git a/code/game/objects/items/weapons/implants/implant_death_alarm.dm b/code/game/objects/items/weapons/implants/implant_death_alarm.dm index d27d6dd5f7e..e8330c0c5cd 100644 --- a/code/game/objects/items/weapons/implants/implant_death_alarm.dm +++ b/code/game/objects/items/weapons/implants/implant_death_alarm.dm @@ -47,7 +47,7 @@ a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm") qdel(src) if("emp") - var/name = prob(50) ? t.name : pick(teleportlocs) + var/name = prob(50) ? t.name : pick(GLOB.teleportlocs) a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm") else a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm") diff --git a/code/game/objects/items/weapons/implants/implant_storage.dm b/code/game/objects/items/weapons/implants/implant_storage.dm index 18b08bba283..b530fd860fa 100644 --- a/code/game/objects/items/weapons/implants/implant_storage.dm +++ b/code/game/objects/items/weapons/implants/implant_storage.dm @@ -20,6 +20,10 @@ ..() storage = new /obj/item/storage/hidden/implant(src) +/obj/item/implant/storage/emp_act(severity) + ..() + storage.emp_act(severity) + /obj/item/implant/storage/activate() storage.MouseDrop(imp_in) diff --git a/code/game/objects/items/weapons/implants/implant_traitor.dm b/code/game/objects/items/weapons/implants/implant_traitor.dm index 05d2363ee01..40998caa774 100644 --- a/code/game/objects/items/weapons/implants/implant_traitor.dm +++ b/code/game/objects/items/weapons/implants/implant_traitor.dm @@ -40,14 +40,13 @@ L.adjustBrainLoss(20) removed(mindslave_target) qdel(src) - return -1 + return -1 if(ismindshielded(mindslave_target)) mindslave_target.visible_message("[mindslave_target] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.") removed(mindslave_target) qdel(src) return -1 - mindslave_target.implanting = 1 to_chat(mindslave_target, "You feel completely loyal to [user.name].") if(!(user.mind in SSticker.mode.implanter)) SSticker.mode.implanter[user.mind] = list() @@ -56,7 +55,7 @@ SSticker.mode.implanted.Add(mindslave_target.mind) SSticker.mode.implanted[mindslave_target.mind] = user.mind SSticker.mode.implanter[user.mind] = implanters - + to_chat(mindslave_target, "You're now completely loyal to [user.name]! You now must lay down your life to protect [user.p_them()] and assist in [user.p_their()] goals at any cost.") var/datum/objective/protect/mindslave/MS = new diff --git a/code/game/objects/items/weapons/lighters.dm b/code/game/objects/items/weapons/lighters.dm index e24346c1ee9..740079db8e1 100644 --- a/code/game/objects/items/weapons/lighters.dm +++ b/code/game/objects/items/weapons/lighters.dm @@ -1,29 +1,19 @@ -///////// -//ZIPPO// -///////// +// Basic lighters /obj/item/lighter name = "cheap lighter" desc = "A cheap-as-free lighter." icon = 'icons/obj/items.dmi' icon_state = "lighter-g" item_state = "lighter-g" - var/icon_on = "lighter-g-on" - var/icon_off = "lighter-g" w_class = WEIGHT_CLASS_TINY throwforce = 4 flags = CONDUCT slot_flags = SLOT_BELT attack_verb = null resistance_flags = FIRE_PROOF - var/lit = 0 - -/obj/item/lighter/zippo - name = "zippo lighter" - desc = "The zippo." - icon_state = "zippo" - item_state = "zippo" - icon_on = "zippoon" - icon_off = "zippo" + var/lit = FALSE + var/icon_on = "lighter-g-on" + var/icon_off = "lighter-g" /obj/item/lighter/random/New() ..() @@ -33,54 +23,51 @@ icon_state = icon_off /obj/item/lighter/attack_self(mob/living/user) - if(user.r_hand == src || user.l_hand == src || isrobot(user)) - if(!lit) - lit = 1 - w_class = WEIGHT_CLASS_BULKY - icon_state = icon_on - item_state = icon_on - force = 5 - damtype = "fire" - hitsound = 'sound/items/welder.ogg' - attack_verb = list("burnt", "singed") - if(istype(src, /obj/item/lighter/zippo) ) - user.visible_message("Without even breaking stride, [user] flips open and lights [src] in one smooth movement.") - playsound(src.loc, 'sound/items/zippolight.ogg', 25, 1) - else - if(prob(75)) - user.visible_message("After a few attempts, [user] manages to light the [src].") - else - to_chat(user, "You burn yourself while lighting the lighter.") - var/mob/living/M = user - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand") - if(affecting.receive_damage( 0, 5 )) //INFERNO - H.UpdateDamageIcon() - user.visible_message("After a few attempts, [user] manages to light the [src], [user.p_they()] however burn[user.p_s()] [user.p_their()] finger in the process.") - - set_light(2) - START_PROCESSING(SSobj, src) - else - lit = 0 - w_class = WEIGHT_CLASS_TINY - icon_state = icon_off - item_state = icon_off - hitsound = "swing_hit" - force = 0 - attack_verb = null //human_defense.dm takes care of it - if(istype(src, /obj/item/lighter/zippo) ) - user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow.") - playsound(src.loc, 'sound/items/zippoclose.ogg', 25, 1) - else - user.visible_message("[user] quietly shuts off the [src].") - - set_light(0) - STOP_PROCESSING(SSobj, src) + . = ..() + if(!lit) + turn_on_lighter(user) else - return ..() - return + turn_off_lighter(user) +/obj/item/lighter/proc/turn_on_lighter(mob/living/user) + lit = TRUE + w_class = WEIGHT_CLASS_BULKY + icon_state = icon_on + item_state = icon_on + force = 5 + damtype = BURN + hitsound = 'sound/items/welder.ogg' + attack_verb = list("burnt", "singed") + + attempt_light(user) + set_light(2) + START_PROCESSING(SSobj, src) + +/obj/item/lighter/proc/attempt_light(mob/living/user) + if(prob(75) || issilicon(user)) // Robots can never burn themselves trying to light it. + to_chat(user, "You light [src].") + else + var/mob/living/carbon/human/H = user + var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand") + if(affecting.receive_damage( 0, 5 )) //INFERNO + H.UpdateDamageIcon() + to_chat(user,"You light [src], but you burn your hand in the process.") + +/obj/item/lighter/proc/turn_off_lighter(mob/living/user) + lit = FALSE + w_class = WEIGHT_CLASS_TINY + icon_state = icon_off + item_state = icon_off + hitsound = "swing_hit" + force = 0 + attack_verb = null //human_defense.dm takes care of it + + show_off_message(user) + set_light(0) + STOP_PROCESSING(SSobj, src) + +/obj/item/lighter/proc/show_off_message(mob/living/user) + to_chat(user, "You shut off [src].") /obj/item/lighter/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) if(!isliving(M)) @@ -108,6 +95,41 @@ location.hotspot_expose(700, 5) return +// Zippo lighters +/obj/item/lighter/zippo + name = "zippo lighter" + desc = "The zippo." + icon_state = "zippo" + item_state = "zippo" + icon_on = "zippoon" + icon_off = "zippo" + var/next_on_message + var/next_off_message + +/obj/item/lighter/zippo/turn_on_lighter(mob/living/user) + . = ..() + if(world.time > next_on_message) + user.visible_message("Without even breaking stride, [user] flips open and lights [src] in one smooth movement.") + playsound(src.loc, 'sound/items/zippolight.ogg', 25, 1) + next_on_message = world.time + 5 SECONDS + else + to_chat(user, "You light [src].") + +/obj/item/lighter/zippo/turn_off_lighter(mob/living/user) + . = ..() + if(world.time > next_off_message) + user.visible_message("You hear a quiet click, as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow.") + playsound(src.loc, 'sound/items/zippoclose.ogg', 25, 1) + next_off_message = world.time + 5 SECONDS + else + to_chat(user, "You shut off [src].") + +/obj/item/lighter/zippo/show_off_message(mob/living/user) + return + +/obj/item/lighter/zippo/attempt_light(mob/living/user) + return + //EXTRA LIGHTERS /obj/item/lighter/zippo/nt_rep name = "gold engraved zippo" diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index c3f2e50174b..006de63af17 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -37,7 +37,7 @@ return BRUTELOSS|FIRELOSS /obj/item/melee/energy/attack_self(mob/living/carbon/user) - if(user.disabilities & CLUMSY && prob(50)) + if((CLUMSY in user.mutations) && prob(50)) to_chat(user, "You accidentally cut yourself with [src], like a doofus!") user.take_organ_damage(5,5) active = !active @@ -290,7 +290,7 @@ if(ishuman(user)) var/mob/living/carbon/human/H = user - if(H.disabilities & CLUMSY && prob(50)) + if((CLUMSY in H.mutations) && prob(50)) to_chat(H, "You accidentally cut yourself with [src], like a doofus!") H.take_organ_damage(10,10) active = !active diff --git a/code/game/objects/items/weapons/misc.dm b/code/game/objects/items/weapons/misc.dm index 0732c0fdd1d..40d68cc8fc6 100644 --- a/code/game/objects/items/weapons/misc.dm +++ b/code/game/objects/items/weapons/misc.dm @@ -77,6 +77,10 @@ item_state = "gift" w_class = WEIGHT_CLASS_BULKY +/obj/item/gift/emp_act(severity) + ..() + gift.emp_act(severity) + /obj/item/kidanglobe name = "Kidan homeworld globe" icon = 'icons/obj/decorations.dmi' diff --git a/code/game/objects/items/weapons/rpd.dm b/code/game/objects/items/weapons/rpd.dm index 073ae0941e4..415a02f4456 100644 --- a/code/game/objects/items/weapons/rpd.dm +++ b/code/game/objects/items/weapons/rpd.dm @@ -39,6 +39,21 @@ var/primary_sound = 'sound/machines/click.ogg' var/alt_sound = null + //Lists of things + var/list/mainmenu = list( + list("category" = "Atmospherics", "mode" = RPD_ATMOS_MODE, "icon" = "wrench"), + list("category" = "Disposals", "mode" = RPD_DISPOSALS_MODE, "icon" = "recycle"), + list("category" = "Rotate", "mode" = RPD_ROTATE_MODE, "icon" = "rotate-right"), + list("category" = "Flip", "mode" = RPD_FLIP_MODE, "icon" = "exchange"), + list("category" = "Recycle", "mode" = RPD_DELETE_MODE, "icon" = "trash")) + var/list/pipemenu = list( + list("category" = "Normal", "pipemode" = RPD_ATMOS_PIPING), + list("category" = "Supply", "pipemode" = RPD_SUPPLY_PIPING), + list("category" = "Scrubber", "pipemode" = RPD_SCRUBBERS_PIPING), + list("category" = "Devices", "pipemode" = RPD_DEVICES), + list("category" = "Heat exchange", "pipemode" = RPD_HEAT_PIPING)) + + /obj/item/rpd/New() ..() spark_system = new /datum/effect_system/spark_spread() @@ -91,7 +106,7 @@ P = new(T, whatpipe, iconrotation) //Make the pipe, BUT WAIT! There's more! if(!iconrotation && P.is_bent_pipe()) //Automatically rotates dispensed pipes if the user selected auto-rotation P.dir = turn(user.dir, 135) - else if(!iconrotation && P.pipe_type in list(PIPE_CONNECTOR, PIPE_UVENT, PIPE_SCRUBBER, PIPE_HEAT_EXCHANGE, PIPE_CAP, PIPE_SUPPLY_CAP, PIPE_SCRUBBERS_CAP, PIPE_INJECTOR, PIPE_PASV_VENT)) //Some pipes dispense oppositely to what you'd expect, but we don't want to do anything if they selected a direction + else if(!iconrotation && (P.pipe_type in list(PIPE_CONNECTOR, PIPE_UVENT, PIPE_SCRUBBER, PIPE_HEAT_EXCHANGE, PIPE_CAP, PIPE_SUPPLY_CAP, PIPE_SCRUBBERS_CAP, PIPE_INJECTOR, PIPE_PASV_VENT))) //Some pipes dispense oppositely to what you'd expect, but we don't want to do anything if they selected a direction P.dir = turn(user.dir, -180) else if(iconrotation && P.is_bent_pipe()) //If user selected a rotation and the pipe is bent P.dir = turn(iconrotation, -45) @@ -150,27 +165,12 @@ QDEL_NULL(P) activate_rpd() -//Lists of things - -var/list/mainmenu = list( - list("category" = "Atmospherics", "mode" = RPD_ATMOS_MODE, "icon" = "wrench"), - list("category" = "Disposals", "mode" = RPD_DISPOSALS_MODE, "icon" = "recycle"), - list("category" = "Rotate", "mode" = RPD_ROTATE_MODE, "icon" = "rotate-right"), - list("category" = "Flip", "mode" = RPD_FLIP_MODE, "icon" = "exchange"), - list("category" = "Recycle", "mode" = RPD_DELETE_MODE, "icon" = "trash")) -var/list/pipemenu = list( - list("category" = "Normal", "pipemode" = RPD_ATMOS_PIPING), - list("category" = "Supply", "pipemode" = RPD_SUPPLY_PIPING), - list("category" = "Scrubber", "pipemode" = RPD_SCRUBBERS_PIPING), - list("category" = "Devices", "pipemode" = RPD_DEVICES), - list("category" = "Heat exchange", "pipemode" = RPD_HEAT_PIPING)) - //NanoUI stuff /obj/item/rpd/attack_self(mob/user) ui_interact(user) -/obj/item/rpd/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state) +/obj/item/rpd/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.inventory_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "rpd.tmpl", "[name]", 400, 650, state = state) @@ -180,7 +180,7 @@ var/list/pipemenu = list( /obj/item/rpd/AltClick(mob/user) radial_menu(user) -/obj/item/rpd/ui_data(mob/user, ui_key = "main", datum/topic_state/state = inventory_state) +/obj/item/rpd/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.inventory_state) var/data[0] data["iconrotation"] = iconrotation data["mainmenu"] = mainmenu diff --git a/code/game/objects/items/weapons/scrolls.dm b/code/game/objects/items/weapons/scrolls.dm index 70add3839ef..14f3b0ab91f 100644 --- a/code/game/objects/items/weapons/scrolls.dm +++ b/code/game/objects/items/weapons/scrolls.dm @@ -47,12 +47,12 @@ var/A - A = input(user, "Area to jump to", "BOOYEA", A) as null|anything in teleportlocs + A = input(user, "Area to jump to", "BOOYEA", A) as null|anything in GLOB.teleportlocs if(!A) return - var/area/thearea = teleportlocs[A] + var/area/thearea = GLOB.teleportlocs[A] if(user.stat || user.restrained()) return @@ -60,7 +60,7 @@ return if(thearea.tele_proof && !istype(thearea, /area/wizard_station)) - to_chat(user, "A mysterious force disrupts your arcane spell matrix, and you remain where you are.") + to_chat(user, "A mysterious force disrupts your arcane spell matrix, and you remain where you are.") return var/datum/effect_system/smoke_spread/smoke = new @@ -79,7 +79,7 @@ L+=T if(!L.len) - to_chat(user, "The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry.") + to_chat(user, "The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry.") return if(user && user.buckled) @@ -100,7 +100,8 @@ break if(!success) - user.loc = pick(L) + user.forceMove(pick(L)) smoke.start() src.uses -= 1 + user.update_action_buttons_icon() //Update action buttons as some spells might now be castable diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm index 362ab601685..19e56e161e3 100644 --- a/code/game/objects/items/weapons/shields.dm +++ b/code/game/objects/items/weapons/shields.dm @@ -76,7 +76,7 @@ return (active) /obj/item/shield/energy/attack_self(mob/living/carbon/human/user) - if(user.disabilities & CLUMSY && prob(50)) + if((CLUMSY in user.mutations) && prob(50)) to_chat(user, "You beat yourself in the head with [src].") user.take_organ_damage(5) active = !active diff --git a/code/game/objects/items/weapons/soap.dm b/code/game/objects/items/weapons/soap.dm index 62f65b5a6cc..cb220ff9565 100644 --- a/code/game/objects/items/weapons/soap.dm +++ b/code/game/objects/items/weapons/soap.dm @@ -11,15 +11,11 @@ throw_speed = 4 throw_range = 20 discrete = 1 - - trip_stun = 4 - trip_weaken = 2 - trip_chance = 100 - trip_walksafe = FALSE - trip_verb = TV_SLIP - var/cleanspeed = 50 //slower than mop +/obj/item/soap/ComponentInitialize() + AddComponent(/datum/component/slippery, src, 4, 2, 100, 0, FALSE) + /obj/item/soap/afterattack(atom/target, mob/user, proximity) if(!proximity) return //I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. diff --git a/code/game/objects/items/weapons/stock_parts.dm b/code/game/objects/items/weapons/stock_parts.dm index 1cc2b25edf0..0d5591bbc16 100644 --- a/code/game/objects/items/weapons/stock_parts.dm +++ b/code/game/objects/items/weapons/stock_parts.dm @@ -235,57 +235,6 @@ rating = 4 materials = list(MAT_METAL=80) -// Subspace stock parts - -/obj/item/stock_parts/subspace/ansible - name = "subspace ansible" - icon_state = "subspace_ansible" - desc = "A compact module capable of sensing extradimensional activity." - origin_tech = "programming=2;magnets=2;materials=2;bluespace=1" - materials = list(MAT_METAL=30, MAT_GLASS=10) - -/obj/item/stock_parts/subspace/filter - name = "hyperwave filter" - icon_state = "hyperwave_filter" - desc = "A tiny device capable of filtering and converting super-intense radiowaves." - origin_tech = "programming=2;magnets=2" - materials = list(MAT_METAL=30, MAT_GLASS=10) - -/obj/item/stock_parts/subspace/amplifier - name = "subspace amplifier" - icon_state = "subspace_amplifier" - desc = "A compact micro-machine capable of amplifying weak subspace transmissions." - origin_tech = "programming=2;magnets=2;materials=2;bluespace=2" - materials = list(MAT_METAL=30, MAT_GLASS=10) - -/obj/item/stock_parts/subspace/treatment - name = "subspace treatment disk" - icon_state = "treatment_disk" - desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves." - origin_tech = "programming=2;magnets=2;materials=2;bluespace=2" - materials = list(MAT_METAL=30, MAT_GLASS=10) - -/obj/item/stock_parts/subspace/analyzer - name = "subspace wavelength analyzer" - icon_state = "wavelength_analyzer" - desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths." - origin_tech = "programming=2;magnets=2;materials=2;bluespace=2" - materials = list(MAT_METAL=30, MAT_GLASS=10) - -/obj/item/stock_parts/subspace/crystal - name = "ansible crystal" - icon_state = "ansible_crystal" - desc = "A crystal made from pure glass used to transmit laser databursts to subspace." - origin_tech = "magnets=2;materials=2;bluespace=2;plasmatech=2" - materials = list(MAT_GLASS=50) - -/obj/item/stock_parts/subspace/transmitter - name = "subspace transmitter" - icon_state = "subspace_transmitter" - desc = "A large piece of equipment used to open a window into the subspace dimension." - origin_tech = "magnets=2;materials=2;bluespace=2" - materials = list(MAT_METAL=50) - /obj/item/research//Makes testing much less of a pain -Sieve name = "research" icon = 'icons/obj/stock_parts.dmi' diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm index 757d2b05757..26045731bd9 100644 --- a/code/game/objects/items/weapons/storage/backpack.dm +++ b/code/game/objects/items/weapons/storage/backpack.dm @@ -230,6 +230,11 @@ desc = "An NT Deluxe satchel, with the finest quality leather and the company logo in a thin gold stitch" icon_state = "nt_deluxe" +/obj/item/storage/backpack/satchel/lizard + name = "lizard skin handbag" + desc = "A handbag made out of what appears to be supple green Unathi skin. A face can be vaguely seen on the front." + icon_state = "satchel-lizard" + /obj/item/storage/backpack/satchel/withwallet/New() ..() new /obj/item/storage/wallet/random(src) diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 755b0076c3c..403088e2b71 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -134,7 +134,8 @@ /obj/item/rad_laser, /obj/item/sensor_device, /obj/item/wrench/medical, - /obj/item/handheld_defibrillator + /obj/item/handheld_defibrillator, + /obj/item/reagent_containers/applicator ) /obj/item/storage/belt/medical/surgery diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index dceab93330a..da0094bb2ef 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -1059,6 +1059,7 @@ name = "clown box" desc = "A colorful cardboard box for the clown" icon_state = "box_clown" + var/robot_arm // This exists for bot construction /obj/item/storage/box/emptysandbags name = "box of empty sandbags" @@ -1123,6 +1124,11 @@ playsound(loc, "rustle", 50, 1, -5) user.visible_message("[user] hugs \the [src].","You hug \the [src].") +/obj/item/storage/box/wizard + name = "magical box" + desc = "It's just an ordinary magical box." + icon_state = "box_wizard" + #undef NODESIGN #undef NANOTRASEN #undef SYNDI diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index bc1e90dac8e..4ff769a7d3f 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -14,7 +14,7 @@ icon_state = "firstaid" throw_speed = 2 throw_range = 8 - var/empty = 0 + var/empty = FALSE req_one_access =list(ACCESS_MEDICAL, ACCESS_ROBOTICS) //Access and treatment are utilized for medbots. var/treatment_brute = "salglu_solution" var/treatment_oxy = "salbutamol" @@ -23,6 +23,7 @@ var/treatment_virus = "spaceacillin" var/med_bot_skin = null var/syndicate_aligned = FALSE + var/robot_arm // This is for robot construction /obj/item/storage/firstaid/fire @@ -32,39 +33,51 @@ item_state = "firstaid-ointment" med_bot_skin = "ointment" - New() - ..() - if(empty) return - - icon_state = pick("ointment","firefirstaid") - - new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src ) - new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src ) - new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src ) - new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src ) - new /obj/item/healthanalyzer( src ) - new /obj/item/reagent_containers/hypospray/autoinjector( src ) - new /obj/item/reagent_containers/food/pill/salicylic( src ) +/obj/item/storage/firstaid/fire/New() + ..() + if(empty) return + icon_state = pick("ointment", "firefirstaid") + new /obj/item/reagent_containers/applicator/burn(src) + new /obj/item/reagent_containers/food/pill/patch/silver_sulf/small(src) + new /obj/item/healthanalyzer(src) + new /obj/item/reagent_containers/hypospray/autoinjector(src) + new /obj/item/reagent_containers/food/pill/salicylic(src) /obj/item/storage/firstaid/fire/empty - empty = 1 + empty = TRUE /obj/item/storage/firstaid/regular desc = "A general medical kit that contains medical patches for both brute damage and burn damage. Also contains an epinephrine syringe for emergency use and a health analyzer" icon_state = "firstaid" - New() - ..() - if(empty) return - new /obj/item/reagent_containers/food/pill/patch/styptic( src ) - new /obj/item/reagent_containers/food/pill/patch/styptic( src ) - new /obj/item/reagent_containers/food/pill/salicylic( src ) - new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src ) - new /obj/item/reagent_containers/food/pill/patch/silver_sulf( src ) - new /obj/item/healthanalyzer( src ) - new /obj/item/reagent_containers/hypospray/autoinjector( src ) +/obj/item/storage/firstaid/regular/New() + ..() + if(empty) return + new /obj/item/reagent_containers/food/pill/patch/styptic(src) + new /obj/item/reagent_containers/food/pill/patch/styptic(src) + new /obj/item/reagent_containers/food/pill/salicylic(src) + new /obj/item/reagent_containers/food/pill/patch/silver_sulf(src) + new /obj/item/reagent_containers/food/pill/patch/silver_sulf(src) + new /obj/item/healthanalyzer(src) + new /obj/item/reagent_containers/hypospray/autoinjector(src) + +/obj/item/storage/firstaid/doctor + desc = "A general medical kit that contains medical patches for both brute damage and burn damage. Also contains an epinephrine syringe for emergency use and a health analyzer" + icon_state = "firstaid" + +/obj/item/storage/firstaid/doctor/New() + ..() + if(empty) + return + new /obj/item/reagent_containers/applicator/brute(src) + new /obj/item/reagent_containers/applicator/burn(src) + new /obj/item/reagent_containers/food/pill/patch/styptic(src) + new /obj/item/reagent_containers/food/pill/patch/silver_sulf(src) + new /obj/item/reagent_containers/food/pill/salicylic(src) + new /obj/item/healthanalyzer/advanced(src) + new /obj/item/reagent_containers/hypospray/autoinjector(src) /obj/item/storage/firstaid/toxin name = "toxin first aid kit" @@ -73,23 +86,21 @@ item_state = "firstaid-toxin" med_bot_skin = "tox" - New() - ..() - if(empty) return - - icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3") - - new /obj/item/reagent_containers/syringe/charcoal( src ) - new /obj/item/reagent_containers/syringe/charcoal( src ) - new /obj/item/reagent_containers/syringe/charcoal( src ) - new /obj/item/reagent_containers/food/pill/charcoal( src ) - new /obj/item/reagent_containers/food/pill/charcoal( src ) - new /obj/item/reagent_containers/food/pill/charcoal( src ) - new /obj/item/healthanalyzer( src ) +/obj/item/storage/firstaid/toxin/New() + ..() + if(empty) return + icon_state = pick("antitoxin", "antitoxfirstaid", "antitoxfirstaid2", "antitoxfirstaid3") + new /obj/item/reagent_containers/syringe/charcoal(src) + new /obj/item/reagent_containers/syringe/charcoal(src) + new /obj/item/reagent_containers/syringe/charcoal(src) + new /obj/item/reagent_containers/food/pill/charcoal(src) + new /obj/item/reagent_containers/food/pill/charcoal(src) + new /obj/item/reagent_containers/food/pill/charcoal(src) + new /obj/item/healthanalyzer(src) /obj/item/storage/firstaid/toxin/empty - empty = 1 + empty = TRUE /obj/item/storage/firstaid/o2 name = "oxygen deprivation first aid kit" @@ -98,18 +109,18 @@ item_state = "firstaid-o2" med_bot_skin = "o2" - New() - ..() - if(empty) return - new /obj/item/reagent_containers/food/pill/salbutamol( src ) - new /obj/item/reagent_containers/food/pill/salbutamol( src ) - new /obj/item/reagent_containers/food/pill/salbutamol( src ) - new /obj/item/reagent_containers/food/pill/salbutamol( src ) - new /obj/item/healthanalyzer( src ) +/obj/item/storage/firstaid/o2/New() + ..() + if(empty) return + new /obj/item/reagent_containers/food/pill/salbutamol(src) + new /obj/item/reagent_containers/food/pill/salbutamol(src) + new /obj/item/reagent_containers/food/pill/salbutamol(src) + new /obj/item/reagent_containers/food/pill/salbutamol(src) + new /obj/item/healthanalyzer(src) /obj/item/storage/firstaid/o2/empty - empty = 1 + empty = TRUE /obj/item/storage/firstaid/brute name = "brute trauma treatment kit" @@ -118,23 +129,19 @@ item_state = "firstaid-brute" med_bot_skin = "brute" - New() - ..() - if(empty) return - - icon_state = pick("brute","brute2") - - new /obj/item/reagent_containers/food/pill/patch/styptic(src) - new /obj/item/reagent_containers/food/pill/patch/styptic(src) - new /obj/item/reagent_containers/food/pill/patch/styptic(src) - new /obj/item/reagent_containers/food/pill/patch/styptic(src) - new /obj/item/healthanalyzer(src) - new /obj/item/reagent_containers/hypospray/autoinjector(src) - new /obj/item/stack/medical/bruise_pack(src) +/obj/item/storage/firstaid/brute/New() + ..() + if(empty) return + icon_state = pick("brute", "brute2") + new /obj/item/reagent_containers/applicator/brute(src) + new /obj/item/reagent_containers/food/pill/patch/styptic/small(src) + new /obj/item/healthanalyzer(src) + new /obj/item/reagent_containers/hypospray/autoinjector(src) + new /obj/item/stack/medical/bruise_pack(src) /obj/item/storage/firstaid/brute/empty - empty = 1 + empty = TRUE /obj/item/storage/firstaid/adv name = "advanced first-aid kit" @@ -156,7 +163,7 @@ new /obj/item/healthanalyzer(src) /obj/item/storage/firstaid/adv/empty - empty = 1 + empty = TRUE /obj/item/storage/firstaid/machine name = "machine repair kit" @@ -177,7 +184,7 @@ new /obj/item/robotanalyzer(src) /obj/item/storage/firstaid/machine/empty - empty = 1 + empty = TRUE /obj/item/storage/firstaid/tactical @@ -195,18 +202,15 @@ /obj/item/storage/firstaid/tactical/New() ..() - if(empty) return + if(empty) + return new /obj/item/reagent_containers/hypospray/combat(src) - new /obj/item/reagent_containers/food/pill/patch/synthflesh(src) // Because you ain't got no time to look at what damage dey taking yo - new /obj/item/reagent_containers/food/pill/patch/synthflesh(src) - new /obj/item/reagent_containers/food/pill/patch/synthflesh(src) - new /obj/item/reagent_containers/food/pill/patch/synthflesh(src) + new /obj/item/reagent_containers/applicator/dual(src) // Because you ain't got no time to look at what damage dey taking yo new /obj/item/defibrillator/compact/combat/loaded(src) new /obj/item/clothing/glasses/hud/health/night(src) - return /obj/item/storage/firstaid/tactical/empty - empty =1 + empty = TRUE /obj/item/storage/firstaid/surgery name = "field surgery kit" @@ -346,15 +350,15 @@ desc = "Contains pills used to counter toxins." wrapper_color = COLOR_GREEN - New() - ..() - new /obj/item/reagent_containers/food/pill/charcoal( src ) - new /obj/item/reagent_containers/food/pill/charcoal( src ) - new /obj/item/reagent_containers/food/pill/charcoal( src ) - new /obj/item/reagent_containers/food/pill/charcoal( src ) - new /obj/item/reagent_containers/food/pill/charcoal( src ) - new /obj/item/reagent_containers/food/pill/charcoal( src ) - new /obj/item/reagent_containers/food/pill/charcoal( src ) +/obj/item/storage/pill_bottle/charcoal/New() + ..() + new /obj/item/reagent_containers/food/pill/charcoal(src) + new /obj/item/reagent_containers/food/pill/charcoal(src) + new /obj/item/reagent_containers/food/pill/charcoal(src) + new /obj/item/reagent_containers/food/pill/charcoal(src) + new /obj/item/reagent_containers/food/pill/charcoal(src) + new /obj/item/reagent_containers/food/pill/charcoal(src) + new /obj/item/reagent_containers/food/pill/charcoal(src) /obj/item/storage/pill_bottle/painkillers name = "Pill Bottle (Salicylic Acid)" diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm index d38c3c97dac..357cb043ca4 100644 --- a/code/game/objects/items/weapons/storage/secure.dm +++ b/code/game/objects/items/weapons/storage/secure.dm @@ -98,6 +98,7 @@ add_fingerprint(usr) to_chat(usr, "It's locked!") return FALSE + return TRUE /obj/item/storage/secure/attack_self(mob/user as mob) user.set_machine(src) diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index d79a121e685..55b25ad725a 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -83,11 +83,14 @@ return /obj/item/storage/AltClick(mob/user) - if(Adjacent(user) && !user.incapacitated(FALSE, TRUE, TRUE)) + if(ishuman(user) && Adjacent(user) && !user.incapacitated(FALSE, TRUE, TRUE)) orient2hud(user) if(user.s_active) user.s_active.close(user) show_to(user) + playsound(loc, "rustle", 50, 1, -5) + add_fingerprint(user) + return ..() /obj/item/storage/proc/return_inv() @@ -479,10 +482,10 @@ return ..() /obj/item/storage/emp_act(severity) - if(!istype(loc, /mob/living)) - for(var/obj/O in contents) - O.emp_act(severity) ..() + for(var/i in contents) + var/atom/A = i + A.emp_act(severity) /obj/item/storage/hear_talk(mob/living/M as mob, list/message_pieces) ..() diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index a0dd6aa485d..9ded7947202 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -156,7 +156,7 @@ // auto update every Master Controller tick ui.set_auto_update(1) -/obj/item/tank/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/item/tank/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/using_internal if(iscarbon(loc)) var/mob/living/carbon/C = loc diff --git a/code/game/objects/items/weapons/tanks/watertank.dm b/code/game/objects/items/weapons/tanks/watertank.dm index 2375c42db65..55dc189fc9b 100644 --- a/code/game/objects/items/weapons/tanks/watertank.dm +++ b/code/game/objects/items/weapons/tanks/watertank.dm @@ -119,7 +119,7 @@ amount_per_transfer_from_this = 50 possible_transfer_amounts = list(25,50,100) volume = 500 - flags = NODROP | NOBLUDGEON + flags = NOBLUDGEON container_type = OPENCONTAINER var/obj/item/watertank/tank diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm index 57c9a5301f6..ed857c18ded 100644 --- a/code/game/objects/items/weapons/twohanded.dm +++ b/code/game/objects/items/weapons/twohanded.dm @@ -179,6 +179,7 @@ slot_flags = SLOT_BACK force_unwielded = 5 force_wielded = 24 + toolspeed = 0.25 attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") hitsound = 'sound/weapons/bladeslice.ogg' usesound = 'sound/items/crowbar.ogg' @@ -542,6 +543,7 @@ w_class = WEIGHT_CLASS_BULKY // can't fit in backpacks force_unwielded = 15 //still pretty robust force_wielded = 40 //you'll gouge their eye out! Or a limb...maybe even their entire body! + hitsound = null // Handled in the snowflaked attack proc wieldsound = 'sound/weapons/chainsawstart.ogg' hitsound = null armour_penetration = 35 diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 6ef379ffcad..32158a9a3ab 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -205,7 +205,7 @@ else if(prob(30)) visible_message("[owner] swings! And [p_they()] miss[p_es()]! How embarassing.", "You swing! You miss! Oh no!") playsound(get_turf(owner), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - do_attack_animation(get_step(owner, pick(alldirs)), ATTACK_EFFECT_DISARM) + do_attack_animation(get_step(owner, pick(GLOB.alldirs)), ATTACK_EFFECT_DISARM) deflectmode = FALSE if(!istype(I, /obj/item/beach_ball)) lastdeflect = world.time + 3000 @@ -214,7 +214,7 @@ visible_message("[owner] swings and deflects [I]!", "You swing and deflect the [I]!") playsound(get_turf(owner), 'sound/weapons/baseball_hit.ogg', 50, 1, -1) do_attack_animation(I, ATTACK_EFFECT_DISARM) - I.throw_at(get_edge_target_turf(owner, pick(cardinal)), rand(8,10), 14, owner) + I.throw_at(get_edge_target_turf(owner, pick(GLOB.cardinal)), rand(8,10), 14, owner) deflectmode = FALSE if(!istype(I, /obj/item/beach_ball)) lastdeflect = world.time + 3000 diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 1816357d450..e1464e47e48 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -205,7 +205,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE) && !(resistance_flags & FIRE_PROOF)) resistance_flags |= ON_FIRE SSfires.processing[src] = src - add_overlay(fire_overlay, TRUE) + add_overlay(GLOB.fire_overlay, TRUE) return 1 ///called when the obj is destroyed by fire @@ -218,7 +218,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e /obj/proc/extinguish() if(resistance_flags & ON_FIRE) resistance_flags &= ~ON_FIRE - cut_overlay(fire_overlay, TRUE) + cut_overlay(GLOB.fire_overlay, TRUE) SSfires.processing -= src ///Called when the obj is hit by a tesla bolt. diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index e30c8c5c4c2..951eb79f853 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -44,7 +44,7 @@ else T.add_blueprints_preround(src) -/obj/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = default_state) +/obj/Topic(href, href_list, var/nowindow = 0, var/datum/topic_state/state = GLOB.default_state) // Calling Topic without a corresponding window open causes runtime errors if(!nowindow && ..()) return 1 @@ -192,13 +192,13 @@ /obj/proc/multitool_menu(var/mob/user,var/obj/item/multitool/P) return "NO MULTITOOL_MENU!" -/obj/proc/linkWith(var/mob/user, var/obj/buffer, var/link/context) +/obj/proc/linkWith(var/mob/user, var/obj/buffer, var/context) return 0 /obj/proc/unlinkFrom(var/mob/user, var/obj/buffer) return 0 -/obj/proc/canLink(var/obj/O, var/link/context) +/obj/proc/canLink(var/obj/O, var/context) return 0 /obj/proc/isLinkedWith(var/obj/O) @@ -251,9 +251,7 @@ a { if(P) if(P.buffer) var/id = null - if(istype(P.buffer, /obj/machinery/telecomms)) - id=P.buffer:id - else if("id_tag" in P.buffer.vars) + if("id_tag" in P.buffer.vars) id=P.buffer:id_tag dat += "

    MULTITOOL BUFFER: [P.buffer] [id ? "([id])" : ""]" diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 3d727142db5..663f210df3e 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -18,11 +18,11 @@ if(climbable) verbs += /obj/structure/proc/climb_on if(SSticker) - cameranet.updateVisibility(src) + GLOB.cameranet.updateVisibility(src) /obj/structure/Destroy() if(SSticker) - cameranet.updateVisibility(src) + GLOB.cameranet.updateVisibility(src) if(smooth) var/turf/T = get_turf(src) spawn(0) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/depot.dm b/code/game/objects/structures/crates_lockers/closets/secure/depot.dm index bba8dc2a866..5ffbdd0cda7 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/depot.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/depot.dm @@ -36,7 +36,7 @@ depotarea.armory_locker_looted() /obj/structure/closet/secure_closet/syndicate/depot/attack_animal(mob/M) - if(isanimal(M) && "syndicate" in M.faction) + if(isanimal(M) && ("syndicate" in M.faction)) to_chat(M, "The [src] resists your attack!") return return ..() diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 7616aa90877..f0a7336389b 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -16,7 +16,7 @@ new /obj/item/storage/backpack/satchel_eng(src) new /obj/item/storage/backpack/duffel/engineering(src) new /obj/item/clothing/head/beret/ce(src) - new /obj/item/areaeditor/blueprints(src) + new /obj/item/areaeditor/blueprints/ce(src) new /obj/item/storage/box/permits(src) new /obj/item/clothing/under/rank/chief_engineer(src) new /obj/item/clothing/under/rank/chief_engineer/skirt(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm index 096133b6e0d..7eab5858772 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/personal.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/personal.dm @@ -54,36 +54,33 @@ new /obj/item/storage/backpack/satchel/withwallet( src ) new /obj/item/radio/headset( src ) -/obj/structure/closet/secure_closet/personal/attackby(obj/item/W as obj, mob/user as mob, params) - if(src.opened) - if(istype(W, /obj/item/grab)) - src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet - user.drop_item() - if(W) W.forceMove(loc) - else if(istype(W, /obj/item/card/id)) - if(src.broken) - to_chat(user, "It appears to be broken.") - return - var/obj/item/card/id/I = W - if(!I || !I.registered_name) return - if(src == user.loc) - to_chat(user, "You can't reach the lock from inside.") - else if(src.allowed(user) || !src.registered_name || (istype(I) && (src.registered_name == I.registered_name))) - //they can open all lockers, or nobody owns this, or they own this locker - src.locked = !( src.locked ) - if(src.locked) - src.icon_state = src.icon_locked - else - src.icon_state = src.icon_closed - registered_name = null - desc = initial(desc) - - if(!src.registered_name && src.locked) - src.registered_name = I.registered_name - src.desc = "Owned by [I.registered_name]." - else - to_chat(user, "Access Denied") - else if((istype(W, /obj/item/card/emag) || istype(W, /obj/item/melee/energy/blade)) && !broken) - emag_act(user) - else +/obj/structure/closet/secure_closet/personal/attackby(obj/item/W, mob/user, params) + if(opened || !istype(W, /obj/item/card/id)) return ..() + + if(broken) + to_chat(user, "It appears to be broken.") + return + + var/obj/item/card/id/I = W + if(!I || !I.registered_name) + return + + if(src == user.loc) + to_chat(user, "You can't reach the lock from inside.") + + else if(allowed(user) || !registered_name || (istype(I) && (registered_name == I.registered_name))) + //they can open all lockers, or nobody owns this, or they own this locker + locked = !locked + if(locked) + icon_state = icon_locked + else + icon_state = icon_closed + registered_name = null + desc = initial(desc) + + if(!registered_name && locked) + registered_name = I.registered_name + desc = "Owned by [I.registered_name]." + else + to_chat(user, "Access Denied") diff --git a/code/game/objects/structures/crates_lockers/closets/statue.dm b/code/game/objects/structures/crates_lockers/closets/statue.dm index 501abd4922d..e285c6a0ae9 100644 --- a/code/game/objects/structures/crates_lockers/closets/statue.dm +++ b/code/game/objects/structures/crates_lockers/closets/statue.dm @@ -19,7 +19,7 @@ L.buckled = 0 L.anchored = 0 L.forceMove(src) - L.disabilities += MUTE + L.mutations |= MUTE max_integrity = L.health + 100 //stoning damaged mobs will result in easier to shatter statues intialTox = L.getToxLoss() intialFire = L.getFireLoss() @@ -69,7 +69,7 @@ for(var/mob/living/M in src) M.forceMove(loc) - M.disabilities -= MUTE + M.mutations -= MUTE M.take_overall_damage((M.health - obj_integrity - 100),0) //any new damage the statue incurred is transfered to the mob ..() diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 45aaf76fb07..f9010c19415 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -212,7 +212,7 @@ /obj/structure/closet/crate/proc/notifyRecipient(var/destination) var/msg = "[capitalize(name)] has arrived at [destination]." if(destination in announce_beacons) - for(var/obj/machinery/requests_console/D in allConsoles) + for(var/obj/machinery/requests_console/D in GLOB.allRequestConsoles) if(D.department in src.announce_beacons[destination]) D.createMessage(name, "Your Crate has Arrived!", msg, 1) diff --git a/code/game/objects/structures/decor/machinery/telecomms.dm b/code/game/objects/structures/decor/machinery/telecomms.dm deleted file mode 100644 index 1068cfb0b4e..00000000000 --- a/code/game/objects/structures/decor/machinery/telecomms.dm +++ /dev/null @@ -1,23 +0,0 @@ -/obj/structure/decor/machinery/telecomms/processor - name = "Processor Unit" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "processor" - desc = "This machine is used to process large quantities of information." - -/obj/structure/decor/machinery/telecomms/hub - name = "Telecommunication Hub" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "hub" - desc = "A mighty piece of hardware used to send/receive massive amounts of data." - -/obj/structure/decor/machinery/telecomms/server - name = "Telecommunication Server" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "comm_server" - desc = "A machine used to store data and network statistics." - -/obj/structure/decor/machinery/telecomms/relay - name = "Telecommunication Relay" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "relay" - desc = "A mighty piece of hardware used to send massive amounts of data far away." diff --git a/code/game/objects/structures/depot.dm b/code/game/objects/structures/depot.dm index e970ac911dc..11eb03c94c5 100644 --- a/code/game/objects/structures/depot.dm +++ b/code/game/objects/structures/depot.dm @@ -79,7 +79,6 @@ var/beepsound = 'sound/items/timer.ogg' var/deliberate = FALSE var/max_cycles = 10 - var/max_fire_range = 9 var/area/syndicate_depot/core/depotarea /obj/effect/overload/New() @@ -101,10 +100,6 @@ if(!deliberate) playsound(loc, beepsound, 50, 0) cycles++ - var/fire_range = min(cycles, max_fire_range) - - for(var/turf/simulated/turf in range(fire_range, T)) - new /obj/effect/hotspot(turf) return if(!istype(depotarea)) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index 7626abb9a7d..cdc5cdb58c4 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -245,6 +245,7 @@ /obj/structure/falsewall/plasma/attackby(obj/item/W, mob/user, params) if(is_hot(W) > 300) + var/turf/T = locate(user) message_admins("Plasma falsewall ignited by [key_name_admin(user)] in [ADMIN_VERBOSEJMP(T)]") log_game("Plasma falsewall ignited by [key_name(user)] in [AREACOORD(T)]") investigate_log("was ignited by [key_name(user)]","atmos") diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 592e67e466d..c657e0056e8 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -131,17 +131,19 @@ AC.ui_interact(user) if("Voice") - var/voice_choice = input(user, "Perhaps...", "Voice effects") as null|anything in list("Comic Sans", "Wingdings", "Swedish", "Chav") + var/voice_choice = input(user, "Perhaps...", "Voice effects") as null|anything in list("Comic Sans", "Wingdings", "Swedish", "Chav", "Mute") var/voice_mutation switch(voice_choice) if("Comic Sans") - voice_mutation = COMICBLOCK + voice_mutation = GLOB.comicblock if("Wingdings") - voice_mutation = WINGDINGSBLOCK + voice_mutation = GLOB.wingdingsblock if("Swedish") - voice_mutation = SWEDEBLOCK + voice_mutation = GLOB.swedeblock if("Chav") - voice_mutation = CHAVBLOCK + voice_mutation = GLOB.chavblock + if("Mute") + voice_mutation = GLOB.muteblock if(voice_mutation) if(H.dna.GetSEState(voice_mutation)) H.dna.SetSEState(voice_mutation, FALSE) diff --git a/code/game/objects/structures/misc.dm b/code/game/objects/structures/misc.dm index 1497344d5c8..44cbf6c52c9 100644 --- a/code/game/objects/structures/misc.dm +++ b/code/game/objects/structures/misc.dm @@ -33,7 +33,7 @@ if(user.z != src.z) return user.loc.loc.Exited(user) - user.loc = pick(carplist) // In the future, possibly make specific NinjaTele landmarks, and give him an option to teleport to North/South/East/West of SS13 instead of just hijacking a carpspawn. + user.loc = pick(GLOB.carplist) // In the future, possibly make specific NinjaTele landmarks, and give him an option to teleport to North/South/East/West of SS13 instead of just hijacking a carpspawn. playsound(user.loc, 'sound/effects/phasein.ogg', 25, 1) diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index 7458c0a4b3b..c3d63c47862 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -121,7 +121,7 @@ ui.open() ui.set_auto_update(1) -/datum/song/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/datum/song/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["lines"] = lines @@ -309,7 +309,7 @@ song.ui_interact(user, ui_key, ui, force_open) -/obj/structure/piano/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/structure/piano/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) return song.ui_data(user, ui_key, state) /obj/structure/piano/Topic(href, href_list) diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index f891aff5592..1102901c8bd 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -25,7 +25,7 @@ GLOBAL_LIST_EMPTY(safes) var/number_of_tumblers = 3 // The amount of tumblers that will be generated. var/list/tumblers = list() // The list of tumbler dial positions that need to be hit. - var/list/current_tumbler_index = 1 // The index in the tumblers list of the tumbler dial position that needs to be hit. + var/current_tumbler_index = 1 // The index in the tumblers list of the tumbler dial position that needs to be hit. var/space = 0 // The combined w_class of everything in the safe. var/maxspace = 24 // The maximum combined w_class of stuff in the safe. @@ -185,7 +185,7 @@ GLOBAL_LIST_EMPTY(safes) ui.open() ui.set_auto_update(1) -/obj/structure/safe/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/structure/safe/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/list/contents_names = list() if(open) diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm index 3f5d667a356..ba5258004a0 100644 --- a/code/game/objects/structures/signs.dm +++ b/code/game/objects/structures/signs.dm @@ -169,7 +169,7 @@ /obj/structure/sign/kiddieplaque name = "AI developers plaque" - desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. The child appears to be retarded. Beneath the image, someone has scratched the word \"PACKETS\"." + desc = "Next to the extremely long list of names and job titles, there is a drawing of a little child. The child's eyes are crossed, and is drooling. Beneath the image, someone has scratched the word \"PACKETS\"." icon_state = "kiddieplaque" /obj/structure/sign/atmosplaque diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm index c4c36d788e2..692d15d79ec 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -1,3 +1,5 @@ +#define MAX_TANK_STORAGE 10 + /obj/structure/dispenser name = "tank storage unit" desc = "A simple yet bulky storage device for gas tanks. Has room for up to ten oxygen tanks, and ten plasma tanks." @@ -5,29 +7,51 @@ icon_state = "dispenser" density = 1 anchored = 1.0 - var/oxygentanks = 10 - var/plasmatanks = 10 - var/list/oxytanks = list() //sorry for the similar var names - var/list/platanks = list() + var/starting_oxygen_tanks = MAX_TANK_STORAGE // The starting amount of oxygen tanks the dispenser gets when it's spawned + var/starting_plasma_tanks = MAX_TANK_STORAGE // Starting amount of plasma tanks + var/list/stored_oxygen_tanks = list() // List of currently stored oxygen tanks + var/list/stored_plasma_tanks = list() // And plasma tanks /obj/structure/dispenser/oxygen - plasmatanks = 0 + starting_plasma_tanks = 0 /obj/structure/dispenser/plasma - oxygentanks = 0 + starting_oxygen_tanks = 0 /obj/structure/dispenser/New() ..() + initialize_tanks() update_icon() +/obj/structure/dispenser/Destroy() + QDEL_LIST(stored_plasma_tanks) + QDEL_LIST(stored_oxygen_tanks) + return ..() + +/obj/structure/dispenser/proc/initialize_tanks() + for(var/I in 1 to starting_plasma_tanks) + var/obj/item/tank/plasma/P = new(src) + stored_plasma_tanks.Add(P) + + for(var/I in 1 to starting_oxygen_tanks) + var/obj/item/tank/oxygen/O = new(src) + stored_oxygen_tanks.Add(O) + /obj/structure/dispenser/update_icon() - overlays.Cut() - switch(oxygentanks) - if(1 to 3) overlays += "oxygen-[oxygentanks]" - if(4 to INFINITY) overlays += "oxygen-4" - switch(plasmatanks) - if(1 to 4) overlays += "plasma-[plasmatanks]" - if(5 to INFINITY) overlays += "plasma-5" + cut_overlays() + var/oxy_tank_amount = LAZYLEN(stored_oxygen_tanks) + switch(oxy_tank_amount) + if(1 to 3) + overlays += "oxygen-[oxy_tank_amount]" + if(4 to INFINITY) + overlays += "oxygen-4" + + var/pla_tank_amount = LAZYLEN(stored_plasma_tanks) + switch(pla_tank_amount) + if(1 to 4) + overlays += "plasma-[pla_tank_amount]" + if(5 to INFINITY) + overlays += "plasma-5" /obj/structure/dispenser/attack_hand(mob/user) if(..()) @@ -38,7 +62,7 @@ /obj/structure/dispenser/attack_ghost(mob/user) ui_interact(user) -/obj/structure/dispenser/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/obj/structure/dispenser/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, master_ui = null, datum/topic_state/state = GLOB.default_state) user.set_machine(src) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) @@ -47,35 +71,19 @@ /obj/structure/dispenser/ui_data(user) var/list/data = list() - data["o_tanks"] = oxygentanks - data["p_tanks"] = plasmatanks + data["o_tanks"] = LAZYLEN(stored_oxygen_tanks) + data["p_tanks"] = LAZYLEN(stored_plasma_tanks) return data /obj/structure/dispenser/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/tank/oxygen) || istype(I, /obj/item/tank/air) || istype(I, /obj/item/tank/anesthetic)) - if(oxygentanks < 10) - user.drop_item() - I.forceMove(src) - oxytanks.Add(I) - oxygentanks++ - update_icon() - to_chat(user, "You put [I] in [src].") - else - to_chat(user, "[src] is full.") - SSnanoui.update_uis(src) + try_insert_tank(user, stored_oxygen_tanks, I) return + if(istype(I, /obj/item/tank/plasma)) - if(plasmatanks < 10) - user.drop_item() - I.forceMove(src) - platanks.Add(I) - plasmatanks++ - update_icon() - to_chat(user, "You put [I] in [src].") - else - to_chat(user, "[src] is full.") - SSnanoui.update_uis(src) + try_insert_tank(user, stored_plasma_tanks, I) return + if(istype(I, /obj/item/wrench)) if(anchored) to_chat(user, "You lean down and unwrench [src].") @@ -88,40 +96,55 @@ /obj/structure/dispenser/Topic(href, href_list) if(..()) - return 1 + return TRUE if(Adjacent(usr)) usr.set_machine(src) + + // The oxygen tank button if(href_list["oxygen"]) - if(oxygentanks > 0) - var/obj/item/tank/oxygen/O - if(oxytanks.len == oxygentanks) - O = oxytanks[1] - oxytanks.Remove(O) - else - O = new /obj/item/tank/oxygen(loc) - O.loc = loc - to_chat(usr, "You take [O] out of [src].") - oxygentanks-- - update_icon() + try_remove_tank(usr, stored_oxygen_tanks) + + // The plasma tank button if(href_list["plasma"]) - if(plasmatanks > 0) - var/obj/item/tank/plasma/P - if(platanks.len == plasmatanks) - P = platanks[1] - platanks.Remove(P) - else - P = new /obj/item/tank/plasma(loc) - P.loc = loc - to_chat(usr, "You take [P] out of [src].") - plasmatanks-- - update_icon() + try_remove_tank(usr, stored_plasma_tanks) + add_fingerprint(usr) updateUsrDialog() - SSnanoui.update_uis(src) + SSnanoui.try_update_ui(usr, src) else SSnanoui.close_user_uis(usr,src) - return 1 + return TRUE + +/// Called when the user clicks on the oxygen or plasma tank UI buttons, and tries to withdraw a tank. +/obj/structure/dispenser/proc/try_remove_tank(mob/living/user, list/tank_list) + if(!LAZYLEN(tank_list)) + return // There are no tanks left to withdraw. + + var/obj/item/tank/T = tank_list[1] + tank_list.Remove(T) + + if(!user.put_in_hands(T)) + T.forceMove(loc) // If the user's hands are full, place it on the tile of the dispenser. + + to_chat(user, "You take [T] out of [src].") + update_icon() + +/// Called when the user clicks on the dispenser with a tank. Tries to insert the tank into the dispenser, and updates the UI if successful. +/obj/structure/dispenser/proc/try_insert_tank(mob/living/user, list/tank_list, obj/item/tank/T) + if(LAZYLEN(tank_list) >= MAX_TANK_STORAGE) + to_chat(user, "[src] is full.") + return + + if(!user.drop_item()) // Antidrop check + to_chat(user, "[T] is stuck to your hand!") + return + + T.forceMove(src) + tank_list.Add(T) + update_icon() + to_chat(user, "You put [T] in [src].") + SSnanoui.try_update_ui(user, src) /obj/structure/tank_dispenser/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) @@ -130,3 +153,5 @@ I.forceMove(loc) new /obj/item/stack/sheet/metal(loc, 2) qdel(src) + +#undef MAX_TANK_STORAGE diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm index f8f406d1381..9d06f870fc3 100644 --- a/code/game/objects/structures/transit_tubes/station.dm +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -38,7 +38,7 @@ if(pod.contents.len) to_chat(AM, "") return - else if(!pod.moving && pod.dir in directions()) + else if(!pod.moving && (pod.dir in directions())) AM.forceMove(pod) return @@ -47,7 +47,7 @@ /obj/structure/transit_tube/station/attack_hand(mob/user as mob) if(!pod_moving) for(var/obj/structure/transit_tube_pod/pod in loc) - if(!pod.moving && pod.dir in directions()) + if(!pod.moving && (pod.dir in directions())) if(icon_state == "closed") open_animation() @@ -100,7 +100,7 @@ /obj/structure/transit_tube/station/proc/launch_pod() for(var/obj/structure/transit_tube_pod/pod in loc) - if(!pod.moving && pod.dir in directions()) + if(!pod.moving && (pod.dir in directions())) spawn(5) pod_moving = 1 close_animation() diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index 7095fd4eeda..8984dc60a52 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -144,9 +144,7 @@ if(istype(mob, /mob) && mob.client) // If the pod is not in a tube at all, you can get out at any time. if(!(locate(/obj/structure/transit_tube) in loc)) - mob.loc = loc - mob.client.Move(get_step(loc, direction), direction) - mob.reset_perspective(null) + mob.forceMove(loc) //if(moving && istype(loc, /turf/space)) // Todo: If you get out of a moving pod in space, you should move as well. @@ -158,9 +156,7 @@ if(!station.pod_moving) if(direction == station.dir) if(station.icon_state == "open") - mob.loc = loc - mob.client.Move(get_step(loc, direction), direction) - mob.reset_perspective(null) + mob.forceMove(loc) else station.open_animation() diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 32c9daf3c76..87107f97abe 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -411,7 +411,7 @@ M.l_hand.clean_blood() if(M.back) if(M.back.clean_blood()) - M.update_inv_back(0) + M.update_inv_back() if(ishuman(M)) var/mob/living/carbon/human/H = M var/washgloves = 1 @@ -437,38 +437,38 @@ if(H.head) if(H.head.clean_blood()) - H.update_inv_head(0,0) + H.update_inv_head() if(H.wear_suit) if(H.wear_suit.clean_blood()) - H.update_inv_wear_suit(0,0) + H.update_inv_wear_suit() else if(H.w_uniform) if(H.w_uniform.clean_blood()) - H.update_inv_w_uniform(0,0) + H.update_inv_w_uniform() if(H.gloves && washgloves) if(H.gloves.clean_blood()) - H.update_inv_gloves(0,0) + H.update_inv_gloves() if(H.shoes && washshoes) if(H.shoes.clean_blood()) - H.update_inv_shoes(0,0) + H.update_inv_shoes() if(H.wear_mask && washmask) if(H.wear_mask.clean_blood()) - H.update_inv_wear_mask(0) + H.update_inv_wear_mask() if(H.glasses && washglasses) if(H.glasses.clean_blood()) - H.update_inv_glasses(0) + H.update_inv_glasses() if(H.l_ear && washears) if(H.l_ear.clean_blood()) - H.update_inv_ears(0) + H.update_inv_ears() if(H.r_ear && washears) if(H.r_ear.clean_blood()) - H.update_inv_ears(0) + H.update_inv_ears() if(H.belt) if(H.belt.clean_blood()) - H.update_inv_belt(0) + H.update_inv_belt() else if(M.wear_mask) //if the mob is not human, it cleans the mask without asking for bitflags if(M.wear_mask.clean_blood()) - M.update_inv_wear_mask(0) + M.update_inv_wear_mask() else O.clean_blood() @@ -704,7 +704,7 @@ return if(proximity_flag != 1) //if we aren't next to the wall return - if(!(get_dir(on_wall, user) in cardinal)) + if(!(get_dir(on_wall, user) in GLOB.cardinal)) to_chat(user, "You need to be standing next to a wall to place \the [src].") return return 1 diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 01136ea1046..9faab45cf97 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -1,6 +1,6 @@ -var/global/wcBar = pick(list("#0d8395", "#58b5c3", "#58c366", "#90d79a", "#ffffff")) -var/global/wcBrig = pick(list("#aa0808", "#7f0606", "#ff0000")) -var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8fcf44", "#ffffff")) +GLOBAL_LIST_INIT(wcBar, pick(list("#0d8395", "#58b5c3", "#58c366", "#90d79a", "#ffffff"))) +GLOBAL_LIST_INIT(wcBrig, pick(list("#aa0808", "#7f0606", "#ff0000"))) +GLOBAL_LIST_INIT(wcCommon, pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8fcf44", "#ffffff"))) /obj/proc/color_windows(obj/W) var/list/wcBarAreas = list(/area/crew_quarters/bar) @@ -13,11 +13,11 @@ var/global/wcCommon = pick(list("#379963", "#0d8395", "#58b5c3", "#49e46e", "#8f var/area/A = T.loc if(is_type_in_list(A,wcBarAreas)) - newcolor = wcBar + newcolor = GLOB.wcBar else if(is_type_in_list(A,wcBrigAreas)) - newcolor = wcBrig + newcolor = GLOB.wcBrig else - newcolor = wcCommon + newcolor = GLOB.wcCommon return newcolor diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 6c10921e6bd..19717991593 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -35,7 +35,12 @@ assume_air(lowertemp) qdel(hotspot) -/turf/simulated/proc/MakeSlippery(wet_setting = TURF_WET_WATER, infinite = FALSE) // 1 = Water, 2 = Lube, 3 = Ice, 4 = Permafrost +/* + * Makes a turf slippery using the given parameters + * @param wet_setting The type of slipperyness used + * @param time Time the turf is slippery. If null it will pick a random time between 790 and 820 ticks. If INFINITY then it won't dry up ever +*/ +/turf/simulated/proc/MakeSlippery(wet_setting = TURF_WET_WATER, time = null) // 1 = Water, 2 = Lube, 3 = Ice, 4 = Permafrost if(wet >= wet_setting) return wet = wet_setting @@ -55,13 +60,13 @@ else wet_overlay = image('icons/effects/water.dmi', src, "wet_static") overlays += wet_overlay - if(!infinite) - spawn(rand(790, 820)) // Purely so for visual effect - if(!istype(src, /turf/simulated)) //Because turfs don't get deleted, they change, adapt, transform, evolve and deform. they are one and they are all. - return - MakeDry(wet_setting) + if(time == INFINITY) + return + if(!time) + time = rand(790, 820) + addtimer(CALLBACK(src, .proc/MakeDry, wet_setting), time) -/turf/simulated/proc/MakeDry(wet_setting = TURF_WET_WATER) +/turf/simulated/MakeDry(wet_setting = TURF_WET_WATER) if(wet > wet_setting) return wet = TURF_DRY diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 72513b2e8b3..2d886f44bfd 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -1,5 +1,5 @@ //This is so damaged or burnt tiles or platings don't get remembered as the default tile -var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","damaged4", +GLOBAL_LIST_INIT(icons_to_ignore_at_floor_init, list("damaged1","damaged2","damaged3","damaged4", "damaged5","panelscorched","floorscorched1","floorscorched2","platingdmg1","platingdmg2", "platingdmg3","plating","light_on","light_on_flicker1","light_on_flicker2", "warnplate", "warnplatecorner","metalfoam", "ironfoam", @@ -11,7 +11,7 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3"," "oldburning","light-on-r","light-on-y","light-on-g","light-on-b", "wood", "wood-broken", "carpet", "carpetcorner", "carpetside", "carpet", "ironsand1", "ironsand2", "ironsand3", "ironsand4", "ironsand5", "ironsand6", "ironsand7", "ironsand8", "ironsand9", "ironsand10", "ironsand11", - "ironsand12", "ironsand13", "ironsand14", "ironsand15") + "ironsand12", "ironsand13", "ironsand14", "ironsand15")) /turf/simulated/floor name = "floor" @@ -34,7 +34,7 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3"," /turf/simulated/floor/New() ..() - if(icon_state in icons_to_ignore_at_floor_init) //so damaged/burned tiles or plating icons aren't saved as the default + if(icon_state in GLOB.icons_to_ignore_at_floor_init) //so damaged/burned tiles or plating icons aren't saved as the default icon_regular_floor = "floor" else icon_regular_floor = icon_state @@ -187,7 +187,7 @@ var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3"," if(T.turf_type == type) return var/obj/item/thing = user.get_inactive_hand() - if(!prying_tool_list.Find(thing.tool_behaviour)) + if(!thing || !prying_tool_list.Find(thing.tool_behaviour)) return var/turf/simulated/floor/plating/P = pry_tile(thing, user, TRUE) if(!istype(P)) diff --git a/code/game/turfs/simulated/floor/asteroid.dm b/code/game/turfs/simulated/floor/asteroid.dm index 983b5abaced..6d5d95dff0e 100644 --- a/code/game/turfs/simulated/floor/asteroid.dm +++ b/code/game/turfs/simulated/floor/asteroid.dm @@ -205,7 +205,7 @@ GLOBAL_LIST_INIT(megafauna_spawn_list, list(/mob/living/simple_animal/hostile/me length = set_length // Get our directiosn - forward_cave_dir = pick(alldirs - exclude_dir) + forward_cave_dir = pick(GLOB.alldirs - exclude_dir) // Get the opposite direction of our facing direction backward_cave_dir = angle2dir(dir2angle(forward_cave_dir) + 180) diff --git a/code/game/turfs/simulated/floor/chasm.dm b/code/game/turfs/simulated/floor/chasm.dm index 1fb97430026..d8ed888bc27 100644 --- a/code/game/turfs/simulated/floor/chasm.dm +++ b/code/game/turfs/simulated/floor/chasm.dm @@ -186,7 +186,7 @@ AM.alpha = oldalpha AM.color = oldcolor AM.transform = oldtransform - AM.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1, 10),rand(1, 10)) + AM.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1, 10),rand(1, 10)) /turf/simulated/floor/chasm/straight_down/lava_land_surface/normal_air oxygen = MOLES_O2STANDARD diff --git a/code/game/turfs/simulated/floor/lava.dm b/code/game/turfs/simulated/floor/lava.dm index 57e90840920..aa1be2200fa 100644 --- a/code/game/turfs/simulated/floor/lava.dm +++ b/code/game/turfs/simulated/floor/lava.dm @@ -113,6 +113,9 @@ /turf/simulated/floor/plating/lava/attackby(obj/item/C, mob/user, params) //Lava isn't a good foundation to build on return +/turf/simulated/floor/plating/lava/screwdriver_act() + return + /turf/simulated/floor/plating/lava/welder_act() return diff --git a/code/game/turfs/simulated/floor/mineral.dm b/code/game/turfs/simulated/floor/mineral.dm index 5eb387abbae..ffb1cce0b5c 100644 --- a/code/game/turfs/simulated/floor/mineral.dm +++ b/code/game/turfs/simulated/floor/mineral.dm @@ -186,7 +186,7 @@ /turf/simulated/floor/mineral/bananium/lubed/Initialize(mapload) . = ..() - MakeSlippery(TURF_WET_LUBE, TRUE) + MakeSlippery(TURF_WET_LUBE, INFINITY) /turf/simulated/floor/mineral/bananium/lubed/pry_tile(obj/item/C, mob/user, silent = FALSE) //I want to get off Mr Honk's Wild Ride if(ishuman(user)) diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm index 33ae636090d..0ca6494497c 100644 --- a/code/game/turfs/simulated/floor/misc_floor.dm +++ b/code/game/turfs/simulated/floor/misc_floor.dm @@ -118,7 +118,7 @@ /turf/simulated/floor/lubed/Initialize(mapload) . = ..() - MakeSlippery(TURF_WET_LUBE, TRUE) + MakeSlippery(TURF_WET_LUBE, INFINITY) /turf/simulated/floor/lubed/pry_tile(obj/item/C, mob/user, silent = FALSE) //I want to get off Mr Honk's Wild Ride if(ishuman(user)) diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 85b03d3378d..588a8387474 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -104,7 +104,7 @@ broken = FALSE update_icon() -/turf/simulated/floor/plating/proc/remove_plating(mob/user) +/turf/simulated/floor/plating/remove_plating(mob/user) if(baseturf == /turf/space) ReplaceWithLattice() else @@ -353,7 +353,7 @@ /turf/simulated/floor/plating/ice/Initialize(mapload) . = ..() - MakeSlippery(TURF_WET_PERMAFROST, TRUE) + MakeSlippery(TURF_WET_PERMAFROST, INFINITY) /turf/simulated/floor/plating/ice/try_replace_tile(obj/item/stack/tile/T, mob/user, params) return diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index d1f7a287c70..ebad3554f18 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -32,7 +32,7 @@ icon = smooth_icon . = ..() if(mineralType && mineralAmt && spread && spreadChance) - for(var/dir in cardinal) + for(var/dir in GLOB.cardinal) if(prob(spreadChance)) var/turf/T = get_step(src, dir) if(istype(T, /turf/simulated/mineral/random)) diff --git a/code/game/turfs/simulated/river.dm b/code/game/turfs/simulated/river.dm index c7a3e742b6c..f463f3fb564 100644 --- a/code/game/turfs/simulated/river.dm +++ b/code/game/turfs/simulated/river.dm @@ -82,7 +82,7 @@ var/turf/simulated/mineral/M = T logged_turf_type = M.turf_type - if(get_dir(src, F) in cardinal) + if(get_dir(src, F) in GLOB.cardinal) cardinal_turfs += F else diagonal_turfs += F diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 078a1b8e513..c18acf19d0a 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -139,7 +139,7 @@ P.setAngle(new_angle_s) return TRUE -/turf/simulated/wall/proc/dismantle_wall(devastated = 0, explode = 0) +/turf/simulated/wall/dismantle_wall(devastated = FALSE, explode = FALSE) if(devastated) devastate_wall() else @@ -156,6 +156,7 @@ O.forceMove(src) ChangeTurf(/turf/simulated/floor/plating) + return TRUE /turf/simulated/wall/proc/break_wall() new sheet_type(src, sheet_amount) diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index bc04a695da7..8b60be916c3 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -277,6 +277,9 @@ /turf/simulated/wall/mineral/titanium/nodecon/burn_down() return +/turf/simulated/wall/mineral/titanium/nodecon/welder_act() + return + /////////////////////Plastitanium walls///////////////////// /turf/simulated/wall/mineral/plastitanium diff --git a/code/game/turfs/simulated/walls_misc.dm b/code/game/turfs/simulated/walls_misc.dm index e43ea15f53f..d2d7f8386ee 100644 --- a/code/game/turfs/simulated/walls_misc.dm +++ b/code/game/turfs/simulated/walls_misc.dm @@ -109,6 +109,7 @@ P.roll_and_drop(src) else O.forceMove(src) + return TRUE /turf/simulated/wall/clockwork/devastate_wall() for(var/i in 1 to 2) diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index 502803bc7d3..a3e9c9ae0f2 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -43,7 +43,7 @@ update_icon() to_chat(user, "You press firmly on the cover, dislodging it.") return - else if(RWALL_SUPPORT_RODS && istype(I, /obj/item/gun/energy/plasmacutter)) + else if(d_state == RWALL_SUPPORT_RODS && istype(I, /obj/item/gun/energy/plasmacutter)) to_chat(user, "You begin slicing through the support rods...") if(I.use_tool(src, user, 70, volume = I.tool_volume) && d_state == RWALL_SUPPORT_RODS) d_state = RWALL_SHEATH @@ -132,11 +132,11 @@ to_chat(user, "You pry off the cover.") if(RWALL_SHEATH) to_chat(user, "You struggle to pry off the outer sheath...") - if(!I.use_tool(src, user, 100, volume = I.tool_volume) || d_state != RWALL_SHEATH) + if(!I.use_tool(src, user, 100, volume = I.tool_volume)) return - to_chat(user, "You pry off the outer sheath.") - dismantle_wall() - return + if(dismantle_wall()) + to_chat(user, "You pry off the outer sheath.") + if(RWALL_BOLTS) to_chat(user, "You start to pry the cover back into place...") playsound(src, I.usesound, 100, 1) @@ -199,6 +199,9 @@ to_chat(user, "You tighten the bolts anchoring the support rods.") update_icon() +/turf/simulated/wall/r_wall/try_decon(obj/item/I, mob/user, params) //Plasma cutter only works in the deconstruction steps! + return FALSE + /turf/simulated/wall/r_wall/try_destroy(obj/item/I, mob/user, params) if(istype(I, /obj/item/pickaxe/drill/diamonddrill)) to_chat(user, "You begin to drill though the wall...") diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index c797601d8e1..f78f520cfd3 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -42,14 +42,14 @@ /turf/space/BeforeChange() ..() - var/datum/space_level/S = space_manager.get_zlev(z) + var/datum/space_level/S = GLOB.space_manager.get_zlev(z) S.remove_from_transit(src) if(light_sources) // Turn off starlight, if present set_light(0) /turf/space/AfterChange(ignore_air, keep_cabling = FALSE) ..() - var/datum/space_level/S = space_manager.get_zlev(z) + var/datum/space_level/S = GLOB.space_manager.get_zlev(z) S.add_to_transit(src) S.apply_transition(src) @@ -137,8 +137,8 @@ if(!cur_pos) return cur_x = cur_pos["x"] cur_y = cur_pos["y"] - next_x = (--cur_x||global_map.len) - y_arr = global_map[next_x] + next_x = (--cur_x||GLOB.global_map.len) + y_arr = GLOB.global_map[next_x] target_z = y_arr[cur_y] /* //debug @@ -162,8 +162,8 @@ if(!cur_pos) return cur_x = cur_pos["x"] cur_y = cur_pos["y"] - next_x = (++cur_x > global_map.len ? 1 : cur_x) - y_arr = global_map[next_x] + next_x = (++cur_x > GLOB.global_map.len ? 1 : cur_x) + y_arr = GLOB.global_map[next_x] target_z = y_arr[cur_y] /* //debug @@ -186,7 +186,7 @@ if(!cur_pos) return cur_x = cur_pos["x"] cur_y = cur_pos["y"] - y_arr = global_map[cur_x] + y_arr = GLOB.global_map[cur_x] next_y = (--cur_y||y_arr.len) target_z = y_arr[next_y] /* @@ -211,7 +211,7 @@ if(!cur_pos) return cur_x = cur_pos["x"] cur_y = cur_pos["y"] - y_arr = global_map[cur_x] + y_arr = GLOB.global_map[cur_x] next_y = (++cur_y > y_arr.len ? 1 : cur_y) target_z = y_arr[next_y] /* diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index d589c3dcb64..aa3f7b898a1 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -70,7 +70,7 @@ /turf/Destroy() // Adds the adjacent turfs to the current atmos processing if(SSair) - for(var/direction in cardinal) + for(var/direction in GLOB.cardinal) if(atmos_adjacent_turfs & direction) var/turf/simulated/T = get_step(src, direction) if(istype(T)) @@ -180,6 +180,9 @@ if(L) qdel(L) +/turf/proc/dismantle_wall(devastated = FALSE, explode = FALSE) + return + /turf/proc/TerraformTurf(path, defer_change = FALSE, keep_icon = TRUE, ignore_air = FALSE) return ChangeTurf(path, defer_change, keep_icon, ignore_air) @@ -187,7 +190,7 @@ /turf/proc/ChangeTurf(path, defer_change = FALSE, keep_icon = TRUE, ignore_air = FALSE) if(!path) return - if(!use_preloader && path == type) // Don't no-op if the map loader requires it to be reconstructed + if(!GLOB.use_preloader && path == type) // Don't no-op if the map loader requires it to be reconstructed return src set_light(0) @@ -266,7 +269,7 @@ var/atemp = 0 var/turf_count = 0 - for(var/direction in cardinal)//Only use cardinals to cut down on lag + for(var/direction in GLOB.cardinal)//Only use cardinals to cut down on lag var/turf/T = get_step(src,direction) if(istype(T,/turf/space))//Counted as no air turf_count++//Considered a valid turf for air calcs @@ -292,6 +295,9 @@ ChangeTurf(baseturf) new /obj/structure/lattice(locate(x, y, z)) +/turf/proc/remove_plating(mob/user) + return + /turf/proc/kill_creatures(mob/U = null)//Will kill people/creatures and damage mechs./N //Useful to batch-add creatures to the list. for(var/mob/living/M in src) @@ -309,6 +315,10 @@ for(var/atom/movable/AM in contents) AM.get_spooked() +// Defined here to avoid runtimes +/turf/proc/MakeDry(wet_setting = TURF_WET_WATER) + return + /turf/proc/burn_down() return @@ -327,7 +337,7 @@ var/list/L = new() var/turf/simulated/T - for(var/dir in cardinal) + for(var/dir in GLOB.cardinal) T = get_step(src, dir) if(istype(T) && !T.density) if(!LinkBlockedWithAccess(src, T, ID)) @@ -340,7 +350,7 @@ var/list/L = new() var/turf/simulated/T - for(var/dir in cardinal) + for(var/dir in GLOB.cardinal) T = get_step(src, dir) if(istype(T) && !T.density) if(!CanAtmosPass(T)) @@ -452,7 +462,7 @@ /turf/proc/visibilityChanged() if(SSticker) - cameranet.updateVisibility(src) + GLOB.cameranet.updateVisibility(src) /turf/attackby(obj/item/I, mob/user, params) if(can_lay_cable()) diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index e94d04f5dfb..824159487eb 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -1,8 +1,8 @@ -var/global/normal_ooc_colour = "#002eb8" -var/global/member_ooc_colour = "#035417" -var/global/mentor_ooc_colour = "#0099cc" -var/global/moderator_ooc_colour = "#184880" -var/global/admin_ooc_colour = "#b82e00" +GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8") +GLOBAL_VAR_INIT(member_ooc_colour, "#035417") +GLOBAL_VAR_INIT(mentor_ooc_colour, "#0099cc") +GLOBAL_VAR_INIT(moderator_ooc_colour, "#184880") +GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00") //Checks if the client already has a text input open /client/proc/checkTyping() @@ -54,21 +54,21 @@ var/global/admin_ooc_colour = "#b82e00" log_ooc(msg, src) - var/display_colour = normal_ooc_colour + var/display_colour = GLOB.normal_ooc_colour if(holder && !holder.fakekey) - display_colour = mentor_ooc_colour + display_colour = GLOB.mentor_ooc_colour if(check_rights(R_MOD,0) && !check_rights(R_ADMIN,0)) - display_colour = moderator_ooc_colour + display_colour = GLOB.moderator_ooc_colour else if(check_rights(R_ADMIN,0)) if(config.allow_admin_ooccolor) display_colour = src.prefs.ooccolor else - display_colour = admin_ooc_colour + display_colour = GLOB.admin_ooc_colour if(prefs.unlock_content) - if(display_colour == normal_ooc_colour) + if(display_colour == GLOB.normal_ooc_colour) if((prefs.toggles & MEMBER_PUBLIC)) - display_colour = member_ooc_colour + display_colour = GLOB.member_ooc_colour for(var/client/C in GLOB.clients) if(C.prefs.toggles & CHAT_OOC) @@ -114,7 +114,7 @@ var/global/admin_ooc_colour = "#b82e00" if(!check_rights(R_SERVER)) return - normal_ooc_colour = newColor + GLOB.normal_ooc_colour = newColor message_admins("[key_name_admin(usr)] has set the default player OOC color to [newColor]") log_admin("[key_name(usr)] has set the default player OOC color to [newColor]") @@ -128,7 +128,7 @@ var/global/admin_ooc_colour = "#b82e00" if(!check_rights(R_SERVER)) return - normal_ooc_colour = initial(normal_ooc_colour) + GLOB.normal_ooc_colour = initial(GLOB.normal_ooc_colour) message_admins("[key_name_admin(usr)] has reset the default player OOC color") log_admin("[key_name(usr)] has reset the default player OOC color") diff --git a/code/game/world.dm b/code/game/world.dm index 83407a6ae46..c1f6a076677 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -1,8 +1,12 @@ #define RECOMMENDED_VERSION 510 -var/global/list/map_transition_config = MAP_TRANSITION_CONFIG +GLOBAL_LIST_INIT(map_transition_config, MAP_TRANSITION_CONFIG) /world/New() + //temporary file used to record errors with loading config, moved to log directory once logging is set up + GLOB.config_error_log = GLOB.world_game_log = GLOB.world_runtime_log = "data/logs/config_error.log" + load_configuration() + // Setup all log paths and stamp them with startups SetupLogs() enable_debugger() // Enable the extools debugger log_world("World loaded at [time_stamp()]") @@ -22,7 +26,7 @@ var/global/list/map_transition_config = MAP_TRANSITION_CONFIG src.update_status() - space_manager.initialize() //Before the MC starts up + GLOB.space_manager.initialize() //Before the MC starts up . = ..() @@ -47,8 +51,8 @@ var/global/list/map_transition_config = MAP_TRANSITION_CONFIG // to_chat(world, "End of Topic() call.") // ..() -var/world_topic_spam_protect_ip = "0.0.0.0" -var/world_topic_spam_protect_time = world.timeofday +GLOBAL_VAR_INIT(world_topic_spam_protect_ip, "0.0.0.0") +GLOBAL_VAR_INIT(world_topic_spam_protect_time, world.timeofday) /world/Topic(T, addr, master, key) log_misc("WORLD/TOPIC: \"[T]\", from:[addr], master:[master], key:[key]") @@ -72,10 +76,10 @@ var/world_topic_spam_protect_time = world.timeofday else if("status" in input) var/list/s = list() var/list/admins = list() - s["version"] = game_version - s["mode"] = master_mode - s["respawn"] = config ? abandon_allowed : 0 - s["enter"] = enter_allowed + s["version"] = GLOB.game_version + s["mode"] = GLOB.master_mode + s["respawn"] = config ? GLOB.abandon_allowed : 0 + s["enter"] = GLOB.enter_allowed s["vote"] = config.allow_vote_mode s["ai"] = config.allow_ai s["host"] = host ? host : null @@ -123,18 +127,18 @@ var/world_topic_spam_protect_time = world.timeofday else if("manifest" in input) var/list/positions = list() var/list/set_names = list( - "heads" = command_positions, - "sec" = security_positions, - "eng" = engineering_positions, - "med" = medical_positions, - "sci" = science_positions, - "car" = supply_positions, - "srv" = service_positions, - "civ" = civilian_positions, - "bot" = nonhuman_positions + "heads" = GLOB.command_positions, + "sec" = GLOB.security_positions, + "eng" = GLOB.engineering_positions, + "med" = GLOB.medical_positions, + "sci" = GLOB.science_positions, + "car" = GLOB.supply_positions, + "srv" = GLOB.service_positions, + "civ" = GLOB.civilian_positions, + "bot" = GLOB.nonhuman_positions ) - for(var/datum/data/record/t in data_core.general) + for(var/datum/data/record/t in GLOB.data_core.general) var/name = t.fields["name"] var/rank = t.fields["rank"] var/real_rank = t.fields["real_rank"] @@ -251,18 +255,22 @@ var/world_topic_spam_protect_time = world.timeofday return "Set listed status to invisible." /proc/keySpamProtect(var/addr) - if(world_topic_spam_protect_ip == addr && abs(world_topic_spam_protect_time - world.time) < 50) + if(GLOB.world_topic_spam_protect_ip == addr && abs(GLOB.world_topic_spam_protect_time - world.time) < 50) spawn(50) - world_topic_spam_protect_time = world.time + GLOB.world_topic_spam_protect_time = world.time return "Bad Key (Throttled)" - world_topic_spam_protect_time = world.time - world_topic_spam_protect_ip = addr + GLOB.world_topic_spam_protect_time = world.time + GLOB.world_topic_spam_protect_ip = addr return "Bad Key" /world/Reboot(var/reason, var/feedback_c, var/feedback_r, var/time) if(reason == 1) //special reboot, do none of the normal stuff if(usr) + if(!check_rights(R_SERVER)) + message_admins("[key_name_admin(usr)] attempted to restart the server via the Profiler, without access.") + log_admin("[key_name(usr)] attempted to restart the server via the Profiler, without access.") + return message_admins("[key_name_admin(usr)] has requested an immediate world restart via client side debugging tools") log_admin("[key_name(usr)] has requested an immediate world restart via client side debugging tools") spawn(0) @@ -270,8 +278,8 @@ var/world_topic_spam_protect_time = world.timeofday shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss. if(config && config.shutdown_on_reboot) sleep(0) - if(shutdown_shell_command) - shell(shutdown_shell_command) + if(GLOB.shutdown_shell_command) + shell(GLOB.shutdown_shell_command) del(world) return else @@ -294,8 +302,8 @@ var/world_topic_spam_protect_time = world.timeofday if(!SSticker.delay_end) world << round_end_sound sleep(delay) - if(blackbox) - blackbox.save_all_data_to_sql() + if(GLOB.blackbox) + GLOB.blackbox.save_all_data_to_sql() if(SSticker.delay_end) to_chat(world, "Reboot was cancelled by an admin.") return @@ -304,7 +312,7 @@ var/world_topic_spam_protect_time = world.timeofday //kick_clients_in_lobby("The round came to an end with you in the lobby.", 1) Master.Shutdown() //run SS shutdowns - dbcon.Disconnect() // DCs cleanly from the database + GLOB.dbcon.Disconnect() // DCs cleanly from the database shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss. for(var/client/C in GLOB.clients) @@ -313,8 +321,8 @@ var/world_topic_spam_protect_time = world.timeofday if(config && config.shutdown_on_reboot) sleep(0) - if(shutdown_shell_command) - shell(shutdown_shell_command) + if(GLOB.shutdown_shell_command) + shell(GLOB.shutdown_shell_command) del(world) return else @@ -329,8 +337,8 @@ var/world_topic_spam_protect_time = world.timeofday var/list/Lines = file2list("data/mode.txt") if(Lines.len) if(Lines[1]) - master_mode = Lines[1] - log_game("Saved mode is '[master_mode]'") + GLOB.master_mode = Lines[1] + log_game("Saved mode is '[GLOB.master_mode]'") /world/proc/save_mode(var/the_mode) var/F = file("data/mode.txt") @@ -342,7 +350,7 @@ var/world_topic_spam_protect_time = world.timeofday return 1 /world/proc/load_motd() - join_motd = file2text("config/motd.txt") + GLOB.join_motd = file2text("config/motd.txt") GLOB.join_tos = file2text("config/tos.txt") /proc/load_configuration() @@ -366,7 +374,7 @@ var/world_topic_spam_protect_time = world.timeofday s += "[config.server_name] — " s += "[station_name()] " if(config && config.githuburl) - s+= "([game_version])" + s+= "([GLOB.game_version])" if(config && config.server_tag_line) s += "
    [config.server_tag_line]" @@ -379,7 +387,7 @@ var/world_topic_spam_protect_time = world.timeofday s += "
    " var/list/features = list() - if(!enter_allowed) + if(!GLOB.enter_allowed) features += "closed" if(config && config.server_extra_features) @@ -391,7 +399,7 @@ var/world_topic_spam_protect_time = world.timeofday if(config && config.wikiurl) features += "Wiki" - if(abandon_allowed) + if(GLOB.abandon_allowed) features += "respawn" if(features) @@ -400,8 +408,8 @@ var/world_topic_spam_protect_time = world.timeofday return s #define FAILED_DB_CONNECTION_CUTOFF 5 -var/failed_db_connections = 0 -var/failed_old_db_connections = 0 +GLOBAL_VAR_INIT(failed_db_connections, 0) +GLOBAL_VAR_INIT(failed_old_db_connections, 0) /world/proc/SetupLogs() GLOB.log_directory = "data/logs/[time2text(world.realtime, "YYYY/MM-Month/DD-Day")]" @@ -436,11 +444,11 @@ var/failed_old_db_connections = 0 /proc/setup_database_connection() - if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore. + if(GLOB.failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to conenct anymore. return 0 - if(!dbcon) - dbcon = new() + if(!GLOB.dbcon) + GLOB.dbcon = new() var/user = sqlfdbklogin var/pass = sqlfdbkpass @@ -448,22 +456,22 @@ var/failed_old_db_connections = 0 var/address = sqladdress var/port = sqlport - dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") - . = dbcon.IsConnected() + GLOB.dbcon.Connect("dbi:mysql:[db]:[address]:[port]","[user]","[pass]") + . = GLOB.dbcon.IsConnected() if( . ) - failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter. + GLOB.failed_db_connections = 0 //If this connection succeeded, reset the failed connections counter. else - failed_db_connections++ //If it failed, increase the failed connections counter. - log_world(dbcon.ErrorMsg()) + GLOB.failed_db_connections++ //If it failed, increase the failed connections counter. + log_world(GLOB.dbcon.ErrorMsg()) return . //This proc ensures that the connection to the feedback database (global variable dbcon) is established proc/establish_db_connection() - if(failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) + if(GLOB.failed_db_connections > FAILED_DB_CONNECTION_CUTOFF) return 0 - if(!dbcon || !dbcon.IsConnected()) + if(!GLOB.dbcon || !GLOB.dbcon.IsConnected()) return setup_database_connection() else return 1 diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm index 8168583e6fa..21b59586bfd 100644 --- a/code/modules/admin/DB ban/functions.dm +++ b/code/modules/admin/DB ban/functions.dm @@ -5,7 +5,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = if(!check_rights(R_BAN)) return establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) return var/serverip = "[world.internet_address]:[world.port]" @@ -86,7 +86,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = message_admins("[key_name_admin(usr)] attempted to add a ban based on a non-existent mob, with no ckey provided. Report this bug.",1) return - var/DBQuery/query = dbcon.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("player")] WHERE ckey = '[ckey]'") query.Execute() var/validckey = 0 if(query.NextRow()) @@ -127,7 +127,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = reason = sanitizeSQL(reason) if(maxadminbancheck) - var/DBQuery/adm_query = dbcon.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") + var/DBQuery/adm_query = GLOB.dbcon.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)") adm_query.Execute() if(adm_query.NextRow()) var/adm_bans = text2num(adm_query.item[1]) @@ -136,7 +136,7 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = return var/sql = "INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)" - var/DBQuery/query_insert = dbcon.NewQuery(sql) + var/DBQuery/query_insert = GLOB.dbcon.NewQuery(sql) query_insert.Execute() to_chat(usr, "Ban saved to database.") message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1) @@ -201,13 +201,13 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "") sql += " AND job = '[job]'" establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) return var/ban_id var/ban_number = 0 //failsafe - var/DBQuery/query = dbcon.NewQuery(sql) + var/DBQuery/query = GLOB.dbcon.NewQuery(sql) query.Execute() while(query.NextRow()) ban_id = query.item[1] @@ -241,7 +241,7 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null) to_chat(usr, "Cancelled") return - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, duration, reason, job FROM [format_table_name("ban")] WHERE id = [banid]") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, duration, reason, job FROM [format_table_name("ban")] WHERE id = [banid]") query.Execute() var/eckey = usr.ckey //Editing admin ckey @@ -271,7 +271,7 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null) to_chat(usr, "Cancelled") return - var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\"
    ') WHERE id = [banid]") + var/DBQuery/update_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("ban")] SET reason = '[value]', edits = CONCAT(edits,'- [eckey] changed ban reason from \\\"[reason]\\\" to \\\"[value]\\\"
    ') WHERE id = [banid]") update_query.Execute() message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s reason from [reason] to [value]",1) if("duration") @@ -281,7 +281,7 @@ datum/admins/proc/DB_ban_edit(var/banid = null, var/param = null) to_chat(usr, "Cancelled") return - var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]
    '), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]") + var/DBQuery/update_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("ban")] SET duration = [value], edits = CONCAT(edits,'- [eckey] changed ban duration from [duration] to [value]
    '), expiration_time = DATE_ADD(bantime, INTERVAL [value] MINUTE) WHERE id = [banid]") message_admins("[key_name_admin(usr)] has edited a ban for [pckey]'s duration from [duration] to [value]",1) update_query.Execute() if("unban") @@ -304,13 +304,13 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) var/sql = "SELECT ckey FROM [format_table_name("ban")] WHERE id = [id]" establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) return var/ban_number = 0 //failsafe var/pckey - var/DBQuery/query = dbcon.NewQuery(sql) + var/DBQuery/query = GLOB.dbcon.NewQuery(sql) query.Execute() while(query.NextRow()) pckey = query.item[1] @@ -334,7 +334,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) var/sql_update = "UPDATE [format_table_name("ban")] SET unbanned = 1, unbanned_datetime = Now(), unbanned_ckey = '[unban_ckey]', unbanned_computerid = '[unban_computerid]', unbanned_ip = '[unban_ip]' WHERE id = [id]" message_admins("[key_name_admin(usr)] has lifted [pckey]'s ban.",1) - var/DBQuery/query_update = dbcon.NewQuery(sql_update) + var/DBQuery/query_update = GLOB.dbcon.NewQuery(sql_update) query_update.Execute() flag_account_for_forum_sync(pckey) @@ -359,7 +359,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) if(!check_rights(R_BAN)) return establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection") return @@ -392,13 +392,13 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) output += "" for(var/j in get_all_jobs()) output += "" - for(var/j in nonhuman_positions) + for(var/j in GLOB.nonhuman_positions) output += "" - for(var/j in other_roles) + for(var/j in GLOB.other_roles) output += "" for(var/j in list("commanddept","securitydept","engineeringdept","medicaldept","sciencedept","supportdept","nonhumandept")) output += "" - for(var/j in list("Syndicate") + antag_roles) + for(var/j in list("Syndicate") + GLOB.antag_roles) output += "" output += "" output += "Reason:

    " @@ -498,7 +498,7 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) bantypesearch += "'PERMABAN' " - var/DBQuery/select_query = dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id, bantime, bantype, reason, job, duration, expiration_time, ckey, a_ckey, unbanned, unbanned_ckey, unbanned_datetime, edits, ip, computerid FROM [format_table_name("ban")] WHERE 1 [playersearch] [adminsearch] [ipsearch] [cidsearch] [bantypesearch] ORDER BY bantime DESC LIMIT 100") select_query.Execute() while(select_query.NextRow()) @@ -575,9 +575,9 @@ datum/admins/proc/DB_ban_unban_by_id(var/id) usr << browse(output,"window=lookupbans;size=900x700") /proc/flag_account_for_forum_sync(ckey) - if(!dbcon) + if(!GLOB.dbcon) return var/skey = sanitizeSQL(ckey) var/sql = "UPDATE [format_table_name("player")] SET fupdate = 1 WHERE ckey = '[skey]'" - var/DBQuery/adm_query = dbcon.NewQuery(sql) + var/DBQuery/adm_query = GLOB.dbcon.NewQuery(sql) adm_query.Execute() diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index d776b4a2095..c7f2baac4ef 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -25,13 +25,13 @@ world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE) if (C && ckey == C.ckey && computer_id == C.computer_id && address == C.address) return //don't recheck connected clients. - if((ckey in admin_datums) || (ckey in GLOB.deadmins)) - var/datum/admins/A = admin_datums[ckey] + if((ckey in GLOB.admin_datums) || (ckey in GLOB.deadmins)) + var/datum/admins/A = GLOB.admin_datums[ckey] if(A && (A.rights & R_ADMIN)) admin = 1 //Guest Checking - if(!guests_allowed && IsGuestKey(key)) + if(!GLOB.guests_allowed && IsGuestKey(key)) log_adminwarn("Failed Login: [key] [computer_id] [address] - Guests not allowed") // message_admins("Failed Login: [key] - Guests not allowed") return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.") @@ -82,7 +82,7 @@ world/IsBanned(key, address, computer_id, type, check_ipintel = TRUE) if(computer_id) cidquery = " OR computerid = '[computer_id]' " - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)") query.Execute() diff --git a/code/modules/admin/NewBan.dm b/code/modules/admin/NewBan.dm index 222fc036db2..7b9a9330704 100644 --- a/code/modules/admin/NewBan.dm +++ b/code/modules/admin/NewBan.dm @@ -1,61 +1,61 @@ -var/CMinutes = null -var/savefile/Banlist - +GLOBAL_VAR(CMinutes) +GLOBAL_DATUM(banlist_savefile, /savefile) +GLOBAL_PROTECT(banlist_savefile) // Obvious reasons /proc/CheckBan(var/ckey, var/id, var/address) - if(!Banlist) // if Banlist cannot be located for some reason + if(!GLOB.banlist_savefile) // if banlist_savefile cannot be located for some reason LoadBans() // try to load the bans - if(!Banlist) // uh oh, can't find bans! + if(!GLOB.banlist_savefile) // uh oh, can't find bans! return 0 // ABORT ABORT ABORT . = list() var/appeal if(config && config.banappeals) appeal = "\nFor more information on your ban, or to appeal, head to [config.banappeals]" - Banlist.cd = "/base" - if( "[ckey][id]" in Banlist.dir ) - Banlist.cd = "[ckey][id]" - if(Banlist["temp"]) - if(!GetExp(Banlist["minutes"])) + GLOB.banlist_savefile.cd = "/base" + if( "[ckey][id]" in GLOB.banlist_savefile.dir ) + GLOB.banlist_savefile.cd = "[ckey][id]" + if(GLOB.banlist_savefile["temp"]) + if(!GetExp(GLOB.banlist_savefile["minutes"])) ClearTempbans() return 0 else - .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]" + .["desc"] = "\nReason: [GLOB.banlist_savefile["reason"]]\nExpires: [GetExp(GLOB.banlist_savefile["minutes"])]\nBy: [GLOB.banlist_savefile["bannedby"]][appeal]" else - Banlist.cd = "/base/[ckey][id]" - .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: PERMENANT\nBy: [Banlist["bannedby"]][appeal]" + GLOB.banlist_savefile.cd = "/base/[ckey][id]" + .["desc"] = "\nReason: [GLOB.banlist_savefile["reason"]]\nExpires: PERMENANT\nBy: [GLOB.banlist_savefile["bannedby"]][appeal]" .["reason"] = "ckey/id" return . else - for(var/A in Banlist.dir) - Banlist.cd = "/base/[A]" + for(var/A in GLOB.banlist_savefile.dir) + GLOB.banlist_savefile.cd = "/base/[A]" var/matches - if( ckey == Banlist["key"] ) + if( ckey == GLOB.banlist_savefile["key"] ) matches += "ckey" - if( id == Banlist["id"] ) + if( id == GLOB.banlist_savefile["id"] ) if(matches) matches += "/" matches += "id" - if( address == Banlist["ip"] ) + if( address == GLOB.banlist_savefile["ip"] ) if(matches) matches += "/" matches += "ip" if(matches) - if(Banlist["temp"]) - if(!GetExp(Banlist["minutes"])) + if(GLOB.banlist_savefile["temp"]) + if(!GetExp(GLOB.banlist_savefile["minutes"])) ClearTempbans() return 0 else - .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: [GetExp(Banlist["minutes"])]\nBy: [Banlist["bannedby"]][appeal]" + .["desc"] = "\nReason: [GLOB.banlist_savefile["reason"]]\nExpires: [GetExp(GLOB.banlist_savefile["minutes"])]\nBy: [GLOB.banlist_savefile["bannedby"]][appeal]" else - .["desc"] = "\nReason: [Banlist["reason"]]\nExpires: PERMENANT\nBy: [Banlist["bannedby"]][appeal]" + .["desc"] = "\nReason: [GLOB.banlist_savefile["reason"]]\nExpires: PERMENANT\nBy: [GLOB.banlist_savefile["bannedby"]][appeal]" .["reason"] = matches return . return 0 /proc/UpdateTime() //No idea why i made this a proc. - CMinutes = (world.realtime / 10) / 60 + GLOB.CMinutes = (world.realtime / 10) / 60 return 1 /hook/startup/proc/loadBans() @@ -63,17 +63,17 @@ var/savefile/Banlist /proc/LoadBans() - Banlist = new("data/banlist.bdb") + GLOB.banlist_savefile = new("data/banlist.bdb") log_admin("Loading Banlist") - if(!length(Banlist.dir)) log_admin("Banlist is empty.") + if(!length(GLOB.banlist_savefile.dir)) log_admin("Banlist is empty.") - if(!Banlist.dir.Find("base")) + if(!GLOB.banlist_savefile.dir.Find("base")) log_admin("Banlist missing base dir.") - Banlist.dir.Add("base") - Banlist.cd = "/base" - else if(Banlist.dir.Find("base")) - Banlist.cd = "/base" + GLOB.banlist_savefile.dir.Add("base") + GLOB.banlist_savefile.cd = "/base" + else if(GLOB.banlist_savefile.dir.Find("base")) + GLOB.banlist_savefile.cd = "/base" ClearTempbans() return 1 @@ -81,17 +81,17 @@ var/savefile/Banlist /proc/ClearTempbans() UpdateTime() - Banlist.cd = "/base" - for(var/A in Banlist.dir) - Banlist.cd = "/base/[A]" - if(!Banlist["key"] || !Banlist["id"]) + GLOB.banlist_savefile.cd = "/base" + for(var/A in GLOB.banlist_savefile.dir) + GLOB.banlist_savefile.cd = "/base/[A]" + if(!GLOB.banlist_savefile["key"] || !GLOB.banlist_savefile["id"]) RemoveBan(A) log_admin("Invalid Ban.") message_admins("Invalid Ban.") continue - if(!Banlist["temp"]) continue - if(CMinutes >= Banlist["minutes"]) RemoveBan(A) + if(!GLOB.banlist_savefile["temp"]) continue + if(GLOB.CMinutes >= GLOB.banlist_savefile["minutes"]) RemoveBan(A) return 1 @@ -102,23 +102,23 @@ var/savefile/Banlist if(temp) UpdateTime() - bantimestamp = CMinutes + minutes + bantimestamp = GLOB.CMinutes + minutes - Banlist.cd = "/base" - if( Banlist.dir.Find("[ckey][computerid]") ) + GLOB.banlist_savefile.cd = "/base" + if( GLOB.banlist_savefile.dir.Find("[ckey][computerid]") ) to_chat(usr, "Ban already exists.") return 0 else - Banlist.dir.Add("[ckey][computerid]") - Banlist.cd = "/base/[ckey][computerid]" - Banlist["key"] << ckey - Banlist["id"] << computerid - Banlist["ip"] << address - Banlist["reason"] << reason - Banlist["bannedby"] << bannedby - Banlist["temp"] << temp + GLOB.banlist_savefile.dir.Add("[ckey][computerid]") + GLOB.banlist_savefile.cd = "/base/[ckey][computerid]" + GLOB.banlist_savefile["key"] << ckey + GLOB.banlist_savefile["id"] << computerid + GLOB.banlist_savefile["ip"] << address + GLOB.banlist_savefile["reason"] << reason + GLOB.banlist_savefile["bannedby"] << bannedby + GLOB.banlist_savefile["temp"] << temp if(temp) - Banlist["minutes"] << bantimestamp + GLOB.banlist_savefile["minutes"] << bantimestamp if(!temp) add_note(ckey, "Permanently banned - [reason]", null, bannedby, 0) else @@ -129,12 +129,12 @@ var/savefile/Banlist var/key var/id - Banlist.cd = "/base/[foldername]" - Banlist["key"] >> key - Banlist["id"] >> id - Banlist.cd = "/base" + GLOB.banlist_savefile.cd = "/base/[foldername]" + GLOB.banlist_savefile["key"] >> key + GLOB.banlist_savefile["id"] >> id + GLOB.banlist_savefile.cd = "/base" - if(!Banlist.dir.Remove(foldername)) return 0 + if(!GLOB.banlist_savefile.dir.Remove(foldername)) return 0 if(!usr) log_admin("Ban Expired: [key]") @@ -145,18 +145,18 @@ var/savefile/Banlist message_admins("[key_name_admin(usr)] unbanned: [key]") feedback_inc("ban_unban",1) usr.client.holder.DB_ban_unban( ckey(key), BANTYPE_ANY_FULLBAN) - for(var/A in Banlist.dir) - Banlist.cd = "/base/[A]" - if(key == Banlist["key"] /*|| id == Banlist["id"]*/) - Banlist.cd = "/base" - Banlist.dir.Remove(A) + for(var/A in GLOB.banlist_savefile.dir) + GLOB.banlist_savefile.cd = "/base/[A]" + if(key == GLOB.banlist_savefile["key"] /*|| id == GLOB.banlist_savefile["id"]*/) + GLOB.banlist_savefile.cd = "/base" + GLOB.banlist_savefile.dir.Remove(A) continue return 1 /proc/GetExp(minutes as num) UpdateTime() - var/exp = minutes - CMinutes + var/exp = minutes - GLOB.CMinutes if(exp <= 0) return 0 else @@ -172,19 +172,19 @@ var/savefile/Banlist /datum/admins/proc/unbanpanel() var/count = 0 var/dat - Banlist.cd = "/base" - for(var/A in Banlist.dir) + GLOB.banlist_savefile.cd = "/base" + for(var/A in GLOB.banlist_savefile.dir) count++ - Banlist.cd = "/base/[A]" + GLOB.banlist_savefile.cd = "/base/[A]" var/ref = UID() - var/key = Banlist["key"] - var/id = Banlist["id"] - var/ip = Banlist["ip"] - var/reason = Banlist["reason"] - var/by = Banlist["bannedby"] + var/key = GLOB.banlist_savefile["key"] + var/id = GLOB.banlist_savefile["id"] + var/ip = GLOB.banlist_savefile["ip"] + var/reason = GLOB.banlist_savefile["reason"] + var/by = GLOB.banlist_savefile["bannedby"] var/expiry - if(Banlist["temp"]) - expiry = GetExp(Banlist["minutes"]) + if(GLOB.banlist_savefile["temp"]) + expiry = GetExp(GLOB.banlist_savefile["minutes"]) if(!expiry) expiry = "Removal Pending" else expiry = "Permaban" @@ -207,26 +207,26 @@ var/savefile/Banlist var/a = pick(1,0) var/b = pick(1,0) if(b) - Banlist.cd = "/base" - Banlist.dir.Add("trash[i]trashid[i]") - Banlist.cd = "/base/trash[i]trashid[i]" - Banlist["key"] << "trash[i]" + GLOB.banlist_savefile.cd = "/base" + GLOB.banlist_savefile.dir.Add("trash[i]trashid[i]") + GLOB.banlist_savefile.cd = "/base/trash[i]trashid[i]" + GLOB.banlist_savefile["key"] << "trash[i]" else - Banlist.cd = "/base" - Banlist.dir.Add("[last]trashid[i]") - Banlist.cd = "/base/[last]trashid[i]" - Banlist["key"] << last - Banlist["id"] << "trashid[i]" - Banlist["reason"] << "Trashban[i]." - Banlist["temp"] << a - Banlist["minutes"] << CMinutes + rand(1,2000) - Banlist["bannedby"] << "trashmin" + GLOB.banlist_savefile.cd = "/base" + GLOB.banlist_savefile.dir.Add("[last]trashid[i]") + GLOB.banlist_savefile.cd = "/base/[last]trashid[i]" + GLOB.banlist_savefile["key"] << last + GLOB.banlist_savefile["id"] << "trashid[i]" + GLOB.banlist_savefile["reason"] << "Trashban[i]." + GLOB.banlist_savefile["temp"] << a + GLOB.banlist_savefile["minutes"] << GLOB.CMinutes + rand(1,2000) + GLOB.banlist_savefile["bannedby"] << "trashmin" last = "trash[i]" - Banlist.cd = "/base" + GLOB.banlist_savefile.cd = "/base" /proc/ClearAllBans() - Banlist.cd = "/base" - for(var/A in Banlist.dir) + GLOB.banlist_savefile.cd = "/base" + for(var/A in GLOB.banlist_savefile.dir) RemoveBan(A) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 31aa6d5bc4c..df156c5b0df 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1,5 +1,5 @@ -var/global/BSACooldown = 0 -var/global/nologevent = 0 +GLOBAL_VAR_INIT(BSACooldown, 0) +GLOBAL_VAR_INIT(nologevent, 0) //////////////////////////////// /proc/message_admins(var/msg) @@ -10,7 +10,7 @@ var/global/nologevent = 0 to_chat(C, msg) /proc/msg_admin_attack(var/text, var/loglevel) - if(!nologevent) + if(!GLOB.nologevent) var/rendered = "ATTACK: [text]" for(var/client/C in GLOB.admins) if(R_ADMIN & C.holder.rights) @@ -197,7 +197,7 @@ var/global/nologevent = 0 for(var/block=1;block<=DNA_SE_LENGTH;block++) if(((block-1)%5)==0) body += "[block-1]" - bname = assigned_blocks[block] + bname = GLOB.assigned_blocks[block] body += "" if(bname) var/bstate=M.dna.GetSEState(block) @@ -306,7 +306,7 @@ var/global/nologevent = 0
    Feed channels and stories entered through here will be uneditable and handled as official news by the rest of the units.
    Note that this panel allows full freedom over the news network, there are no constrictions except the few basic ones. Don't break things!
    "} - if(news_network.wanted_issue) + if(GLOB.news_network.wanted_issue) dat+= "


    Read Wanted Issue" dat+= {"

    Create Feed Channel @@ -316,7 +316,7 @@ var/global/nologevent = 0 "} var/wanted_already = 0 - if(news_network.wanted_issue) + if(GLOB.news_network.wanted_issue) wanted_already = 1 dat+={"
    Feed Security functions:
    @@ -327,10 +327,10 @@ var/global/nologevent = 0 "} if(1) dat+= "Station Feed Channels
    " - if( isemptylist(news_network.network_channels) ) + if( isemptylist(GLOB.news_network.network_channels) ) dat+="No active channels found..." else - for(var/datum/feed_channel/CHANNEL in news_network.network_channels) + for(var/datum/feed_channel/CHANNEL in GLOB.news_network.network_channels) if(CHANNEL.is_admin_channel) dat+="[CHANNEL.channel_name]
    " else @@ -377,7 +377,7 @@ var/global/nologevent = 0 if(src.admincaster_feed_channel.channel_name =="" || src.admincaster_feed_channel.channel_name == "\[REDACTED\]") dat+="•Invalid channel name.
    " var/check = 0 - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == src.admincaster_feed_channel.channel_name) check = 1 break @@ -414,10 +414,10 @@ var/global/nologevent = 0 Keep in mind that users attempting to view a censored feed will instead see the \[REDACTED\] tag above it.

    Select Feed channel to get Stories from:
    "} - if(isemptylist(news_network.network_channels)) + if(isemptylist(GLOB.news_network.network_channels)) dat+="No feed channels found active...
    " else - for(var/datum/feed_channel/CHANNEL in news_network.network_channels) + for(var/datum/feed_channel/CHANNEL in GLOB.news_network.network_channels) dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
    " dat+="
    Cancel" if(11) @@ -427,10 +427,10 @@ var/global/nologevent = 0 morale, integrity or disciplinary behaviour. A D-Notice will render a channel unable to be updated by anyone, without deleting any feed stories it might contain at the time. You can lift a D-Notice if you have the required access at any time.

    "} - if(isemptylist(news_network.network_channels)) + if(isemptylist(GLOB.news_network.network_channels)) dat+="No feed channels found active...
    " else - for(var/datum/feed_channel/CHANNEL in news_network.network_channels) + for(var/datum/feed_channel/CHANNEL in GLOB.news_network.network_channels) dat+="[CHANNEL.channel_name] [(CHANNEL.censored) ? ("***") : ""]
    " dat+="
    Back" @@ -470,7 +470,7 @@ var/global/nologevent = 0 dat+="Wanted Issue Handler:" var/wanted_already = 0 var/end_param = 1 - if(news_network.wanted_issue) + if(GLOB.news_network.wanted_issue) wanted_already = 1 end_param = 2 if(wanted_already) @@ -481,7 +481,7 @@ var/global/nologevent = 0 Description: [src.admincaster_feed_message.body]
    "} if(wanted_already) - dat+="Wanted Issue created by: [news_network.wanted_issue.backup_author]
    " + dat+="Wanted Issue created by: [GLOB.news_network.wanted_issue.backup_author]
    " else dat+="Wanted Issue will be created under prosecutor: [src.admincaster_signature]
    " dat+="
    [(wanted_already) ? ("Edit Issue") : ("Submit")]" @@ -507,13 +507,13 @@ var/global/nologevent = 0 "} if(18) dat+={" - -- STATIONWIDE WANTED ISSUE --
    \[Submitted by: [news_network.wanted_issue.backup_author]\]
    - Criminal: [news_network.wanted_issue.author]
    - Description: [news_network.wanted_issue.body]
    + -- STATIONWIDE WANTED ISSUE --
    \[Submitted by: [GLOB.news_network.wanted_issue.backup_author]\]
    + Criminal: [GLOB.news_network.wanted_issue.author]
    + Description: [GLOB.news_network.wanted_issue.body]
    Photo:: "} - if(news_network.wanted_issue.img) - usr << browse_rsc(news_network.wanted_issue.img, "tmp_photow.png") + if(GLOB.news_network.wanted_issue.img) + usr << browse_rsc(GLOB.news_network.wanted_issue.img, "tmp_photow.png") dat+="
    " else dat+="None" @@ -536,7 +536,7 @@ var/global/nologevent = 0 return var/dat = "Job Bans!
    " - for(var/t in jobban_keylist) + for(var/t in GLOB.jobban_keylist) var/r = t if( findtext(r,"##") ) r = copytext( r, 1, findtext(r,"##") )//removes the description @@ -552,7 +552,7 @@ var/global/nologevent = 0
    Game Panel

    \n Change Game Mode
    "} - if(master_mode == "secret") + if(GLOB.master_mode == "secret") dat += "(Force Secret Mode)
    " dat += {" @@ -714,8 +714,8 @@ var/global/nologevent = 0 if(!check_rights(R_SERVER)) return - enter_allowed = !( enter_allowed ) - if(!( enter_allowed )) + GLOB.enter_allowed = !( GLOB.enter_allowed ) + if(!( GLOB.enter_allowed )) to_chat(world, "New players may no longer enter the game.") else to_chat(world, "New players may now enter the game.") @@ -750,13 +750,13 @@ var/global/nologevent = 0 if(!check_rights(R_SERVER)) return - abandon_allowed = !( abandon_allowed ) - if(abandon_allowed) + GLOB.abandon_allowed = !( GLOB.abandon_allowed ) + if(GLOB.abandon_allowed) to_chat(world, "You may now respawn.") else to_chat(world, "You may no longer respawn :(") - message_admins("[key_name_admin(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].", 1) - log_admin("[key_name(usr)] toggled respawn to [abandon_allowed ? "On" : "Off"].") + message_admins("[key_name_admin(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].", 1) + log_admin("[key_name(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].") world.update_status() feedback_add_details("admin_verb","TR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -768,9 +768,9 @@ var/global/nologevent = 0 if(!check_rights(R_EVENT)) return - aliens_allowed = !aliens_allowed - log_admin("[key_name(usr)] toggled aliens to [aliens_allowed].") - message_admins("[key_name_admin(usr)] toggled aliens [aliens_allowed ? "on" : "off"].") + GLOB.aliens_allowed = !GLOB.aliens_allowed + log_admin("[key_name(usr)] toggled aliens to [GLOB.aliens_allowed].") + message_admins("[key_name_admin(usr)] toggled aliens [GLOB.aliens_allowed ? "on" : "off"].") feedback_add_details("admin_verb","TA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /datum/admins/proc/delay() @@ -786,13 +786,13 @@ var/global/nologevent = 0 log_admin("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].") message_admins("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1) return //alert("Round end delayed", null, null, null, null, null) - if(going) - going = FALSE + if(SSticker.ticker_going) + SSticker.ticker_going = FALSE SSticker.delay_end = TRUE to_chat(world, "The game start has been delayed.") log_admin("[key_name(usr)] delayed the game.") else - going = TRUE + SSticker.ticker_going = TRUE to_chat(world, "The game will start soon.") log_admin("[key_name(usr)] removed the delay.") feedback_add_details("admin_verb","DELAY") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -899,13 +899,13 @@ var/global/nologevent = 0 if(!check_rights(R_SERVER)) return - guests_allowed = !( guests_allowed ) - if(!( guests_allowed )) + GLOB.guests_allowed = !( GLOB.guests_allowed ) + if(!( GLOB.guests_allowed )) to_chat(world, "Guests may no longer enter the game.") else to_chat(world, "Guests may now enter the game.") - log_admin("[key_name(usr)] toggled guests game entering [guests_allowed ? "" : "dis"]allowed.") - message_admins("[key_name_admin(usr)] toggled guests game entering [guests_allowed ? "" : "dis"]allowed.", 1) + log_admin("[key_name(usr)] toggled guests game entering [GLOB.guests_allowed ? "" : "dis"]allowed.") + message_admins("[key_name_admin(usr)] toggled guests game entering [GLOB.guests_allowed ? "" : "dis"]allowed.", 1) feedback_add_details("admin_verb","TGU") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /datum/admins/proc/output_ai_laws() @@ -954,12 +954,12 @@ var/global/nologevent = 0 //ALL DONE //********************************************************************************************************* -var/gamma_ship_location = 1 // 0 = station , 1 = space +GLOBAL_VAR_INIT(gamma_ship_location, 1) // 0 = station , 1 = space /proc/move_gamma_ship() var/area/fromArea var/area/toArea - if(gamma_ship_location == 1) + if(GLOB.gamma_ship_location == 1) fromArea = locate(/area/shuttle/gamma/space) toArea = locate(/area/shuttle/gamma/station) else @@ -970,10 +970,10 @@ var/gamma_ship_location = 1 // 0 = station , 1 = space for(var/obj/machinery/mech_bay_recharge_port/P in toArea) P.update_recharge_turf() - if(gamma_ship_location) - gamma_ship_location = 0 + if(GLOB.gamma_ship_location) + GLOB.gamma_ship_location = 0 else - gamma_ship_location = 1 + GLOB.gamma_ship_location = 1 return /proc/formatJumpTo(var/location,var/where="") diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm index 49b2f06d003..13b786c5174 100644 --- a/code/modules/admin/admin_investigate.dm +++ b/code/modules/admin/admin_investigate.dm @@ -23,18 +23,18 @@ if(!message) return var/F = investigate_subject2file(subject) if(!F) return - investigate_log_subjects |= subject + GLOB.investigate_log_subjects |= subject F << "[time_stamp()] \ref[src] ([x],[y],[z]) || [src] [message]
    " /proc/log_investigate(message, subject) if(!message) return var/F = investigate_subject2file(subject) if(!F) return - investigate_log_subjects |= subject + GLOB.investigate_log_subjects |= subject F << "[time_stamp()] || [message]
    " //ADMINVERBS -/client/proc/investigate_show( subject in investigate_log_subjects ) +/client/proc/investigate_show( subject in GLOB.investigate_log_subjects ) set name = "Investigate" set category = "Admin" if(!holder) return diff --git a/code/modules/admin/admin_memo.dm b/code/modules/admin/admin_memo.dm index 530b9e7958e..455b38e1e0f 100644 --- a/code/modules/admin/admin_memo.dm +++ b/code/modules/admin/admin_memo.dm @@ -3,7 +3,7 @@ set category = "Server" if(!check_rights(R_SERVER)) return - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(src, "Failed to establish database connection.") return var/memotask = input(usr,"Choose task.","Memo") in list("Show","Write","Edit","Remove") @@ -16,13 +16,13 @@ return if(!task) return - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(src, "Failed to establish database connection.") return var/sql_ckey = sanitizeSQL(src.ckey) switch(task) if("Write") - var/DBQuery/query_memocheck = dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")] WHERE ckey = '[sql_ckey]'") + var/DBQuery/query_memocheck = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")] WHERE ckey = '[sql_ckey]'") if(!query_memocheck.Execute()) var/err = query_memocheck.ErrorMsg() log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n") @@ -35,7 +35,7 @@ return memotext = sanitizeSQL(memotext) var/timestamp = SQLtime() - var/DBQuery/query_memoadd = dbcon.NewQuery("INSERT INTO [format_table_name("memo")] (ckey, memotext, timestamp) VALUES ('[sql_ckey]', '[memotext]', '[timestamp]')") + var/DBQuery/query_memoadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("memo")] (ckey, memotext, timestamp) VALUES ('[sql_ckey]', '[memotext]', '[timestamp]')") if(!query_memoadd.Execute()) var/err = query_memoadd.ErrorMsg() log_game("SQL ERROR adding new memo. Error : \[[err]\]\n") @@ -43,7 +43,7 @@ log_admin("[key_name(src)] has set a memo: [memotext]") message_admins("[key_name_admin(src)] has set a memo:
    [memotext]") if("Edit") - var/DBQuery/query_memolist = dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]") + var/DBQuery/query_memolist = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]") if(!query_memolist.Execute()) var/err = query_memolist.ErrorMsg() log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n") @@ -59,7 +59,7 @@ if(!target_ckey) return var/target_sql_ckey = sanitizeSQL(target_ckey) - var/DBQuery/query_memofind = dbcon.NewQuery("SELECT memotext FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'") + var/DBQuery/query_memofind = GLOB.dbcon.NewQuery("SELECT memotext FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'") if(!query_memofind.Execute()) var/err = query_memofind.ErrorMsg() log_game("SQL ERROR obtaining memotext from memo table. Error : \[[err]\]\n") @@ -72,7 +72,7 @@ new_memo = sanitizeSQL(new_memo) var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from
    [old_memo]
    to
    [new_memo]
    " edit_text = sanitizeSQL(edit_text) - var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("memo")] SET memotext = '[new_memo]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'") + var/DBQuery/update_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("memo")] SET memotext = '[new_memo]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'") if(!update_query.Execute()) var/err = update_query.ErrorMsg() log_game("SQL ERROR editing memo. Error : \[[err]\]\n") @@ -84,7 +84,7 @@ log_admin("[key_name(src)] has edited [target_sql_ckey]'s memo from \"[old_memo]\" to \"[new_memo]\"") message_admins("[key_name_admin(src)] has edited [target_sql_ckey]'s memo from \"[old_memo]\" to \"[new_memo]\"") if("Show") - var/DBQuery/query_memoshow = dbcon.NewQuery("SELECT ckey, memotext, timestamp, last_editor FROM [format_table_name("memo")]") + var/DBQuery/query_memoshow = GLOB.dbcon.NewQuery("SELECT ckey, memotext, timestamp, last_editor FROM [format_table_name("memo")]") if(!query_memoshow.Execute()) var/err = query_memoshow.ErrorMsg() log_game("SQL ERROR obtaining ckey, memotext, timestamp, last_editor from memo table. Error : \[[err]\]\n") @@ -104,7 +104,7 @@ else if(!silent) to_chat(src, "No memos found in database.") if("Remove") - var/DBQuery/query_memodellist = dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]") + var/DBQuery/query_memodellist = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")]") if(!query_memodellist.Execute()) var/err = query_memodellist.ErrorMsg() log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n") @@ -120,7 +120,7 @@ if(!target_ckey) return var/target_sql_ckey = sanitizeSQL(target_ckey) - var/DBQuery/query_memodel = dbcon.NewQuery("DELETE FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'") + var/DBQuery/query_memodel = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'") if(!query_memodel.Execute()) var/err = query_memodel.ErrorMsg() log_game("SQL ERROR removing memo. Error : \[[err]\]\n") diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm index 82f82d3dabe..5956819d3d4 100644 --- a/code/modules/admin/admin_ranks.dm +++ b/code/modules/admin/admin_ranks.dm @@ -1,8 +1,9 @@ -var/list/admin_ranks = list() //list of all ranks with associated rights +GLOBAL_LIST_EMPTY(admin_ranks) //list of all ranks with associated rights +GLOBAL_PROTECT(admin_ranks) // this shit is being protected for obvious reasons //load our rank - > rights associations /proc/load_admin_ranks() - admin_ranks.Cut() + GLOB.admin_ranks.Cut() var/previous_rights = 0 @@ -43,14 +44,15 @@ var/list/admin_ranks = list() //list of all ranks with associated rights if("mod") rights |= R_MOD if("mentor") rights |= R_MENTOR if("proccall") rights |= R_PROCCALL + if("viewruntimes") rights |= R_VIEWRUNTIMES - admin_ranks[rank] = rights + GLOB.admin_ranks[rank] = rights previous_rights = rights #ifdef TESTING var/msg = "Permission Sets Built:\n" - for(var/rank in admin_ranks) - msg += "\t[rank] - [admin_ranks[rank]]\n" + for(var/rank in GLOB.admin_ranks) + msg += "\t[rank] - [GLOB.admin_ranks[rank]]\n" testing(msg) #endif @@ -60,12 +62,16 @@ var/list/admin_ranks = list() //list of all ranks with associated rights /proc/load_admins() //clear the datums references - admin_datums.Cut() + GLOB.admin_datums.Cut() for(var/client/C in GLOB.admins) C.remove_admin_verbs() C.holder = null GLOB.admins.Cut() + // Remove all profiler access + for(var/A in world.GetConfig("admin")) + world.SetConfig("APP/admin", A, null) + if(config.admin_legacy_system) load_admin_ranks() @@ -91,11 +97,14 @@ var/list/admin_ranks = list() //list of all ranks with associated rights rank = ckeyEx(List[2]) //load permissions associated with this rank - var/rights = admin_ranks[rank] + var/rights = GLOB.admin_ranks[rank] //create the admin datum and store it for later use var/datum/admins/D = new /datum/admins(rank, rights, ckey) + if(D.rights & R_DEBUG || D.rights & R_VIEWRUNTIMES) // Grants profiler access to anyone with R_DEBUG or R_VIEWRUNTIMES + world.SetConfig("APP/admin", ckey, "role=admin") + //find the client for a ckey if they are connected and associate them with the new admin datum D.associate(GLOB.directory[ckey]) @@ -103,13 +112,13 @@ var/list/admin_ranks = list() //list of all ranks with associated rights //The current admin system uses SQL establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) log_world("Failed to connect to database in load_admins(). Reverting to legacy system.") config.admin_legacy_system = 1 load_admins() return - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, level, flags FROM [format_table_name("admin")]") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, rank, level, flags FROM [format_table_name("admin")]") query.Execute() while(query.NextRow()) var/ckey = query.item[1] @@ -120,9 +129,12 @@ var/list/admin_ranks = list() //list of all ranks with associated rights if(istext(rights)) rights = text2num(rights) var/datum/admins/D = new /datum/admins(rank, rights, ckey) + if(D.rights & R_DEBUG || D.rights & R_VIEWRUNTIMES) // Grants profiler access to anyone with R_DEBUG or R_VIEWRUNTIMES + world.SetConfig("APP/admin", ckey, "role=admin") + //find the client for a ckey if they are connected and associate them with the new admin datum D.associate(GLOB.directory[ckey]) - if(!admin_datums) + if(!GLOB.admin_datums) log_world("The database query in load_admins() resulted in no admins being added to the list. Reverting to legacy system.") config.admin_legacy_system = 1 load_admins() @@ -130,9 +142,9 @@ var/list/admin_ranks = list() //list of all ranks with associated rights #ifdef TESTING var/msg = "Admins Built:\n" - for(var/ckey in admin_datums) + for(var/ckey in GLOB.admin_datums) var/rank - var/datum/admins/D = admin_datums[ckey] + var/datum/admins/D = GLOB.admin_datums[ckey] if(D) rank = D.rank msg += "\t[ckey] - [rank]\n" testing(msg) @@ -140,12 +152,12 @@ var/list/admin_ranks = list() //list of all ranks with associated rights #ifdef TESTING -/client/verb/changerank(newrank in admin_ranks) +/client/verb/changerank(newrank in GLOB.admin_ranks) if(holder) holder.rank = newrank - holder.rights = admin_ranks[newrank] + holder.rights = GLOB.admin_ranks[newrank] else - holder = new /datum/admins(newrank,admin_ranks[newrank],ckey) + holder = new /datum/admins(newrank,GLOB.admin_ranks[newrank],ckey) remove_admin_verbs() holder.associate(src) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 9a60d41aa66..4e3d2d65f30 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -1,13 +1,13 @@ //admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless -var/list/admin_verbs_default = list( +GLOBAL_LIST_INIT(admin_verbs_default, list( /client/proc/deadmin_self, /*destroys our own admin datum so we can play as a regular player*/ /client/proc/hide_verbs, /*hides all our adminverbs*/ /client/proc/toggleadminhelpsound, /client/proc/togglementorhelpsound, /client/proc/cmd_mentor_check_new_players, /client/proc/cmd_mentor_check_player_exp /* shows players by playtime */ - ) -var/list/admin_verbs_admin = list( + )) +GLOBAL_LIST_INIT(admin_verbs_admin, list( /client/proc/check_antagonists, /*shows all antags*/ /datum/admins/proc/show_player_panel, /client/proc/player_panel, /*shows an interface for all players, with links to various panels (old style)*/ @@ -26,6 +26,7 @@ var/list/admin_verbs_admin = list( /client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/ /client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/ /client/proc/cmd_admin_check_contents, /*displays the contents of an instance*/ + /client/proc/cmd_admin_open_logging_view, /client/proc/getserverlogs, /*allows us to fetch server logs (diary) for other days*/ /client/proc/jumptocoord, /*we ghost and jump to a coordinate*/ /client/proc/Getmob, /*teleports a mob to our location*/ @@ -67,7 +68,6 @@ var/list/admin_verbs_admin = list( /client/proc/empty_ai_core_toggle_latejoin, /client/proc/aooc, /client/proc/freeze, - /client/proc/freezemecha, /client/proc/alt_check, /client/proc/secrets, /client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */ @@ -79,20 +79,20 @@ var/list/admin_verbs_admin = list( /client/proc/list_ssds_afks, /client/proc/cmd_admin_headset_message, /client/proc/spawn_floor_cluwne -) -var/list/admin_verbs_ban = list( +)) +GLOBAL_LIST_INIT(admin_verbs_ban, list( /client/proc/unban_panel, /client/proc/jobbans, /client/proc/stickybanpanel - ) -var/list/admin_verbs_sounds = list( + )) +GLOBAL_LIST_INIT(admin_verbs_sounds, list( /client/proc/play_local_sound, /client/proc/play_sound, /client/proc/play_server_sound, /client/proc/play_intercomm_sound, /client/proc/stop_global_admin_sounds - ) -var/list/admin_verbs_event = list( + )) +GLOBAL_LIST_INIT(admin_verbs_event, list( /client/proc/object_talk, /client/proc/cmd_admin_dress, /client/proc/cmd_admin_gib_self, @@ -117,14 +117,14 @@ var/list/admin_verbs_event = list( /client/proc/event_manager_panel, /client/proc/modify_goals, /client/proc/outfit_manager - ) + )) -var/list/admin_verbs_spawn = list( +GLOBAL_LIST_INIT(admin_verbs_spawn, list( /datum/admins/proc/spawn_atom, /*allows us to spawn instances*/ /client/proc/respawn_character, /client/proc/admin_deserialize - ) -var/list/admin_verbs_server = list( + )) +GLOBAL_LIST_INIT(admin_verbs_server, list( /client/proc/ToRban, /client/proc/Set_Holiday, /datum/admins/proc/startnow, @@ -144,8 +144,8 @@ var/list/admin_verbs_server = list( /client/proc/toggle_antagHUD_restrictions, /client/proc/set_ooc, /client/proc/reset_ooc - ) -var/list/admin_verbs_debug = list( + )) +GLOBAL_LIST_INIT(admin_verbs_debug, list( /client/proc/cmd_admin_list_open_jobs, /client/proc/Debug2, /client/proc/cmd_debug_make_powernets, @@ -172,21 +172,21 @@ var/list/admin_verbs_debug = list( /client/proc/admin_serialize, /client/proc/jump_to_ruin, /client/proc/toggle_medal_disable, - ) -var/list/admin_verbs_possess = list( + )) +GLOBAL_LIST_INIT(admin_verbs_possess, list( /proc/possess, /proc/release - ) -var/list/admin_verbs_permissions = list( + )) +GLOBAL_LIST_INIT(admin_verbs_permissions, list( /client/proc/edit_admin_permissions, /client/proc/create_poll, /client/proc/big_brother - ) -var/list/admin_verbs_rejuv = list( + )) +GLOBAL_LIST_INIT(admin_verbs_rejuv, list( /client/proc/respawn_character, /client/proc/cmd_admin_rejuvenate - ) -var/list/admin_verbs_mod = list( + )) +GLOBAL_LIST_INIT(admin_verbs_mod, list( /client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/ /client/proc/cmd_admin_pm_panel, /*admin-pm list*/ /client/proc/cmd_admin_pm_by_key_panel, /*admin-pm list by key*/ @@ -199,8 +199,8 @@ var/list/admin_verbs_mod = list( /datum/admins/proc/show_player_panel, /client/proc/jobbans, /client/proc/debug_variables /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/ -) -var/list/admin_verbs_mentor = list( +)) +GLOBAL_LIST_INIT(admin_verbs_mentor, list( /client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/ /client/proc/cmd_admin_pm_panel, /*admin-pm list*/ /client/proc/cmd_admin_pm_by_key_panel, /*admin-pm list by key*/ @@ -208,20 +208,20 @@ var/list/admin_verbs_mentor = list( /client/proc/toggleMentorTicketLogs, /client/proc/cmd_mentor_say /* mentor say*/ // cmd_mentor_say is added/removed by the toggle_mentor_chat verb -) -var/list/admin_verbs_proccall = list( +)) +GLOBAL_LIST_INIT(admin_verbs_proccall, list( /client/proc/callproc, /client/proc/callproc_datum, /client/proc/SDQL2_query -) -var/list/admin_verbs_ticket = list( +)) +GLOBAL_LIST_INIT(admin_verbs_ticket, list( /client/proc/openAdminTicketUI, /client/proc/toggleticketlogs, /client/proc/openMentorTicketUI, /client/proc/toggleMentorTicketLogs, /client/proc/resolveAllAdminTickets, /client/proc/resolveAllMentorTickets -) +)) /client/proc/on_holder_add() if(chatOutput && chatOutput.loaded) @@ -229,62 +229,71 @@ var/list/admin_verbs_ticket = list( /client/proc/add_admin_verbs() if(holder) - verbs += admin_verbs_default + // If they have ANYTHING OTHER THAN ONLY VIEW RUNTIMES (65536), then give them the default admin verbs + if(holder.rights != R_VIEWRUNTIMES) + verbs += GLOB.admin_verbs_default if(holder.rights & R_BUILDMODE) verbs += /client/proc/togglebuildmodeself if(holder.rights & R_ADMIN) - verbs += admin_verbs_admin - verbs += admin_verbs_ticket + verbs += GLOB.admin_verbs_admin + verbs += GLOB.admin_verbs_ticket spawn(1) control_freak = 0 if(holder.rights & R_BAN) - verbs += admin_verbs_ban + verbs += GLOB.admin_verbs_ban if(holder.rights & R_EVENT) - verbs += admin_verbs_event + verbs += GLOB.admin_verbs_event if(holder.rights & R_SERVER) - verbs += admin_verbs_server + verbs += GLOB.admin_verbs_server if(holder.rights & R_DEBUG) - verbs += admin_verbs_debug + verbs += GLOB.admin_verbs_debug + spawn(1) + control_freak = 0 // Setting control_freak to 0 allows you to use the Profiler and other client-side tools if(holder.rights & R_POSSESS) - verbs += admin_verbs_possess + verbs += GLOB.admin_verbs_possess if(holder.rights & R_PERMISSIONS) - verbs += admin_verbs_permissions + verbs += GLOB.admin_verbs_permissions if(holder.rights & R_STEALTH) verbs += /client/proc/stealth if(holder.rights & R_REJUVINATE) - verbs += admin_verbs_rejuv + verbs += GLOB.admin_verbs_rejuv if(holder.rights & R_SOUNDS) - verbs += admin_verbs_sounds + verbs += GLOB.admin_verbs_sounds if(holder.rights & R_SPAWN) - verbs += admin_verbs_spawn + verbs += GLOB.admin_verbs_spawn if(holder.rights & R_MOD) - verbs += admin_verbs_mod + verbs += GLOB.admin_verbs_mod if(holder.rights & R_MENTOR) - verbs += admin_verbs_mentor + verbs += GLOB.admin_verbs_mentor if(holder.rights & R_PROCCALL) - verbs += admin_verbs_proccall + verbs += GLOB.admin_verbs_proccall + if(holder.rights & R_VIEWRUNTIMES) + verbs += /client/proc/view_runtimes + spawn(1) // This setting exposes the profiler for people with R_VIEWRUNTIMES. They must still have it set in cfg/admin.txt + control_freak = 0 + /client/proc/remove_admin_verbs() verbs.Remove( - admin_verbs_default, + GLOB.admin_verbs_default, /client/proc/togglebuildmodeself, - admin_verbs_admin, - admin_verbs_ban, - admin_verbs_event, - admin_verbs_server, - admin_verbs_debug, - admin_verbs_possess, - admin_verbs_permissions, + GLOB.admin_verbs_admin, + GLOB.admin_verbs_ban, + GLOB.admin_verbs_event, + GLOB.admin_verbs_server, + GLOB.admin_verbs_debug, + GLOB.admin_verbs_possess, + GLOB.admin_verbs_permissions, /client/proc/stealth, - admin_verbs_rejuv, - admin_verbs_sounds, - admin_verbs_spawn, - admin_verbs_mod, - admin_verbs_mentor, - admin_verbs_proccall, - admin_verbs_show_debug_verbs, + GLOB.admin_verbs_rejuv, + GLOB.admin_verbs_sounds, + GLOB.admin_verbs_spawn, + GLOB.admin_verbs_mod, + GLOB.admin_verbs_mentor, + GLOB.admin_verbs_proccall, + GLOB.admin_verbs_show_debug_verbs, /client/proc/readmin, - admin_verbs_ticket + GLOB.admin_verbs_ticket ) /client/proc/hide_verbs() @@ -514,14 +523,14 @@ var/list/admin_verbs_ticket = list( return if(!warned_ckey || !istext(warned_ckey)) return - if(warned_ckey in admin_datums) + if(warned_ckey in GLOB.admin_datums) to_chat(usr, "Error: warn(): You can't warn admins.") return var/datum/preferences/D var/client/C = GLOB.directory[warned_ckey] if(C) D = C.prefs - else D = preferences_datums[warned_ckey] + else D = GLOB.preferences_datums[warned_ckey] if(!D) to_chat(src, "Error: warn(): No such ckey found.") @@ -601,7 +610,7 @@ var/list/admin_verbs_ticket = list( var/list/spell_list = list() var/type_length = length("/obj/effect/proc_holder/spell") + 2 - for(var/A in spells) + for(var/A in GLOB.spells) spell_list[copytext("[A]", type_length)] = A var/obj/effect/proc_holder/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spell_list if(!S) @@ -620,7 +629,7 @@ var/list/admin_verbs_ticket = list( set category = "Event" set name = "Give Disease" set desc = "Gives a Disease to a mob." - var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in diseases + var/datum/disease/D = input("Choose the disease to give to that guy", "ACHOO") as null|anything in GLOB.diseases if(!D) return T.ForceContractDisease(new D) feedback_add_details("admin_verb","GD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -694,7 +703,7 @@ var/list/admin_verbs_ticket = list( set category = "Admin" set desc = "Regain your admin powers." - var/datum/admins/D = admin_datums[ckey] + var/datum/admins/D = GLOB.admin_datums[ckey] var/rank = null if(config.admin_legacy_system) //load text from file @@ -707,26 +716,26 @@ var/list/admin_verbs_ticket = list( break continue else - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) message_admins("Warning, MySQL database is not connected.") to_chat(src, "Warning, MYSQL database is not connected.") return var/sql_ckey = sanitizeSQL(ckey) - var/DBQuery/query = dbcon.NewQuery("SELECT rank FROM [format_table_name("admin")] WHERE ckey = '[sql_ckey]'") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT rank FROM [format_table_name("admin")] WHERE ckey = '[sql_ckey]'") query.Execute() while(query.NextRow()) rank = ckeyEx(query.item[1]) if(!D) if(config.admin_legacy_system) - if(admin_ranks[rank] == null) + if(GLOB.admin_ranks[rank] == null) error("Error while re-adminning [src], admin rank ([rank]) does not exist.") to_chat(src, "Error while re-adminning, admin rank ([rank]) does not exist.") return - D = new(rank, admin_ranks[rank], ckey) + D = new(rank, GLOB.admin_ranks[rank], ckey) else var/sql_ckey = sanitizeSQL(ckey) - var/DBQuery/query = dbcon.NewQuery("SELECT ckey, rank, flags FROM [format_table_name("admin")] WHERE ckey = '[sql_ckey]'") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey, rank, flags FROM [format_table_name("admin")] WHERE ckey = '[sql_ckey]'") query.Execute() while(query.NextRow()) var/admin_ckey = query.item[1] @@ -791,7 +800,7 @@ var/list/admin_verbs_ticket = list( if(!S) return var/datum/nano_module/law_manager/L = new(S) - L.ui_interact(usr, state = admin_state) + L.ui_interact(usr, state = GLOB.admin_state) log_and_message_admins("has opened [S]'s law manager.") feedback_add_details("admin_verb","MSL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/banappearance.dm b/code/modules/admin/banappearance.dm index ff461c0f333..b561e0169ff 100644 --- a/code/modules/admin/banappearance.dm +++ b/code/modules/admin/banappearance.dm @@ -1,22 +1,22 @@ //ban people from using custom names and appearances. that'll show 'em. -var/appearanceban_runonce //Updates legacy bans with new info -var/appearance_keylist[0] //to store the keys +GLOBAL_VAR(appearanceban_runonce) //Updates legacy bans with new info +GLOBAL_LIST_EMPTY(appearance_keylist) //to store the keys /proc/appearance_fullban(mob/M, reason) if(!M || !M.key) return - appearance_keylist.Add(text("[M.ckey] ## [reason]")) + GLOB.appearance_keylist.Add(text("[M.ckey] ## [reason]")) appearance_savebanfile() /proc/appearance_client_fullban(ckey) if(!ckey) return - appearance_keylist.Add(text("[ckey]")) + GLOB.appearance_keylist.Add(text("[ckey]")) appearance_savebanfile() //returns a reason if M is banned, returns 0 otherwise /proc/appearance_isbanned(mob/M) if(M) - for(var/s in appearance_keylist) + for(var/s in GLOB.appearance_keylist) if(findtext(s, "[M.ckey]") == 1) var/startpos = findtext(s, "## ") + 3 if(startpos && startpos < length(s)) @@ -43,12 +43,12 @@ DEBUG /proc/appearance_loadbanfile() if(config.ban_legacy_system) var/savefile/S=new("data/appearance_full.ban") - S["keys[0]"] >> appearance_keylist + S["keys[0]"] >> GLOB.appearance_keylist log_admin("Loading appearance_rank") - S["runonce"] >> appearanceban_runonce + S["runonce"] >> GLOB.appearanceban_runonce - if(!length(appearance_keylist)) - appearance_keylist=list() + if(!length(GLOB.appearance_keylist)) + GLOB.appearance_keylist=list() log_admin("appearance_keylist was empty") else if(!establish_db_connection()) @@ -58,17 +58,17 @@ DEBUG return //appearance bans - var/DBQuery/query = dbcon.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("ban")] WHERE bantype = 'APPEARANCE_BAN' AND NOT unbanned = 1") query.Execute() while(query.NextRow()) var/ckey = query.item[1] - appearance_keylist.Add("[ckey]") + GLOB.appearance_keylist.Add("[ckey]") /proc/appearance_savebanfile() var/savefile/S=new("data/appearance_full.ban") - to_chat(S["keys[0]"], appearance_keylist) + to_chat(S["keys[0]"], GLOB.appearance_keylist) /proc/appearance_unban(mob/M) appearance_remove("[M.ckey]") @@ -76,18 +76,18 @@ DEBUG /proc/appearance_updatelegacybans() - if(!appearanceban_runonce) + if(!GLOB.appearanceban_runonce) log_admin("Updating appearancefile!") // Updates bans.. Or fixes them. Either way. - for(var/T in appearance_keylist) + for(var/T in GLOB.appearance_keylist) if(!T) continue - appearanceban_runonce++ //don't run this update again + GLOB.appearanceban_runonce++ //don't run this update again /proc/appearance_remove(X) - for(var/i = 1; i <= length(appearance_keylist); i++) - if( findtext(appearance_keylist[i], "[X]") ) - appearance_keylist.Remove(appearance_keylist[i]) + for(var/i = 1; i <= length(GLOB.appearance_keylist); i++) + if( findtext(GLOB.appearance_keylist[i], "[X]") ) + GLOB.appearance_keylist.Remove(GLOB.appearance_keylist[i]) appearance_savebanfile() return 1 return 0 diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index 81060503f06..9efc4c9ce88 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -1,21 +1,21 @@ -var/jobban_runonce // Updates legacy bans with new info -var/jobban_keylist[0] // Linear list of jobban strings, kept around for the legacy system -var/jobban_assoclist[0] // Associative list, for efficiency +GLOBAL_VAR(jobban_runonce) // Updates legacy bans with new info +GLOBAL_LIST_INIT(jobban_keylist, new()) // Linear list of jobban strings, kept around for the legacy system +GLOBAL_LIST_INIT(jobban_assoclist, new()) // Associative list, for efficiency // Matches string-based jobbans into ckey, rank, and reason groups -var/regex/jobban_regex = regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ## (.+))?") +GLOBAL_DATUM_INIT(jobban_regex, /regex, regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ## (.+))?")) /proc/jobban_assoc_insert(ckey, rank, reason) if(!ckey || !rank) return - if(!jobban_assoclist[ckey]) - jobban_assoclist[ckey] = list() - jobban_assoclist[ckey][rank] = reason || "Reason Unspecified" + if(!GLOB.jobban_assoclist[ckey]) + GLOB.jobban_assoclist[ckey] = list() + GLOB.jobban_assoclist[ckey][rank] = reason || "Reason Unspecified" /proc/jobban_fullban(mob/M, rank, reason) if(!M || !M.key) return - jobban_keylist.Add(text("[M.ckey] - [rank] ## [reason]")) + GLOB.jobban_keylist.Add(text("[M.ckey] - [rank] ## [reason]")) jobban_assoc_insert(M.ckey, rank, reason) if(config.ban_legacy_system) jobban_savebanfile() @@ -23,7 +23,7 @@ var/regex/jobban_regex = regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ## (.+))?") /proc/jobban_client_fullban(ckey, rank) if(!ckey || !rank) return - jobban_keylist.Add(text("[ckey] - [rank]")) + GLOB.jobban_keylist.Add(text("[ckey] - [rank]")) jobban_assoc_insert(ckey, rank) if(config.ban_legacy_system) jobban_savebanfile() @@ -37,8 +37,8 @@ var/regex/jobban_regex = regex("(\[\\S]+) - (\[^#]+\[^# ])(?: ## (.+))?") if(IsGuestKey(M.key)) return "Guest Job-ban" - if(jobban_assoclist[M.ckey]) - return jobban_assoclist[M.ckey][rank] + if(GLOB.jobban_assoclist[M.ckey]) + return GLOB.jobban_assoclist[M.ckey][rank] else return 0 @@ -63,17 +63,17 @@ DEBUG /proc/jobban_loadbanfile() if(config.ban_legacy_system) var/savefile/S=new("data/job_full.ban") - S["keys[0]"] >> jobban_keylist + S["keys[0]"] >> GLOB.jobban_keylist log_admin("Loading jobban_rank") - S["runonce"] >> jobban_runonce + S["runonce"] >> GLOB.jobban_runonce - if(!length(jobban_keylist)) - jobban_keylist=list() + if(!length(GLOB.jobban_keylist)) + GLOB.jobban_keylist=list() log_admin("jobban_keylist was empty") - for(var/s in jobban_keylist) - if(jobban_regex.Find(s)) - jobban_assoc_insert(jobban_regex.group[1], jobban_regex.group[2], jobban_regex.group[3]) + for(var/s in GLOB.jobban_keylist) + if(GLOB.jobban_regex.Find(s)) + jobban_assoc_insert(GLOB.jobban_regex.group[1], GLOB.jobban_regex.group[2], GLOB.jobban_regex.group[3]) else log_runtime(EXCEPTION("Skipping malformed job ban: [s]")) else @@ -84,10 +84,10 @@ DEBUG return //Job permabans - var/DBQuery/permabans = dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)") + var/DBQuery/permabans = GLOB.dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_PERMABAN' AND isnull(unbanned)") permabans.Execute() // Job tempbans - var/DBQuery/tempbans = dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()") + var/DBQuery/tempbans = GLOB.dbcon.NewQuery("SELECT ckey, job FROM [format_table_name("ban")] WHERE bantype = 'JOB_TEMPBAN' AND isnull(unbanned) AND expiration_time > Now()") tempbans.Execute() while(TRUE) @@ -102,12 +102,12 @@ DEBUG else break - jobban_keylist.Add("[ckey] - [job]") + GLOB.jobban_keylist.Add("[ckey] - [job]") jobban_assoc_insert(ckey, job) /proc/jobban_savebanfile() var/savefile/S=new("data/job_full.ban") - S["keys[0]"] << jobban_keylist + S["keys[0]"] << GLOB.jobban_keylist /proc/jobban_unban(mob/M, rank) jobban_remove("[M.ckey] - [rank]") @@ -120,19 +120,19 @@ DEBUG /proc/jobban_remove(X) - for(var/i = 1; i <= length(jobban_keylist); i++) - if( findtext(jobban_keylist[i], "[X]") ) + for(var/i = 1; i <= length(GLOB.jobban_keylist); i++) + if( findtext(GLOB.jobban_keylist[i], "[X]") ) // This need to be here, instead of jobban_unban, due to direct calls to jobban_remove - if(jobban_regex.Find(X)) - var/ckey = jobban_regex.group[1] - var/rank = jobban_regex.group[2] - if(jobban_assoclist[ckey] && jobban_assoclist[ckey][rank]) - jobban_assoclist[ckey] -= rank + if(GLOB.jobban_regex.Find(X)) + var/ckey = GLOB.jobban_regex.group[1] + var/rank = GLOB.jobban_regex.group[2] + if(GLOB.jobban_assoclist[ckey] && GLOB.jobban_assoclist[ckey][rank]) + GLOB.jobban_assoclist[ckey] -= rank else log_runtime(EXCEPTION("Attempted to remove non-existent job ban: [X]")) else log_runtime(EXCEPTION("Failed to remove malformed job ban from associative list: [X]")) - jobban_keylist.Remove(jobban_keylist[i]) + GLOB.jobban_keylist.Remove(GLOB.jobban_keylist[i]) if(config.ban_legacy_system) jobban_savebanfile() return 1 @@ -152,7 +152,7 @@ DEBUG else //using the SQL ban system var/is_actually_banned = FALSE - var/DBQuery/select_query = dbcon.NewQuery("SELECT bantime, bantype, reason, job, duration, expiration_time, a_ckey FROM [format_table_name("ban")] WHERE ckey like '[ckey]' AND ((bantype like 'JOB_TEMPBAN' AND expiration_time > Now()) OR (bantype like 'JOB_PERMABAN')) AND isnull(unbanned) ORDER BY bantime DESC LIMIT 100") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT bantime, bantype, reason, job, duration, expiration_time, a_ckey FROM [format_table_name("ban")] WHERE ckey like '[ckey]' AND ((bantype like 'JOB_TEMPBAN' AND expiration_time > Now()) OR (bantype like 'JOB_PERMABAN')) AND isnull(unbanned) ORDER BY bantime DESC LIMIT 100") select_query.Execute() while(select_query.NextRow()) diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index e6148c7f554..616d5aa9ee8 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -1,9 +1,9 @@ -/var/create_mob_html = null +GLOBAL_VAR(create_mob_html) /datum/admins/proc/create_mob(var/mob/user) - if(!create_mob_html) + if(!GLOB.create_mob_html) var/mobjs = null mobjs = jointext(typesof(/mob), ";") - create_mob_html = file2text('html/create_object.html') - create_mob_html = replacetext(create_mob_html, "null /* object types */", "\"[mobjs]\"") + GLOB.create_mob_html = file2text('html/create_object.html') + GLOB.create_mob_html = replacetext(GLOB.create_mob_html, "null /* object types */", "\"[mobjs]\"") - user << browse(replacetext(create_mob_html, "/* ref src */", UID()), "window=create_mob;size=425x475") + user << browse(replacetext(GLOB.create_mob_html, "/* ref src */", UID()), "window=create_mob;size=425x475") diff --git a/code/modules/admin/create_object.dm b/code/modules/admin/create_object.dm index e3a930058bd..c311be0d017 100644 --- a/code/modules/admin/create_object.dm +++ b/code/modules/admin/create_object.dm @@ -1,23 +1,23 @@ -var/create_object_html = null -var/list/create_object_forms = list(/obj, /obj/structure, /obj/machinery, /obj/effect, /obj/item, /obj/mecha, /obj/item/clothing, /obj/item/stack, /obj/item/reagent_containers, /obj/item/gun) +GLOBAL_VAR(create_object_html) +GLOBAL_LIST_INIT(create_object_forms, list(/obj, /obj/structure, /obj/machinery, /obj/effect, /obj/item, /obj/mecha, /obj/item/clothing, /obj/item/stack, /obj/item/reagent_containers, /obj/item/gun)) /datum/admins/proc/create_object(var/mob/user) - if(!create_object_html) + if(!GLOB.create_object_html) var/objectjs = null objectjs = jointext(typesof(/obj), ";") - create_object_html = file2text('html/create_object.html') - create_object_html = replacetext(create_object_html, "null /* object types */", "\"[objectjs]\"") + GLOB.create_object_html = file2text('html/create_object.html') + GLOB.create_object_html = replacetext(GLOB.create_object_html, "null /* object types */", "\"[objectjs]\"") - user << browse(replacetext(create_object_html, "/* ref src */", UID()), "window=create_object;size=425x475") + user << browse(replacetext(GLOB.create_object_html, "/* ref src */", UID()), "window=create_object;size=425x475") /datum/admins/proc/quick_create_object(var/mob/user) - var/path = input("Select the path of the object you wish to create.", "Path", /obj) in create_object_forms - var/html_form = create_object_forms[path] + var/path = input("Select the path of the object you wish to create.", "Path", /obj) in GLOB.create_object_forms + var/html_form = GLOB.create_object_forms[path] if(!html_form) var/objectjs = jointext(typesof(path), ";") html_form = file2text('html/create_object.html') html_form = replacetext(html_form, "null /* object types */", "\"[objectjs]\"") - create_object_forms[path] = html_form + GLOB.create_object_forms[path] = html_form user << browse(replacetext(html_form, "/* ref src */", UID()), "window=qco[path];size=425x475") diff --git a/code/modules/admin/create_poll.dm b/code/modules/admin/create_poll.dm index a1c6de98d93..63592663469 100644 --- a/code/modules/admin/create_poll.dm +++ b/code/modules/admin/create_poll.dm @@ -1,15 +1,15 @@ /client/proc/create_poll() set name = "Create Server Poll" set category = "Server" - if(!check_rights(R_SERVER)) + if(!check_rights(R_SERVER)) return - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(src, "Failed to establish database connection.") return create_poll_window() /client/proc/create_poll_window(var/errormessage = "") - if(!check_rights(R_SERVER)) + if(!check_rights(R_SERVER)) return var/output={" @@ -75,7 +75,7 @@ function onload() {
    "} - for(var/adm_ckey in admin_datums) - var/datum/admins/D = admin_datums[adm_ckey] + for(var/adm_ckey in GLOB.admin_datums) + var/datum/admins/D = GLOB.admin_datums[adm_ckey] if(!D) continue var/rank = D.rank ? D.rank : "*none*" var/rights = rights2text(D.rights," ") @@ -62,7 +62,7 @@ establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection") return @@ -77,7 +77,7 @@ if(!istext(adm_ckey) || !istext(new_rank)) return - var/DBQuery/select_query = dbcon.NewQuery("SELECT id FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'") select_query.Execute() var/new_admin = 1 @@ -88,16 +88,16 @@ flag_account_for_forum_sync(adm_ckey) if(new_admin) - var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin")] (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)") + var/DBQuery/insert_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin")] (`id`, `ckey`, `rank`, `level`, `flags`) VALUES (null, '[adm_ckey]', '[new_rank]', -1, 0)") insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');") + var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added new admin [adm_ckey] to rank [new_rank]');") log_query.Execute() to_chat(usr, "New admin added.") else if(!isnull(admin_id) && isnum(admin_id)) - var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE id = [admin_id]") + var/DBQuery/insert_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("admin")] SET rank = '[new_rank]' WHERE id = [admin_id]") insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');") + var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Edited the rank of [adm_ckey] to [new_rank]');") log_query.Execute() to_chat(usr, "Admin rank changed.") @@ -112,7 +112,7 @@ return establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection") return @@ -130,7 +130,7 @@ if(!istext(adm_ckey) || !isnum(new_permission)) return - var/DBQuery/select_query = dbcon.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id, flags FROM [format_table_name("admin")] WHERE ckey = '[adm_ckey]'") select_query.Execute() var/admin_id @@ -144,27 +144,27 @@ flag_account_for_forum_sync(adm_ckey) if(admin_rights & new_permission) //This admin already has this permission, so we are removing it. - var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]") + var/DBQuery/insert_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = [admin_rights & ~new_permission] WHERE id = [admin_id]") insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');") + var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Removed permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]');") log_query.Execute() to_chat(usr, "Permission removed.") else //This admin doesn't have this permission, so we are adding it. - var/DBQuery/insert_query = dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]") + var/DBQuery/insert_query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("admin")] SET flags = '[admin_rights | new_permission]' WHERE id = [admin_id]") insert_query.Execute() - var/DBQuery/log_query = dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')") + var/DBQuery/log_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("admin_log")] (`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (Now() , '[usr.ckey]', '[usr.client.address]', 'Added permission [rights2text(new_permission)] (flag = [new_permission]) to admin [adm_ckey]')") log_query.Execute() to_chat(usr, "Permission added.") /datum/admins/proc/updateranktodb(ckey,newrank) establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) return if(!check_rights(R_PERMISSIONS)) return var/sql_ckey = sanitizeSQL(ckey) var/sql_admin_rank = sanitizeSQL(newrank) - var/DBQuery/query_update = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sql_admin_rank]' WHERE ckey = '[sql_ckey]'") + var/DBQuery/query_update = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastadminrank = '[sql_admin_rank]' WHERE ckey = '[sql_ckey]'") query_update.Execute() flag_account_for_forum_sync(sql_ckey) diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 9ed6f0cd997..0d55840b5b8 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -2,6 +2,10 @@ /datum/admins/proc/player_panel_new()//The new one if(!usr.client.holder) return + // This stops the panel from being invoked by mentors who press F7. + if(!check_rights(R_ADMIN)) + message_admins("[key_name_admin(usr)] attempted to invoke player panel without admin rights. If this is a mentor, its a chance they accidentally hit F7. If this is NOT a mentor, there is a high chance an exploit is being used") + return var/dat = "Admin Player Panel" //javascript, the part that does most of the work~ @@ -392,11 +396,12 @@ var/logout_status logout_status = M.client ? "" : " (logged out)" var/dname = M.real_name + var/area/A = get_area(M) if(!dname) dname = M - return {" - [close ? "" : ""]"} + return {" + [close ? "" : ""]"} /datum/admins/proc/check_antagonists() if(!check_rights(R_ADMIN)) return @@ -465,7 +470,7 @@ if(GAMEMODE_IS_BLOB) var/datum/game_mode/blob/mode = SSticker.mode dat += "
    - +
    @@ -99,7 +99,7 @@ function onload() { src << browse(output, "window=createplayerpoll;size=950x500") /client/proc/create_poll_function(href_list) - if(!check_rights(R_SERVER)) + if(!check_rights(R_SERVER)) return var/polltype = href_list["createpoll"] if(polltype != POLLTYPE_OPTION && polltype != POLLTYPE_TEXT && polltype != POLLTYPE_RATING && polltype != POLLTYPE_MULTI) @@ -122,15 +122,15 @@ function onload() { create_poll_window("Question cannot be blank.") return question = sanitizeSQL(question) - + var/starttime var/endtime - var/DBQuery/query = dbcon.NewQuery("SELECT Now() AS starttime, ADDDATE(Now(), INTERVAL [poll_len] DAY) AS endtime") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT Now() AS starttime, ADDDATE(Now(), INTERVAL [poll_len] DAY) AS endtime") query.Execute() while(query.NextRow()) starttime = query.item[1] endtime = query.item[2] - + var/pollquery = "INSERT INTO [format_table_name("poll_question")] (polltype, starttime, endtime, question, adminonly, multiplechoiceoptions, createdby_ckey, createdby_ip) VALUES ('[polltype]', '[starttime]', '[endtime]', '[question]', '[adminonly]', '[choice_amount]', '[sql_ckey]', '[address]')" var/idquery = "SELECT id FROM [format_table_name("poll_question")] WHERE question = '[question]' AND starttime = '[starttime]' AND endtime = '[endtime]' AND createdby_ckey = '[sql_ckey]' AND createdby_ip = '[address]'" var/list/option_queries = list() @@ -175,15 +175,15 @@ function onload() { if(descmax) descmax = sanitizeSQL(descmax) option_queries += "INSERT INTO [format_table_name("poll_option")] (pollid, text, percentagecalc, minval, maxval, descmin, descmid, descmax) VALUES ('{POLLID}', '[option]', '[percentagecalc]', '[minval]', '[maxval]', '[descmin]', '[descmid]', '[descmax]')" - - query = dbcon.NewQuery(pollquery) + + query = GLOB.dbcon.NewQuery(pollquery) if(!query.Execute()) var/err = query.ErrorMsg() create_poll_window("An SQL error has occured while creating your poll") log_game("SQL ERROR adding new poll question to table. Error : \[[err]\]\n") return var/pollid = 0 - query = dbcon.NewQuery(idquery) + query = GLOB.dbcon.NewQuery(idquery) if(!query.Execute()) var/err = query.ErrorMsg() create_poll_window("An SQL error has occured while creating your poll") @@ -192,7 +192,7 @@ function onload() { if(query.NextRow()) pollid = text2num(query.item[1]) for(var/querytext in option_queries) - query = dbcon.NewQuery(replacetext(idquery, "{POLLID}", pollid)) + query = GLOB.dbcon.NewQuery(replacetext(idquery, "{POLLID}", pollid)) if(!query.Execute()) var/err = query.ErrorMsg() create_poll_window("An SQL error has occured while creating your poll") diff --git a/code/modules/admin/create_turf.dm b/code/modules/admin/create_turf.dm index b895032d374..c65c7b22b1a 100644 --- a/code/modules/admin/create_turf.dm +++ b/code/modules/admin/create_turf.dm @@ -1,9 +1,9 @@ -/var/create_turf_html = null +GLOBAL_VAR(create_turf_html) /datum/admins/proc/create_turf(var/mob/user) - if(!create_turf_html) + if(!GLOB.create_turf_html) var/turfjs = null turfjs = jointext(typesof(/turf), ";") - create_turf_html = file2text('html/create_object.html') - create_turf_html = replacetext(create_turf_html, "null /* object types */", "\"[turfjs]\"") + GLOB.create_turf_html = file2text('html/create_object.html') + GLOB.create_turf_html = replacetext(GLOB.create_turf_html, "null /* object types */", "\"[turfjs]\"") - user << browse(replacetext(create_turf_html, "/* ref src */", UID()), "window=create_turf;size=425x475") + user << browse(replacetext(GLOB.create_turf_html, "/* ref src */", UID()), "window=create_turf;size=425x475") diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 33654c7e341..740d182f3f2 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -1,4 +1,5 @@ -var/list/admin_datums = list() +GLOBAL_LIST_EMPTY(admin_datums) +GLOBAL_PROTECT(admin_datums) // This is protected because we dont want people making their own admin ranks, for obvious reasons /datum/admins var/rank = "Temporary Admin" @@ -22,7 +23,7 @@ var/list/admin_datums = list() admincaster_signature = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]" rank = initial_rank rights = initial_rights - admin_datums[ckey] = src + GLOB.admin_datums[ckey] = src /datum/admins/Destroy() ..() @@ -87,7 +88,7 @@ you will have to do something like if(client.holder.rights & R_ADMIN) yourself. return 0 /client/proc/deadmin() - admin_datums -= ckey + GLOB.admin_datums -= ckey if(holder) holder.disassociate() qdel(holder) diff --git a/code/modules/admin/ipintel.dm b/code/modules/admin/ipintel.dm index 8f9cba102fe..8bfce6c05f0 100644 --- a/code/modules/admin/ipintel.dm +++ b/code/modules/admin/ipintel.dm @@ -34,9 +34,9 @@ cachedintel.cache = TRUE return cachedintel - if(dbcon.IsConnected()) + if(GLOB.dbcon.IsConnected()) var/rating_bad = config.ipintel_rating_bad - var/DBQuery/query_get_ip_intel = dbcon.NewQuery({" + var/DBQuery/query_get_ip_intel = GLOB.dbcon.NewQuery({" SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW()) FROM [format_table_name("ipintel")] WHERE @@ -67,8 +67,8 @@ res.intel = ip_intel_query(ip) if(updatecache && res.intel >= 0) SSipintel.cache[ip] = res - if(dbcon.IsConnected()) - var/DBQuery/query_add_ip_intel = dbcon.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()") + if(GLOB.dbcon.IsConnected()) + var/DBQuery/query_add_ip_intel = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()") query_add_ip_intel.Execute() qdel(query_add_ip_intel) @@ -139,7 +139,7 @@ return FALSE if(!config.ipintel_whitelist) return FALSE - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) return FALSE if(!ipintel_badip_check(t_ip)) return FALSE @@ -160,7 +160,7 @@ rating_bad = sanitizeSQL(rating_bad) valid_hours = sanitizeSQL(valid_hours) var/check_sql = {"SELECT * FROM [format_table_name("ipintel")] WHERE ip = INET_ATON('[target_ip]') AND intel >= [rating_bad] AND (date + INTERVAL [valid_hours] HOUR) > NOW()"} - var/DBQuery/query_get_ip_intel = dbcon.NewQuery(check_sql) + var/DBQuery/query_get_ip_intel = GLOB.dbcon.NewQuery(check_sql) if(!query_get_ip_intel.Execute()) log_debug("ipintel_badip_check reports failed query execution") qdel(query_get_ip_intel) @@ -175,7 +175,7 @@ if(!config.ipintel_whitelist) return FALSE var/target_sql_ckey = ckey(target_ckey) - var/DBQuery/query_whitelist_check = dbcon.NewQuery("SELECT * FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'") + var/DBQuery/query_whitelist_check = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'") if(!query_whitelist_check.Execute()) var/err = query_whitelist_check.ErrorMsg() log_debug("SQL ERROR on proc/vpn_whitelist_check for ckey '[target_sql_ckey]'. Error : \[[err]\]\n") @@ -190,7 +190,7 @@ if(!reason_string) return FALSE reason_string = sanitizeSQL(reason_string) - var/DBQuery/query_whitelist_add = dbcon.NewQuery("INSERT INTO [format_table_name("vpn_whitelist")] (ckey,reason) VALUES ('[target_sql_ckey]','[reason_string]')") + var/DBQuery/query_whitelist_add = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("vpn_whitelist")] (ckey,reason) VALUES ('[target_sql_ckey]','[reason_string]')") if(!query_whitelist_add.Execute()) var/err = query_whitelist_add.ErrorMsg() log_debug("SQL ERROR on proc/vpn_whitelist_add for ckey '[target_sql_ckey]'. Error : \[[err]\]\n") @@ -199,7 +199,7 @@ /proc/vpn_whitelist_remove(target_ckey) var/target_sql_ckey = ckey(target_ckey) - var/DBQuery/query_whitelist_remove = dbcon.NewQuery("DELETE FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'") + var/DBQuery/query_whitelist_remove = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("vpn_whitelist")] WHERE ckey = '[target_sql_ckey]'") if(!query_whitelist_remove.Execute()) var/err = query_whitelist_remove.ErrorMsg() log_debug("SQL ERROR on proc/vpn_whitelist_remove for ckey '[target_sql_ckey]'. Error : \[[err]\]\n") diff --git a/code/modules/admin/permissionverbs/permissionedit.dm b/code/modules/admin/permissionverbs/permissionedit.dm index 5a3f38afc86..795538c7c33 100644 --- a/code/modules/admin/permissionverbs/permissionedit.dm +++ b/code/modules/admin/permissionverbs/permissionedit.dm @@ -25,8 +25,8 @@
    [dname][caption][logout_status][M.stat == 2 ? " (DEAD)" : ""]PM
    [dname][caption][logout_status][istype(A, /area/security/permabrig) ? " (PERMA) " : ""][M.stat == 2 ? " (DEAD)" : ""]PM [ADMIN_FLW(M, "FLW")]
    " - dat += "" + dat += "" for(var/datum/mind/blob in mode.infected_crew) var/mob/M = blob.current @@ -475,7 +480,7 @@ else dat += "" dat += "
    Blob
    Progress: [blobs.len]/[mode.blobwincount]
    Progress: [GLOB.blobs.len]/[mode.blobwincount]
    Blob not found!
    " - + if(SSticker.mode.blob_overminds.len) dat += check_role_table("Blob Overminds", SSticker.mode.blob_overminds) @@ -492,7 +497,7 @@ dat += check_role_table("Ninjas", ticker.mode.ninjas)*/ if(SSticker.mode.cult.len) - dat += check_role_table("Cultists", SSticker.mode.cult, 0) + dat += check_role_table("Cultists", SSticker.mode.cult) dat += "
    use Cult Mindspeak" if(GAMEMODE_IS_CULT) var/datum/game_mode/cult/cult_round = SSticker.mode @@ -541,9 +546,9 @@ if(SSticker.mode.eventmiscs.len) dat += check_role_table("Event Roles", SSticker.mode.eventmiscs) - if(ts_spiderlist.len) + if(GLOB.ts_spiderlist.len) var/list/spider_minds = list() - for(var/mob/living/simple_animal/hostile/poison/terror_spider/S in ts_spiderlist) + for(var/mob/living/simple_animal/hostile/poison/terror_spider/S in GLOB.ts_spiderlist) if(S.ckey) spider_minds += S.mind if(spider_minds.len) @@ -551,10 +556,10 @@ var/count_eggs = 0 var/count_spiderlings = 0 - for(var/obj/structure/spider/eggcluster/terror_eggcluster/E in ts_egg_list) + for(var/obj/structure/spider/eggcluster/terror_eggcluster/E in GLOB.ts_egg_list) if(is_station_level(E.z)) count_eggs += E.spiderling_number - for(var/obj/structure/spider/spiderling/terror_spiderling/L in ts_spiderling_list) + for(var/obj/structure/spider/spiderling/terror_spiderling/L in GLOB.ts_spiderling_list) if(!L.stillborn && is_station_level(L.z)) count_spiderlings += 1 dat += "
    Growing TS on-station: [count_eggs] egg[count_eggs != 1 ? "s" : ""], [count_spiderlings] spiderling[count_spiderlings != 1 ? "s" : ""].
    " diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm index 4e2fe2d7ae2..cbda6699694 100644 --- a/code/modules/admin/secrets.dm +++ b/code/modules/admin/secrets.dm @@ -27,8 +27,8 @@ Bombs
    [check_rights(R_SERVER, 0) ? "  Toggle bomb cap
    " : "
    "] Lists
    - Show last [length(lastsignalers)] signalers   - Show last [length(lawchanges)] law changes
    + Show last [length(GLOB.lastsignalers)] signalers   + Show last [length(GLOB.lawchanges)] law changes
    List DNA (Blood)   List Fingerprints
    Power
    @@ -105,7 +105,7 @@ Turn all humans into monkeys
    Make all items look like guns
    Warp all Players to Prison
    - Make all players retarded
    + Make all players stupid
    Misc
    Remove firesuits, grilles, and pods   Triple AI mode (needs to be used in the lobby)
    diff --git a/code/modules/admin/sql_notes.dm b/code/modules/admin/sql_notes.dm index a6ac31a4114..238c380f417 100644 --- a/code/modules/admin/sql_notes.dm +++ b/code/modules/admin/sql_notes.dm @@ -1,7 +1,7 @@ /proc/add_note(target_ckey, notetext, timestamp, adminckey, logged = 1, server, checkrights = 1) if(checkrights && !check_rights(R_ADMIN|R_MOD)) return - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection.") return @@ -13,7 +13,7 @@ else target_ckey = ckey(target_ckey) - var/DBQuery/query_find_ckey = dbcon.NewQuery("SELECT ckey, exp FROM [format_table_name("player")] WHERE ckey = '[target_ckey]'") + var/DBQuery/query_find_ckey = GLOB.dbcon.NewQuery("SELECT ckey, exp FROM [format_table_name("player")] WHERE ckey = '[target_ckey]'") if(!query_find_ckey.Execute()) var/err = query_find_ckey.ErrorMsg() log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n") @@ -46,7 +46,7 @@ if(config && config.server_name) server = config.server_name server = sanitizeSQL(server) - var/DBQuery/query_noteadd = dbcon.NewQuery("INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime) VALUES ('[target_ckey]', '[timestamp]', '[notetext]', '[admin_sql_ckey]', '[server]', '[crew_number]')") + var/DBQuery/query_noteadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("notes")] (ckey, timestamp, notetext, adminckey, server, crew_playtime) VALUES ('[target_ckey]', '[timestamp]', '[notetext]', '[admin_sql_ckey]', '[server]', '[crew_number]')") if(!query_noteadd.Execute()) var/err = query_noteadd.ErrorMsg() log_game("SQL ERROR adding new note to table. Error : \[[err]\]\n") @@ -62,13 +62,13 @@ var/ckey var/notetext var/adminckey - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection.") return if(!note_id) return note_id = text2num(note_id) - var/DBQuery/query_find_note_del = dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]") + var/DBQuery/query_find_note_del = GLOB.dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]") if(!query_find_note_del.Execute()) var/err = query_find_note_del.ErrorMsg() log_game("SQL ERROR obtaining ckey, notetext, adminckey from player table. Error : \[[err]\]\n") @@ -77,7 +77,7 @@ ckey = query_find_note_del.item[1] notetext = query_find_note_del.item[2] adminckey = query_find_note_del.item[3] - var/DBQuery/query_del_note = dbcon.NewQuery("DELETE FROM [format_table_name("notes")] WHERE id = [note_id]") + var/DBQuery/query_del_note = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("notes")] WHERE id = [note_id]") if(!query_del_note.Execute()) var/err = query_del_note.ErrorMsg() log_game("SQL ERROR removing note from table. Error : \[[err]\]\n") @@ -89,7 +89,7 @@ /proc/edit_note(note_id) if(!check_rights(R_ADMIN|R_MOD)) return - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) to_chat(usr, "Failed to establish database connection.") return if(!note_id) @@ -97,7 +97,7 @@ note_id = text2num(note_id) var/target_ckey var/sql_ckey = usr.ckey - var/DBQuery/query_find_note_edit = dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]") + var/DBQuery/query_find_note_edit = GLOB.dbcon.NewQuery("SELECT ckey, notetext, adminckey FROM [format_table_name("notes")] WHERE id = [note_id]") if(!query_find_note_edit.Execute()) var/err = query_find_note_edit.ErrorMsg() log_game("SQL ERROR obtaining notetext from notes table. Error : \[[err]\]\n") @@ -112,7 +112,7 @@ new_note = sanitizeSQL(new_note) var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from \"[old_note]\" to \"[new_note]\"
    " edit_text = sanitizeSQL(edit_text) - var/DBQuery/query_update_note = dbcon.NewQuery("UPDATE [format_table_name("notes")] SET notetext = '[new_note]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [note_id]") + var/DBQuery/query_update_note = GLOB.dbcon.NewQuery("UPDATE [format_table_name("notes")] SET notetext = '[new_note]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE id = [note_id]") if(!query_update_note.Execute()) var/err = query_update_note.ErrorMsg() log_game("SQL ERROR editing note. Error : \[[err]\]\n") @@ -139,7 +139,7 @@ output = navbar if(target_ckey) var/target_sql_ckey = ckey(target_ckey) - var/DBQuery/query_get_notes = dbcon.NewQuery("SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp") + var/DBQuery/query_get_notes = GLOB.dbcon.NewQuery("SELECT id, timestamp, notetext, adminckey, last_editor, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp") if(!query_get_notes.Execute()) var/err = query_get_notes.ErrorMsg() log_game("SQL ERROR obtaining ckey, notetext, adminckey, last_editor, server, crew_playtime from notes table. Error : \[[err]\]\n") @@ -181,7 +181,7 @@ search = "^\[^\[:alpha:\]\]" else search = "^[index]" - var/DBQuery/query_list_notes = dbcon.NewQuery("SELECT DISTINCT ckey FROM [format_table_name("notes")] WHERE ckey REGEXP '[search]' ORDER BY ckey") + var/DBQuery/query_list_notes = GLOB.dbcon.NewQuery("SELECT DISTINCT ckey FROM [format_table_name("notes")] WHERE ckey REGEXP '[search]' ORDER BY ckey") if(!query_list_notes.Execute()) var/err = query_list_notes.ErrorMsg() log_game("SQL ERROR obtaining ckey from notes table. Error : \[[err]\]\n") @@ -196,7 +196,7 @@ /proc/show_player_info_irc(var/key as text) var/target_sql_ckey = ckey(key) - var/DBQuery/query_get_notes = dbcon.NewQuery("SELECT timestamp, notetext, adminckey, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp") + var/DBQuery/query_get_notes = GLOB.dbcon.NewQuery("SELECT timestamp, notetext, adminckey, server, crew_playtime FROM [format_table_name("notes")] WHERE ckey = '[target_sql_ckey]' ORDER BY timestamp") if(!query_get_notes.Execute()) var/err = query_get_notes.ErrorMsg() log_game("SQL ERROR obtaining timestamp, notetext, adminckey, server, crew_playtime from notes table. Error : \[[err]\]\n") diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 60156930408..1a040d46e90 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -183,7 +183,7 @@ if(task == "add") var/new_ckey = ckey(clean_input("New admin's ckey","Admin ckey", null)) if(!new_ckey) return - if(new_ckey in admin_datums) + if(new_ckey in GLOB.admin_datums) to_chat(usr, "Error: Topic 'editrights': [new_ckey] is already an admin") return adm_ckey = new_ckey @@ -194,12 +194,12 @@ to_chat(usr, "Error: Topic 'editrights': No valid ckey") return - var/datum/admins/D = admin_datums[adm_ckey] + var/datum/admins/D = GLOB.admin_datums[adm_ckey] if(task == "remove") if(alert("Are you sure you want to remove [adm_ckey]?","Message","Yes","Cancel") == "Yes") if(!D) return - admin_datums -= adm_ckey + GLOB.admin_datums -= adm_ckey D.disassociate() updateranktodb(adm_ckey, "player") @@ -209,8 +209,8 @@ else if(task == "rank") var/new_rank - if(admin_ranks.len) - new_rank = input("Please select a rank", "New rank", null, null) as null|anything in (admin_ranks|"*New Rank*") + if(GLOB.admin_ranks.len) + new_rank = input("Please select a rank", "New rank", null, null) as null|anything in (GLOB.admin_ranks|"*New Rank*") else new_rank = input("Please select a rank", "New rank", null, null) as null|anything in list("Mentor", "Trial Admin", "Game Admin", "*New Rank*") @@ -227,15 +227,15 @@ to_chat(usr, "Error: Topic 'editrights': Invalid rank") return if(config.admin_legacy_system) - if(admin_ranks.len) - if(new_rank in admin_ranks) - rights = admin_ranks[new_rank] //we typed a rank which already exists, use its rights + if(GLOB.admin_ranks.len) + if(new_rank in GLOB.admin_ranks) + rights = GLOB.admin_ranks[new_rank] //we typed a rank which already exists, use its rights else - admin_ranks[new_rank] = 0 //add the new rank to admin_ranks + GLOB.admin_ranks[new_rank] = 0 //add the new rank to admin_ranks else if(config.admin_legacy_system) new_rank = ckeyEx(new_rank) - rights = admin_ranks[new_rank] //we input an existing rank, use its rights + rights = GLOB.admin_ranks[new_rank] //we input an existing rank, use its rights if(D) D.disassociate() //remove adminverbs and unlink from client @@ -308,7 +308,7 @@ var/timer = input("Enter new shuttle duration (seconds):","Edit Shuttle Timeleft", SSshuttle.emergency.timeLeft() ) as num SSshuttle.emergency.setTimer(timer*10) log_admin("[key_name(usr)] edited the Emergency Shuttle's timeleft to [timer] seconds") - minor_announcement.Announce("The emergency shuttle will reach its destination in [round(SSshuttle.emergency.timeLeft(600))] minutes.") + GLOB.minor_announcement.Announce("The emergency shuttle will reach its destination in [round(SSshuttle.emergency.timeLeft(600))] minutes.") message_admins("[key_name_admin(usr)] edited the Emergency Shuttle's timeleft to [timer] seconds") href_list["secrets"] = "check_antagonist" @@ -369,8 +369,8 @@ if(!check_rights(R_BAN)) return var/banfolder = href_list["unbanf"] - Banlist.cd = "/base/[banfolder]" - var/key = Banlist["key"] + GLOB.banlist_savefile.cd = "/base/[banfolder]" + var/key = GLOB.banlist_savefile["key"] if(alert(usr, "Are you sure you want to unban [key]?", "Confirmation", "Yes", "No") == "Yes") if(RemoveBan(banfolder)) unbanpanel() @@ -388,14 +388,14 @@ var/reason var/banfolder = href_list["unbane"] - Banlist.cd = "/base/[banfolder]" - var/reason2 = Banlist["reason"] - var/temp = Banlist["temp"] + GLOB.banlist_savefile.cd = "/base/[banfolder]" + var/reason2 = GLOB.banlist_savefile["reason"] + var/temp = GLOB.banlist_savefile["temp"] - var/minutes = Banlist["minutes"] + var/minutes = GLOB.banlist_savefile["minutes"] - var/banned_key = Banlist["key"] - Banlist.cd = "/base" + var/banned_key = GLOB.banlist_savefile["key"] + GLOB.banlist_savefile.cd = "/base" var/duration @@ -403,12 +403,12 @@ if("Yes") temp = 1 var/mins = 0 - if(minutes > CMinutes) - mins = minutes - CMinutes + if(minutes > GLOB.CMinutes) + mins = minutes - GLOB.CMinutes mins = input(usr,"How long (in minutes)? (Default: 1440)","Ban time",mins ? mins : 1440) as num|null if(!mins) return mins = min(525599,mins) - minutes = CMinutes + mins + minutes = GLOB.CMinutes + mins duration = GetExp(minutes) reason = input(usr,"Please state the reason","Reason",reason2) as message|null if(!reason) return @@ -421,12 +421,12 @@ log_admin("[key_name(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]") ban_unban_log_save("[key_name(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]") message_admins("[key_name_admin(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]", 1) - Banlist.cd = "/base/[banfolder]" - to_chat(Banlist["reason"], reason) - to_chat(Banlist["temp"], temp) - to_chat(Banlist["minutes"], minutes) - to_chat(Banlist["bannedby"], usr.ckey) - Banlist.cd = "/base" + GLOB.banlist_savefile.cd = "/base/[banfolder]" + to_chat(GLOB.banlist_savefile["reason"], reason) + to_chat(GLOB.banlist_savefile["temp"], temp) + to_chat(GLOB.banlist_savefile["minutes"], minutes) + to_chat(GLOB.banlist_savefile["bannedby"], usr.ckey) + GLOB.banlist_savefile.cd = "/base" feedback_inc("ban_edit",1) unbanpanel() @@ -512,8 +512,8 @@ //Regular jobs //Command (Blue) jobs += "" - jobs += "" - for(var/jobPos in command_positions) + jobs += "" + for(var/jobPos in GLOB.command_positions) if(!jobPos) continue var/datum/job/job = SSjobs.GetJob(jobPos) if(!job) continue @@ -533,8 +533,8 @@ //Security (Red) counter = 0 jobs += "
    Command Positions
    Command Positions
    " - jobs += "" - for(var/jobPos in security_positions) + jobs += "" + for(var/jobPos in GLOB.security_positions) if(!jobPos) continue var/datum/job/job = SSjobs.GetJob(jobPos) if(!job) continue @@ -554,8 +554,8 @@ //Engineering (Yellow) counter = 0 jobs += "
    Security Positions
    Security Positions
    " - jobs += "" - for(var/jobPos in engineering_positions) + jobs += "" + for(var/jobPos in GLOB.engineering_positions) if(!jobPos) continue var/datum/job/job = SSjobs.GetJob(jobPos) if(!job) continue @@ -575,8 +575,8 @@ //Medical (White) counter = 0 jobs += "
    Engineering Positions
    Engineering Positions
    " - jobs += "" - for(var/jobPos in medical_positions) + jobs += "" + for(var/jobPos in GLOB.medical_positions) if(!jobPos) continue var/datum/job/job = SSjobs.GetJob(jobPos) if(!job) continue @@ -596,8 +596,8 @@ //Science (Purple) counter = 0 jobs += "
    Medical Positions
    Medical Positions
    " - jobs += "" - for(var/jobPos in science_positions) + jobs += "" + for(var/jobPos in GLOB.science_positions) if(!jobPos) continue var/datum/job/job = SSjobs.GetJob(jobPos) if(!job) continue @@ -617,8 +617,8 @@ //Support (Grey) counter = 0 jobs += "
    Science Positions
    Science Positions
    " - jobs += "" - for(var/jobPos in support_positions) + jobs += "" + for(var/jobPos in GLOB.support_positions) if(!jobPos) continue var/datum/job/job = SSjobs.GetJob(jobPos) if(!job) continue @@ -638,8 +638,8 @@ //Non-Human (Green) counter = 0 jobs += "
    Support Positions
    Support Positions
    " - jobs += "" - for(var/jobPos in nonhuman_positions) + jobs += "" + for(var/jobPos in GLOB.nonhuman_positions) if(!jobPos) continue var/datum/job/job = SSjobs.GetJob(jobPos) if(!job) continue @@ -675,7 +675,7 @@ jobs += "" counter = 0 - for(var/role in antag_roles) + for(var/role in GLOB.antag_roles) if(jobban_isbanned(M, role) || isbanned_dept) jobs += "" else @@ -692,7 +692,7 @@ jobs += "" counter = 0 - for(var/role in other_roles) + for(var/role in GLOB.other_roles) if(jobban_isbanned(M, role) || isbanned_dept) jobs += "" else @@ -707,8 +707,8 @@ //Whitelisted positions counter = 0 jobs += "
    Non-human Positions
    Non-human Positions
    Antagonist Positions
    [replacetext(role, " ", " ")]
    Other
    [replacetext(role, " ", " ")]
    " - jobs += "" - for(var/jobPos in whitelisted_positions) + jobs += "" + for(var/jobPos in GLOB.whitelisted_positions) if(!jobPos) continue var/datum/job/job = SSjobs.GetJob(jobPos) if(!job) continue @@ -754,50 +754,50 @@ var/list/joblist = list() switch(href_list["jobban3"]) if("commanddept") - for(var/jobPos in command_positions) + for(var/jobPos in GLOB.command_positions) if(!jobPos) continue var/datum/job/temp = SSjobs.GetJob(jobPos) if(!temp) continue joblist += temp.title if("securitydept") - for(var/jobPos in security_positions) + for(var/jobPos in GLOB.security_positions) if(!jobPos) continue var/datum/job/temp = SSjobs.GetJob(jobPos) if(!temp) continue joblist += temp.title if("engineeringdept") - for(var/jobPos in engineering_positions) + for(var/jobPos in GLOB.engineering_positions) if(!jobPos) continue var/datum/job/temp = SSjobs.GetJob(jobPos) if(!temp) continue joblist += temp.title if("medicaldept") - for(var/jobPos in medical_positions) + for(var/jobPos in GLOB.medical_positions) if(!jobPos) continue var/datum/job/temp = SSjobs.GetJob(jobPos) if(!temp) continue joblist += temp.title if("sciencedept") - for(var/jobPos in science_positions) + for(var/jobPos in GLOB.science_positions) if(!jobPos) continue var/datum/job/temp = SSjobs.GetJob(jobPos) if(!temp) continue joblist += temp.title if("supportdept") - for(var/jobPos in support_positions) + for(var/jobPos in GLOB.support_positions) if(!jobPos) continue var/datum/job/temp = SSjobs.GetJob(jobPos) if(!temp) continue joblist += temp.title if("nonhumandept") joblist += "pAI" - for(var/jobPos in nonhuman_positions) + for(var/jobPos in GLOB.nonhuman_positions) if(!jobPos) continue var/datum/job/temp = SSjobs.GetJob(jobPos) if(!temp) continue joblist += temp.title if("whitelistdept") - for(var/jobPos in whitelisted_positions) + for(var/jobPos in GLOB.whitelisted_positions) if(!jobPos) continue var/datum/job/temp = SSjobs.GetJob(jobPos) if(!temp) continue @@ -953,7 +953,7 @@ else if(href_list["noteedits"]) var/note_id = sanitizeSQL("[href_list["noteedits"]]") - var/DBQuery/query_noteedits = dbcon.NewQuery("SELECT edits FROM [format_table_name("notes")] WHERE id = '[note_id]'") + var/DBQuery/query_noteedits = GLOB.dbcon.NewQuery("SELECT edits FROM [format_table_name("notes")] WHERE id = '[note_id]'") if(!query_noteedits.Execute()) var/err = query_noteedits.ErrorMsg() log_game("SQL ERROR obtaining edits from notes table. Error : \[[err]\]\n") @@ -1073,7 +1073,7 @@ else if(href_list["watcheditlog"]) var/target_ckey = sanitizeSQL("[href_list["watcheditlog"]]") - var/DBQuery/query_watchedits = dbcon.NewQuery("SELECT edits FROM [format_table_name("watch")] WHERE ckey = '[target_ckey]'") + var/DBQuery/query_watchedits = GLOB.dbcon.NewQuery("SELECT edits FROM [format_table_name("watch")] WHERE ckey = '[target_ckey]'") if(!query_watchedits.Execute()) var/err = query_watchedits.ErrorMsg() log_game("SQL ERROR obtaining edits from watch table. Error : \[[err]\]\n") @@ -1106,7 +1106,7 @@ dat += {"[config.mode_names[mode]]
    "} dat += {"Secret
    "} dat += {"Random
    "} - dat += {"Now: [master_mode]"} + dat += {"Now: [GLOB.master_mode]"} usr << browse(dat, "window=c_mode") else if(href_list["f_secret"]) @@ -1114,13 +1114,13 @@ if(SSticker && SSticker.mode) return alert(usr, "The game has already started.", null, null, null, null) - if(master_mode != "secret") + if(GLOB.master_mode != "secret") return alert(usr, "The game mode has to be secret!", null, null, null, null) var/dat = {"What game mode do you want to force secret to be? Use this if you want to change the game mode, but want the players to believe it's secret. This will only work if the current game mode is secret.
    "} for(var/mode in config.modes) dat += {"[config.mode_names[mode]]
    "} dat += {"Random (default)
    "} - dat += {"Now: [secret_force_mode]"} + dat += {"Now: [GLOB.secret_force_mode]"} usr << browse(dat, "window=f_secret") else if(href_list["c_mode2"]) @@ -1128,12 +1128,12 @@ if(SSticker && SSticker.mode) return alert(usr, "The game has already started.", null, null, null, null) - master_mode = href_list["c_mode2"] - log_admin("[key_name(usr)] set the mode as [master_mode].") - message_admins("[key_name_admin(usr)] set the mode as [master_mode].", 1) - to_chat(world, "The mode is now: [master_mode]") + GLOB.master_mode = href_list["c_mode2"] + log_admin("[key_name(usr)] set the mode as [GLOB.master_mode].") + message_admins("[key_name_admin(usr)] set the mode as [GLOB.master_mode].", 1) + to_chat(world, "The mode is now: [GLOB.master_mode]") Game() // updates the main game menu - world.save_mode(master_mode) + world.save_mode(GLOB.master_mode) .(href, list("c_mode"=1)) else if(href_list["f_secret2"]) @@ -1141,11 +1141,11 @@ if(SSticker && SSticker.mode) return alert(usr, "The game has already started.", null, null, null, null) - if(master_mode != "secret") + if(GLOB.master_mode != "secret") return alert(usr, "The game mode has to be secret!", null, null, null, null) - secret_force_mode = href_list["f_secret2"] - log_admin("[key_name(usr)] set the forced secret mode as [secret_force_mode].") - message_admins("[key_name_admin(usr)] set the forced secret mode as [secret_force_mode].", 1) + GLOB.secret_force_mode = href_list["f_secret2"] + log_admin("[key_name(usr)] set the forced secret mode as [GLOB.secret_force_mode].") + message_admins("[key_name_admin(usr)] set the forced secret mode as [GLOB.secret_force_mode].", 1) Game() // updates the main game menu .(href, list("f_secret"=1)) @@ -1231,7 +1231,7 @@ to_chat(usr, "This cannot be used on instances of type /mob/living/silicon/ai") return - var/turf/prison_cell = pick(prisonwarp) + var/turf/prison_cell = pick(GLOB.prisonwarp) if(!prison_cell) return var/obj/structure/closet/secure_closet/brig/locker = new /obj/structure/closet/secure_closet/brig(prison_cell) @@ -1311,7 +1311,7 @@ M.Paralyse(5) sleep(5) - M.loc = pick(tdome1) + M.loc = pick(GLOB.tdome1) spawn(50) to_chat(M, "You have been sent to the Thunderdome.") log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team 1)") @@ -1341,7 +1341,7 @@ M.Paralyse(5) sleep(5) - M.loc = pick(tdome2) + M.loc = pick(GLOB.tdome2) spawn(50) to_chat(M, "You have been sent to the Thunderdome.") log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Team 2)") @@ -1363,7 +1363,7 @@ M.Paralyse(5) sleep(5) - M.loc = pick(tdomeadmin) + M.loc = pick(GLOB.tdomeadmin) spawn(50) to_chat(M, "You have been sent to the Thunderdome.") log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Admin.)") @@ -1397,7 +1397,7 @@ observer.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(observer), slot_shoes) M.Paralyse(5) sleep(5) - M.loc = pick(tdomeobserve) + M.loc = pick(GLOB.tdomeobserve) spawn(50) to_chat(M, "You have been sent to the Thunderdome.") log_admin("[key_name(usr)] has sent [key_name(M)] to the thunderdome. (Observer.)") @@ -1419,7 +1419,7 @@ M.Paralyse(5) sleep(5) - M.loc = pick(aroomwarp) + M.loc = pick(GLOB.aroomwarp) spawn(50) to_chat(M, "You have been sent to the Admin Room!.") log_admin("[key_name(usr)] has sent [key_name(M)] to the Admin Room") @@ -1667,13 +1667,13 @@ if(alert(owner, "Are you sure you wish to hit [key_name(M)] with Bluespace Artillery?", "Confirm Firing?" , "Yes" , "No") != "Yes") return - if(BSACooldown) + if(GLOB.BSACooldown) to_chat(owner, "Standby. Reload cycle in progress. Gunnery crews ready in five seconds!") return - BSACooldown = 1 + GLOB.BSACooldown = 1 spawn(50) - BSACooldown = 0 + GLOB.BSACooldown = 0 to_chat(M, "You've been hit by bluespace artillery!") log_admin("[key_name(M)] has been hit by Bluespace Artillery fired by [key_name(owner)]") @@ -1787,7 +1787,7 @@ var/logmsg = null switch(blessing) if("To Arrivals") - M.forceMove(pick(latejoin)) + M.forceMove(pick(GLOB.latejoin)) to_chat(M, "You are abruptly pulled through space!") logmsg = "a teleport to arrivals." if("Moderate Heal") @@ -1803,13 +1803,13 @@ H.reagents.add_reagent("spaceacillin", 20) logmsg = "a heal over time." if("Permanent Regeneration") - H.dna.SetSEState(REGENERATEBLOCK, 1) - genemutcheck(H, REGENERATEBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.regenerateblock, 1) + genemutcheck(H, GLOB.regenerateblock, null, MUTCHK_FORCED) H.update_mutations() H.gene_stability = 100 logmsg = "permanent regeneration." if("Super Powers") - var/list/default_genes = list(REGENERATEBLOCK, BREATHLESSBLOCK, COLDBLOCK) + var/list/default_genes = list(GLOB.regenerateblock, GLOB.breathlessblock, GLOB.coldblock) for(var/gene in default_genes) H.dna.SetSEState(gene, 1) genemutcheck(H, gene, null, MUTCHK_FORCED) @@ -1905,11 +1905,13 @@ ptypes += "Crew Traitor" ptypes += "Floor Cluwne" ptypes += "Shamebrero" + ptypes += "Dust" var/punishment = input(owner, "How would you like to smite [M]?", "Its good to be baaaad...", "") as null|anything in ptypes if(!(punishment in ptypes)) return var/logmsg = null switch(punishment) + // These smiting types are valid for all living mobs if("Lightning bolt") M.electrocute_act(5, "Lightning Bolt", safety = TRUE, override = TRUE) playsound(get_turf(M), 'sound/magic/lightningshock.ogg', 50, 1, -1) @@ -1927,6 +1929,7 @@ M.gib(FALSE) logmsg = "gibbed." + // These smiting types are only valid for ishuman() mobs if("Brain Damage") H.adjustBrainLoss(75) logmsg = "75 brain damage." @@ -1974,38 +1977,34 @@ logmsg = "hunter." if("Crew Traitor") if(!H.mind) - to_chat(usr, "This mob has no mind!") + to_chat(usr, "ERROR: This mob ([H]) has no mind!") return - var/list/possible_traitors = list() - for(var/mob/living/player in GLOB.living_mob_list) + for(var/mob/living/player in GLOB.alive_mob_list) if(player.client && player.mind && player.stat != DEAD && player != H) if(ishuman(player) && !player.mind.special_role) if(player.client && (ROLE_TRAITOR in player.client.prefs.be_special) && !jobban_isbanned(player, ROLE_TRAITOR) && !jobban_isbanned(player, "Syndicate")) possible_traitors += player.mind - for(var/datum/mind/player in possible_traitors) if(player.current) if(ismindshielded(player.current)) possible_traitors -= player - if(possible_traitors.len) var/datum/mind/newtraitormind = pick(possible_traitors) var/datum/objective/assassinate/kill_objective = new() kill_objective.target = H.mind kill_objective.owner = newtraitormind - kill_objective.explanation_text = "Assassinate [H.mind], the [H.mind.assigned_role]" - H.mind.objectives += kill_objective + kill_objective.explanation_text = "Assassinate [H.mind.name], the [H.mind.assigned_role]" + newtraitormind.objectives += kill_objective var/datum/antagonist/traitor/T = new() T.give_objectives = FALSE - to_chat(newtraitormind, "ATTENTION: It is time to pay your debt to the Syndicate...") - to_chat(newtraitormind, "Goal: KILL [H.real_name], currently in [get_area(H.loc)]") + to_chat(newtraitormind.current, "ATTENTION: It is time to pay your debt to the Syndicate...") + to_chat(newtraitormind.current, "Goal: KILL [H.real_name], currently in [get_area(H.loc)]") newtraitormind.add_antag_datum(T) else - to_chat(usr, "ERROR: Failed to create a traitor.") + to_chat(usr, "ERROR: Unable to find any valid candidate to send after [H].") return logmsg = "crew traitor." - if("Floor Cluwne") var/turf/T = get_turf(M) var/mob/living/simple_animal/hostile/floor_cluwne/FC = new /mob/living/simple_animal/hostile/floor_cluwne(T) @@ -2018,6 +2017,9 @@ var/obj/item/clothing/head/sombrero/shamebrero/S = new(H.loc) H.equip_to_slot_or_del(S, slot_head) logmsg = "shamebrero" + if("Dust") + H.dust() + logmsg = "dust" if(logmsg) log_admin("[key_name(owner)] smited [key_name(M)] with: [logmsg]") message_admins("[key_name_admin(owner)] smited [key_name_admin(M)] with: [logmsg]") @@ -2056,7 +2058,7 @@ P.name = "Central Command - paper" var/stypes = list("Handle it yourselves!","Illegible fax","Fax not signed","Not Right Now","You are wasting our time", "Keep up the good work", "ERT Instructions") var/stype = input(src.owner, "Which type of standard reply do you wish to send to [H]?","Choose your paperwork", "") as null|anything in stypes - var/tmsg = "



    Nanotrasen Science Station [using_map.station_short]


    NAS Trurl Communications Department Report


    " + var/tmsg = "



    Nanotrasen Science Station [GLOB.using_map.station_short]


    NAS Trurl Communications Department Report


    " if(stype == "Handle it yourselves!") tmsg += "Greetings, esteemed crewmember. Your fax has been DECLINED automatically by NAS Trurl Fax Registration.

    Please proceed in accordance with Standard Operating Procedure and/or Space Law. You are fully trained to handle this situation without Central Command intervention.

    This is an automatic message." else if(stype == "Illegible fax") @@ -2134,7 +2136,7 @@ var/input = input(src.owner, "Please enter a reason for denying [key_name(H)]'s ERT request.","Outgoing message from CentComm", "") if(!input) return - ert_request_answered = TRUE + GLOB.ert_request_answered = TRUE to_chat(src.owner, "You sent [input] to [H] via a secure channel.") log_admin("[src.owner] denied [key_name(H)]'s ERT request with the message [input].") to_chat(H, "Incoming priority transmission from Central Command. Message as follows, Your ERT request has been denied for the following reasons: [input].") @@ -2194,17 +2196,23 @@ var/reply_to = locate(href_list["replyto"]) var/destination var/notify - - var/obj/item/paper/P = new /obj/item/paper(null) //hopefully the null loc won't cause trouble for us - + var/obj/item/paper/P + var/use_letterheard = alert("Use letterhead? If so, do not add your own header or a footer. Type and format only your actual message.",,"Nanotrasen","Syndicate", "No") + switch(use_letterheard) + if("Nanotrasen") + P = new /obj/item/paper/central_command(null) + if("Syndicate") + P = new /obj/item/paper/syndicate(null) + if("No") + P = new /obj/item/paper(null) if(!fax) - var/list/departmentoptions = alldepartments + hidden_departments + "All Departments" + var/list/departmentoptions = GLOB.alldepartments + GLOB.hidden_departments + "All Departments" destination = input(usr, "To which department?", "Choose a department", "") as null|anything in departmentoptions if(!destination) qdel(P) return - for(var/obj/machinery/photocopier/faxmachine/F in allfaxes) + for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes) if(destination != "All Departments" && F.department == destination) fax = F @@ -2300,7 +2308,7 @@ to_chat(src.owner, "Message transmission failed.") return else - for(var/obj/machinery/photocopier/faxmachine/F in allfaxes) + for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes) if(is_station_level(F.z)) spawn(0) if(!F.receivefax(P)) @@ -2541,7 +2549,7 @@ else if(href_list["memoeditlist"]) if(!check_rights(R_SERVER)) return var/sql_key = sanitizeSQL("[href_list["memoeditlist"]]") - var/DBQuery/query_memoedits = dbcon.NewQuery("SELECT edits FROM [format_table_name("memo")] WHERE (ckey = '[sql_key]')") + var/DBQuery/query_memoedits = GLOB.dbcon.NewQuery("SELECT edits FROM [format_table_name("memo")] WHERE (ckey = '[sql_key]')") if(!query_memoedits.Execute()) var/err = query_memoedits.ErrorMsg() log_game("SQL ERROR obtaining edits from memo table. Error : \[[err]\]\n") @@ -2616,19 +2624,19 @@ if(!(SSticker && SSticker.mode)) to_chat(usr, "Please wait until the game starts! Not sure how it will work otherwise.") return - gravity_is_on = !gravity_is_on + GLOB.gravity_is_on = !GLOB.gravity_is_on for(var/area/A in world) - A.gravitychange(gravity_is_on,A) + A.gravitychange(GLOB.gravity_is_on,A) feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","Grav") - if(gravity_is_on) + if(GLOB.gravity_is_on) log_admin("[key_name(usr)] toggled gravity on.", 1) message_admins("[key_name_admin(usr)] toggled gravity on.", 1) - event_announcement.Announce("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") + GLOB.event_announcement.Announce("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") else log_admin("[key_name(usr)] toggled gravity off.", 1) message_admins("[key_name_admin(usr)] toggled gravity off.", 1) - event_announcement.Announce("Feedback surge detected in mass-distributions systems. Artifical gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.") + GLOB.event_announcement.Announce("Feedback surge detected in mass-distributions systems. Artifical gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.") if("power") feedback_inc("admin_secrets_fun_used",1) @@ -2658,7 +2666,7 @@ for(var/mob/living/carbon/human/H in GLOB.mob_list) var/turf/loc = find_loc(H) var/security = 0 - if(!is_station_level(loc.z) || prisonwarped.Find(H)) + if(!is_station_level(loc.z) || GLOB.prisonwarped.Find(H)) //don't warp them if they aren't ready or are already there continue @@ -2683,13 +2691,13 @@ W.layer = initial(W.layer) W.plane = initial(W.plane) //teleport person to cell - H.loc = pick(prisonwarp) + H.loc = pick(GLOB.prisonwarp) H.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(H), slot_shoes) else //teleport security person - H.loc = pick(prisonsecuritywarp) - prisonwarped += H + H.loc = pick(GLOB.prisonsecuritywarp) + GLOB.prisonwarped += H if("traitor_all") if(!SSticker) alert("The game hasn't started yet!") @@ -2716,21 +2724,21 @@ feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","BC") - var/newBombCap = input(usr,"What would you like the new bomb cap to be. (entered as the light damage range (the 3rd number in common (1,2,3) notation)) Must be between 4 and 128)", "New Bomb Cap", MAX_EX_LIGHT_RANGE) as num|null + var/newBombCap = input(usr,"What would you like the new bomb cap to be. (entered as the light damage range (the 3rd number in common (1,2,3) notation)) Must be between 4 and 128)", "New Bomb Cap", GLOB.max_ex_light_range) as num|null if(newBombCap < 4) return if(newBombCap > 128) newBombCap = 128 - MAX_EX_DEVASTATION_RANGE = round(newBombCap/4) - MAX_EX_HEAVY_RANGE = round(newBombCap/2) - MAX_EX_LIGHT_RANGE = newBombCap + GLOB.max_ex_devastation_range = round(newBombCap/4) + GLOB.max_ex_heavy_range = round(newBombCap/2) + GLOB.max_ex_light_range = newBombCap //I don't know why these are their own variables, but fuck it, they are. - MAX_EX_FLASH_RANGE = newBombCap - MAX_EX_FLAME_RANGE = newBombCap + GLOB.max_ex_flash_range = newBombCap + GLOB.max_ex_flame_range = newBombCap - message_admins("[key_name_admin(usr)] changed the bomb cap to [MAX_EX_DEVASTATION_RANGE], [MAX_EX_HEAVY_RANGE], [MAX_EX_LIGHT_RANGE]") - log_admin("[key_name(usr)] changed the bomb cap to [MAX_EX_DEVASTATION_RANGE], [MAX_EX_HEAVY_RANGE], [MAX_EX_LIGHT_RANGE]") + message_admins("[key_name_admin(usr)] changed the bomb cap to [GLOB.max_ex_devastation_range], [GLOB.max_ex_heavy_range], [GLOB.max_ex_light_range]") + log_admin("[key_name(usr)] changed the bomb cap to [GLOB.max_ex_devastation_range], [GLOB.max_ex_heavy_range], [GLOB.max_ex_light_range]") if("flicklights") feedback_inc("admin_secrets_fun_used",1) @@ -2805,13 +2813,13 @@ return SSweather.run_weather(/datum/weather/ash_storm) message_admins("[key_name_admin(usr)] spawned an ash storm on the mining level") - if("retardify") + if("stupify") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","RET") for(var/mob/living/carbon/human/H in GLOB.player_list) to_chat(H, "You suddenly feel stupid.") H.setBrainLoss(60) - message_admins("[key_name_admin(usr)] made everybody retarded") + message_admins("[key_name_admin(usr)] made everybody stupid") if("fakeguns") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","FG") @@ -2838,7 +2846,7 @@ if(is_station_level(W.z) && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison)) W.req_access = list() message_admins("[key_name_admin(usr)] activated Egalitarian Station mode") - event_announcement.Announce("Centcomm airlock control override activated. Please take this time to get acquainted with your coworkers.", new_sound = 'sound/AI/commandreport.ogg') + GLOB.event_announcement.Announce("Centcomm airlock control override activated. Please take this time to get acquainted with your coworkers.", new_sound = 'sound/AI/commandreport.ogg') if("onlyone") feedback_inc("admin_secrets_fun_used",1) feedback_add_details("admin_secrets_fun_used","OO") @@ -2958,13 +2966,13 @@ var/ok = 0 switch(href_list["secretsadmin"]) if("list_signalers") - var/dat = "Showing last [length(lastsignalers)] signalers.
    " - for(var/sig in lastsignalers) + var/dat = "Showing last [length(GLOB.lastsignalers)] signalers.
    " + for(var/sig in GLOB.lastsignalers) dat += "[sig]
    " usr << browse(dat, "window=lastsignalers;size=800x500") if("list_lawchanges") - var/dat = "Showing last [length(lawchanges)] law changes.
    " - for(var/sig in lawchanges) + var/dat = "Showing last [length(GLOB.lawchanges)] law changes.
    " + for(var/sig in GLOB.lawchanges) dat += "[sig]
    " usr << browse(dat, "window=lawchanges;size=800x500") if("list_job_debug") @@ -3046,9 +3054,9 @@ switch(href_list["secretscoder"]) if("spawn_objects") var/dat = "Admin Log
    " - for(var/l in admin_log) + for(var/l in GLOB.admin_log) dat += "
  • [l]
  • " - if(!admin_log.len) + if(!GLOB.admin_log.len) dat += "No-one has done anything this round!" usr << browse(dat, "window=admin_log") if("maint_ACCESS_BRIG") @@ -3085,7 +3093,7 @@ else if(href_list["ac_submit_new_channel"]) var/check = 0 - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == src.admincaster_feed_channel.channel_name) check = 1 break @@ -3100,14 +3108,14 @@ newChannel.locked = src.admincaster_feed_channel.locked newChannel.is_admin_channel = 1 feedback_inc("newscaster_channels",1) - news_network.network_channels += newChannel //Adding channel to the global network + GLOB.news_network.network_channels += newChannel //Adding channel to the global network log_admin("[key_name_admin(usr)] created command feed channel: [src.admincaster_feed_channel.channel_name]!") src.admincaster_screen=5 src.access_news_network() else if(href_list["ac_set_channel_receiving"]) var/list/available_channels = list() - for(var/datum/feed_channel/F in news_network.network_channels) + for(var/datum/feed_channel/F in GLOB.news_network.network_channels) available_channels += F.channel_name src.admincaster_feed_channel.channel_name = adminscrub(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels ) src.access_news_network() @@ -3127,13 +3135,13 @@ newMsg.body = src.admincaster_feed_message.body newMsg.is_admin_message = 1 feedback_inc("newscaster_stories",1) - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == src.admincaster_feed_channel.channel_name) FC.messages += newMsg //Adding message to the network's appropriate feed_channel break src.admincaster_screen=4 - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters) NEWSCASTER.newsAlert(src.admincaster_feed_channel.channel_name) log_admin("[key_name_admin(usr)] submitted a feed story to channel: [src.admincaster_feed_channel.channel_name]!") @@ -3157,12 +3165,12 @@ else if(href_list["ac_menu_wanted"]) var/already_wanted = 0 - if(news_network.wanted_issue) + if(GLOB.news_network.wanted_issue) already_wanted = 1 if(already_wanted) - src.admincaster_feed_message.author = news_network.wanted_issue.author - src.admincaster_feed_message.body = news_network.wanted_issue.body + src.admincaster_feed_message.author = GLOB.news_network.wanted_issue.author + src.admincaster_feed_message.body = GLOB.news_network.wanted_issue.body src.admincaster_screen = 14 src.access_news_network() @@ -3191,15 +3199,15 @@ WANTED.body = src.admincaster_feed_message.body //Wanted desc WANTED.backup_author = src.admincaster_signature //Submitted by WANTED.is_admin_message = 1 - news_network.wanted_issue = WANTED - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + GLOB.news_network.wanted_issue = WANTED + for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters) NEWSCASTER.newsAlert() NEWSCASTER.update_icon() src.admincaster_screen = 15 else - news_network.wanted_issue.author = src.admincaster_feed_message.author - news_network.wanted_issue.body = src.admincaster_feed_message.body - news_network.wanted_issue.backup_author = src.admincaster_feed_message.backup_author + GLOB.news_network.wanted_issue.author = src.admincaster_feed_message.author + GLOB.news_network.wanted_issue.body = src.admincaster_feed_message.body + GLOB.news_network.wanted_issue.backup_author = src.admincaster_feed_message.backup_author src.admincaster_screen = 19 log_admin("[key_name_admin(usr)] issued a Station-wide Wanted Notification for [src.admincaster_feed_message.author]!") src.access_news_network() @@ -3207,8 +3215,8 @@ else if(href_list["ac_cancel_wanted"]) var/choice = alert("Please confirm Wanted Issue removal","Network Security Handler","Confirm","Cancel") if(choice=="Confirm") - news_network.wanted_issue = null - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + GLOB.news_network.wanted_issue = null + for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters) NEWSCASTER.update_icon() src.admincaster_screen=17 src.access_news_network() @@ -3333,7 +3341,7 @@ var/isbn = sanitizeSQL(href_list["library_book_id"]) if(href_list["view_library_book"]) - var/DBQuery/query_view_book = dbcon.NewQuery("SELECT content, title FROM [format_table_name("library")] WHERE id=[isbn]") + var/DBQuery/query_view_book = GLOB.dbcon.NewQuery("SELECT content, title FROM [format_table_name("library")] WHERE id=[isbn]") if(!query_view_book.Execute()) var/err = query_view_book.ErrorMsg() log_game("SQL ERROR viewing book. Error : \[[err]\]\n") @@ -3358,7 +3366,7 @@ return else if(href_list["unflag_library_book"]) - var/DBQuery/query_unflag_book = dbcon.NewQuery("UPDATE [format_table_name("library")] SET flagged = 0 WHERE id=[isbn]") + var/DBQuery/query_unflag_book = GLOB.dbcon.NewQuery("UPDATE [format_table_name("library")] SET flagged = 0 WHERE id=[isbn]") if(!query_unflag_book.Execute()) var/err = query_unflag_book.ErrorMsg() log_game("SQL ERROR unflagging book. Error : \[[err]\]\n") @@ -3368,7 +3376,7 @@ message_admins("[key_name_admin(usr)] has unflagged the book [isbn].") else if(href_list["delete_library_book"]) - var/DBQuery/query_delbook = dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[isbn]") + var/DBQuery/query_delbook = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[isbn]") if(!query_delbook.Execute()) var/err = query_delbook.ErrorMsg() log_game("SQL ERROR deleting book. Error : \[[err]\]\n") @@ -3381,11 +3389,12 @@ src.view_flagged_books() // Force unlink a discord key + // TODO: Delete this else if(href_list["force_discord_unlink"]) if(!check_rights(R_ADMIN)) return var/target_ckey = href_list["force_discord_unlink"] - var/DBQuery/admin_unlink_discord_id = dbcon.NewQuery("DELETE FROM [format_table_name("discord")] WHERE ckey = '[target_ckey]'") + var/DBQuery/admin_unlink_discord_id = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("discord")] WHERE ckey = '[target_ckey]'") if(!admin_unlink_discord_id.Execute()) var/err = admin_unlink_discord_id.ErrorMsg() log_game("SQL ERROR while admin-unlinking discord account. Error : \[[err]\]\n") @@ -3441,7 +3450,7 @@ return var/datum/mind/hunter_mind = new /datum/mind(key_of_hunter) hunter_mind.active = 1 - var/mob/living/carbon/human/hunter_mob = new /mob/living/carbon/human(pick(latejoin)) + var/mob/living/carbon/human/hunter_mob = new /mob/living/carbon/human(pick(GLOB.latejoin)) hunter_mind.transfer_to(hunter_mob) hunter_mob.equipOutfit(O, FALSE) var/obj/item/pinpointer/advpinpointer/N = new /obj/item/pinpointer/advpinpointer(hunter_mob) @@ -3450,6 +3459,7 @@ N.mode = 2 N.target = H N.point_at(N.target) + N.modelocked = TRUE if(!locate(/obj/item/implant/dust, hunter_mob)) var/obj/item/implant/dust/D = new /obj/item/implant/dust(hunter_mob) D.implant(hunter_mob) @@ -3471,7 +3481,7 @@ if(killthem) to_chat(hunter_mob, "If you kill [H.p_them()], [H.p_they()] cannot be revived."); hunter_mob.mind.special_role = SPECIAL_ROLE_TRAITOR - var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR] + var/datum/atom_hud/antag/tatorhud = GLOB.huds[ANTAG_HUD_TRAITOR] tatorhud.join_hud(hunter_mob) set_antag_hud(hunter_mob, "hudsyndicate") diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 1a13539c520..8ac9c4fd2b0 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -1,7 +1,7 @@ //This is a list of words which are ignored by the parser when comparing message contents for names. MUST BE IN LOWER CASE! -var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as") +GLOBAL_LIST_INIT(adminhelp_ignored_words, list("unknown","the","a","an","of","monkey","alien","as")) /client/verb/adminhelp() set category = "Admin" @@ -66,7 +66,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," for(var/original_word in msglist) var/word = ckey(original_word) if(word) - if(!(word in adminhelp_ignored_words)) + if(!(word in GLOB.adminhelp_ignored_words)) if(word == "ai") ai_found = 1 else diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 32355cd17fd..164d499e04a 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -261,7 +261,7 @@ /datum/pm_tracker var/current_title = "" var/open = FALSE - var/list/pms = list() + var/list/datum/pm_convo/pms = list() var/show_archived = FALSE var/window_id = "pms_window" diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm index 74eeff49692..a0e8b4b9088 100644 --- a/code/modules/admin/verbs/adminsay.dm +++ b/code/modules/admin/verbs/adminsay.dm @@ -20,7 +20,7 @@ /client/proc/get_admin_say() var/msg = input(src, null, "asay \"text\"") as text|null cmd_admin_say(msg) - + /client/proc/cmd_mentor_say(msg as text) set category = "Admin" set name = "Msay" @@ -59,12 +59,12 @@ var/enabling var/msay = /client/proc/cmd_mentor_say - if(msay in admin_verbs_mentor) + if(msay in GLOB.admin_verbs_mentor) enabling = FALSE - admin_verbs_mentor -= msay + GLOB.admin_verbs_mentor -= msay else enabling = TRUE - admin_verbs_mentor += msay + GLOB.admin_verbs_mentor += msay for(var/client/C in GLOB.admins) if(check_rights(R_ADMIN|R_MOD, 0, C.mob)) diff --git a/code/modules/admin/verbs/alt_check.dm b/code/modules/admin/verbs/alt_check.dm index d5118d4eb8f..c8060f22036 100644 --- a/code/modules/admin/verbs/alt_check.dm +++ b/code/modules/admin/verbs/alt_check.dm @@ -6,7 +6,7 @@
    Additionally make an attempt to introduce new players to the server
    "} - if(dbcon.IsConnected()) + if(GLOB.dbcon.IsConnected()) for(var/client/C in GLOB.clients) dat += "

    [C.ckey] (Player Age: [C.player_age]) - [C.computer_id] / [C.address]
    " if(C.related_accounts_cid.len) diff --git a/code/modules/admin/verbs/atmosdebug.dm b/code/modules/admin/verbs/atmosdebug.dm index 0624e4d1909..087a90eebe6 100644 --- a/code/modules/admin/verbs/atmosdebug.dm +++ b/code/modules/admin/verbs/atmosdebug.dm @@ -28,7 +28,7 @@ to_chat(usr, "Checking for overlapping pipes...") for(var/turf/T in world) - for(var/dir in cardinal) + for(var/dir in GLOB.cardinal) var/list/check = list(0, 0, 0) var/done = 0 for(var/obj/machinery/atmospherics/pipe in T) diff --git a/code/modules/admin/verbs/custom_event.dm b/code/modules/admin/verbs/custom_event.dm index 68d3301b11e..b3d1543aedc 100644 --- a/code/modules/admin/verbs/custom_event.dm +++ b/code/modules/admin/verbs/custom_event.dm @@ -7,9 +7,9 @@ to_chat(src, "Only administrators may use this command.") return - var/input = input(usr, "Enter the description of the custom event. Be descriptive. To cancel the event, make this blank or hit cancel.", "Custom Event", custom_event_msg) as message|null + var/input = input(usr, "Enter the description of the custom event. Be descriptive. To cancel the event, make this blank or hit cancel.", "Custom Event", GLOB.custom_event_msg) as message|null if(!input || input == "") - custom_event_msg = null + GLOB.custom_event_msg = null log_admin("[key_name(usr)] has cleared the custom event text.") message_admins("[key_name_admin(usr)] has cleared the custom event text.") return @@ -17,11 +17,11 @@ log_admin("[key_name(usr)] has changed the custom event text.") message_admins("[key_name_admin(usr)] has changed the custom event text.") - custom_event_msg = input + GLOB.custom_event_msg = input to_chat(world, "

    Custom Event

    ") to_chat(world, "

    A custom event is starting. OOC Info:

    ") - to_chat(world, "[html_encode(custom_event_msg)]") + to_chat(world, "[html_encode(GLOB.custom_event_msg)]") to_chat(world, "
    ") // normal verb for players to view info @@ -29,12 +29,12 @@ set category = "OOC" set name = "Custom Event Info" - if(!custom_event_msg || custom_event_msg == "") + if(!GLOB.custom_event_msg || GLOB.custom_event_msg == "") to_chat(src, "There currently is no known custom event taking place.") to_chat(src, "Keep in mind: it is possible that an admin has not properly set this.") return to_chat(src, "

    Custom Event

    ") to_chat(src, "

    A custom event is taking place. OOC Info:

    ") - to_chat(src, "[html_encode(custom_event_msg)]") + to_chat(src, "[html_encode(GLOB.custom_event_msg)]") to_chat(src, "
    ") diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index ad3a0403e87..c92e100b641 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -5,12 +5,12 @@ if(!check_rights(R_DEBUG)) return - if(Debug2) - Debug2 = 0 + if(GLOB.debug2) + GLOB.debug2 = 0 message_admins("[key_name_admin(src)] toggled debugging off.") log_admin("[key_name(src)] toggled debugging off.") else - Debug2 = 1 + GLOB.debug2 = 1 message_admins("[key_name_admin(src)] toggled debugging on.") log_admin("[key_name(src)] toggled debugging on.") @@ -291,9 +291,9 @@ GLOBAL_PROTECT(AdminProcCaller) pai.real_name = pai.name pai.key = choice.key card.setPersonality(pai) - for(var/datum/paiCandidate/candidate in paiController.pai_candidates) + for(var/datum/paiCandidate/candidate in GLOB.paiController.pai_candidates) if(candidate.key == choice.key) - paiController.pai_candidates.Remove(candidate) + GLOB.paiController.pai_candidates.Remove(candidate) feedback_add_details("admin_verb","MPAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/cmd_admin_alienize(var/mob/M in GLOB.mob_list) @@ -716,23 +716,25 @@ GLOBAL_PROTECT(AdminProcCaller) if(!check_rights(R_DEBUG)) return - switch(input("Which list?") in list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Silicons","Clients","Respawnable Mobs")) + switch(input("Which list?") in list("Players", "Admins", "Mobs", "Living Mobs", "Alive Mobs", "Dead Mobs", "Silicons", "Clients", "Respawnable Mobs")) if("Players") - to_chat(usr, jointext(GLOB.player_list,",")) + to_chat(usr, jointext(GLOB.player_list, ",")) if("Admins") - to_chat(usr, jointext(GLOB.admins,",")) + to_chat(usr, jointext(GLOB.admins, ",")) if("Mobs") - to_chat(usr, jointext(GLOB.mob_list,",")) + to_chat(usr, jointext(GLOB.mob_list, ",")) if("Living Mobs") - to_chat(usr, jointext(GLOB.living_mob_list,",")) + to_chat(usr, jointext(GLOB.mob_living_list, ",")) + if("Alive Mobs") + to_chat(usr, jointext(GLOB.alive_mob_list, ",")) if("Dead Mobs") - to_chat(usr, jointext(GLOB.dead_mob_list,",")) + to_chat(usr, jointext(GLOB.dead_mob_list, ",")) if("Silicons") - to_chat(usr, jointext(GLOB.silicon_mob_list,",")) + to_chat(usr, jointext(GLOB.silicon_mob_list, ",")) if("Clients") - to_chat(usr, jointext(GLOB.clients,",")) + to_chat(usr, jointext(GLOB.clients, ",")) if("Respawnable Mobs") - to_chat(usr, jointext(GLOB.respawnable_list,",")) + to_chat(usr, jointext(GLOB.respawnable_list, ",")) /client/proc/cmd_display_del_log() set category = "Debug" @@ -806,7 +808,7 @@ GLOBAL_PROTECT(AdminProcCaller) genemutcheck(M,block,null,MUTCHK_FORCED) M.update_mutations() var/state="[M.dna.GetSEState(block)?"on":"off"]" - var/blockname=assigned_blocks[block] + var/blockname=GLOB.assigned_blocks[block] message_admins("[key_name_admin(src)] has toggled [M.key]'s [blockname] block [state]!") log_admin("[key_name(src)] has toggled [M.key]'s [blockname] block [state]!") else @@ -832,10 +834,10 @@ GLOBAL_PROTECT(AdminProcCaller) set name = "View Runtimes" set desc = "Open the Runtime Viewer" - if(!check_rights(R_DEBUG)) + if(!check_rights(R_DEBUG|R_VIEWRUNTIMES)) return - error_cache.showTo(usr) + GLOB.error_cache.showTo(usr) /client/proc/jump_to_ruin() set category = "Debug" diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index 6770ca114aa..ce10383ca4e 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -19,8 +19,8 @@ for(var/datum/gas/trace_gas in GM.trace_gases) to_chat(usr, "[trace_gas.type]: [trace_gas.moles]") - message_admins("[key_name_admin(usr)] has checked the air status of [T]") - log_admin("[key_name(usr)] has checked the air status of [T]") + message_admins("[key_name_admin(usr)] has checked the air status of [target]") + log_admin("[key_name(usr)] has checked the air status of [target]") feedback_add_details("admin_verb","DAST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -85,7 +85,7 @@ var/output = "Radio Report
    " for(var/fq in SSradio.frequencies) output += "Freq: [fq]
    " - var/list/datum/radio_frequency/fqs = SSradio.frequencies[fq] + var/datum/radio_frequency/fqs = SSradio.frequencies[fq] if(!fqs) output += "  ERROR
    " continue @@ -131,7 +131,7 @@ return to_chat(usr, "Jobbans active in this round.") - for(var/t in jobban_keylist) + for(var/t in GLOB.jobban_keylist) to_chat(usr, "[t]") message_admins("[key_name_admin(usr)] has printed the jobban log") @@ -150,7 +150,7 @@ return to_chat(usr, "Jobbans active in this round.") - for(var/t in jobban_keylist) + for(var/t in GLOB.jobban_keylist) if(findtext(t, filter)) to_chat(usr, "[t]") diff --git a/code/modules/admin/verbs/freeze.dm b/code/modules/admin/verbs/freeze.dm index 9b01e94846c..0f52680acea 100644 --- a/code/modules/admin/verbs/freeze.dm +++ b/code/modules/admin/verbs/freeze.dm @@ -5,121 +5,99 @@ //////Allows admin's to right click on any mob/mech and freeze them in place./// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -var/global/list/frozen_mob_list = list() -/client/proc/freeze(var/mob/living/M as mob in GLOB.mob_list) + +GLOBAL_LIST_EMPTY(frozen_atom_list) // A list of admin-frozen atoms. + +/client/proc/freeze(atom/movable/M) set name = "Freeze" set category = null if(!check_rights(R_ADMIN)) return - if(!istype(M)) - return + M.admin_Freeze(src) - if(M in frozen_mob_list) - M.admin_unFreeze(src) - else - M.admin_Freeze(src) +/// Created here as a base proc. Override as needed for any type of object or mob you want able to be frozen. +/atom/movable/proc/admin_Freeze(client/admin) + to_chat(admin, "Freeze is not able to be called on this type of object.You have been frozen by [admin]") - message_admins("[key_name_admin(admin)] froze [key_name_admin(src)]") - log_admin("[key_name(admin)] froze [key_name(src)]") +/mob/living/admin_Freeze(client/admin, skip_overlays = FALSE, mech = null) + if(!istype(admin)) + return - var/obj/effect/overlay/adminoverlay/AO = new - if(skip_overlays) - overlays += AO + if(!(src in GLOB.frozen_atom_list)) + GLOB.frozen_atom_list += src - anchored = TRUE - canmove = FALSE - admin_prev_sleeping = sleeping - AdjustSleeping(20000) - frozen = AO - if(!(src in frozen_mob_list)) - frozen_mob_list += src + var/obj/effect/overlay/adminoverlay/AO = new + if(skip_overlays) + overlays += AO -/mob/living/proc/admin_unFreeze(client/admin, skip_overlays = FALSE) - if(istype(admin)) - to_chat(src, "You have been unfrozen by [admin]") - message_admins("[key_name_admin(admin)] unfroze [key_name_admin(src)]") - log_admin("[key_name(admin)] unfroze [key_name(src)]") + anchored = TRUE + canmove = FALSE + admin_prev_sleeping = sleeping + AdjustSleeping(20000) + frozen = AO - if(skip_overlays) - overlays -= frozen + else + GLOB.frozen_atom_list -= src - anchored = FALSE - canmove = TRUE - frozen = null - SetSleeping(admin_prev_sleeping) - admin_prev_sleeping = null - if(src in frozen_mob_list) - frozen_mob_list -= src + if(skip_overlays) + overlays -= frozen + anchored = FALSE + canmove = TRUE + frozen = null + SetSleeping(admin_prev_sleeping) + admin_prev_sleeping = null + + to_chat(src, "You have been [frozen ? "frozen" : "unfrozen"] by [admin]") + message_admins("[key_name_admin(admin)] [frozen ? "froze" : "unfroze"] [key_name_admin(src)] [mech ? "in a [mech]" : ""]") + log_admin("[key_name(admin)] [frozen ? "froze" : "unfroze"] [key_name(src)] [mech ? "in a [mech]" : ""]") update_icons() + return frozen + /mob/living/simple_animal/slime/admin_Freeze(admin) - ..(admin) - adjustHealth(1000) //arbitrary large value - -/mob/living/simple_animal/slime/admin_unFreeze(admin) - ..(admin) - revive() - + if(..()) // The result of the parent call here will be the value of the mob's `frozen` variable after they get (un)frozen. + adjustHealth(1000) //arbitrary large value + else + revive() /mob/living/simple_animal/var/admin_prev_health = null /mob/living/simple_animal/admin_Freeze(admin) - ..(admin) - admin_prev_health = health - health = 0 - -/mob/living/simple_animal/admin_unFreeze(admin) - ..(admin) - revive() - overlays.Cut() + if(..()) // The result of the parent call here will be the value of the mob's `frozen` variable after they get (un)frozen. + admin_prev_health = health + health = 0 + else + revive() + overlays.Cut() //////////////////////////Freeze Mech -/client/proc/freezemecha(var/obj/mecha/O as obj in GLOB.mechas_list) - set name = "Freeze Mech" - set category = null - - if(!check_rights(R_ADMIN)) - return - - var/obj/mecha/M = O - if(!istype(M,/obj/mecha)) - to_chat(src, "This can only be used on mechs!") - return +/obj/mecha/admin_Freeze(client/admin) + var/obj/effect/overlay/adminoverlay/freeze_overlay = new + if(!frozen) + GLOB.frozen_atom_list += src + frozen = TRUE + overlays += freeze_overlay else - if(usr) - if(usr.client) - if(usr.client.holder) - var/adminomaly = new/obj/effect/overlay/adminoverlay - if(M.can_move == 1) - M.can_move = 0 - M.overlays += adminomaly - if(M.occupant) - to_chat(M.occupant, "You have been frozen by [key]") - message_admins("[key_name_admin(usr)] froze [key_name(M.occupant)] in a [M.name]") - log_admin("[key_name(usr)] froze [key_name(M.occupant)] in a [M.name]") - else - message_admins("[key_name_admin(usr)] froze an empty [M.name]") - log_admin("[key_name(usr)] froze an empty [M.name]") - else if(M.can_move == 0) - M.can_move = 1 - M.overlays -= adminomaly - if(M.occupant) - to_chat(M.occupant, "You have been unfrozen by [key]") - message_admins("[key_name_admin(usr)] unfroze [key_name(M.occupant)] in a [M.name]") - log_admin("[key_name(usr)] unfroze [key_name(M.occupant)] in a [M.name]") - else - message_admins("[key_name_admin(usr)] unfroze an empty [M.name]") - log_admin("[key_name(usr)] unfroze an empty [M.name]") + GLOB.frozen_atom_list -= src + frozen = FALSE + overlays -= freeze_overlay + + if(occupant) + occupant.admin_Freeze(admin, mech = name) // We also want to freeze the driver of the mech. + else + message_admins("[key_name_admin(admin)] [frozen ? "froze" : "unfroze"] an empty [name]") + log_admin("[key_name(admin)] [frozen ? "froze" : "unfroze"] an empty [name]") diff --git a/code/modules/admin/verbs/gimmick_team.dm b/code/modules/admin/verbs/gimmick_team.dm index cad93e8b880..37afe35ef6a 100644 --- a/code/modules/admin/verbs/gimmick_team.dm +++ b/code/modules/admin/verbs/gimmick_team.dm @@ -27,7 +27,7 @@ if(!themission) alert("No mission specified. Aborting.") return - var/admin_outfits = subtypesof(/datum/outfit/admin) + var/admin_outfits = subtypesof(/datum/outfit/admin) + list(/datum/outfit/naked) var/outfit_list = list() for(var/type in admin_outfits) var/datum/outfit/admin/O = type diff --git a/code/modules/admin/verbs/honksquad.dm b/code/modules/admin/verbs/honksquad.dm index 238706c1038..8c8d46ec97b 100644 --- a/code/modules/admin/verbs/honksquad.dm +++ b/code/modules/admin/verbs/honksquad.dm @@ -1,7 +1,7 @@ //HONKsquad #define HONKSQUAD_POSSIBLE 6 //if more Commandos are needed in the future -var/global/sent_honksquad = 0 +GLOBAL_VAR_INIT(sent_honksquad, 0) /client/proc/honksquad() if(!SSticker) @@ -10,7 +10,7 @@ var/global/sent_honksquad = 0 if(world.time < 6000) to_chat(usr, "There are [(6000-world.time)/10] seconds remaining before it may be called.") return - if(sent_honksquad == 1) + if(GLOB.sent_honksquad == 1) to_chat(usr, "Clown Planet has already dispatched a HONKsquad.") return if(alert("Do you want to send in the HONKsquad? Once enabled, this is irreversible.",,"Yes","No")!="Yes") @@ -24,11 +24,11 @@ var/global/sent_honksquad = 0 if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") return - if(sent_honksquad) + if(GLOB.sent_honksquad) to_chat(usr, "Looks like someone beat you to it. HONK.") return - sent_honksquad = 1 + GLOB.sent_honksquad = 1 var/honksquad_number = HONKSQUAD_POSSIBLE //for selecting a leader diff --git a/code/modules/admin/verbs/infiltratorteam_syndicate.dm b/code/modules/admin/verbs/infiltratorteam_syndicate.dm index 4cea0538520..459f2b8fb4b 100644 --- a/code/modules/admin/verbs/infiltratorteam_syndicate.dm +++ b/code/modules/admin/verbs/infiltratorteam_syndicate.dm @@ -1,7 +1,7 @@ // Syndicate Infiltration Team (SIT) // A little like Syndicate Strike Team (SST) but geared towards stealthy team missions rather than murderbone. -var/global/sent_syndicate_infiltration_team = 0 +GLOBAL_VAR_INIT(sent_syndicate_infiltration_team, 0) /client/proc/syndicate_infiltration_team() set category = "Event" @@ -35,7 +35,7 @@ var/global/sent_syndicate_infiltration_team = 0 var/tctext = input(src, "How much TC do you want to give each team member? Suggested: 20-30. They cannot trade TC.") as num var/tcamount = text2num(tctext) tcamount = between(0, tcamount, 1000) - if(sent_syndicate_infiltration_team == 1) + if(GLOB.sent_syndicate_infiltration_team == 1) if(alert("A Syndicate Infiltration Team has already been sent. Sure you want to send another?",,"Yes","No")=="No") return @@ -61,7 +61,7 @@ var/global/sent_syndicate_infiltration_team = 0 to_chat(src, "Nobody volunteered.") return 0 - sent_syndicate_infiltration_team = 1 + GLOB.sent_syndicate_infiltration_team = 1 var/list/sit_spawns = list() var/list/sit_spawns_leader = list() @@ -90,7 +90,7 @@ var/global/sent_syndicate_infiltration_team = 0 to_chat(new_syndicate_infiltrator, "You are a [!syndicate_leader_selected?"Infiltrator":"Lead Infiltrator"] in the service of the Syndicate. \nYour current mission is: [input]") to_chat(new_syndicate_infiltrator, "You are equipped with an uplink implant to help you achieve your objectives. ((activate it via button in top left of screen))") new_syndicate_infiltrator.faction += "syndicate" - data_core.manifest_inject(new_syndicate_infiltrator) + GLOB.data_core.manifest_inject(new_syndicate_infiltrator) if(syndicate_leader_selected) var/obj/effect/landmark/warpto = pick(sit_spawns_leader) new_syndicate_infiltrator.loc = warpto.loc @@ -104,7 +104,7 @@ var/global/sent_syndicate_infiltration_team = 0 new_syndicate_infiltrator.mind.store_memory("Mission: [input] ") new_syndicate_infiltrator.mind.store_memory("Team Leader: [team_leader] ") new_syndicate_infiltrator.mind.store_memory("Starting Equipment:
    - Syndicate Headset ((.h for your radio))
    - Chameleon Jumpsuit ((right click to Change Color))
    - Agent ID card ((disguise as another job))
    - Uplink Implant ((top left of screen))
    - Dust Implant ((destroys your body on death))
    - Combat Gloves ((insulated, disguised as black gloves))
    - Anything bought with your uplink implant") - var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS] + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] opshud.join_hud(new_syndicate_infiltrator.mind.current) set_antag_hud(new_syndicate_infiltrator.mind.current, "hudoperative") new_syndicate_infiltrator.regenerate_icons() diff --git a/code/modules/admin/verbs/logging_view.dm b/code/modules/admin/verbs/logging_view.dm new file mode 100644 index 00000000000..903926f4923 --- /dev/null +++ b/code/modules/admin/verbs/logging_view.dm @@ -0,0 +1,11 @@ +GLOBAL_LIST_INIT(open_logging_views, list()) + +/client/proc/cmd_admin_open_logging_view() + set category = "Admin" + set name = "Open Logging View" + set desc = "Opens the detailed logging viewer" + + if(!GLOB.open_logging_views[usr.client.ckey]) + GLOB.open_logging_views[usr.client.ckey] = new /datum/log_viewer() + var/datum/log_viewer/LV = GLOB.open_logging_views[usr.client.ckey] + LV.show_ui(usr) diff --git a/code/modules/admin/verbs/map_template_loadverb.dm b/code/modules/admin/verbs/map_template_loadverb.dm index f447810d860..edbca5a842f 100644 --- a/code/modules/admin/verbs/map_template_loadverb.dm +++ b/code/modules/admin/verbs/map_template_loadverb.dm @@ -6,10 +6,10 @@ return var/datum/map_template/template - var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in map_templates + var/map = input(usr, "Choose a Map Template to place at your CURRENT LOCATION","Place Map Template") as null|anything in GLOB.map_templates if(!map) return - template = map_templates[map] + template = GLOB.map_templates[map] var/turf/T = get_turf(mob) if(!T) @@ -48,7 +48,7 @@ var/datum/map_template/M = new(map=map, rename="[map]") if(M.preload_size(map)) to_chat(usr, "Map template '[map]' ready to place ([M.width]x[M.height])") - map_templates[M.name] = M + GLOB.map_templates[M.name] = M message_admins("[key_name_admin(usr)] has uploaded a map template ([map]). Took [stop_watch(timer)]s.") else to_chat(usr, "Map template '[map]' failed to load properly") diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 61356f46027..10ad31ef410 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -19,8 +19,8 @@ //- Identify how hard it is to break into the area and where the weak points are //- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels. -var/camera_range_display_status = 0 -var/intercom_range_display_status = 0 +GLOBAL_VAR_INIT(camera_range_display_status, 0) +GLOBAL_VAR_INIT(intercom_range_display_status, 0) /obj/effect/debugging/camera_range icon = 'icons/480x480.dmi' @@ -50,16 +50,16 @@ var/intercom_range_display_status = 0 if(!check_rights(R_DEBUG)) return - if(camera_range_display_status) - camera_range_display_status = 0 + if(GLOB.camera_range_display_status) + GLOB.camera_range_display_status = 0 else - camera_range_display_status = 1 + GLOB.camera_range_display_status = 1 for(var/obj/effect/debugging/camera_range/C in world) qdel(C) - if(camera_range_display_status) - for(var/obj/machinery/camera/C in cameranet.cameras) + if(GLOB.camera_range_display_status) + for(var/obj/machinery/camera/C in GLOB.cameranet.cameras) new/obj/effect/debugging/camera_range(C.loc) feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -72,7 +72,7 @@ var/intercom_range_display_status = 0 var/list/obj/machinery/camera/CL = list() - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in GLOB.cameranet.cameras) CL += C var/output = {"CAMERA ANOMALIES REPORT
    @@ -109,15 +109,15 @@ var/intercom_range_display_status = 0 if(!check_rights(R_DEBUG)) return - if(intercom_range_display_status) - intercom_range_display_status = 0 + if(GLOB.intercom_range_display_status) + GLOB.intercom_range_display_status = 0 else - intercom_range_display_status = 1 + GLOB.intercom_range_display_status = 1 for(var/obj/effect/debugging/marker/M in world) qdel(M) - if(intercom_range_display_status) + if(GLOB.intercom_range_display_status) for(var/obj/item/radio/intercom/I in world) for(var/turf/T in orange(7,I)) var/obj/effect/debugging/marker/F = new/obj/effect/debugging/marker(T) diff --git a/code/modules/admin/verbs/massmodvar.dm b/code/modules/admin/verbs/massmodvar.dm index 50c329f17d2..50629d5a1cc 100644 --- a/code/modules/admin/verbs/massmodvar.dm +++ b/code/modules/admin/verbs/massmodvar.dm @@ -45,16 +45,16 @@ var/default var/var_value = O.vars[variable] - if(variable in VVckey_edit) + if(variable in GLOB.VVckey_edit) to_chat(src, "It's forbidden to mass-modify ckeys. It'll crash everyone's client you dummy.") return - if(variable in VVlocked) + if(variable in GLOB.VVlocked) if(!check_rights(R_DEBUG)) return - if(variable in VVicon_edit_lock) + if(variable in GLOB.VVicon_edit_lock) if(!check_rights(R_EVENT | R_DEBUG)) return - if(variable in VVpixelmovement) + if(variable in GLOB.VVpixelmovement) if(!check_rights(R_DEBUG)) return var/prompt = alert(src, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT ", "Continue", " ABORT") diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index bd0624bcdff..079446b0994 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -1,7 +1,7 @@ -var/list/VVlocked = list("vars", "var_edited", "client", "firemut", "ishulk", "telekinesis", "xray", "ka", "virus", "viruses", "cuffed", "last_eaten", "unlock_content") // R_DEBUG -var/list/VVicon_edit_lock = list("icon", "icon_state", "overlays", "underlays", "resize") // R_EVENT | R_DEBUG -var/list/VVckey_edit = list("key", "ckey") // R_EVENT | R_DEBUG -var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", "bound_width", "bound_x", "bound_y") // R_DEBUG + warning +GLOBAL_LIST_INIT(VVlocked, list("vars", "var_edited", "client", "firemut", "ishulk", "telekinesis", "xray", "ka", "virus", "viruses", "cuffed", "last_eaten", "unlock_content")) // R_DEBUG +GLOBAL_LIST_INIT(VVicon_edit_lock, list("icon", "icon_state", "overlays", "underlays", "resize")) // R_EVENT | R_DEBUG +GLOBAL_LIST_INIT(VVckey_edit, list("key", "ckey")) // R_EVENT | R_DEBUG +GLOBAL_LIST_INIT(VVpixelmovement, list("step_x", "step_y", "step_size", "bound_height", "bound_width", "bound_x", "bound_y")) // R_DEBUG + warning /client/proc/vv_get_class(var/var_value) if(isnull(var_value)) . = VV_NULL @@ -517,16 +517,16 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", message_admins("[key_name_admin(src)] modified [original_name]'s varlist [objectvar]: [original_var]=[new_var]") /proc/vv_varname_lockcheck(param_var_name) - if(param_var_name in VVlocked) + if(param_var_name in GLOB.VVlocked) if(!check_rights(R_DEBUG)) return FALSE - if(param_var_name in VVckey_edit) + if(param_var_name in GLOB.VVckey_edit) if(!check_rights(R_EVENT | R_DEBUG)) return FALSE - if(param_var_name in VVicon_edit_lock) + if(param_var_name in GLOB.VVicon_edit_lock) if(!check_rights(R_EVENT | R_DEBUG)) return FALSE - if(param_var_name in VVpixelmovement) + if(param_var_name in GLOB.VVpixelmovement) if(!check_rights(R_DEBUG)) return FALSE var/prompt = alert(usr, "Editing this var may irreparably break tile gliding for the rest of the round. THIS CAN'T BE UNDONE", "DANGER", "ABORT ", "Continue", " ABORT") @@ -543,7 +543,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", var/var_value if(param_var_name) - if(!param_var_name in O.vars) + if(!(param_var_name in O.vars)) to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this datum ([O])") return variable = param_var_name @@ -627,6 +627,7 @@ var/list/VVpixelmovement = list("step_x", "step_y", "step_size", "bound_height", if(!O.vv_edit_var(variable, var_new)) to_chat(src, "Your edit was rejected by the object.") return + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_VAR_EDIT, args) log_world("### VarEdit by [src]: [O.type] [variable]=[html_encode("[var_new]")]") log_admin("[key_name(src)] modified [original_name]'s [variable] to [var_new]") var/msg = "[key_name_admin(src)] modified [original_name]'s [variable] to [var_new]" diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index f1a8d9990c5..57f7cad31c4 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -177,11 +177,11 @@ client/proc/one_click_antag() H = pick(candidates) SSticker.mode.add_cultist(H.mind) candidates.Remove(H) - if(!summon_spots.len) - while(summon_spots.len < SUMMON_POSSIBILITIES) - var/area/summon = pick(return_sorted_areas() - summon_spots) + if(!GLOB.summon_spots.len) + while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES) + var/area/summon = pick(return_sorted_areas() - GLOB.summon_spots) if(summon && is_station_level(summon.z) && summon.valid_territory) - summon_spots += summon + GLOB.summon_spots += summon return 1 return 0 @@ -379,7 +379,7 @@ client/proc/one_click_antag() if(!G_found || !G_found.key) return //First we spawn a dude. - var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. + var/mob/living/carbon/human/new_character = new(pick(GLOB.latejoin))//The mob being spawned. var/datum/preferences/A = new(G_found.client) A.copy_to(new_character) @@ -513,7 +513,7 @@ client/proc/one_click_antag() //Now apply cortical stack. var/obj/item/implant/cortical/I = new(new_vox) I.implant(new_vox) - cortical_stacks += I + GLOB.cortical_stacks += I new_vox.equip_vox_raider() new_vox.regenerate_icons() diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm index c3299c212ad..e51f6da991a 100644 --- a/code/modules/admin/verbs/onlyone.dm +++ b/code/modules/admin/verbs/onlyone.dm @@ -54,7 +54,7 @@ message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ONE! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1) log_admin("[key_name(usr)] used there can be only one.") - nologevent = 1 + GLOB.nologevent = 1 world << sound('sound/music/thunderdome.ogg') /client/proc/only_me() @@ -100,5 +100,5 @@ message_admins("[key_name_admin(usr)] used THERE CAN BE ONLY ME! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1) log_admin("[key_name(usr)] used there can be only me.") - nologevent = 1 + GLOB.nologevent = 1 world << sound('sound/music/thunderdome.ogg') diff --git a/code/modules/admin/verbs/onlyoneteam.dm b/code/modules/admin/verbs/onlyoneteam.dm index 846a77c508a..9575cc5b340 100644 --- a/code/modules/admin/verbs/onlyoneteam.dm +++ b/code/modules/admin/verbs/onlyoneteam.dm @@ -29,7 +29,7 @@ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/white(H), slot_shoes) if(!team_toggle) - team_alpha += H + GLOB.team_alpha += H H.equip_to_slot_or_del(new /obj/item/clothing/under/color/red/dodgeball(H), slot_w_uniform) var/obj/item/card/id/W = new(H) @@ -42,7 +42,7 @@ H.equip_to_slot_or_del(W, slot_wear_id) else - team_bravo += H + GLOB.team_bravo += H H.equip_to_slot_or_del(new /obj/item/clothing/under/color/blue/dodgeball(H), slot_w_uniform) var/obj/item/card/id/W = new(H) @@ -60,7 +60,7 @@ message_admins("[key_name_admin(usr)] used DODGEBAWWWWWWWL! -NO ATTACK LOGS WILL BE SENT TO ADMINS FROM THIS POINT FORTH-", 1) log_admin("[key_name(usr)] used dodgeball.") - nologevent = 1 + GLOB.nologevent = 1 /obj/item/beach_ball/dodgeball name = "dodgeball" @@ -76,13 +76,13 @@ if(H.r_hand == src) return if(H.l_hand == src) return var/mob/A = H.LAssailant - if((H in team_alpha) && (A in team_alpha)) + if((H in GLOB.team_alpha) && (A in GLOB.team_alpha)) to_chat(A, "He's on your team!") return - else if((H in team_bravo) && (A in team_bravo)) + else if((H in GLOB.team_bravo) && (A in GLOB.team_bravo)) to_chat(A, "He's on your team!") return - else if(!A in team_alpha && !A in team_bravo) + else if(!(A in GLOB.team_alpha) && !(A in GLOB.team_bravo)) to_chat(A, "You're not part of the dodgeball game, sorry!") return else diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm index 4717ba67f65..6ec103cccc9 100644 --- a/code/modules/admin/verbs/playsound.dm +++ b/code/modules/admin/verbs/playsound.dm @@ -1,4 +1,4 @@ -var/list/sounds_cache = list() +GLOBAL_LIST_EMPTY(sounds_cache) /client/proc/stop_global_admin_sounds() set category = "Event" @@ -21,7 +21,7 @@ var/list/sounds_cache = list() var/sound/uploaded_sound = sound(S, repeat = 0, wait = 1, channel = CHANNEL_ADMIN) uploaded_sound.priority = 250 - sounds_cache += S + GLOB.sounds_cache += S if(alert("Are you sure?\nSong: [S]\nNow you can also play this sound using \"Play Server Sound\".", "Confirmation request" ,"Play", "Cancel") == "Cancel") return @@ -54,7 +54,7 @@ var/list/sounds_cache = list() if(!check_rights(R_SOUNDS)) return var/list/sounds = file2list("sound/serversound_list.txt"); - sounds += sounds_cache + sounds += GLOB.sounds_cache var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds if(!melody) return @@ -72,7 +72,7 @@ var/list/sounds_cache = list() if(A != "Yep") return var/list/sounds = file2list("sound/serversound_list.txt"); - sounds += sounds_cache + sounds += GLOB.sounds_cache var/melody = input("Select a sound from the server to play", "Server sound list") as null|anything in sounds if(!melody) return diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index cc13601e23b..a7763f31fb1 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -33,7 +33,7 @@ //teleport person to cell M.Paralyse(5) sleep(5) //so they black out before warping - M.loc = pick(prisonwarp) + M.loc = pick(GLOB.prisonwarp) if(istype(M, /mob/living/carbon/human)) var/mob/living/carbon/human/prisoner = M prisoner.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(prisoner), slot_w_uniform) @@ -361,8 +361,8 @@ Traitors and the like can also be revived with the previous role mostly intact. if(G_found.mind.assigned_role=="Alien") if(alert("This character appears to have been an alien. Would you like to respawn them as such?",,"Yes","No")=="Yes") var/turf/T - if(xeno_spawn.len) T = pick(xeno_spawn) - else T = pick(latejoin) + if(GLOB.xeno_spawn.len) T = pick(GLOB.xeno_spawn) + else T = pick(GLOB.latejoin) var/mob/living/carbon/alien/new_xeno switch(G_found.mind.special_role)//If they have a mind, we can determine which caste they were. @@ -381,14 +381,14 @@ Traitors and the like can also be revived with the previous role mostly intact. message_admins("[key_name_admin(usr)] has respawned [new_xeno.key] as a filthy xeno.", 1) return //all done. The ghost is auto-deleted - var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned. + var/mob/living/carbon/human/new_character = new(pick(GLOB.latejoin))//The mob being spawned. var/datum/data/record/record_found //Referenced to later to either randomize or not randomize the character. if(G_found.mind && !G_found.mind.active) //mind isn't currently in use by someone/something /*Try and locate a record for the person being respawned through data_core. This isn't an exact science but it does the trick more often than not.*/ var/id = md5("[G_found.real_name][G_found.mind.assigned_role]") - for(var/datum/data/record/t in data_core.locked) + for(var/datum/data/record/t in GLOB.data_core.locked) if(t.fields["id"]==id) record_found = t//We shall now reference the record. break @@ -446,7 +446,7 @@ Traitors and the like can also be revived with the previous role mostly intact. else new_character.mind.add_antag_datum(/datum/antagonist/traitor) if("Wizard") - new_character.loc = pick(wizardstart) + new_character.loc = pick(GLOB.wizardstart) //ticker.mode.learn_basic_spells(new_character) SSticker.mode.equip_wizard(new_character) if("Syndicate") @@ -481,7 +481,7 @@ Traitors and the like can also be revived with the previous role mostly intact. if(!record_found && new_character.mind.assigned_role != new_character.mind.special_role)//If there are no records for them. If they have a record, this info is already in there. Offstation special characters announced anyway. //Power to the user! if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes") - data_core.manifest_inject(new_character) + GLOB.data_core.manifest_inject(new_character) if(alert(new_character,"Would you like an active AI to announce this character?",,"No","Yes")=="Yes") call(/mob/new_player/proc/AnnounceArrival)(new_character, new_character.mind.assigned_role) @@ -511,7 +511,7 @@ Traitors and the like can also be revived with the previous role mostly intact. if(!istext(ckey)) return 0 var/alien_caste = input(usr, "Please choose which caste to spawn.","Pick a caste",null) as null|anything in list("Queen","Hunter","Sentinel","Drone","Larva") - var/obj/effect/landmark/spawn_here = xeno_spawn.len ? pick(xeno_spawn) : pick(latejoin) + var/obj/effect/landmark/spawn_here = GLOB.xeno_spawn.len ? pick(GLOB.xeno_spawn) : pick(GLOB.latejoin) var/mob/living/carbon/alien/new_xeno switch(alien_caste) if("Queen") new_xeno = new /mob/living/carbon/alien/humanoid/queen/large(spawn_here) @@ -533,7 +533,7 @@ Traitors and the like can also be revived with the previous role mostly intact. var/list/mobs = list() var/list/ghosts = list() var/list/sortmob = sortAtom(GLOB.mob_list) // get the mob list. - /var/any=0 + var/any=0 for(var/mob/dead/observer/M in sortmob) mobs.Add(M) //filter it where it's only ghosts any = 1 //if no ghosts show up, any will just be 0 @@ -623,11 +623,11 @@ Traitors and the like can also be revived with the previous role mostly intact. if("Yes") var/beepsound = input(usr, "What sound should the announcement make?", "Announcement Sound", "") as anything in MsgSound - command_announcement.Announce(input, customname, MsgSound[beepsound], , , type) + GLOB.command_announcement.Announce(input, customname, MsgSound[beepsound], , , type) print_command_report(input, "[command_name()] Update") if("No") //same thing as the blob stuff - it's not public, so it's classified, dammit - command_announcer.autosay("A classified message has been printed out at all communication consoles."); + GLOB.command_announcer.autosay("A classified message has been printed out at all communication consoles."); print_command_report(input, "Classified [command_name()] Update") else return @@ -885,7 +885,7 @@ Traitors and the like can also be revived with the previous role mostly intact. return to_chat(usr, text("Attack Log for []", mob)) - for(var/t in M.attack_log) + for(var/t in M.attack_log_old) to_chat(usr, t) feedback_add_details("admin_verb","ATTL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -954,7 +954,9 @@ Traitors and the like can also be revived with the previous role mostly intact. if(confirm != "Yes") return - GLOB.nttc_config.reset() + for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines) + C.nttc.reset() + log_admin("[key_name(usr)] reset NTTC scripts.") message_admins("[key_name_admin(usr)] reset NTTC scripts.") feedback_add_details("admin_verb","RAT2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -977,7 +979,7 @@ Traitors and the like can also be revived with the previous role mostly intact. var/role_string var/obj_count = 0 var/obj_string = "" - for(var/mob/living/carbon/human/H in GLOB.living_mob_list) + for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) if(!isLivingSSD(H)) continue mins_ssd = round((world.time - H.last_logout) / 600) @@ -986,7 +988,7 @@ Traitors and the like can also be revived with the previous role mostly intact. else job_string = "-" key_string = H.key - if(job_string in command_positions) + if(job_string in GLOB.command_positions) job_string = "" + job_string + "" role_string = "-" obj_count = 0 @@ -1014,7 +1016,7 @@ Traitors and the like can also be revived with the previous role mostly intact. msg += "AFK Players:
    Whitelisted Positions
    Whitelisted Positions
    " msg += "" var/mins_afk - for(var/mob/living/carbon/human/H in GLOB.living_mob_list) + for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) if(H.client == null || H.stat == DEAD) // No clientless or dead continue mins_afk = round(H.client.inactivity / 600) @@ -1025,7 +1027,7 @@ Traitors and the like can also be revived with the previous role mostly intact. else job_string = "-" key_string = H.key - if(job_string in command_positions) + if(job_string in GLOB.command_positions) job_string = "" + job_string + "" role_string = "-" obj_count = 0 diff --git a/code/modules/admin/verbs/space_transitions.dm b/code/modules/admin/verbs/space_transitions.dm index eda17996c65..4589e5354b5 100644 --- a/code/modules/admin/verbs/space_transitions.dm +++ b/code/modules/admin/verbs/space_transitions.dm @@ -13,7 +13,7 @@ message_admins("[key_name_admin(usr)] re-assigned all space transitions") - space_manager.do_transition_setup() + GLOB.space_manager.do_transition_setup() log_admin("[key_name(usr)] re-assigned all space transitions") feedback_add_details("admin_verb","SPCRST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -37,5 +37,5 @@ message_admins("[key_name_admin(usr)] made a space map") - space_manager.map_as_turfs(get_turf(usr)) + GLOB.space_manager.map_as_turfs(get_turf(usr)) log_admin("[key_name(usr)] made a space map") diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm index a040d1cc8c3..a03c37c4f67 100644 --- a/code/modules/admin/verbs/striketeam.dm +++ b/code/modules/admin/verbs/striketeam.dm @@ -1,13 +1,13 @@ //STRIKE TEAMS #define COMMANDOS_POSSIBLE 6 //if more Commandos are needed in the future -var/global/sent_strike_team = 0 +GLOBAL_VAR_INIT(sent_strike_team, 0) /client/proc/strike_team() if(!SSticker) to_chat(usr, "The game hasn't started yet!") return - if(sent_strike_team == 1) + if(GLOB.sent_strike_team == 1) to_chat(usr, "CentComm is already sending a team.") return if(alert("Do you want to send in the CentComm death squad? Once enabled, this is irreversible.",,"Yes","No")!="Yes") @@ -23,7 +23,7 @@ var/global/sent_strike_team = 0 if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") return - if(sent_strike_team) + if(GLOB.sent_strike_team) to_chat(usr, "Looks like someone beat you to it.") return @@ -37,12 +37,12 @@ var/global/sent_strike_team = 0 break // Find ghosts willing to be DS - var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, COMMANDOS_POSSIBLE, "Join the DeathSquad?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) + var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, COMMANDOS_POSSIBLE, "Join the DeathSquad?",, 21, 600, 1, GLOB.role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) if(!commando_ghosts.len) to_chat(usr, "Nobody volunteered to join the DeathSquad.") return - sent_strike_team = 1 + GLOB.sent_strike_team = 1 // Spawns commandos and equips them. var/commando_number = COMMANDOS_POSSIBLE //for selecting a leader @@ -158,6 +158,8 @@ var/global/sent_strike_team = 0 var/obj/item/radio/R = new /obj/item/radio/headset/alt(src) R.set_frequency(DTH_FREQ) + R.requires_tcomms = FALSE + R.instant = TRUE equip_to_slot_or_del(R, slot_l_ear) if(is_leader) equip_to_slot_or_del(new /obj/item/clothing/under/rank/centcom_officer(src), slot_w_uniform) diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm index 8dc2881911c..73ee5edb82d 100644 --- a/code/modules/admin/verbs/striketeam_syndicate.dm +++ b/code/modules/admin/verbs/striketeam_syndicate.dm @@ -1,7 +1,7 @@ //STRIKE TEAMS #define SYNDICATE_COMMANDOS_POSSIBLE 6 //if more Commandos are needed in the future -var/global/sent_syndicate_strike_team = 0 +GLOBAL_VAR_INIT(sent_syndicate_strike_team, 0) /client/proc/syndicate_strike_team() set category = "Event" set name = "Spawn Syndicate Strike Team" @@ -12,7 +12,7 @@ var/global/sent_syndicate_strike_team = 0 if(!SSticker) alert("The game hasn't started yet!") return - if(sent_syndicate_strike_team == 1) + if(GLOB.sent_syndicate_strike_team == 1) alert("The Syndicate are already sending a team, Mr. Dumbass.") return if(alert("Do you want to send in the Syndicate Strike Team? Once enabled, this is irreversible.",,"Yes","No")=="No") @@ -28,7 +28,7 @@ var/global/sent_syndicate_strike_team = 0 if(alert("Error, no mission set. Do you want to exit the setup process?",,"Yes","No")=="Yes") return - if(sent_syndicate_strike_team) + if(GLOB.sent_syndicate_strike_team) to_chat(src, "Looks like someone beat you to it.") return @@ -45,12 +45,12 @@ var/global/sent_syndicate_strike_team = 0 break // Find ghosts willing to be SST - var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, SYNDICATE_COMMANDOS_POSSIBLE, "Join the Syndicate Strike Team?",, 21, 600, 1, role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) + var/list/commando_ghosts = pollCandidatesWithVeto(src, usr, SYNDICATE_COMMANDOS_POSSIBLE, "Join the Syndicate Strike Team?",, 21, 600, 1, GLOB.role_playtime_requirements[ROLE_DEATHSQUAD], TRUE, FALSE) if(!commando_ghosts.len) to_chat(usr, "Nobody volunteered to join the SST.") return - sent_syndicate_strike_team = 1 + GLOB.sent_syndicate_strike_team = 1 //Spawns commandos and equips them. for(var/obj/effect/landmark/L in GLOB.landmarks_list) @@ -85,7 +85,7 @@ var/global/sent_syndicate_strike_team = 0 to_chat(new_syndicate_commando, "You are an Elite Syndicate [is_leader ? "TEAM LEADER" : "commando"] in the service of the Syndicate. \nYour current mission is: [input]") new_syndicate_commando.faction += "syndicate" - var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS] + var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS] opshud.join_hud(new_syndicate_commando.mind.current) set_antag_hud(new_syndicate_commando.mind.current, "hudoperative") new_syndicate_commando.regenerate_icons() diff --git a/code/modules/admin/verbs/toggledebugverbs.dm b/code/modules/admin/verbs/toggledebugverbs.dm index 85c61ac978f..216f5c3e4b0 100644 --- a/code/modules/admin/verbs/toggledebugverbs.dm +++ b/code/modules/admin/verbs/toggledebugverbs.dm @@ -1,4 +1,4 @@ -var/list/admin_verbs_show_debug_verbs = list( +GLOBAL_LIST_INIT(admin_verbs_show_debug_verbs, list( /client/proc/camera_view, /client/proc/sec_camera_report, /client/proc/intercom_view, @@ -22,7 +22,7 @@ var/list/admin_verbs_show_debug_verbs = list( /client/proc/admin_redo_space_transitions, /client/proc/make_turf_space_map, /client/proc/vv_by_ref -) +)) // Would be nice to make this a permanent admin pref so we don't need to click it each time /client/proc/enable_debug_verbs() @@ -32,6 +32,6 @@ var/list/admin_verbs_show_debug_verbs = list( if(!check_rights(R_DEBUG)) return - verbs += admin_verbs_show_debug_verbs + verbs += GLOB.admin_verbs_show_debug_verbs feedback_add_details("admin_verb","mDV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/admin/verbs/vox_raiders.dm b/code/modules/admin/verbs/vox_raiders.dm index 3e42ebe65fb..048939a7c6d 100644 --- a/code/modules/admin/verbs/vox_raiders.dm +++ b/code/modules/admin/verbs/vox_raiders.dm @@ -1,4 +1,4 @@ -var/global/vox_tick = 1 +GLOBAL_VAR_INIT(vox_tick, 1) /mob/living/carbon/human/proc/equip_vox_raider() @@ -10,7 +10,7 @@ var/global/vox_tick = 1 equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(src), slot_shoes) // REPLACE THESE WITH CODED VOX ALTERNATIVES. equip_to_slot_or_del(new /obj/item/clothing/gloves/color/yellow/vox(src), slot_gloves) // AS ABOVE. - switch(vox_tick) + switch(GLOB.vox_tick) if(1) // Vox raider! equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/carapace(src), slot_wear_suit) equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/carapace(src), slot_head) @@ -59,7 +59,7 @@ var/global/vox_tick = 1 W.registered_user = src equip_to_slot_or_del(W, slot_wear_id) - vox_tick++ - if(vox_tick > 4) vox_tick = 1 + GLOB.vox_tick++ + if(GLOB.vox_tick > 4) GLOB.vox_tick = 1 return 1 diff --git a/code/modules/admin/watchlist.dm b/code/modules/admin/watchlist.dm index a908c2c264b..002a3b7ffe4 100644 --- a/code/modules/admin/watchlist.dm +++ b/code/modules/admin/watchlist.dm @@ -6,7 +6,7 @@ if(!new_ckey) return new_ckey = sanitizeSQL(new_ckey) - var/DBQuery/query_watchfind = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'") + var/DBQuery/query_watchfind = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'") if(!query_watchfind.Execute()) var/err = query_watchfind.ErrorMsg() log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n") @@ -29,7 +29,7 @@ if(!adminckey) return var/admin_sql_ckey = sanitizeSQL(adminckey) - var/DBQuery/query_watchadd = dbcon.NewQuery("INSERT INTO [format_table_name("watch")] (ckey, reason, adminckey, timestamp) VALUES ('[target_sql_ckey]', '[reason]', '[admin_sql_ckey]', '[timestamp]')") + var/DBQuery/query_watchadd = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("watch")] (ckey, reason, adminckey, timestamp) VALUES ('[target_sql_ckey]', '[reason]', '[admin_sql_ckey]', '[timestamp]')") if(!query_watchadd.Execute()) var/err = query_watchadd.ErrorMsg() log_game("SQL ERROR during adding new watch entry. Error : \[[err]\]\n") @@ -43,7 +43,7 @@ if(!check_rights(R_ADMIN)) return var/target_sql_ckey = sanitizeSQL(target_ckey) - var/DBQuery/query_watchdel = dbcon.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'") + var/DBQuery/query_watchdel = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'") if(!query_watchdel.Execute()) var/err = query_watchdel.ErrorMsg() log_game("SQL ERROR during removing watch entry. Error : \[[err]\]\n") @@ -57,7 +57,7 @@ if(!check_rights(R_ADMIN)) return var/target_sql_ckey = sanitizeSQL(target_ckey) - var/DBQuery/query_watchreason = dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'") + var/DBQuery/query_watchreason = GLOB.dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'") if(!query_watchreason.Execute()) var/err = query_watchreason.ErrorMsg() log_game("SQL ERROR obtaining reason from watch table. Error : \[[err]\]\n") @@ -71,7 +71,7 @@ var/sql_ckey = sanitizeSQL(usr.ckey) var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from \"[watch_reason]\" to \"[new_reason]\"" edit_text = sanitizeSQL(edit_text) - var/DBQuery/query_watchupdate = dbcon.NewQuery("UPDATE [format_table_name("watch")] SET reason = '[new_reason]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'") + var/DBQuery/query_watchupdate = GLOB.dbcon.NewQuery("UPDATE [format_table_name("watch")] SET reason = '[new_reason]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'") if(!query_watchupdate.Execute()) var/err = query_watchupdate.ErrorMsg() log_game("SQL ERROR editing watchlist reason. Error : \[[err]\]\n") @@ -96,7 +96,7 @@ else search = "^." search = sanitizeSQL(search) - var/DBQuery/query_watchlist = dbcon.NewQuery("SELECT ckey, reason, adminckey, timestamp, last_editor FROM [format_table_name("watch")] WHERE ckey REGEXP '[search]' ORDER BY ckey") + var/DBQuery/query_watchlist = GLOB.dbcon.NewQuery("SELECT ckey, reason, adminckey, timestamp, last_editor FROM [format_table_name("watch")] WHERE ckey REGEXP '[search]' ORDER BY ckey") if(!query_watchlist.Execute()) var/err = query_watchlist.ErrorMsg() log_game("SQL ERROR obtaining ckey, reason, adminckey, timestamp, last_editor from watch table. Error : \[[err]\]\n") @@ -115,7 +115,7 @@ /proc/check_watchlist(target_ckey) var/target_sql_ckey = sanitizeSQL(target_ckey) - var/DBQuery/query_watch = dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'") + var/DBQuery/query_watch = GLOB.dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'") if(!query_watch.Execute()) var/err = query_watch.ErrorMsg() log_game("SQL ERROR obtaining reason from watch table. Error : \[[err]\]\n") diff --git a/code/modules/antagonists/_common/antag_hud.dm b/code/modules/antagonists/_common/antag_hud.dm index 178f84387ac..0cb800aa38d 100644 --- a/code/modules/antagonists/_common/antag_hud.dm +++ b/code/modules/antagonists/_common/antag_hud.dm @@ -47,11 +47,11 @@ newhud.join_hud(current) /datum/mind/proc/leave_all_huds() - for(var/datum/atom_hud/antag/hud in huds) + for(var/datum/atom_hud/antag/hud in GLOB.huds) if(current in hud.hudusers) hud.leave_hud(current) - for(var/datum/atom_hud/data/hud in huds) + for(var/datum/atom_hud/data/hud in GLOB.huds) if(current in hud.hudusers) hud.remove_hud_from(current) diff --git a/code/modules/antagonists/_common/antag_spawner.dm b/code/modules/antagonists/_common/antag_spawner.dm index d57c3124f61..beefc41735b 100644 --- a/code/modules/antagonists/_common/antag_spawner.dm +++ b/code/modules/antagonists/_common/antag_spawner.dm @@ -266,7 +266,7 @@ to_chat(user, "The sludge does not respond to your attempt to awake it. Perhaps you should try again later.") /obj/item/antag_spawner/morph/spawn_antag(client/C, turf/T, type = "", mob/user) - var/mob/living/simple_animal/hostile/morph/wizard/M = new /mob/living/simple_animal/hostile/morph/wizard(pick(xeno_spawn)) + var/mob/living/simple_animal/hostile/morph/wizard/M = new /mob/living/simple_animal/hostile/morph/wizard(pick(GLOB.xeno_spawn)) M.key = C.key M.mind.assigned_role = SPECIAL_ROLE_MORPH M.mind.special_role = SPECIAL_ROLE_MORPH diff --git a/code/modules/antagonists/traitor/datum_mindslave.dm b/code/modules/antagonists/traitor/datum_mindslave.dm index 5efd35715ad..6fcb4bac63a 100644 --- a/code/modules/antagonists/traitor/datum_mindslave.dm +++ b/code/modules/antagonists/traitor/datum_mindslave.dm @@ -44,10 +44,10 @@ owner.objectives -= O /datum/antagonist/mindslave/proc/update_mindslave_icons_added() - var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR] + var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR] traitorhud.join_hud(owner.current, null) set_antag_hud(owner.current, "hudmindslave") /datum/antagonist/mindslave/proc/update_mindslave_icons_removed() - var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR] + var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR] traitorhud.leave_hud(owner.current, null) diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 3cd7998edd8..e13fb701317 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -118,7 +118,7 @@ var/objective_amount = config.traitor_objectives_amount - + if(is_hijacker && objective_count <= objective_amount) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount if (!(locate(/datum/objective/hijack) in objectives)) var/datum/objective/hijack/hijack_objective = new @@ -187,7 +187,7 @@ destroy_objective.owner = owner destroy_objective.find_target() if("[destroy_objective]" in assigned_targets) // Is this target already in their list of assigned targets? If so, don't add this objective and return - return 0 + return 0 else if(destroy_objective.target) // Is the target a real one and not null? If so, add it to our list of targets to avoid duplicate targets assigned_targets.Add("[destroy_objective.target]") // This logic is applied to all traitor objectives including steal objectives add_objective(destroy_objective) @@ -221,7 +221,7 @@ else if(kill_objective.target) assigned_targets.Add("[kill_objective.target]") add_objective(kill_objective) - + else var/datum/objective/steal/steal_objective = new steal_objective.owner = owner @@ -231,7 +231,7 @@ else if(steal_objective.steal_target) assigned_targets.Add("[steal_objective.steal_target]") add_objective(steal_objective) - + /datum/antagonist/traitor/proc/forge_single_AI_objective() . = 1 @@ -251,13 +251,13 @@ /datum/antagonist/traitor/proc/update_traitor_icons_added(datum/mind/traitor_mind) - var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR] + var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR] traitorhud.join_hud(owner.current, null) set_antag_hud(owner.current, "hudsyndicate") /datum/antagonist/traitor/proc/update_traitor_icons_removed(datum/mind/traitor_mind) - var/datum/atom_hud/antag/traitorhud = huds[ANTAG_HUD_TRAITOR] + var/datum/atom_hud/antag/traitorhud = GLOB.huds[ANTAG_HUD_TRAITOR] traitorhud.leave_hud(owner.current, null) set_antag_hud(owner.current, null) @@ -273,7 +273,7 @@ if(should_equip) equip_traitor() owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/tatoralert.ogg', 100, FALSE, pressure_affected = FALSE) - + /datum/antagonist/traitor/proc/give_codewords() if(!owner.current) @@ -309,7 +309,7 @@ if(traitor_kind == TRAITOR_HUMAN) var/mob/living/carbon/human/traitor_mob = owner.current - + // find a radio! toolbox(es), backpack, belt, headset var/obj/item/R = locate(/obj/item/pda) in traitor_mob.contents //Hide the uplink in a PDA if available, otherwise radio if(!R) diff --git a/code/modules/antagonists/wishgranter/wishgranter.dm b/code/modules/antagonists/wishgranter/wishgranter.dm index b5414df33bf..cb6fad39d34 100644 --- a/code/modules/antagonists/wishgranter/wishgranter.dm +++ b/code/modules/antagonists/wishgranter/wishgranter.dm @@ -22,56 +22,56 @@ if(!istype(H)) return H.ignore_gene_stability = TRUE - H.dna.SetSEState(HULKBLOCK, TRUE) - genemutcheck(H, HULKBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.hulkblock, TRUE) + genemutcheck(H, GLOB.hulkblock, null, MUTCHK_FORCED) - H.dna.SetSEState(XRAYBLOCK, TRUE) - genemutcheck(H, XRAYBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.xrayblock, TRUE) + genemutcheck(H, GLOB.xrayblock, null, MUTCHK_FORCED) - H.dna.SetSEState(FIREBLOCK, TRUE) - genemutcheck(H, FIREBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.fireblock, TRUE) + genemutcheck(H, GLOB.fireblock, null, MUTCHK_FORCED) - H.dna.SetSEState(COLDBLOCK, TRUE) - genemutcheck(H, COLDBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.coldblock, TRUE) + genemutcheck(H, GLOB.coldblock, null, MUTCHK_FORCED) - H.dna.SetSEState(TELEBLOCK, TRUE) - genemutcheck(H, TELEBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.teleblock, TRUE) + genemutcheck(H, GLOB.teleblock, null, MUTCHK_FORCED) - H.dna.SetSEState(INCREASERUNBLOCK, TRUE) - genemutcheck(H, INCREASERUNBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.increaserunblock, TRUE) + genemutcheck(H, GLOB.increaserunblock, null, MUTCHK_FORCED) - H.dna.SetSEState(BREATHLESSBLOCK, TRUE) - genemutcheck(H, BREATHLESSBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.breathlessblock, TRUE) + genemutcheck(H, GLOB.breathlessblock, null, MUTCHK_FORCED) - H.dna.SetSEState(REGENERATEBLOCK, TRUE) - genemutcheck(H, REGENERATEBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.regenerateblock, TRUE) + genemutcheck(H, GLOB.regenerateblock, null, MUTCHK_FORCED) - H.dna.SetSEState(SHOCKIMMUNITYBLOCK, TRUE) - genemutcheck(H, SHOCKIMMUNITYBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.shockimmunityblock, TRUE) + genemutcheck(H, GLOB.shockimmunityblock, null, MUTCHK_FORCED) - H.dna.SetSEState(SMALLSIZEBLOCK, TRUE) - genemutcheck(H, SMALLSIZEBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.smallsizeblock, TRUE) + genemutcheck(H, GLOB.smallsizeblock, null, MUTCHK_FORCED) - H.dna.SetSEState(SOBERBLOCK, TRUE) - genemutcheck(H, SOBERBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.soberblock, TRUE) + genemutcheck(H, GLOB.soberblock, null, MUTCHK_FORCED) - H.dna.SetSEState(PSYRESISTBLOCK, TRUE) - genemutcheck(H, PSYRESISTBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.psyresistblock, TRUE) + genemutcheck(H, GLOB.psyresistblock, null, MUTCHK_FORCED) - H.dna.SetSEState(SHADOWBLOCK, TRUE) - genemutcheck(H, SHADOWBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.shadowblock, TRUE) + genemutcheck(H, GLOB.shadowblock, null, MUTCHK_FORCED) - H.dna.SetSEState(CRYOBLOCK, TRUE) - genemutcheck(H, CRYOBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.cryoblock, TRUE) + genemutcheck(H, GLOB.cryoblock, null, MUTCHK_FORCED) - H.dna.SetSEState(EATBLOCK, TRUE) - genemutcheck(H, EATBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.eatblock, TRUE) + genemutcheck(H, GLOB.eatblock, null, MUTCHK_FORCED) - H.dna.SetSEState(JUMPBLOCK, TRUE) - genemutcheck(H, JUMPBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.jumpblock, TRUE) + genemutcheck(H, GLOB.jumpblock, null, MUTCHK_FORCED) - H.dna.SetSEState(IMMOLATEBLOCK, TRUE) - genemutcheck(H, IMMOLATEBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.immolateblock, TRUE) + genemutcheck(H, GLOB.immolateblock, null, MUTCHK_FORCED) H.mutations.Add(LASER) H.update_mutations() diff --git a/code/modules/arcade/arcade_prize.dm b/code/modules/arcade/arcade_prize.dm index 47b0ac97bf8..832d1c46649 100644 --- a/code/modules/arcade/arcade_prize.dm +++ b/code/modules/arcade/arcade_prize.dm @@ -20,7 +20,7 @@ opening = 1 playsound(src.loc, 'sound/items/bubblewrap.ogg', 30, 1, extrarange = -4, falloff = 10) icon_state = "prizeconfetti" - src.color = pick(random_color_list) + src.color = pick(GLOB.random_color_list) var/prize_inside = pick(possible_contents) spawn(10) user.unEquip(src) diff --git a/code/modules/arcade/claw_game.dm b/code/modules/arcade/claw_game.dm index 904adaffeb5..6ee5c83b89c 100644 --- a/code/modules/arcade/claw_game.dm +++ b/code/modules/arcade/claw_game.dm @@ -1,4 +1,4 @@ -/var/claw_game_html = null +GLOBAL_VAR(claw_game_html) /obj/machinery/arcade/claw name = "Claw Game" @@ -30,8 +30,8 @@ component_parts += new /obj/item/stack/sheet/glass(null, 1) RefreshParts() - if(!claw_game_html) - claw_game_html = file2text('code/modules/arcade/crane.html') + if(!GLOB.claw_game_html) + GLOB.claw_game_html = file2text('code/modules/arcade/crane.html') /obj/machinery/arcade/claw/RefreshParts() var/bin_upgrades = 0 @@ -58,14 +58,14 @@ atom_say("WINNER!") new /obj/item/toy/prizeball(get_turf(src)) playsound(src.loc, 'sound/arcade/win.ogg', 50, 1, extrarange = -3, falloff = 10) - addtimer(CALLBACK(src, .update_icon), 10) + addtimer(CALLBACK(src, .proc/update_icon), 10) /obj/machinery/arcade/claw/start_play(mob/user as mob) ..() user << browse_rsc('page.css') for(var/i in 1 to img_resources.len) user << browse_rsc(img_resources[i]) - var/my_game_html = replacetext(claw_game_html, "/* ref src */", UID()) + var/my_game_html = replacetext(GLOB.claw_game_html, "/* ref src */", UID()) user << browse(my_game_html, "window=[window_name];size=915x600;can_resize=0") /obj/machinery/arcade/claw/Topic(href, list/href_list) diff --git a/code/modules/arcade/mob_hunt/mob_datums.dm b/code/modules/arcade/mob_hunt/mob_datums.dm index d9fc1220a79..a50fab183e6 100644 --- a/code/modules/arcade/mob_hunt/mob_datums.dm +++ b/code/modules/arcade/mob_hunt/mob_datums.dm @@ -108,7 +108,7 @@ /datum/mob_hunt/proc/get_possible_areas() var/list/possible_areas = list() //setup, sets all station areas (and subtypes) to weight 1 - for(var/A in the_station_areas) + for(var/A in GLOB.the_station_areas) if(A == /area/holodeck) //don't allow holodeck areas as possible spawns since it will allow it to spawn in the holodeck rooms on z2 as well continue if(A in possible_areas) diff --git a/code/modules/arcade/prize_counter.dm b/code/modules/arcade/prize_counter.dm index 4d1d6973909..9c8a4dea685 100644 --- a/code/modules/arcade/prize_counter.dm +++ b/code/modules/arcade/prize_counter.dm @@ -140,11 +140,11 @@ th.cost.toomuch {background:maroon;} "} - for(var/datum/prize_item/item in global_prizes.prizes) + for(var/datum/prize_item/item in GLOB.global_prizes.prizes) var/cost_class="affordable" if(item.cost>tickets) cost_class="toomuch" - var/itemID = global_prizes.prizes.Find(item) + var/itemID = GLOB.global_prizes.prizes.Find(item) var/row_color="light" if(itemID%2 == 0) row_color="dark" @@ -185,12 +185,12 @@ th.cost.toomuch {background:maroon;} if(href_list["buy"]) var/itemID = text2num(href_list["buy"]) - var/datum/prize_item/item = global_prizes.prizes[itemID] + var/datum/prize_item/item = GLOB.global_prizes.prizes[itemID] var/sure = alert(usr,"Are you sure you wish to purchase [item.name] for [item.cost] tickets?","You sure?","Yes","No") in list("Yes","No") if(sure=="No") updateUsrDialog() return - if(!global_prizes.PlaceOrder(src, itemID)) + if(!GLOB.global_prizes.PlaceOrder(src, itemID)) to_chat(usr, "Unable to complete the exchange.") else to_chat(usr, "You've successfully purchased the item.") diff --git a/code/modules/arcade/prize_datums.dm b/code/modules/arcade/prize_datums.dm index 8a3d598bb3d..1edad36b8f3 100644 --- a/code/modules/arcade/prize_datums.dm +++ b/code/modules/arcade/prize_datums.dm @@ -1,5 +1,4 @@ - -var/global/datum/prizes/global_prizes = new +GLOBAL_DATUM_INIT(global_prizes, /datum/prizes, new()) /datum/prizes var/list/prizes = list() @@ -14,7 +13,7 @@ var/global/datum/prizes/global_prizes = new return if(!prize_counter) return 0 - var/datum/prize_item/item = global_prizes.prizes[itemID] + var/datum/prize_item/item = GLOB.global_prizes.prizes[itemID] if(!item) return 0 if(prize_counter.tickets >= item.cost) diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index 9b4c9b38677..35e80e53d18 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -89,7 +89,7 @@ /obj/item/assembly/mousetrap/attack_hand(mob/living/user) if(armed) - if((user.getBrainLoss() >= 60 || CLUMSY in user.mutations) && prob(50)) + if((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50)) var/which_hand = "l_hand" if(!user.hand) which_hand = "r_hand" diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index 93db1674fa7..f774d28921f 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -127,7 +127,7 @@ var/time = time2text(world.realtime,"hh:mm:ss") var/turf/T = get_turf(src) if(usr) - lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + GLOB.lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") /obj/item/assembly/signaler/pulse(var/radio = FALSE) if(connected && wires) diff --git a/code/modules/atmos_automation/console.dm b/code/modules/atmos_automation/console.dm index a810d3b08c5..8d23bb390aa 100644 --- a/code/modules/atmos_automation/console.dm +++ b/code/modules/atmos_automation/console.dm @@ -54,7 +54,7 @@ /obj/machinery/computer/general_air_control/atmos_automation/proc/selectValidChildFor(datum/automation/parent, mob/user, list/valid_returntypes) var/list/choices=list() - for(var/childtype in automation_types) + for(var/childtype in GLOB.automation_types) var/datum/automation/A = new childtype(src) if(A.returntype == null) continue @@ -217,7 +217,7 @@ testing("AAC: Null cData in root JS array.") continue var/Atype=text2path(cData["type"]) - if(!(Atype in automation_types)) + if(!(Atype in GLOB.automation_types)) testing("AAC: Unrecognized Atype [Atype].") continue var/datum/automation/A = new Atype(src) diff --git a/code/modules/atmos_automation/implementation/scrubbers.dm b/code/modules/atmos_automation/implementation/scrubbers.dm index 5be0967d9a8..54829d01cea 100644 --- a/code/modules/atmos_automation/implementation/scrubbers.dm +++ b/code/modules/atmos_automation/implementation/scrubbers.dm @@ -84,13 +84,13 @@ parent.updateUsrDialog() return 1 -var/global/list/gas_labels=list( +GLOBAL_LIST_INIT(gas_labels, list( "co2" = "CO2", "tox" = "Plasma", "n2o" = "N2O", "o2" = "O2", "n2" = "N2" -) +)) /datum/automation/set_scrubber_gasses name="Scrubber: Gasses" @@ -131,7 +131,7 @@ var/global/list/gas_labels=list( GetText() var/txt = "Set Scrubber [fmtString(scrubber)] to scrub " for(var/gas in gasses) - txt += " [gas_labels[gas]] ([gasses[gas] ? "on" : "off"])," + txt += " [GLOB.gas_labels[gas]] ([gasses[gas] ? "on" : "off"])," return txt Topic(href,href_list) diff --git a/code/modules/atmos_automation/implementation/sensors.dm b/code/modules/atmos_automation/implementation/sensors.dm index d86d9612470..e1ef348a617 100644 --- a/code/modules/atmos_automation/implementation/sensors.dm +++ b/code/modules/atmos_automation/implementation/sensors.dm @@ -22,7 +22,7 @@ field = json["field"] Evaluate() - if(sensor && field && sensor in parent.sensor_information) + if(sensor && field && (sensor in parent.sensor_information)) return parent.sensor_information[sensor][field] return 0 diff --git a/code/modules/atmos_automation/statements.dm b/code/modules/atmos_automation/statements.dm index 1e92fcab493..3f5ed0fb6a7 100644 --- a/code/modules/atmos_automation/statements.dm +++ b/code/modules/atmos_automation/statements.dm @@ -1,4 +1,4 @@ -var/global/automation_types = subtypesof(/datum/automation) +GLOBAL_LIST_INIT(automation_types, subtypesof(/datum/automation)) #define AUTOM_RT_NULL 0 #define AUTOM_RT_NUM 1 @@ -56,7 +56,7 @@ var/global/automation_types = subtypesof(/datum/automation) if(isnull(cData) || !("type" in cData)) return null var/Atype=text2path(cData["type"]) - if(!(Atype in automation_types)) + if(!(Atype in GLOB.automation_types)) return null var/datum/automation/A = new Atype(parent) A.Import(cData) @@ -70,7 +70,7 @@ var/global/automation_types = subtypesof(/datum/automation) . += null continue var/Atype=text2path(cData["type"]) - if(!(Atype in automation_types)) + if(!(Atype in GLOB.automation_types)) continue var/datum/automation/A = new Atype(parent) A.Import(cData) diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 1086f43dd48..bac8d64d9f2 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -163,11 +163,11 @@ var/pda = -1 var/backpack_contents = -1 var/suit_store = -1 - var/hair_style var/facial_hair_style var/skin_tone + var/list/del_types = list(/obj/item/pda, /obj/item/radio/headset) /obj/effect/mob_spawn/human/Initialize() if(ispath(outfit)) @@ -227,7 +227,6 @@ if(!isnum(T)) outfit.vars[slot] = T H.equipOutfit(outfit) - var/list/del_types = list(/obj/item/pda, /obj/item/radio/headset) for(var/del_type in del_types) var/obj/item/I = locate(del_type) in H qdel(I) diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm index 76e3fed2ebf..d7e298e8c96 100644 --- a/code/modules/awaymissions/gateway.dm +++ b/code/modules/awaymissions/gateway.dm @@ -1,4 +1,4 @@ -var/obj/machinery/gateway/centerstation/the_gateway = null +GLOBAL_DATUM_INIT(the_gateway, /obj/machinery/gateway/centerstation, null) /obj/machinery/gateway name = "gateway" desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations." @@ -41,8 +41,8 @@ var/obj/machinery/gateway/centerstation/the_gateway = null /obj/machinery/gateway/centerstation/New() ..() - if(!the_gateway) - the_gateway = src + if(!GLOB.the_gateway) + GLOB.the_gateway = src /obj/machinery/gateway/centerstation/Initialize() ..() @@ -54,8 +54,8 @@ var/obj/machinery/gateway/centerstation/the_gateway = null return /obj/machinery/gateway/centerstation/Destroy() - if(the_gateway == src) - the_gateway = null + if(GLOB.the_gateway == src) + GLOB.the_gateway = null return ..() /obj/machinery/gateway/centerstation/update_icon() @@ -79,7 +79,7 @@ var/obj/machinery/gateway/centerstation/the_gateway = null linked = list() //clear the list var/turf/T = loc - for(var/i in alldirs) + for(var/i in GLOB.alldirs) T = get_step(loc, i) var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T if(G) @@ -150,7 +150,7 @@ var/obj/machinery/gateway/centerstation/the_gateway = null M.dir = SOUTH return else - var/obj/effect/landmark/dest = pick(awaydestinations) + var/obj/effect/landmark/dest = pick(GLOB.awaydestinations) if(dest) M.forceMove(dest.loc) M.dir = SOUTH @@ -197,7 +197,7 @@ var/obj/machinery/gateway/centerstation/the_gateway = null linked = list() //clear the list var/turf/T = loc - for(var/i in alldirs) + for(var/i in GLOB.alldirs) T = get_step(loc, i) var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T if(G) diff --git a/code/modules/awaymissions/map_rng.dm b/code/modules/awaymissions/map_rng.dm index 77954eafb9f..0c1d776fa7b 100644 --- a/code/modules/awaymissions/map_rng.dm +++ b/code/modules/awaymissions/map_rng.dm @@ -17,7 +17,7 @@ if(tname) template_name = tname if(template_name) - template = map_templates[template_name] + template = GLOB.map_templates[template_name] /obj/effect/landmark/map_loader/Initialize() . = ..() @@ -47,5 +47,5 @@ ..() if(template_list) template_name = safepick(splittext(template_list, ";")) - template = map_templates[template_name] + template = GLOB.map_templates[template_name] load(template) diff --git a/code/modules/awaymissions/maploader/dmm_suite.dm b/code/modules/awaymissions/maploader/dmm_suite.dm index a4da02b4170..1eee3d8fc34 100644 --- a/code/modules/awaymissions/maploader/dmm_suite.dm +++ b/code/modules/awaymissions/maploader/dmm_suite.dm @@ -1,5 +1,4 @@ -var/global/dmm_suite/maploader = new - +GLOBAL_DATUM_INIT(maploader, /dmm_suite, new()) dmm_suite{ /* diff --git a/code/modules/awaymissions/maploader/reader.dm b/code/modules/awaymissions/maploader/reader.dm index 4d5d464e136..9a7cf6b6405 100644 --- a/code/modules/awaymissions/maploader/reader.dm +++ b/code/modules/awaymissions/maploader/reader.dm @@ -4,8 +4,8 @@ //As of 3.6.2016 //global datum that will preload variables on atoms instanciation -var/global/use_preloader = FALSE -var/global/dmm_suite/preloader/_preloader = new +GLOBAL_VAR_INIT(use_preloader, FALSE) +GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new()) /dmm_suite // These regexes are global - meaning that starting the maploader again mid-load will @@ -96,7 +96,7 @@ var/global/dmm_suite/preloader/_preloader = new if(cropMap) continue else - space_manager.increase_max_zlevel_to(zcrd) //create a new z_level if needed + GLOB.space_manager.increase_max_zlevel_to(zcrd) //create a new z_level if needed bounds[MAP_MINX] = min(bounds[MAP_MINX], xcrdStart) bounds[MAP_MINZ] = min(bounds[MAP_MINZ], zcrd) @@ -156,10 +156,10 @@ var/global/dmm_suite/preloader/_preloader = new CHECK_TICK catch(var/exception/e) - _preloader.reset() + GLOB._preloader.reset() throw e - _preloader.reset() + GLOB._preloader.reset() log_debug("Loaded map in [stop_watch(watch)]s.") qdel(LM) if(bounds[MAP_MINX] == 1.#INF) // Shouldn't need to check every item @@ -271,14 +271,14 @@ var/global/dmm_suite/preloader/_preloader = new throw EXCEPTION("Oh no, I thought this was an area!") var/atom/instance - _preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation + GLOB._preloader.setup(members_attributes[index])//preloader for assigning set variables on atom creation instance = LM.area_path_to_real_area(members[index]) if(crds) instance.contents.Add(crds) - if(use_preloader && instance) - _preloader.load(instance) + if(GLOB.use_preloader && instance) + GLOB._preloader.load(instance) //then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect @@ -316,7 +316,7 @@ var/global/dmm_suite/preloader/_preloader = new //Instance an atom at (x,y,z) and gives it the variables in attributes /dmm_suite/proc/instance_atom(path,list/attributes, x, y, z) var/atom/instance - _preloader.setup(attributes, path) + GLOB._preloader.setup(attributes, path) var/turf/T = locate(x,y,z) if(T) @@ -328,8 +328,8 @@ var/global/dmm_suite/preloader/_preloader = new else instance = new path (T)//first preloader pass - if(use_preloader && instance)//second preloader pass, for those atoms that don't ..() in New() - _preloader.load(instance) + if(GLOB.use_preloader && instance)//second preloader pass, for those atoms that don't ..() in New() + GLOB._preloader.load(instance) return instance @@ -439,7 +439,7 @@ var/global/dmm_suite/preloader/_preloader = new json_ready = 0 if("map_json_data" in the_attributes) json_ready = 1 - use_preloader = TRUE + GLOB.use_preloader = TRUE attributes = the_attributes target_path = path @@ -458,11 +458,11 @@ var/global/dmm_suite/preloader/_preloader = new if(islist(value)) value = deepCopyList(value) what.vars[attribute] = value - use_preloader = FALSE + GLOB.use_preloader = FALSE // If the map loader fails, make this safe /dmm_suite/preloader/proc/reset() - use_preloader = FALSE + GLOB.use_preloader = FALSE attributes = list() target_path = null diff --git a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm index b41ec901573..f06a9a37f9c 100644 --- a/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm +++ b/code/modules/awaymissions/mission_code/UO71-terrorspiders.dm @@ -191,26 +191,27 @@ origin_tech = null selfcharge = 1 can_charge = 0 - var/inawaymission = 1 + // Selfcharge is enabled and disabled, and used as the away mission tracker + selfcharge = TRUE -/obj/item/gun/energy/laser/awaymission_aeg/process() - var/turf/my_loc = get_turf(src) - if(is_away_level(my_loc.z)) - if(inawaymission) - return ..() +/obj/item/gun/energy/laser/awaymission_aeg/Initialize(mapload) + . = ..() + // Force update it incase it spawns outside an away mission and shouldnt be charged + onTransitZ(new_z = loc.z) + +/obj/item/gun/energy/laser/awaymission_aeg/onTransitZ(old_z, new_z) + if(is_away_level(new_z)) if(ismob(loc)) to_chat(loc, "Your [src] activates, starting to draw power from a nearby wireless power source.") - inawaymission = 1 + selfcharge = TRUE else - if(inawaymission) + if(selfcharge) if(ismob(loc)) to_chat(loc, "Your [src] deactivates, as it is out of range from its power source.") cell.charge = 0 - inawaymission = 0 + selfcharge = FALSE update_icon() - - /obj/item/reagent_containers/glass/beaker/terror_black_toxin name = "beaker 'Black Terror Venom'" diff --git a/code/modules/awaymissions/mission_code/academy.dm b/code/modules/awaymissions/mission_code/academy.dm index f8d66058199..7cddddd8b08 100644 --- a/code/modules/awaymissions/mission_code/academy.dm +++ b/code/modules/awaymissions/mission_code/academy.dm @@ -108,7 +108,7 @@ if(3) //Swarm of creatures T.visible_message("A swarm of creatures surround [user]!") - for(var/direction in alldirs) + for(var/direction in GLOB.alldirs) new /mob/living/simple_animal/hostile/netherworld(get_step(get_turf(user),direction)) if(4) //Destroy Equipment @@ -131,7 +131,7 @@ T.visible_message("Unseen forces throw [user]!") user.Stun(6) user.adjustBruteLoss(50) - var/throw_dir = cardinal + var/throw_dir = GLOB.cardinal var/atom/throw_target = get_edge_target_turf(user, throw_dir) user.throw_at(throw_target, 200, 4) if(8) @@ -160,7 +160,7 @@ //Mad Dosh T.visible_message("Mad dosh shoots out of [src]!") var/turf/Start = get_turf(src) - for(var/direction in alldirs) + for(var/direction in GLOB.alldirs) var/turf/dirturf = get_step(Start,direction) if(rand(0,1)) new /obj/item/stack/spacecash/c1000(dirturf) @@ -255,7 +255,7 @@ if(!target_mob) return var/turf/Start = get_turf(user) - for(var/direction in alldirs) + for(var/direction in GLOB.alldirs) var/turf/T = get_step(Start,direction) if(!T.density) target_mob.Move(T) diff --git a/code/modules/awaymissions/mission_code/ruins/gps.dm b/code/modules/awaymissions/mission_code/ruins/gps.dm new file mode 100644 index 00000000000..fa26eea5d0d --- /dev/null +++ b/code/modules/awaymissions/mission_code/ruins/gps.dm @@ -0,0 +1,13 @@ +//local gps units to let the ruins be found easier. + +/obj/item/gps/ruin + name = "navigation console" + desc = "A console for navigation in local space, gives off a weak signal that can be picked up if sufficiently close." + icon = 'icons/obj/terminals.dmi' + icon_state = "gps_console" + anchored = TRUE + local = TRUE + gpstag = "Unknown Signal" + +/obj/item/gps/ruin/attack_hand(mob/user) + attack_self(user) diff --git a/code/modules/awaymissions/mission_code/ruins/oldstation.dm b/code/modules/awaymissions/mission_code/ruins/oldstation.dm index e939cf06f32..4d3c54f8f4b 100644 --- a/code/modules/awaymissions/mission_code/ruins/oldstation.dm +++ b/code/modules/awaymissions/mission_code/ruins/oldstation.dm @@ -105,7 +105,7 @@ /obj/item/paper/fluff/ruins/oldstation/damagereport name = "Damage Report" - info = "*Damage Report*

    Alpha Station - Destroyed

    Beta Station - Catastrophic Damage. Medical, destroyed. Atmospherics, partially destroyed. Engine Core, destroyed.

    Charlie Station - Intact. Loss of oxygen to eastern side of main corridor.

    Delta Station - Intact. WARNING: Unknown force occupying Delta Station. Intent unknown. Species unknown. Numbers unknown.

    Recommendation - Reestablish station powernet via solar array. Reestablish station atmospherics system to restore air." + info = "*Damage Report*

    Alpha Station - Destroyed

    Beta Station - Catastrophic Damage. Medical, destroyed. Atmospherics, partially destroyed. Engine Core, destroyed.

    Charlie Station - Intact. Loss of oxygen to eastern side of main corridor.

    Theta Station - Intact. WARNING: Unknown force occupying Theta Station. Intent unknown. Species unknown. Numbers unknown.

    Recommendation - Reestablish station powernet via solar array. Reestablish station atmospherics system to restore air." /obj/item/paper/fluff/ruins/oldstation/protosuit name = "B01-RIG Hardsuit Report" @@ -145,7 +145,7 @@ info = "Artificial Program's report to surviving crewmembers.

    Crew were placed into cryostasis on March 10th, 2445.

    Crew were awoken from cryostasis around June, 2557.

    \ SIGNIFICANT EVENTS OF NOTE
    1: The primary radiation detectors were taken offline after 112 years due to power failure, secondary radiation detectors showed no residual \ radiation on station. Deduction, primarily detector was malfunctioning and was producing a radiation signal when there was none.

    2: A data burst from a nearby Nanotrasen Space \ - Station was received, this data burst contained research data that has been uploaded to our RnD labs.

    3: Unknown invasion force has occupied Delta station." + Station was received, this data burst contained research data that has been uploaded to our RnD labs.

    3: Unknown invasion force has occupied Theta station." /obj/item/paper/fluff/ruins/oldstation/generator_manual name = "S.U.P.E.R.P.A.C.M.A.N.-type portable generator manual" @@ -350,16 +350,16 @@ name = "Charlie Station Security" icon_state = "red" -/area/ruin/space/ancientstation/deltacorridor - name = "Delta Station Main Corridor" +/area/ruin/space/ancientstation/thetacorridor + name = "Theta Station Main Corridor" icon_state = "green" /area/ruin/space/ancientstation/proto - name = "Delta Station Prototype Lab" + name = "Theta Station Prototype Lab" icon_state = "toxlab" /area/ruin/space/ancientstation/rnd - name = "Delta Station Research and Development" + name = "Theta Station Research and Development" icon_state = "toxlab" /area/ruin/space/ancientstation/hivebot diff --git a/code/modules/awaymissions/mission_code/spacehotel.dm b/code/modules/awaymissions/mission_code/spacehotel.dm index 45ebf9700ca..8f2f03aea62 100644 --- a/code/modules/awaymissions/mission_code/spacehotel.dm +++ b/code/modules/awaymissions/mission_code/spacehotel.dm @@ -272,7 +272,7 @@ var/mob/deadbeat = D.occupant - radio.autosay("[deadbeat], your card has been rejected. You have 30 seconds to check out.", name, zlevel = list(z)) + radio.autosay("[deadbeat], your card has been rejected. You have 30 seconds to check out.", name) spawn(300) if(D.occupant == deadbeat) // they still haven't checked out... diff --git a/code/modules/awaymissions/mission_code/stationCollision.dm b/code/modules/awaymissions/mission_code/stationCollision.dm index deab7570d3a..1beba373724 100644 --- a/code/modules/awaymissions/mission_code/stationCollision.dm +++ b/code/modules/awaymissions/mission_code/stationCollision.dm @@ -94,11 +94,11 @@ obj/item/gun/energy/laser/retro/sc_retro */ //These vars hold the code itself, they'll be generated at round-start -var/sc_safecode1 = "[rand(0,9)]" -var/sc_safecode2 = "[rand(0,9)]" -var/sc_safecode3 = "[rand(0,9)]" -var/sc_safecode4 = "[rand(0,9)]" -var/sc_safecode5 = "[rand(0,9)]" +GLOBAL_VAR_INIT(sc_safecode1, "[rand(0,9)]") // Do these even need to be strings? Probably for the best +GLOBAL_VAR_INIT(sc_safecode2, "[rand(0,9)]") +GLOBAL_VAR_INIT(sc_safecode3, "[rand(0,9)]") +GLOBAL_VAR_INIT(sc_safecode4, "[rand(0,9)]") +GLOBAL_VAR_INIT(sc_safecode5, "[rand(0,9)]") //Pieces of paper actually containing the hints /obj/item/paper/sc_safehint_paper_prison @@ -106,13 +106,13 @@ var/sc_safecode5 = "[rand(0,9)]" /obj/item/paper/sc_safehint_paper_prison/New() ..() - info = "The ink is smudged, you can only make out a couple numbers: '[sc_safecode1]**[sc_safecode4]*'" + info = "The ink is smudged, you can only make out a couple numbers: '[GLOB.sc_safecode1]**[GLOB.sc_safecode4]*'" /obj/item/paper/sc_safehint_paper_hydro name = "shredded paper" /obj/item/paper/sc_safehint_paper_hydro/New() ..() - info = "Although the paper is shredded, you can clearly see the number: '[sc_safecode2]'" + info = "Although the paper is shredded, you can clearly see the number: '[GLOB.sc_safecode2]'" /obj/item/paper/sc_safehint_paper_caf name = "blood-soaked paper" @@ -124,7 +124,7 @@ var/sc_safecode5 = "[rand(0,9)]" /obj/item/paper/sc_safehint_paper_bible/New() ..() info = {"It would appear that the pen hidden with the paper had leaked ink over the paper. - However you can make out the last three digits:'[sc_safecode3][sc_safecode4][sc_safecode5]' + However you can make out the last three digits:
    '[GLOB.sc_safecode3][GLOB.sc_safecode4][GLOB.sc_safecode5]' "} /obj/item/paper/sc_safehint_paper_shuttle @@ -148,7 +148,7 @@ var/sc_safecode5 = "[rand(0,9)]" /obj/item/storage/secure/safe/sc_ssafe/New() ..() - l_code = "[sc_safecode1][sc_safecode2][sc_safecode3][sc_safecode4][sc_safecode5]" + l_code = "[GLOB.sc_safecode1][GLOB.sc_safecode2][GLOB.sc_safecode3][GLOB.sc_safecode4][GLOB.sc_safecode5]" l_set = 1 new /obj/item/gun/energy/mindflayer(src) new /obj/item/soulstone(src) diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm index ca79a1ea2a6..5aa3e89192f 100644 --- a/code/modules/awaymissions/mission_code/wildwest.dm +++ b/code/modules/awaymissions/mission_code/wildwest.dm @@ -173,23 +173,9 @@ to_chat(C, "Death is not your end!") spawn(rand(800,1200)) - if(C.stat == DEAD) - GLOB.dead_mob_list -= C - GLOB.living_mob_list += C - C.stat = CONSCIOUS - C.timeofdeath = 0 - C.setToxLoss(0) - C.setOxyLoss(0) - C.setCloneLoss(0) - C.SetParalysis(0) - C.SetStunned(0) - C.SetWeakened(0) - C.radiation = 0 - C.heal_overall_damage(C.getBruteLoss(), C.getFireLoss()) - C.reagents.clear_reagents() + C.revive() to_chat(C, "You have regenerated.") C.visible_message("[usr] appears to wake from the dead, having healed all wounds.") - C.update_canmove() return 1 /obj/item/wildwest_communicator @@ -247,7 +233,7 @@ used = TRUE /obj/item/wildwest_communicator/proc/stand_down() - for(var/mob/living/simple_animal/hostile/syndicate/ranged/wildwest/W in GLOB.living_mob_list) + for(var/mob/living/simple_animal/hostile/syndicate/ranged/wildwest/W in GLOB.alive_mob_list) W.on_alert = FALSE /mob/living/simple_animal/hostile/syndicate/ranged/wildwest @@ -262,6 +248,6 @@ // putting this up here so we don't say anything after deathgasp if(can_die() && !on_alert) say("How could you betray the Syndicate?") - for(var/mob/living/simple_animal/hostile/syndicate/ranged/wildwest/W in GLOB.living_mob_list) + for(var/mob/living/simple_animal/hostile/syndicate/ranged/wildwest/W in GLOB.alive_mob_list) W.on_alert = TRUE return ..(gibbed) diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm index c406a76cb73..3b31a8bbcfc 100644 --- a/code/modules/awaymissions/zlevel.dm +++ b/code/modules/awaymissions/zlevel.dm @@ -1,4 +1,4 @@ -var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away_mission_config.txt") +GLOBAL_LIST_INIT(potentialRandomZlevels, generateMapList(filename = "config/away_mission_config.txt")) // Call this before you remove the last dirt on a z level - that way, all objects // will have proper atmos and other important enviro things @@ -39,27 +39,27 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away T.ChangeTurf(T.baseturf) /proc/createRandomZlevel() - if(awaydestinations.len) //crude, but it saves another var! + if(GLOB.awaydestinations.len) //crude, but it saves another var! return - if(potentialRandomZlevels && potentialRandomZlevels.len) + if(GLOB.potentialRandomZlevels && GLOB.potentialRandomZlevels.len) var/watch = start_watch() log_startup_progress("Loading away mission...") - var/map = pick(potentialRandomZlevels) + var/map = pick(GLOB.potentialRandomZlevels) var/file = file(map) if(isfile(file)) - var/zlev = space_manager.add_new_zlevel(AWAY_MISSION, linkage = UNAFFECTED, traits = list(AWAY_LEVEL,BLOCK_TELEPORT)) - space_manager.add_dirt(zlev) - maploader.load_map(file, z_offset = zlev) + var/zlev = GLOB.space_manager.add_new_zlevel(AWAY_MISSION, linkage = UNAFFECTED, traits = list(AWAY_LEVEL,BLOCK_TELEPORT)) + GLOB.space_manager.add_dirt(zlev) + GLOB.maploader.load_map(file, z_offset = zlev) late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev))) - space_manager.remove_dirt(zlev) + GLOB.space_manager.remove_dirt(zlev) log_world(" Away mission loaded: [map]") for(var/obj/effect/landmark/L in GLOB.landmarks_list) if(L.name != "awaystart") continue - awaydestinations.Add(L) + GLOB.awaydestinations.Add(L) log_startup_progress(" Away mission loaded in [stop_watch(watch)]s.") @@ -69,22 +69,22 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away /proc/createALLZlevels() - if(awaydestinations.len) //crude, but it saves another var! + if(GLOB.awaydestinations.len) //crude, but it saves another var! return - if(potentialRandomZlevels && potentialRandomZlevels.len) + if(GLOB.potentialRandomZlevels && GLOB.potentialRandomZlevels.len) var/watch = start_watch() log_startup_progress("Loading away missions...") - for(var/map in potentialRandomZlevels) + for(var/map in GLOB.potentialRandomZlevels) var/file = file(map) if(isfile(file)) log_startup_progress("Loading away mission: [map]") - var/zlev = space_manager.add_new_zlevel() - space_manager.add_dirt(zlev) - maploader.load_map(file, z_offset = zlev) + var/zlev = GLOB.space_manager.add_new_zlevel() + GLOB.space_manager.add_dirt(zlev) + GLOB.maploader.load_map(file, z_offset = zlev) late_setup_level(block(locate(1, 1, zlev), locate(world.maxx, world.maxy, zlev))) - space_manager.remove_dirt(zlev) + GLOB.space_manager.remove_dirt(zlev) log_world(" Away mission loaded: [map]") //map_transition_config.Add(AWAY_MISSION_LIST) @@ -92,7 +92,7 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away for(var/obj/effect/landmark/L in GLOB.landmarks_list) if(L.name != "awaystart") continue - awaydestinations.Add(L) + GLOB.awaydestinations.Add(L) log_startup_progress(" Away mission loaded in [stop_watch(watch)]s.") watch = start_watch() @@ -172,87 +172,3 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away new /obj/effect/landmark/ruin(central_turf, src) return TRUE return FALSE - -/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins) - if(!z_levels || !z_levels.len) - WARNING("No Z levels provided - Not generating ruins") - return - - for(var/zl in z_levels) - var/turf/T = locate(1, 1, zl) - if(!T) - WARNING("Z level [zl] does not exist - Not generating ruins") - return - - var/list/ruins = potentialRuins.Copy() - - var/list/forced_ruins = list() //These go first on the z level associated (same random one by default) - var/list/ruins_availible = list() //we can try these in the current pass - var/forced_z //If set we won't pick z level and use this one instead. - - //Set up the starting ruin list - for(var/key in ruins) - var/datum/map_template/ruin/R = ruins[key] - if(R.cost > budget) //Why would you do that - continue - if(R.always_place) - forced_ruins[R] = -1 - if(R.unpickable) - continue - ruins_availible[R] = R.placement_weight - - while(budget > 0 && (ruins_availible.len || forced_ruins.len)) - var/datum/map_template/ruin/current_pick - var/forced = FALSE - if(forced_ruins.len) //We have something we need to load right now, so just pick it - for(var/ruin in forced_ruins) - current_pick = ruin - if(forced_ruins[ruin] > 0) //Load into designated z - forced_z = forced_ruins[ruin] - forced = TRUE - break - else //Otherwise just pick random one - current_pick = pickweight(ruins_availible) - - var/placement_tries = PLACEMENT_TRIES - var/failed_to_place = TRUE - var/z_placed = 0 - while(placement_tries > 0) - placement_tries-- - z_placed = pick(z_levels) - if(!current_pick.try_to_place(forced_z ? forced_z : z_placed,whitelist)) - continue - else - failed_to_place = FALSE - break - - //That's done remove from priority even if it failed - if(forced) - //TODO : handle forced ruins with multiple variants - forced_ruins -= current_pick - forced = FALSE - - if(failed_to_place) - for(var/datum/map_template/ruin/R in ruins_availible) - if(R.id == current_pick.id) - ruins_availible -= R - log_world("Failed to place [current_pick.name] ruin.") - else - budget -= current_pick.cost - if(!current_pick.allow_duplicates) - for(var/datum/map_template/ruin/R in ruins_availible) - if(R.id == current_pick.id) - ruins_availible -= R - if(current_pick.never_spawn_with) - for(var/blacklisted_type in current_pick.never_spawn_with) - for(var/possible_exclusion in ruins_availible) - if(istype(possible_exclusion,blacklisted_type)) - ruins_availible -= possible_exclusion - forced_z = 0 - - //Update the availible list - for(var/datum/map_template/ruin/R in ruins_availible) - if(R.cost > budget) - ruins_availible -= R - - log_world("Ruin loader finished with [budget] left to spend.") diff --git a/code/modules/buildmode/bm_mode.dm b/code/modules/buildmode/bm_mode.dm index 1ce23555e3e..0169df7cd62 100644 --- a/code/modules/buildmode/bm_mode.dm +++ b/code/modules/buildmode/bm_mode.dm @@ -47,11 +47,11 @@ overlaystate = "blueOverlay" preview += image('icons/turf/overlays.dmi', T, overlaystate) BM.holder.images += preview - return T + return T /datum/buildmode_mode/proc/highlight_region(region) BM.holder.images -= preview - for(var/t in region) + for(var/T in region) preview += image('icons/turf/overlays.dmi', T, "redOverlay") BM.holder.images += preview diff --git a/code/modules/buildmode/submodes/link.dm b/code/modules/buildmode/submodes/link.dm index 136ffad6433..25a6d92bfa3 100644 --- a/code/modules/buildmode/submodes/link.dm +++ b/code/modules/buildmode/submodes/link.dm @@ -46,17 +46,21 @@ if(!M.id || M.id == "") M.id = input(user, "Please select an ID for the button", "Buildmode", "") if(!M.id || M.id == "") - goto line_jump + speed_execute() + return if(P.id_tag == M.id && P.id_tag && P.id_tag != "") P.id_tag = null to_chat(user, "[P] unlinked.") - goto line_jump + speed_execute() + return if(!M.normaldoorcontrol) if(link_lines.len && alert(user, "Warning: This will disable links to connected pod doors. Continue?", "Buildmode", "Yes", "No") == "No") - goto line_jump + speed_execute() + return M.normaldoorcontrol = 1 if(P.id_tag && alert(user, "Warning: This will unlink something else from the door. Continue?", "Buildmode", "Yes", "No") == "No") - goto line_jump + speed_execute() + return P.id_tag = M.id if(istype(link_obj, /obj/machinery/door_control) && istype(object, /obj/machinery/door/poddoor)) var/obj/machinery/door_control/M = link_obj @@ -64,24 +68,29 @@ if(!M.id || M.id == "") M.id = input(user, "Please select an ID for the button", "Buildmode", "") if(!M.id || M.id == "") - goto line_jump + speed_execute() + return if(P.id_tag == M.id && P.id_tag && P.id_tag != "") P.id_tag = null to_chat(user, "[P] unlinked.") - goto line_jump + speed_execute() + return if(M.normaldoorcontrol) if(link_lines.len && alert(user, "Warning: This will disable links to connected airlocks. Continue?", "Buildmode", "Yes", "No") == "No") - goto line_jump + speed_execute() + return M.normaldoorcontrol = 0 if(!M.id || M.id == "") M.id = input(user, "Please select an ID for the button", "Buildmode", "") if(!M.id || M.id == "") - goto line_jump + speed_execute() + return if(P.id_tag && P.id_tag != 1 && alert(user, "Warning: This will unlink something else from the door. Continue?", "Buildmode", "Yes", "No") == "No") - goto line_jump + speed_execute() + return P.id_tag = M.id - line_jump // For the goto +/datum/buildmode_mode/link/proc/speed_execute() // For exiting out of hell clear_lines() if(istype(link_obj, /obj/machinery/door_control)) diff --git a/code/modules/buildmode/submodes/save.dm b/code/modules/buildmode/submodes/save.dm index 43a1f9af174..34a57e1f7e4 100644 --- a/code/modules/buildmode/submodes/save.dm +++ b/code/modules/buildmode/submodes/save.dm @@ -3,7 +3,7 @@ use_corner_selection = TRUE var/use_json = TRUE - + /datum/buildmode_mode/save/show_help(mob/user) to_chat(user, "***********************************************************") to_chat(user, "Left Mouse Button on turf/obj/mob = Select corner") @@ -23,6 +23,6 @@ if(use_json) map_flags = 32 // Magic number defined in `writer.dm` that I can't use directly // because #defines are for some reason our coding standard - var/our_map = maploader.save_map(cornerA, cornerB, map_name, map_flags) + var/our_map = GLOB.maploader.save_map(cornerA, cornerB, map_name, map_flags) user << ftp(our_map) // send the map they've made! Or are stealing, whatever to_chat(user, "Map saving complete! [our_map]") diff --git a/code/modules/busy_space/air_traffic.dm b/code/modules/busy_space/air_traffic.dm index a7f28f49fb6..e21414e8ed3 100644 --- a/code/modules/busy_space/air_traffic.dm +++ b/code/modules/busy_space/air_traffic.dm @@ -1,6 +1,5 @@ //Cactus, Speedbird, Dynasty, oh my - -var/datum/lore/atc_controller/atc = new/datum/lore/atc_controller +GLOBAL_DATUM_INIT(atc, /datum/lore/atc_controller, new) /datum/lore/atc_controller var/delay_max = 10 MINUTES //Maximum amount of tiem between ATC messages. Default is 10 mins. @@ -30,29 +29,29 @@ var/datum/lore/atc_controller/atc = new/datum/lore/atc_controller /datum/lore/atc_controller/proc/msg(var/message,var/sender) ASSERT(message) - global_announcer.autosay("[message]", sender ? sender : "[using_map.station_short] Space Control") + GLOB.global_announcer.autosay("[message]", sender ? sender : "[GLOB.using_map.station_short] Space Control") /datum/lore/atc_controller/proc/reroute_traffic(var/yes = 1) if(yes) if(!squelched) - msg("Rerouting traffic away from [using_map.station_name].") + msg("Rerouting traffic away from [GLOB.using_map.station_name].") squelched = TRUE else if(squelched) - msg("Resuming normal traffic routing around [using_map.station_name].") + msg("Resuming normal traffic routing around [GLOB.using_map.station_name].") squelched = FALSE /datum/lore/atc_controller/proc/shift_ending(var/evac = 0) - msg("Automated Shuttle departing [using_map.station_name] for [using_map.dock_name] on routine transfer route.", "NT Automated Shuttle") + msg("Automated Shuttle departing [GLOB.using_map.station_name] for [GLOB.using_map.dock_name] on routine transfer route.", "NT Automated Shuttle") sleep(5 SECONDS) - msg("Automated Shuttle, cleared to complete routine transfer from [using_map.station_name] to [using_map.dock_name].") + msg("Automated Shuttle, cleared to complete routine transfer from [GLOB.using_map.station_name] to [GLOB.using_map.dock_name].") /datum/lore/atc_controller/proc/random_convo() - var/one = pick(loremaster.organizations) //These will pick an index, not an instance - var/two = pick(loremaster.organizations) + var/one = pick(GLOB.loremaster.organizations) //These will pick an index, not an instance + var/two = pick(GLOB.loremaster.organizations) - var/datum/lore/organization/source = loremaster.organizations[one] //Resolve to the instances - var/datum/lore/organization/dest = loremaster.organizations[two] + var/datum/lore/organization/source = GLOB.loremaster.organizations[one] //Resolve to the instances + var/datum/lore/organization/dest = GLOB.loremaster.organizations[two] //Let's get some mission parameters var/owner = source.short_name //Use the short name @@ -62,13 +61,13 @@ var/datum/lore/atc_controller/atc = new/datum/lore/atc_controller var/destname = pick(dest.destination_names) //Pick a random holding from the destination var/combined_name = "[owner] [prefix] [shipname]" - var/alt_atc_names = list("[using_map.station_short] TraCon", "[using_map.station_short] Control", "[using_map.station_short] STC", "[using_map.station_short] Airspace") - var/wrong_atc_names = list("Sol Command", "Orion Control", "[using_map.dock_name]") + var/alt_atc_names = list("[GLOB.using_map.station_short] TraCon", "[GLOB.using_map.station_short] Control", "[GLOB.using_map.station_short] STC", "[GLOB.using_map.station_short] Airspace") + var/wrong_atc_names = list("Sol Command", "Orion Control", "[GLOB.using_map.dock_name]") var/mission_noun = list("flight", "mission", "route") var/request_verb = list("requesting", "calling for", "asking for") //First response is 'yes', second is 'no' - var/requests = list("[using_map.station_short] transit clearance" = list("cleared to transit", "unable to approve, contact regional on 953.5"), + var/requests = list("[GLOB.using_map.station_short] transit clearance" = list("cleared to transit", "unable to approve, contact regional on 953.5"), "planetary flight rules" = list("cleared planetary flight rules", "unable to approve planetary flight rules due to traffic"), "special flight rules" = list("cleared special flight rules", "unable to approve special flight rules for your traffic class"), "current solar weather info" = list("sending you the relevant information via tightbeam", "cannot fulfill your request at the moment"), @@ -104,20 +103,20 @@ var/datum/lore/atc_controller/atc = new/datum/lore/atc_controller if("wrong_freq") callname = pick(wrong_atc_names) full_request = "[callname], this is [combined_name] on a [mission] [pick(mission_noun)] to [destname], [pick(request_verb)] [request]." - full_response = "[combined_name], this is [using_map.station_short] TraCon, wrong frequency. Switch to [rand(700,999)].[rand(1,9)]." - full_closure = "[using_map.station_short] TraCon, copy, apologies." + full_response = "[combined_name], this is [GLOB.using_map.station_short] TraCon, wrong frequency. Switch to [rand(700,999)].[rand(1,9)]." + full_closure = "[GLOB.using_map.station_short] TraCon, copy, apologies." if("wrong_lang") //Can't implement this until autosay has language support if("emerg") var/problem = pick("hull breaches on multiple decks","unknown life forms on board","a drive about to go critical","asteroids impacting the hull","a total loss of engine power","people trying to board the ship") full_request = "Mayday, mayday, mayday, this is [combined_name] declaring an emergency! We have [problem]!" var/rand_freq = "[rand(700,999)].[rand(1,9)]" - full_response = "[combined_name], this is [using_map.station_short] TraCon, copy. Switch to emergency responder channel [rand_freq]." - full_closure = "Roger, [using_map.station_short] TraCon, contacting [rand_freq]." + full_response = "[combined_name], this is [GLOB.using_map.station_short] TraCon, copy. Switch to emergency responder channel [rand_freq]." + full_closure = "Roger, [GLOB.using_map.station_short] TraCon, contacting [rand_freq]." else full_request = "[callname], this is [combined_name] on a [mission] [pick(mission_noun)] to [destname], [pick(request_verb)] [request]." - full_response = "[combined_name], this is [using_map.station_short] TraCon, [response]." //Station TraCon always calls themselves TraCon - full_closure = "[using_map.station_short] TraCon, [yes ? "thank you" : "copy"], good day." //They always copy what TraCon called themselves in the end when they realize they said it wrong + full_response = "[combined_name], this is [GLOB.using_map.station_short] TraCon, [response]." //Station TraCon always calls themselves TraCon + full_closure = "[GLOB.using_map.station_short] TraCon, [yes ? "thank you" : "copy"], good day." //They always copy what TraCon called themselves in the end when they realize they said it wrong //Ship sends request to ATC msg(full_request,"[prefix] [shipname]") diff --git a/code/modules/busy_space/loremaster.dm b/code/modules/busy_space/loremaster.dm index 28dca0055b0..77b8a8ed53d 100644 --- a/code/modules/busy_space/loremaster.dm +++ b/code/modules/busy_space/loremaster.dm @@ -1,6 +1,5 @@ //I AM THE LOREMASTER, ARE YOU THE GATEKEEPER? - -var/datum/lore/loremaster/loremaster = new/datum/lore/loremaster +GLOBAL_DATUM_INIT(loremaster, /datum/lore/loremaster, new) /datum/lore/loremaster var/list/organizations = list() diff --git a/code/modules/busy_space/organizations.dm b/code/modules/busy_space/organizations.dm index df86aefd75e..c39e92ea49e 100644 --- a/code/modules/busy_space/organizations.dm +++ b/code/modules/busy_space/organizations.dm @@ -123,7 +123,7 @@ ..() spawn(1) // BYOND shenanigans means using_map is not initialized yet. Wait a tick. // Get rid of the current map from the list, so ships flying in don't say they're coming to the current map. - var/string_to_test = "[using_map.station_name] in [using_map.starsys_name]" + var/string_to_test = "[GLOB.using_map.station_name] in [GLOB.using_map.starsys_name]" if(string_to_test in destination_names) destination_names.Remove(string_to_test) diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index 57a6df32ab6..e1e68bd0617 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -147,16 +147,16 @@ You can set verify to TRUE if you want send() to sleep until the client has the //These datums are used to populate the asset cache, the proc "register()" does this. //all of our asset datums, used for referring to these later -/var/global/list/asset_datums = list() +GLOBAL_LIST_EMPTY(asset_datums) //get a assetdatum or make a new one /proc/get_asset_datum(var/type) - if(!(type in asset_datums)) + if(!(type in GLOB.asset_datums)) return new type() - return asset_datums[type] + return GLOB.asset_datums[type] /datum/asset/New() - asset_datums[type] = src + GLOB.asset_datums[type] = src /datum/asset/proc/register() return @@ -195,7 +195,8 @@ You can set verify to TRUE if you want send() to sleep until the client has the "large_stamp-rep.png" = 'icons/paper_icons/large_stamp-rep.png', "large_stamp-magistrate.png"= 'icons/paper_icons/large_stamp-magistrate.png', "talisman.png" = 'icons/paper_icons/talisman.png', - "ntlogo.png" = 'icons/paper_icons/ntlogo.png' + "ntlogo.png" = 'icons/paper_icons/ntlogo.png', + "syndielogo.png" ='icons/paper_icons/syndielogo.png' ) /datum/asset/simple/chess @@ -313,14 +314,14 @@ You can set verify to TRUE if you want send() to sleep until the client has the if(!(state in list("cap", "connector", "dtvalve", "dual-port vent", "dvalve", "filter", "he", "heunary", "injector", "junction", "manifold", "mixer", "tvalve", "mvalve", "passive vent", "passivegate", "pump", "scrubber", "simple", "universal", "uvent", "volumepump"))) //Basically all the pipes we want sprites for continue if(state in list("he", "simple")) - for(var/D in alldirs) + for(var/D in GLOB.alldirs) assets["[state]-[dir2text(D)].png"] = icon('icons/obj/pipe-item.dmi', state, D) - for(var/D in cardinal) + for(var/D in GLOB.cardinal) assets["[state]-[dir2text(D)].png"] = icon('icons/obj/pipe-item.dmi', state, D) for(var/state in icon_states('icons/obj/pipes/disposal.dmi')) if(!(state in list("pipe-c", "pipe-j1", "pipe-s", "pipe-t", "pipe-y", "intake", "outlet", "pipe-j1s"))) //Pipes we want sprites for continue - for(var/D in cardinal) + for(var/D in GLOB.cardinal) assets["[state]-[dir2text(D)].png"] = icon('icons/obj/pipes/disposal.dmi', state, D) for(var/asset_name in assets) register_asset(asset_name, assets[asset_name]) diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index 85615be1ee5..3cd6458afdf 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -20,7 +20,6 @@ var/skip_antag = FALSE //TRUE when a player declines to be included for the selection process of game mode antagonists. var/move_delay = 1 var/moving = null - var/adminobs = null var/area = null var/time_died_as_mouse = null //when the client last died as a mouse @@ -28,13 +27,6 @@ var/adminhelped = 0 - // var/gc_destroyed //Time when this object was destroyed. [Inherits from datum] - -#ifdef TESTING - var/running_find_references - var/last_find_references = 0 -#endif - /////////////// //SOUND STUFF// /////////////// diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index e504a796052..561b0b48149 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -319,16 +319,16 @@ if(!config.disable_localhost_admin) if(is_connecting_from_localhost()) new /datum/admins("!LOCALHOST!", R_HOST, ckey) // Makes localhost rank - holder = admin_datums[ckey] + holder = GLOB.admin_datums[ckey] if(holder) GLOB.admins += src holder.owner = src //preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum) - prefs = preferences_datums[ckey] + prefs = GLOB.preferences_datums[ckey] if(!prefs) prefs = new /datum/preferences(src) - preferences_datums[ckey] = prefs + GLOB.preferences_datums[ckey] = prefs else prefs.parent = src prefs.last_ip = address //these are gonna be used for banning @@ -339,8 +339,8 @@ spawn() // Goonchat does some non-instant checks in start() chatOutput.start() - if( (world.address == address || !address) && !host ) - host = key + if( (world.address == address || !address) && !GLOB.host ) + GLOB.host = key world.update_status() if(holder) @@ -373,13 +373,11 @@ send_resources() if(prefs.toggles & UI_DARKMODE) // activates dark mode if its flagged. -AA07 - if(establish_db_connection()) - activate_darkmode() + activate_darkmode() + else + // activate_darkmode() calls the CL update button proc, so we dont want it double called + SSchangelog.UpdatePlayerChangelogButton(src) - if(prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates. -CP - if(establish_db_connection()) - to_chat(src, "Changelog has changed since your last visit.") - update_changelog_button() if(prefs.toggles & DISABLE_KARMA) // activates if karma is disabled if(establish_db_connection()) @@ -393,10 +391,10 @@ check_forum_link() - if(custom_event_msg && custom_event_msg != "") + if(GLOB.custom_event_msg && GLOB.custom_event_msg != "") to_chat(src, "

    Custom Event

    ") to_chat(src, "

    A custom event is taking place. OOC Info:

    ") - to_chat(src, "[html_encode(custom_event_msg)]") + to_chat(src, "[html_encode(GLOB.custom_event_msg)]") to_chat(src, "
    ") if(!winexists(src, "asset_cache_browser")) // The client is using a custom skin, tell them. @@ -427,7 +425,7 @@ /client/proc/is_connecting_from_localhost() var/localhost_addresses = list("127.0.0.1", "::1") // Adresses - if(!isnull(address) && address in localhost_addresses) + if(!isnull(address) && (address in localhost_addresses)) return TRUE return FALSE @@ -452,7 +450,7 @@ return establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) return if(check_rights(R_ADMIN, 0, mob)) // Yes, the mob is required, regardless of other examples in this file, it won't work otherwise @@ -461,7 +459,7 @@ return //Donator stuff. - var/DBQuery/query_donor_select = dbcon.NewQuery("SELECT ckey, tier, active FROM `[format_table_name("donators")]` WHERE ckey = '[ckey]'") + var/DBQuery/query_donor_select = GLOB.dbcon.NewQuery("SELECT ckey, tier, active FROM `[format_table_name("donators")]` WHERE ckey = '[ckey]'") query_donor_select.Execute() while(query_donor_select.NextRow()) if(!text2num(query_donor_select.item[3])) @@ -482,11 +480,11 @@ establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) return - var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey = '[ckey]'") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey = '[ckey]'") query.Execute() var/sql_id = 0 player_age = 0 // New players won't have an entry so knowing we have a connection we set this to zero to be updated if there is a record. @@ -496,7 +494,7 @@ break - var/DBQuery/query_ip = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = '[address]'") + var/DBQuery/query_ip = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ip = '[address]'") query_ip.Execute() related_accounts_ip = list() while(query_ip.NextRow()) @@ -504,7 +502,7 @@ related_accounts_ip.Add("[query_ip.item[1]]") - var/DBQuery/query_cid = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]'") + var/DBQuery/query_cid = GLOB.dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE computerid = '[computer_id]'") query_cid.Execute() related_accounts_cid = list() while(query_cid.NextRow()) @@ -546,7 +544,7 @@ if(sql_id) //Player already identified previously, we need to just update the 'lastseen', 'ip' and 'computer_id' variables - var/DBQuery/query_update = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]") + var/DBQuery/query_update = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastseen = Now(), ip = '[sql_ip]', computerid = '[sql_computerid]', lastadminrank = '[sql_admin_rank]' WHERE id = [sql_id]") if(!query_update.Execute()) var/err = query_update.ErrorMsg() log_game("SQL ERROR during log_client_to_db (update). Error : \[[err]\]\n") @@ -561,14 +559,14 @@ del(src) return // Dont insert or they can just go in again - var/DBQuery/query_insert = dbcon.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')") + var/DBQuery/query_insert = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("player")] (id, ckey, firstseen, lastseen, ip, computerid, lastadminrank) VALUES (null, '[ckey]', Now(), Now(), '[sql_ip]', '[sql_computerid]', '[sql_admin_rank]')") if(!query_insert.Execute()) var/err = query_insert.ErrorMsg() log_game("SQL ERROR during log_client_to_db (insert). Error : \[[err]\]\n") message_admins("SQL ERROR during log_client_to_db (insert). Error : \[[err]\]\n") // Log player connections to DB - var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`datetime`,`ckey`,`ip`,`computerid`) VALUES(Now(),'[ckey]','[sql_ip]','[sql_computerid]');") + var/DBQuery/query_accesslog = GLOB.dbcon.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`datetime`,`ckey`,`ip`,`computerid`) VALUES(Now(),'[ckey]','[sql_ip]','[sql_computerid]');") query_accesslog.Execute() /client/proc/check_ip_intel() @@ -616,14 +614,14 @@ to_chat(src, "You have no verified forum account. VERIFY FORUM ACCOUNT") /client/proc/create_oauth_token() - var/DBQuery/query_find_token = dbcon.NewQuery("SELECT token FROM [format_table_name("oauth_tokens")] WHERE ckey = '[ckey]' limit 1") + var/DBQuery/query_find_token = GLOB.dbcon.NewQuery("SELECT token FROM [format_table_name("oauth_tokens")] WHERE ckey = '[ckey]' limit 1") if(!query_find_token.Execute()) log_debug("create_oauth_token: failed db read") return if(query_find_token.NextRow()) return query_find_token.item[1] var/tokenstr = md5("[ckey][rand()]") - var/DBQuery/query_insert_token = dbcon.NewQuery("INSERT INTO [format_table_name("oauth_tokens")] (ckey, token) VALUES('[ckey]','[tokenstr]')") + var/DBQuery/query_insert_token = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("oauth_tokens")] (ckey, token) VALUES('[ckey]','[tokenstr]')") if(!query_insert_token.Execute()) return return tokenstr @@ -638,7 +636,7 @@ if(!fromban) to_chat(src, "Your forum account is already set.") return - var/DBQuery/query_find_link = dbcon.NewQuery("SELECT fuid FROM [format_table_name("player")] WHERE ckey = '[ckey]' limit 1") + var/DBQuery/query_find_link = GLOB.dbcon.NewQuery("SELECT fuid FROM [format_table_name("player")] WHERE ckey = '[ckey]' limit 1") if(!query_find_link.Execute()) log_debug("link_forum_account: failed db read") return @@ -682,7 +680,7 @@ var/oldcid = cidcheck[ckey] if(!oldcid) - var/DBQuery/query_cidcheck = dbcon.NewQuery("SELECT computerid FROM [format_table_name("player")] WHERE ckey = '[ckey]'") + var/DBQuery/query_cidcheck = GLOB.dbcon.NewQuery("SELECT computerid FROM [format_table_name("player")] WHERE ckey = '[ckey]'") query_cidcheck.Execute() var/lastcid = computer_id @@ -747,7 +745,7 @@ var/const/adminckey = "CID-Error" // Check for notes in the last day - only 1 note per 24 hours - var/DBQuery/query_get_notes = dbcon.NewQuery("SELECT id from [format_table_name("notes")] WHERE ckey = '[ckey]' AND adminckey = '[adminckey]' AND timestamp + INTERVAL 1 DAY < NOW()") + var/DBQuery/query_get_notes = GLOB.dbcon.NewQuery("SELECT id from [format_table_name("notes")] WHERE ckey = '[ckey]' AND adminckey = '[adminckey]' AND timestamp + INTERVAL 1 DAY < NOW()") if(!query_get_notes.Execute()) var/err = query_get_notes.ErrorMsg() log_game("SQL ERROR obtaining id from notes table. Error : \[[err]\]\n") @@ -756,7 +754,7 @@ return // Only add a note if their most recent note isn't from the randomizer blocker, either - query_get_notes = dbcon.NewQuery("SELECT adminckey FROM [format_table_name("notes")] WHERE ckey = '[ckey]' ORDER BY timestamp DESC LIMIT 1") + query_get_notes = GLOB.dbcon.NewQuery("SELECT adminckey FROM [format_table_name("notes")] WHERE ckey = '[ckey]' ORDER BY timestamp DESC LIMIT 1") if(!query_get_notes.Execute()) var/err = query_get_notes.ErrorMsg() log_game("SQL ERROR obtaining adminckey from notes table. Error : \[[err]\]\n") @@ -825,7 +823,7 @@ // IF YOU CHANGE ANYTHING IN ACTIVATE, MAKE SURE IT HAS A DEACTIVATE METHOD, -AA07 /client/proc/activate_darkmode() ///// BUTTONS ///// - update_changelog_button() + SSchangelog.UpdatePlayerChangelogButton(src) /* Rpane */ winset(src, "rpane.textb", "background-color=#40628a;text-color=#FFFFFF") winset(src, "rpane.infob", "background-color=#40628a;text-color=#FFFFFF") @@ -857,7 +855,7 @@ /client/proc/deactivate_darkmode() ///// BUTTONS ///// - update_changelog_button() + SSchangelog.UpdatePlayerChangelogButton(src) /* Rpane */ winset(src, "rpane.textb", "background-color=none;text-color=#000000") winset(src, "rpane.infob", "background-color=none;text-color=#000000") @@ -887,22 +885,6 @@ ///// NOTIFY USER ///// to_chat(src, "Darkmode Disabled") // what a sick fuck -// Better changelog button handling -/client/proc/update_changelog_button() - if(establish_db_connection()) - if(prefs.lastchangelog != changelog_hash) - winset(src, "rpane.changelog", "background-color=#bb7700;text-color=#FFFFFF;font-style=bold") - else - if(prefs.toggles & UI_DARKMODE) - winset(src, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF") - else - winset(src, "rpane.changelog", "background-color=none;text-color=#000000") - else - if(prefs.toggles & UI_DARKMODE) - winset(src, "rpane.changelog", "background-color=#40628a;text-color=#FFFFFF") - else - winset(src, "rpane.changelog", "background-color=none;text-color=#000000") - /client/proc/generate_clickcatcher() if(!void) void = new() @@ -920,7 +902,7 @@ return FALSE if(M && M.player_logged < SSD_WARNING_TIMER) return FALSE - to_chat(src, "Interacting with SSD players is against server rules unless you've ahelped first for permission. If you have, confirm that and proceed.") + to_chat(src, "Are you taking this person to cryo or giving them medical treatment? If you are, confirm that and proceed. Interacting with SSD players in other ways is against server rules unless you've ahelped first for permission.") return TRUE #undef SSD_WARNING_TIMER diff --git a/code/modules/client/preference/loadout/gear_tweaks.dm b/code/modules/client/preference/loadout/gear_tweaks.dm index 6458a51b9a3..9446008b762 100644 --- a/code/modules/client/preference/loadout/gear_tweaks.dm +++ b/code/modules/client/preference/loadout/gear_tweaks.dm @@ -16,8 +16,7 @@ /* * Color adjustment */ - -var/datum/gear_tweak/color/gear_tweak_free_color_choice = new() +GLOBAL_DATUM_INIT(gear_tweak_free_color_choice, /datum/gear_tweak/color, new()) /datum/gear_tweak/color var/list/valid_colors diff --git a/code/modules/client/preference/loadout/loadout.dm b/code/modules/client/preference/loadout/loadout.dm index 63825cc1237..1091b38a11c 100644 --- a/code/modules/client/preference/loadout/loadout.dm +++ b/code/modules/client/preference/loadout/loadout.dm @@ -1,5 +1,5 @@ -var/list/loadout_categories = list() -var/list/gear_datums = list() +GLOBAL_LIST_EMPTY(loadout_categories) +GLOBAL_LIST_EMPTY(gear_datums) /datum/loadout_category var/category = "" @@ -30,15 +30,15 @@ var/list/gear_datums = list() error("Loadout - Missing path definition: [G]") continue - if(!loadout_categories[use_category]) - loadout_categories[use_category] = new /datum/loadout_category(use_category) - var/datum/loadout_category/LC = loadout_categories[use_category] - gear_datums[use_name] = new geartype - LC.gear[use_name] = gear_datums[use_name] + if(!GLOB.loadout_categories[use_category]) + GLOB.loadout_categories[use_category] = new /datum/loadout_category(use_category) + var/datum/loadout_category/LC = GLOB.loadout_categories[use_category] + GLOB.gear_datums[use_name] = new geartype + LC.gear[use_name] = GLOB.gear_datums[use_name] - loadout_categories = sortAssoc(loadout_categories) - for(var/loadout_category in loadout_categories) - var/datum/loadout_category/LC = loadout_categories[loadout_category] + GLOB.loadout_categories = sortAssoc(GLOB.loadout_categories) + for(var/loadout_category in GLOB.loadout_categories) + var/datum/loadout_category/LC = GLOB.loadout_categories[loadout_category] LC.gear = sortAssoc(LC.gear) return 1 diff --git a/code/modules/client/preference/loadout/loadout_general.dm b/code/modules/client/preference/loadout/loadout_general.dm index 50105813fd6..8c08063ad7e 100644 --- a/code/modules/client/preference/loadout/loadout_general.dm +++ b/code/modules/client/preference/loadout/loadout_general.dm @@ -29,7 +29,7 @@ /datum/gear/sechud display_name = "a classic security HUD" path = /obj/item/clothing/glasses/hud/security - allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot", "Internal Affairs Agent") + allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot", "Internal Affairs Agent","Magistrate") /datum/gear/matches display_name = "a box of matches" @@ -42,7 +42,7 @@ /datum/gear/doublecards display_name = "a double deck of standard cards" path = /obj/item/deck/doublecards - + /datum/gear/tarot display_name = "a deck of tarot cards" path = /obj/item/deck/tarot diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 4e8ef94aeec..7b3133c0103 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -1,6 +1,7 @@ -var/list/preferences_datums = list() +GLOBAL_LIST_EMPTY(preferences_datums) +GLOBAL_PROTECT(preferences_datums) // These feel like something that shouldnt be fucked with -var/global/list/special_role_times = list( //minimum age (in days) for accounts to play these roles +GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts to play these roles ROLE_PAI = 0, ROLE_POSIBRAIN = 0, ROLE_GUARDIAN = 0, @@ -24,7 +25,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts ROLE_GSPIDER = 21, ROLE_ABDUCTOR = 30, ROLE_DEVIL = 14 -) +)) /proc/player_old_enough_antag(client/C, role) if(available_in_days_antag(C, role)) @@ -42,7 +43,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts return 0 if(!isnum(C.player_age)) return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced - var/minimal_player_age_antag = special_role_times[num2text(role)] + var/minimal_player_age_antag = GLOB.special_role_times[num2text(role)] if(!isnum(minimal_player_age_antag)) return 0 @@ -78,7 +79,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/last_id //game-preferences - var/lastchangelog = "" //Saved changlog filesize to detect if there was a change + var/lastchangelog = "1" //Saved changlog timestamp (unix epoch) to detect if there was a change. Dont set this to 0 unless you want the last changelog date to be 4x longer than the expected lifespan of the universe. var/exp var/ooccolor = "#b82e00" var/list/be_special = list() //Special role selection @@ -199,7 +200,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/unlock_content = 0 //Gear stuff - var/list/gear = list() + var/list/loadout_gear = list() var/gear_tab = "General" // Parallax var/parallax = PARALLAX_HIGH @@ -343,11 +344,11 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "Eyes: " dat += "Color [color_square(e_colour)]
    " - if((S.bodyflags & HAS_SKIN_COLOR) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins + if((S.bodyflags & HAS_SKIN_COLOR) || GLOB.body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins dat += "Body Color: " dat += "Color [color_square(s_colour)]
    " - if(body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) + if(GLOB.body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) dat += "Body Accessory: " dat += "[body_accessory ? "[body_accessory]" : "None"]
    " @@ -397,6 +398,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts organ_name = "right hand" if("eyes") organ_name = "eyes" + if("ears") + organ_name = "ears" if("heart") organ_name = "heart" if("lungs") @@ -413,10 +416,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts switch(status) if("cyborg") var/datum/robolimb/R - if(rlimb_data[name] && all_robolimbs[rlimb_data[name]]) - R = all_robolimbs[rlimb_data[name]] + if(rlimb_data[name] && GLOB.all_robolimbs[rlimb_data[name]]) + R = GLOB.all_robolimbs[rlimb_data[name]] else - R = basic_robolimb + R = GLOB.basic_robolimb dat += "\t[R.company] [organ_name] prosthesis" if("amputated") dat += "\tAmputated [organ_name]" @@ -461,7 +464,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "Ghost Sight: [(toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]
    " dat += "Ghost PDA: [(toggles & CHAT_GHOSTPDA) ? "All PDA Messages" : "No PDA Messages"]
    " if(check_rights(R_ADMIN,0)) - dat += "OOC Color:     Change
    " + dat += "OOC Color:     Change
    " if(config.allow_Metadata) dat += "OOC Notes: Edit
    " dat += "Parallax (Fancy Space): " @@ -488,7 +491,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "You are banned from special roles." be_special = list() else - for(var/i in special_roles) + for(var/i in GLOB.special_roles) if(jobban_isbanned(user, i)) dat += "Be [capitalize(i)]: \[BANNED]
    " else if(!player_old_enough_antag(user.client, i)) @@ -507,9 +510,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(TAB_GEAR) var/total_cost = 0 var/list/type_blacklist = list() - if(gear && gear.len) - for(var/i = 1, i <= gear.len, i++) - var/datum/gear/G = gear_datums[gear[i]] + if(loadout_gear && loadout_gear.len) + for(var/i = 1, i <= loadout_gear.len, i++) + var/datum/gear/G = GLOB.gear_datums[loadout_gear[i]] if(G) if(!G.subtype_cost_overlap) if(G.subtype_path in type_blacklist) @@ -525,7 +528,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += "
    " - var/datum/loadout_category/LC = loadout_categories[gear_tab] + var/datum/loadout_category/LC = GLOB.loadout_categories[gear_tab] dat += "" dat += "" dat += "" for(var/gear_name in LC.gear) var/datum/gear/G = LC.gear[gear_name] - var/ticked = (G.display_name in gear) + var/ticked = (G.display_name in loadout_gear) if(G.donator_tier > user.client.donator_level) dat += "" else @@ -575,10 +578,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts /datum/preferences/proc/get_gear_metadata(var/datum/gear/G) - . = gear[G.display_name] + . = loadout_gear[G.display_name] if(!.) . = list() - gear[G.display_name] = . + loadout_gear[G.display_name] = . /datum/preferences/proc/get_tweak_metadata(var/datum/gear/G, var/datum/gear_tweak/tweak) var/list/metadata = get_gear_metadata(G) @@ -621,6 +624,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(job.admin_only) continue + if(job.hidden_from_job_prefs) + continue + index += 1 if((index >= limit) || (job.title in splitJobs)) if((index < limit) && (lastJob != null)) @@ -654,7 +660,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if((job_support_low & JOB_CIVILIAN) && (rank != "Civilian")) HTML += "[rank]" continue - if((rank in command_positions) || (rank == "AI"))//Bold head jobs + if((rank in GLOB.command_positions) || (rank == "AI"))//Bold head jobs HTML += "[rank]" else HTML += "[rank]" @@ -720,7 +726,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts HTML += "" for(var/i = 1, i < (limit - index), i += 1) // Finish the column so it is even - HTML += "" + HTML += "" HTML += "
    KeyReal NameJobMins AFKSpecial RoleAreaPPNCryo
    " var/firstcat = 1 - for(var/category in loadout_categories) + for(var/category in GLOB.loadout_categories) if(firstcat) firstcat = 0 else @@ -536,13 +539,13 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts dat += " [category] " dat += "

    [LC.category]

    [G.display_name]
      
      
    " @@ -846,9 +852,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts return 1 /datum/preferences/proc/ShowDisabilityState(mob/user, flag, label) - var/datum/species/S = GLOB.all_species[species] - if(flag == DISABILITY_FLAG_FAT && !(CAN_BE_FAT in S.species_traits)) - return "
  • [species] cannot be fat.
  • " return "
  • [label]: [disabilities & flag ? "Yes" : "No"]
  • " /datum/preferences/proc/SetDisabilities(mob/user) @@ -1115,9 +1118,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts SetDisabilities(user) if("input") var/dflag=text2num(href_list["disability"]) - if(dflag >= 0) - if(!(dflag==DISABILITY_FLAG_FAT && !(CAN_BE_FAT in S.species_traits))) //If the disability isn't fatness, toggle it. If it IS fatness, check to see if the species can be fat before going ahead. - disabilities ^= text2num(href_list["disability"]) //MAGIC + if(dflag >= 0) // Toggle it. + disabilities ^= text2num(href_list["disability"]) //MAGIC SetDisabilities(user) else SetDisabilities(user) @@ -1160,17 +1162,17 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(href_list["preference"] == "gear") if(href_list["toggle_gear"]) - var/datum/gear/TG = gear_datums[href_list["toggle_gear"]] - if(TG.display_name in gear) - gear -= TG.display_name + var/datum/gear/TG = GLOB.gear_datums[href_list["toggle_gear"]] + if(TG.display_name in loadout_gear) + loadout_gear -= TG.display_name else if(TG.donator_tier && user.client.donator_level < TG.donator_tier) to_chat(user, "That gear is only available at a higher donation tier than you are on.") return var/total_cost = 0 var/list/type_blacklist = list() - for(var/gear_name in gear) - var/datum/gear/G = gear_datums[gear_name] + for(var/gear_name in loadout_gear) + var/datum/gear/G = GLOB.gear_datums[gear_name] if(istype(G)) if(!G.subtype_cost_overlap) if(G.subtype_path in type_blacklist) @@ -1179,10 +1181,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts total_cost += G.cost if((total_cost + TG.cost) <= max_gear_slots) - gear += TG.display_name + loadout_gear += TG.display_name else if(href_list["gear"] && href_list["tweak"]) - var/datum/gear/gear = gear_datums[href_list["gear"]] + var/datum/gear/gear = GLOB.gear_datums[href_list["gear"]] var/datum/gear_tweak/tweak = locate(href_list["tweak"]) if(!tweak || !istype(gear) || !(tweak in gear.gear_tweaks)) return @@ -1193,7 +1195,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts else if(href_list["select_category"]) gear_tab = href_list["select_category"] else if(href_list["clear_loadout"]) - gear.Cut() + loadout_gear.Cut() ShowChoices(user) return @@ -1203,7 +1205,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/datum/robolimb/robohead if(S.bodyflags & ALL_RPARTS) var/head_model = "[!rlimb_data["head"] ? "Morpheus Cyberkinetics" : rlimb_data["head"]]" - robohead = all_robolimbs[head_model] + robohead = GLOB.all_robolimbs[head_model] switch(href_list["preference"]) if("name") real_name = random_name(gender,species) @@ -1320,7 +1322,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts var/datum/robolimb/robohead if(NS.bodyflags & ALL_RPARTS) var/head_model = "[!rlimb_data["head"] ? "Morpheus Cyberkinetics" : rlimb_data["head"]]" - robohead = all_robolimbs[head_model] + robohead = GLOB.all_robolimbs[head_model] //grab one of the valid hair styles for the newly chosen species h_style = random_hair_style(gender, species, robohead) @@ -1453,7 +1455,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts head_model = "Morpheus Cyberkinetics" else head_model = rlimb_data["head"] - var/datum/robolimb/robohead = all_robolimbs[head_model] + var/datum/robolimb/robohead = GLOB.all_robolimbs[head_model] if((species in SA.species_allowed) && robohead.is_monitor && ((SA.models_allowed && (robohead.company in SA.models_allowed)) || !SA.models_allowed)) //If this is a hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_hairstyles += hairstyle //Give them their hairstyles if they do. else @@ -1536,7 +1538,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts head_model = "Morpheus Cyberkinetics" else head_model = rlimb_data["head"] - var/datum/robolimb/robohead = all_robolimbs[head_model] + var/datum/robolimb/robohead = GLOB.all_robolimbs[head_model] if(robohead.is_monitor && M.name != "None") //If the character can have prosthetic heads and they have the default Morpheus head (or another monitor-head), no optic markings. continue else if(!robohead.is_monitor && M.name != "None") //Otherwise, if they DON'T have the default head and the head's not a monitor but the head's not in the style's list of allowed models, skip. @@ -1613,10 +1615,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("body_accessory") var/list/possible_body_accessories = list() if(check_rights(R_ADMIN, 1, user)) - possible_body_accessories = body_accessory_by_name.Copy() + possible_body_accessories = GLOB.body_accessory_by_name.Copy() else - for(var/B in body_accessory_by_name) - var/datum/body_accessory/accessory = body_accessory_by_name[B] + for(var/B in GLOB.body_accessory_by_name) + var/datum/body_accessory/accessory = GLOB.body_accessory_by_name[B] if(!istype(accessory)) possible_body_accessories += "None" //the only null entry should be the "None" option continue @@ -1660,7 +1662,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts head_model = "Morpheus Cyberkinetics" else head_model = rlimb_data["head"] - var/datum/robolimb/robohead = all_robolimbs[head_model] + var/datum/robolimb/robohead = GLOB.all_robolimbs[head_model] if((species in SA.species_allowed) && robohead.is_monitor && ((SA.models_allowed && (robohead.company in SA.models_allowed)) || !SA.models_allowed)) //If this is a facial hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_facial_hairstyles += facialhairstyle //Give them their facial hairstyles if they do. else @@ -1750,7 +1752,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts s_tone = max(min(round(skin_c), S.icon_skin_tones.len), 1) if("skin") - if((S.bodyflags & HAS_SKIN_COLOR) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) + if((S.bodyflags & HAS_SKIN_COLOR) || GLOB.body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference", s_colour) as color|null if(new_skin) s_colour = new_skin @@ -1869,7 +1871,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if(!choice) return R.company = choice - R = all_robolimbs[R.company] + R = GLOB.all_robolimbs[R.company] if(R.has_subtypes == 1) //If the company the user selected provides more than just one base model, lets handle it. var/list/robolimb_models = list() for(var/limb_type in typesof(R)) //Handling the different models of parts that manufacturers can provide. @@ -1904,7 +1906,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts rlimb_data[second_limb] = choice organ_data[second_limb] = "cyborg" if("organs") - var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Eyes", "Heart", "Lungs", "Liver", "Kidneys") + var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Eyes", "Ears", "Heart", "Lungs", "Liver", "Kidneys") if(!organ_name) return @@ -1912,6 +1914,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts switch(organ_name) if("Eyes") organ = "eyes" + if("Ears") + organ = "ears" if("Heart") organ = "heart" if("Lungs") @@ -2000,6 +2004,11 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts windowflashing = !windowflashing if("afk_watch") + if(!afk_watch) + to_chat(user, "You will now get put into cryo dorms after [config.auto_cryo_afk] minutes. \ + Then after [config.auto_despawn_afk] minutes you will be fully despawned. You will receive a visual and auditory warning before you will be put into cryodorms.") + else + to_chat(user, "Automatic cryoing turned off.") afk_watch = !afk_watch if("UIcolor") @@ -2022,7 +2031,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("be_special") var/r = href_list["role"] - if(r in special_roles) + if(r in GLOB.special_roles) be_special ^= r if("name") @@ -2208,7 +2217,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.m_styles = m_styles if(body_accessory) - character.body_accessory = body_accessory_by_name["[body_accessory]"] + character.body_accessory = GLOB.body_accessory_by_name["[body_accessory]"] character.backbag = backbag @@ -2220,54 +2229,54 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts character.change_eye_color(e_colour) - if(disabilities & DISABILITY_FLAG_FAT && (CAN_BE_FAT in character.dna.species.species_traits)) - character.dna.SetSEState(FATBLOCK, TRUE, TRUE) + if(disabilities & DISABILITY_FLAG_FAT) + character.dna.SetSEState(GLOB.fatblock, TRUE, TRUE) character.overeatduration = 600 - character.dna.default_blocks.Add(FATBLOCK) + character.dna.default_blocks.Add(GLOB.fatblock) if(disabilities & DISABILITY_FLAG_NEARSIGHTED) - character.dna.SetSEState(GLASSESBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(GLASSESBLOCK) + character.dna.SetSEState(GLOB.glassesblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.glassesblock) if(disabilities & DISABILITY_FLAG_BLIND) - character.dna.SetSEState(BLINDBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(BLINDBLOCK) + character.dna.SetSEState(GLOB.blindblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.blindblock) if(disabilities & DISABILITY_FLAG_DEAF) - character.dna.SetSEState(DEAFBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(DEAFBLOCK) + character.dna.SetSEState(GLOB.deafblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.deafblock) if(disabilities & DISABILITY_FLAG_COLOURBLIND) - character.dna.SetSEState(COLOURBLINDBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(COLOURBLINDBLOCK) + character.dna.SetSEState(GLOB.colourblindblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.colourblindblock) if(disabilities & DISABILITY_FLAG_MUTE) - character.dna.SetSEState(MUTEBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(MUTEBLOCK) + character.dna.SetSEState(GLOB.muteblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.muteblock) if(disabilities & DISABILITY_FLAG_NERVOUS) - character.dna.SetSEState(NERVOUSBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(NERVOUSBLOCK) + character.dna.SetSEState(GLOB.nervousblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.nervousblock) if(disabilities & DISABILITY_FLAG_SWEDISH) - character.dna.SetSEState(SWEDEBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(SWEDEBLOCK) + character.dna.SetSEState(GLOB.swedeblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.swedeblock) if(disabilities & DISABILITY_FLAG_CHAV) - character.dna.SetSEState(CHAVBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(CHAVBLOCK) + character.dna.SetSEState(GLOB.chavblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.chavblock) if(disabilities & DISABILITY_FLAG_LISP) - character.dna.SetSEState(LISPBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(LISPBLOCK) + character.dna.SetSEState(GLOB.lispblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.lispblock) if(disabilities & DISABILITY_FLAG_DIZZY) - character.dna.SetSEState(DIZZYBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(DIZZYBLOCK) + character.dna.SetSEState(GLOB.dizzyblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.dizzyblock) if(disabilities & DISABILITY_FLAG_WINGDINGS && (CAN_WINGDINGS in character.dna.species.species_traits)) - character.dna.SetSEState(WINGDINGSBLOCK, TRUE, TRUE) - character.dna.default_blocks.Add(WINGDINGSBLOCK) + character.dna.SetSEState(GLOB.wingdingsblock, TRUE, TRUE) + character.dna.default_blocks.Add(GLOB.wingdingsblock) character.dna.species.handle_dna(character) @@ -2286,7 +2295,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts /datum/preferences/proc/open_load_dialog(mob/user) - var/DBQuery/query = dbcon.NewQuery("SELECT slot,real_name FROM [format_table_name("characters")] WHERE ckey='[user.ckey]' ORDER BY slot") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT slot,real_name FROM [format_table_name("characters")] WHERE ckey='[user.ckey]' ORDER BY slot") var/list/slotnames[max_save_slots] if(!query.Execute()) diff --git a/code/modules/client/preference/preferences_mysql.dm b/code/modules/client/preference/preferences_mysql.dm index 6090538f2b3..94f724b77a6 100644 --- a/code/modules/client/preference/preferences_mysql.dm +++ b/code/modules/client/preference/preferences_mysql.dm @@ -1,6 +1,6 @@ /datum/preferences/proc/load_preferences(client/C) - var/DBQuery/query = dbcon.NewQuery({"SELECT + var/DBQuery/query = GLOB.dbcon.NewQuery({"SELECT ooccolor, UI_style, UI_style_color, @@ -84,11 +84,11 @@ // Might as well scrub out any malformed be_special list entries while we're here for(var/role in be_special) - if(!(role in special_roles)) + if(!(role in GLOB.special_roles)) log_runtime(EXCEPTION("[C.key] had a malformed role entry: '[role]'. Removing!"), src) be_special -= role - var/DBQuery/query = dbcon.NewQuery({"UPDATE [format_table_name("player")] + var/DBQuery/query = GLOB.dbcon.NewQuery({"UPDATE [format_table_name("player")] SET ooccolor='[ooccolor]', UI_style='[UI_style]', @@ -126,11 +126,11 @@ slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot)) if(slot != default_slot) default_slot = slot - var/DBQuery/firstquery = dbcon.NewQuery("UPDATE [format_table_name("player")] SET default_slot=[slot] WHERE ckey='[C.ckey]'") + var/DBQuery/firstquery = GLOB.dbcon.NewQuery("UPDATE [format_table_name("player")] SET default_slot=[slot] WHERE ckey='[C.ckey]'") firstquery.Execute() // Let's not have this explode if you sneeze on the DB - var/DBQuery/query = dbcon.NewQuery({"SELECT + var/DBQuery/query = GLOB.dbcon.NewQuery({"SELECT OOC_Notes, real_name, name_is_always_random, @@ -259,7 +259,7 @@ //socks socks = query.item[49] body_accessory = query.item[50] - gear = params2list(query.item[51]) + loadout_gear = params2list(query.item[51]) autohiss_mode = text2num(query.item[52]) //Sanitize @@ -318,7 +318,11 @@ if(!player_alt_titles) player_alt_titles = new() if(!organ_data) src.organ_data = list() if(!rlimb_data) src.rlimb_data = list() - if(!gear) gear = list() + if(!loadout_gear) loadout_gear = list() + + // Check if the current body accessory exists + if(!GLOB.body_accessory_by_name[body_accessory]) + body_accessory = null return 1 @@ -336,14 +340,14 @@ rlimblist = list2params(rlimb_data) if(!isemptylist(player_alt_titles)) playertitlelist = list2params(player_alt_titles) - if(!isemptylist(gear)) - gearlist = list2params(gear) + if(!isemptylist(loadout_gear)) + gearlist = list2params(loadout_gear) - var/DBQuery/firstquery = dbcon.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' ORDER BY slot") + var/DBQuery/firstquery = GLOB.dbcon.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' ORDER BY slot") firstquery.Execute() while(firstquery.NextRow()) if(text2num(firstquery.item[1]) == default_slot) - var/DBQuery/query = dbcon.NewQuery({"UPDATE [format_table_name("characters")] SET OOC_Notes='[sanitizeSQL(metadata)]', + var/DBQuery/query = GLOB.dbcon.NewQuery({"UPDATE [format_table_name("characters")] SET OOC_Notes='[sanitizeSQL(metadata)]', real_name='[sanitizeSQL(real_name)]', name_is_always_random='[be_random_name]', gender='[gender]', @@ -406,7 +410,7 @@ return return 1 - var/DBQuery/query = dbcon.NewQuery({" + var/DBQuery/query = GLOB.dbcon.NewQuery({" INSERT INTO [format_table_name("characters")] (ckey, slot, OOC_Notes, real_name, name_is_always_random, gender, age, species, language, hair_colour, secondary_hair_colour, @@ -473,7 +477,7 @@ return 1 /datum/preferences/proc/load_random_character_slot(client/C) - var/DBQuery/query = dbcon.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' ORDER BY slot") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' ORDER BY slot") var/list/saves = list() if(!query.Execute()) @@ -491,17 +495,3 @@ load_character(C,pick(saves)) return 1 -/datum/preferences/proc/SetChangelog(client/C,hash) - lastchangelog=hash - if(preferences_datums[C.ckey].toggles & UI_DARKMODE) - winset(C, "rpane.changelog", "background-color=#40628a;font-color=#ffffff;font-style=none") - else - winset(C, "rpane.changelog", "background-color=none;font-style=none") - var/DBQuery/query = dbcon.NewQuery("UPDATE [format_table_name("player")] SET lastchangelog='[lastchangelog]' WHERE ckey='[C.ckey]'") - if(!query.Execute()) - var/err = query.ErrorMsg() - log_game("SQL ERROR during lastchangelog updating. Error : \[[err]\]\n") - message_admins("SQL ERROR during lastchangelog updating. Error : \[[err]\]\n") - to_chat(C, "Couldn't update your last seen changelog, please try again later.") - return - return 1 diff --git a/code/modules/client/preference/preferences_spawnpoints.dm b/code/modules/client/preference/preferences_spawnpoints.dm index 38b6b87ef43..5708567130e 100644 --- a/code/modules/client/preference/preferences_spawnpoints.dm +++ b/code/modules/client/preference/preferences_spawnpoints.dm @@ -1,10 +1,10 @@ -var/list/spawntypes = list() +GLOBAL_LIST_EMPTY(spawntypes) /proc/populate_spawn_points() - spawntypes = list() + // GLOB.spawntypes = list() | This is already done, is it not for(var/type in subtypesof(/datum/spawnpoint)) var/datum/spawnpoint/S = new type() - spawntypes[S.display_name] = S + GLOB.spawntypes[S.display_name] = S /datum/spawnpoint var/msg //Message to display on the arrivals computer. @@ -28,7 +28,7 @@ var/list/spawntypes = list() /datum/spawnpoint/arrivals/New() ..() - turfs = latejoin + turfs = GLOB.latejoin /datum/spawnpoint/gateway display_name = "Gateway" @@ -36,7 +36,7 @@ var/list/spawntypes = list() /datum/spawnpoint/gateway/New() ..() - turfs = latejoin_gateway + turfs = GLOB.latejoin_gateway /datum/spawnpoint/cryo display_name = "Cryogenic Storage" @@ -45,7 +45,7 @@ var/list/spawntypes = list() /datum/spawnpoint/cryo/New() ..() - turfs = latejoin_cryo + turfs = GLOB.latejoin_cryo /datum/spawnpoint/cyborg display_name = "Cyborg Storage" @@ -54,4 +54,4 @@ var/list/spawntypes = list() /datum/spawnpoint/cyborg/New() ..() - turfs = latejoin_cyborg + turfs = GLOB.latejoin_cyborg diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm index da0873f162f..38b49314667 100644 --- a/code/modules/clothing/chameleon.dm +++ b/code/modules/clothing/chameleon.dm @@ -9,6 +9,10 @@ ..() initialize_outfits() +/datum/action/chameleon_outfit/Destroy() + STOP_PROCESSING(SSprocessing, src) + return ..() + /datum/action/chameleon_outfit/proc/initialize_outfits() var/static/list/standard_outfit_options if(!standard_outfit_options) @@ -140,29 +144,29 @@ UpdateButtonIcon() /datum/action/item_action/chameleon/change/proc/update_item(obj/item/picked_item) - // Species-related variables are lists, which can not be retrieved using initial(). As such, we need to instantiate the picked item. - var/obj/item/P = new picked_item(null) - - target.name = P.name - target.desc = P.desc - target.icon_state = P.icon_state + target.name = initial(picked_item.name) + target.desc = initial(picked_item.desc) + target.icon_state = initial(picked_item.icon_state) if(isitem(target)) var/obj/item/I = target - I.item_state = P.item_state - I.item_color = P.item_color + I.item_state = initial(picked_item.item_state) + I.item_color = initial(picked_item.item_color) - I.icon_override = P.icon_override - I.sprite_sheets = P.sprite_sheets + I.icon_override = initial(picked_item.icon_override) + if(initial(picked_item.sprite_sheets)) + // Species-related variables are lists, which can not be retrieved using initial(). As such, we need to instantiate the picked item. + var/obj/item/P = new picked_item(null) + I.sprite_sheets = P.sprite_sheets + qdel(P) - if(istype(I, /obj/item/clothing) && istype(P, /obj/item/clothing)) + if(istype(I, /obj/item/clothing) && istype(initial(picked_item), /obj/item/clothing)) var/obj/item/clothing/CL = I - var/obj/item/clothing/PCL = P - CL.flags_cover = PCL.flags_cover + var/obj/item/clothing/PCL = picked_item + CL.flags_cover = initial(PCL.flags_cover) - target.icon = P.icon - qdel(P) + target.icon = initial(picked_item.icon) /datum/action/item_action/chameleon/change/Trigger() if(!IsAvailable()) @@ -198,7 +202,7 @@ var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/clothing/under/chameleon/Initialize() +/obj/item/clothing/under/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/clothing/under @@ -206,11 +210,15 @@ chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/under, /obj/item/clothing/under/color, /obj/item/clothing/under/rank), only_root_path = TRUE) chameleon_action.initialize_disguises() +/obj/item/clothing/under/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/clothing/under/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/clothing/under/chameleon/broken/Initialize() +/obj/item/clothing/under/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -229,7 +237,7 @@ var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/clothing/suit/chameleon/Initialize() +/obj/item/clothing/suit/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/clothing/suit @@ -237,11 +245,15 @@ chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/suit/armor/abductor), only_root_path = TRUE) chameleon_action.initialize_disguises() +/obj/item/clothing/suit/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/clothing/suit/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/clothing/suit/chameleon/broken/Initialize() +/obj/item/clothing/suit/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -261,7 +273,7 @@ var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/clothing/glasses/chameleon/Initialize() +/obj/item/clothing/glasses/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/clothing/glasses @@ -269,11 +281,15 @@ chameleon_action.chameleon_blacklist = list() chameleon_action.initialize_disguises() +/obj/item/clothing/glasses/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/clothing/glasses/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/clothing/glasses/chameleon/broken/Initialize() +/obj/item/clothing/glasses/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -289,7 +305,7 @@ var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/clothing/glasses/hud/security/chameleon/Initialize() +/obj/item/clothing/glasses/hud/security/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/clothing/glasses @@ -297,11 +313,15 @@ chameleon_action.chameleon_blacklist = list() chameleon_action.initialize_disguises() +/obj/item/clothing/glasses/hud/security/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/clothing/glasses/hud/security/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/clothing/glasses/hud/security/chameleon/broken/Initialize() +/obj/item/clothing/glasses/hud/security/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -316,7 +336,7 @@ var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/clothing/gloves/chameleon/Initialize() +/obj/item/clothing/gloves/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/clothing/gloves @@ -324,11 +344,15 @@ chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/gloves, /obj/item/clothing/gloves/color), only_root_path = TRUE) chameleon_action.initialize_disguises() +/obj/item/clothing/gloves/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/clothing/gloves/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/clothing/gloves/chameleon/broken/Initialize() +/obj/item/clothing/gloves/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -347,7 +371,7 @@ var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/clothing/head/chameleon/Initialize() +/obj/item/clothing/head/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/clothing/head @@ -355,11 +379,15 @@ chameleon_action.chameleon_blacklist = list() chameleon_action.initialize_disguises() +/obj/item/clothing/head/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/clothing/head/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/clothing/head/chameleon/broken/Initialize() +/obj/item/clothing/head/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -389,7 +417,7 @@ var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/clothing/mask/chameleon/Initialize() +/obj/item/clothing/mask/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) @@ -402,13 +430,14 @@ /obj/item/clothing/mask/chameleon/Destroy() QDEL_NULL(voice_changer) + QDEL_NULL(chameleon_action) return ..() /obj/item/clothing/mask/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/clothing/mask/chameleon/broken/Initialize() +/obj/item/clothing/mask/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -423,7 +452,7 @@ var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/clothing/shoes/chameleon/Initialize() +/obj/item/clothing/shoes/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/clothing/shoes @@ -431,6 +460,10 @@ chameleon_action.chameleon_blacklist = list() chameleon_action.initialize_disguises() +/obj/item/clothing/shoes/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/clothing/shoes/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() @@ -442,7 +475,7 @@ desc = "A pair of black shoes." flags = NOSLIP -/obj/item/clothing/shoes/chameleon/noslip/broken/Initialize() +/obj/item/clothing/shoes/chameleon/noslip/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -455,18 +488,22 @@ var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/storage/backpack/chameleon/Initialize() +/obj/item/storage/backpack/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/storage/backpack chameleon_action.chameleon_name = "Backpack" chameleon_action.initialize_disguises() +/obj/item/storage/backpack/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/storage/backpack/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/storage/backpack/chameleon/broken/Initialize() +/obj/item/storage/backpack/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -475,7 +512,7 @@ desc = "Holds tools." var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/storage/belt/chameleon/Initialize() +/obj/item/storage/belt/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) @@ -483,11 +520,15 @@ chameleon_action.chameleon_name = "Belt" chameleon_action.initialize_disguises() +/obj/item/storage/belt/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/storage/belt/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/storage/belt/chameleon/broken/Initialize() +/obj/item/storage/belt/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -495,18 +536,22 @@ name = "radio headset" var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/radio/headset/chameleon/Initialize() +/obj/item/radio/headset/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/radio/headset chameleon_action.chameleon_name = "Headset" chameleon_action.initialize_disguises() +/obj/item/radio/headset/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/radio/headset/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/radio/headset/chameleon/broken/Initialize() +/obj/item/radio/headset/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) @@ -514,7 +559,7 @@ name = "PDA" var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/pda/chameleon/Initialize() +/obj/item/pda/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/pda @@ -522,24 +567,32 @@ chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/pda/heads), only_root_path = TRUE) chameleon_action.initialize_disguises() +/obj/item/pda/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + /obj/item/pda/chameleon/emp_act(severity) . = ..() chameleon_action.emp_randomise() -/obj/item/pda/chameleon/broken/Initialize() +/obj/item/pda/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) /obj/item/stamp/chameleon var/datum/action/item_action/chameleon/change/chameleon_action -/obj/item/stamp/chameleon/Initialize() +/obj/item/stamp/chameleon/Initialize(mapload) . = ..() chameleon_action = new(src) chameleon_action.chameleon_type = /obj/item/stamp chameleon_action.chameleon_name = "Stamp" chameleon_action.initialize_disguises() -/obj/item/stamp/chameleon/broken/Initialize() +/obj/item/stamp/chameleon/Destroy() + QDEL_NULL(chameleon_action) + return ..() + +/obj/item/stamp/chameleon/broken/Initialize(mapload) . = ..() chameleon_action.emp_randomise(INFINITY) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index d816e067502..bfa43b92fa3 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -335,7 +335,6 @@ BLIND // can't see anything set category = "Object" set src in usr set_sensors(usr) - ..() //Head /obj/item/clothing/head @@ -563,7 +562,7 @@ BLIND // can't see anything return user.update_inv_wear_suit() else - to_chat(user, "You attempt to button up the velcro on \the [src], before promptly realising how retarded you are.") + to_chat(user, "You attempt to button up the velcro on \the [src], before promptly realising how foolish you are.") /obj/item/clothing/suit/equipped(var/mob/living/carbon/human/user, var/slot) //Handle tail-hiding on a by-species basis. ..() @@ -739,7 +738,7 @@ BLIND // can't see anything if(!usr.incapacitated()) if(copytext(item_color,-2) != "_d") basecolor = item_color - if(basecolor + "_d_s" in icon_states('icons/mob/uniform.dmi')) + if((basecolor + "_d_s") in icon_states('icons/mob/uniform.dmi')) item_color = item_color == "[basecolor]" ? "[basecolor]_d" : "[basecolor]" usr.update_inv_w_uniform() else diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 1b9c87f56e5..011bc60cdc4 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -376,7 +376,6 @@ desc = "Covers the eyes, preventing sight." icon_state = "blindfold" item_state = "blindfold" - //vision_flags = BLIND flash_protect = 2 tint = 3 //to make them blind prescription_upgradable = 0 @@ -412,7 +411,7 @@ if(M.glasses == src) M.EyeBlind(3) M.EyeBlurry(5) - if(!(M.disabilities & NEARSIGHTED)) + if(!(NEARSIGHTED in M.mutations)) M.BecomeNearsighted() spawn(100) M.CureNearsighted() diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index feee4845a9c..4d2255a09ab 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -11,13 +11,13 @@ /obj/item/clothing/glasses/hud/equipped(mob/living/carbon/human/user, slot) ..() if(HUDType && slot == slot_glasses) - var/datum/atom_hud/H = huds[HUDType] + var/datum/atom_hud/H = GLOB.huds[HUDType] H.add_hud_to(user) /obj/item/clothing/glasses/hud/dropped(mob/living/carbon/human/user) ..() if(HUDType && istype(user) && user.glasses == src) - var/datum/atom_hud/H = huds[HUDType] + var/datum/atom_hud/H = GLOB.huds[HUDType] H.remove_hud_from(user) /obj/item/clothing/glasses/hud/emp_act(severity) diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 993f2050b51..e2736054899 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -100,7 +100,7 @@ name = "head of security cap" desc = "The robust standard-issue cap of the Head of Security. For showing the officers who's in charge." icon_state = "hoscap" - armor = list("melee" = 40, "bullet" = 30, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 60) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 60) strip_delay = 80 /obj/item/clothing/head/HoS/beret @@ -121,14 +121,14 @@ desc = "A red cap with an old-fashioned badge on the front for establishing that you are, in fact, the law." icon_state = "customshelm" item_state = "customshelm" - armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 50) + armor = list("melee" = 35, "bullet" = 30, "laser" = 30,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 50) strip_delay = 60 /obj/item/clothing/head/beret/sec name = "security beret" desc = "A beret with the security insignia emblazoned on it. For officers that are more inclined towards style than safety." icon_state = "beret_officer" - armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 50) + armor = list("melee" = 35, "bullet" = 30, "laser" = 30,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 50) strip_delay = 60 dog_fashion = null diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index 0255109620a..d34584ff425 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -107,7 +107,7 @@ desc = "It's baseball hat in tasteful red colour." icon_state = "secsoft" item_color = "sec" - armor = list("melee" = 30, "bullet" = 25, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 50) + armor = list("melee" = 35, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = 50) strip_delay = 60 dog_fashion = null diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index b798c1d8df0..b02bfc537bd 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -152,6 +152,12 @@ item_state = "mime" resistance_flags = FLAMMABLE +/obj/item/clothing/mask/gas/mime/wizard + name = "magical mime mask" + desc = "A mime mask glowing with power. Its eyes gaze deep into your soul." + flags_inv = HIDEEARS | HIDEEYES + magical = TRUE + /obj/item/clothing/mask/gas/mime/nodrop flags = NODROP diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm index 0bf54e8692f..5bf6b90c98e 100644 --- a/code/modules/clothing/shoes/colour.dm +++ b/code/modules/clothing/shoes/colour.dm @@ -86,21 +86,25 @@ name = "orange shoes" icon_state = "orange" item_color = "orange" + var/obj/item/restraints/handcuffs/shackles -/obj/item/clothing/shoes/orange/attack_self(mob/user as mob) - if(src.chained) - src.chained = null - src.slowdown = SHOES_SLOWDOWN - new /obj/item/restraints/handcuffs( user.loc ) - src.icon_state = "orange" - return +/obj/item/clothing/shoes/orange/Destroy() + QDEL_NULL(shackles) + return ..() -/obj/item/clothing/shoes/orange/attackby(obj/H, loc, params) - ..() - if(istype(H, /obj/item/restraints/handcuffs) && !chained && !(H.flags & NODROP)) - if(src.icon_state != "orange") return - qdel(H) - src.chained = 1 - src.slowdown = 15 - src.icon_state = "orange1" - return +/obj/item/clothing/shoes/orange/attack_self(mob/user) + if(shackles) + user.put_in_hands(shackles) + shackles = null + slowdown = SHOES_SLOWDOWN + icon_state = "orange" + +/obj/item/clothing/shoes/orange/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/restraints/handcuffs) && !shackles) + if(user.drop_item()) + I.forceMove(src) + shackles = I + slowdown = 15 + icon_state = "orange1" + return + return ..() diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 916cb8e89d4..129b07af36e 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -73,16 +73,15 @@ obj/item/clothing/shoes/magboots/syndie/advance //For the Syndicate Strike Team shoe_sound = "clownstep" origin_tech = "magnets=4;syndicate=2" var/enabled_waddle = TRUE - var/datum/component/waddle /obj/item/clothing/shoes/magboots/clown/equipped(mob/user, slot) . = ..() if(slot == slot_shoes && enabled_waddle) - waddle = user.AddComponent(/datum/component/waddling) + user.AddElement(/datum/element/waddling) /obj/item/clothing/shoes/magboots/clown/dropped(mob/user) . = ..() - QDEL_NULL(waddle) + user.RemoveElement(/datum/element/waddling) /obj/item/clothing/shoes/magboots/clown/CtrlClick(mob/living/user) if(!isliving(user)) diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 6858355f876..962cfed80c5 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -71,16 +71,15 @@ var/footstep = 1 //used for squeeks whilst walking shoe_sound = "clownstep" var/enabled_waddle = TRUE - var/datum/component/waddle /obj/item/clothing/shoes/clown_shoes/equipped(mob/user, slot) . = ..() if(slot == slot_shoes && enabled_waddle) - waddle = user.AddComponent(/datum/component/waddling) + user.AddElement(/datum/element/waddling) /obj/item/clothing/shoes/clown_shoes/dropped(mob/user) . = ..() - QDEL_NULL(waddle) + user.RemoveElement(/datum/element/waddling) /obj/item/clothing/shoes/clown_shoes/CtrlClick(mob/living/user) if(!isliving(user)) diff --git a/code/modules/clothing/spacesuits/breaches.dm b/code/modules/clothing/spacesuits/breaches.dm index 483c122fd80..899cb8e8d46 100644 --- a/code/modules/clothing/spacesuits/breaches.dm +++ b/code/modules/clothing/spacesuits/breaches.dm @@ -23,23 +23,23 @@ ..() base_name = "[name]" -//Some simple descriptors for breaches. Global because lazy, TODO: work out a better way to do this. +//Some simple descriptors for breaches. Global because lazy, TODO: work out a better way to do this. | 6 years late, but atleast they are proper globals now -var/global/list/breach_brute_descriptors = list( +GLOBAL_LIST_INIT(breach_brute_descriptors, list( "tiny puncture", "ragged tear", "large split", "huge tear", "gaping wound" - ) + )) -var/global/list/breach_burn_descriptors = list( +GLOBAL_LIST_INIT(breach_burn_descriptors, list( "small burn", "melted patch", "sizable burn", "large scorched area", "huge scorched area" - ) + )) /datum/breach/proc/update_descriptor() @@ -47,9 +47,9 @@ var/global/list/breach_burn_descriptors = list( class = max(1,min(class,5)) //Apply the correct descriptor. if(damtype == BURN) - descriptor = breach_burn_descriptors[class] + descriptor = GLOB.breach_burn_descriptors[class] else if(damtype == BRUTE) - descriptor = breach_brute_descriptors[class] + descriptor = GLOB.breach_brute_descriptors[class] //Repair a certain amount of brute or burn damage to the suit. /obj/item/clothing/suit/space/proc/repair_breaches(var/damtype, var/amount, var/mob/user) diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index 4f6468fb9b7..94773ceaa31 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -95,7 +95,7 @@ phaseanim.loc = to_turf sleep(7) if(holder) - if(user && user in holder.contents) + if(user && (user in holder.contents)) user.loc = to_turf if(user.client) if(camera) diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm index 225b32e59fe..c412bb40f7d 100644 --- a/code/modules/clothing/spacesuits/ert.dm +++ b/code/modules/clothing/spacesuits/ert.dm @@ -22,7 +22,7 @@ else camera = new /obj/machinery/camera(src) camera.network = list("ERT") - cameranet.removeCamera(camera) + GLOB.cameranet.removeCamera(camera) camera.c_tag = user.name to_chat(user, "User scanned as [camera.c_tag]. Camera activated.") diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index f6ab79e628a..158aea81f7f 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -130,7 +130,6 @@ item_state = "santa" slowdown = 0 flags = STOPSPRESSUREDMAGE - flags_size = ONESIZEFITSALL allowed = list(/obj/item) //for stuffing extra special presents //Space pirate outfit diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 77d7b99fde0..49d3fd5fb53 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -68,7 +68,7 @@ on = !on icon_state = "[initial(icon_state)][on ? "-light":""]" item_state = icon_state - + var/mob/living/carbon/human/H = user if(istype(H)) H.update_inv_head() @@ -93,14 +93,14 @@ /obj/item/clothing/head/helmet/space/plasmaman/security name = "security plasma envirosuit helmet" - desc = "A plasmaman containment helmet designed for security officers, protecting them from being flashed and burning alive, along-side other undesirables." + desc = "A plasmaman containment helmet designed for security officers, protecting them from being flashed and burning alive, alongside other undesirables." icon_state = "security_envirohelm" item_state = "security_envirohelm" armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75) /obj/item/clothing/head/helmet/space/plasmaman/security/warden name = "warden's plasma envirosuit helmet" - desc = "A plasmaman containment helmet designed for the warden, a pair of white stripes being added to differeciate them from other members of security." + desc = "A plasmaman containment helmet designed for the warden, a pair of white stripes being added to differentiate them from other members of security." icon_state = "warden_envirohelm" item_state = "warden_envirohelm" @@ -111,14 +111,14 @@ item_state = "hos_envirohelm" /obj/item/clothing/head/helmet/space/plasmaman/medical - name = "medical's plasma envirosuit helmet" - desc = "An envriohelmet designed for plasmaman medical doctors, having two stripes down it's length to denote as much" + name = "medical plasma envirosuit helmet" + desc = "An envirohelmet designed for plasmaman medical doctors, having two stripes down its length to denote as much." icon_state = "doctor_envirohelm" item_state = "doctor_envirohelm" /obj/item/clothing/head/helmet/space/plasmaman/cmo name = "chief medical officer's plasma envirosuit helmet" - desc = "An envriohelmet designed for plasmaman employed as the cheif medical officer." + desc = "An envirohelmet designed for plasmamen employed as the chief medical officer." icon_state = "cmo_envirohelm" item_state = "cmo_envirohelm" @@ -136,7 +136,7 @@ /obj/item/clothing/head/helmet/space/plasmaman/chemist name = "chemistry plasma envirosuit helmet" - desc = "A plasmaman envirosuit designed for chemists, two orange stripes going down it's face." + desc = "A plasmaman envirohelmet designed for chemists, two orange stripes going down its face." icon_state = "chemist_envirohelm" item_state = "chemist_envirohelm" @@ -167,7 +167,7 @@ /obj/item/clothing/head/helmet/space/plasmaman/engineering/ce name = "chief engineer's plasma envirosuit helmet" - desc = "A space-worthy helmet specially designed for chief engineer employed plasmamen." + desc = "A space-worthy helmet specially designed for plasmamen employed as the chief engineer." icon_state = "ce_envirohelm" item_state = "ce_envirohelm" @@ -179,13 +179,13 @@ /obj/item/clothing/head/helmet/space/plasmaman/cargo name = "cargo plasma envirosuit helmet" - desc = "An plasmaman envirohelmet designed for cargo techs and quartermasters." + desc = "A plasmaman envirohelmet designed for cargo techs and quartermasters." icon_state = "cargo_envirohelm" item_state = "cargo_envirohelm" /obj/item/clothing/head/helmet/space/plasmaman/mining name = "mining plasma envirosuit helmet" - desc = "A khaki helmet given to plasmamen miners operating on lavaland." + desc = "A khaki helmet given to plasmaman miners operating on Lavaland." icon_state = "explorer_envirohelm" item_state = "explorer_envirohelm" visor_icon = "explorer_envisor" @@ -210,7 +210,7 @@ /obj/item/clothing/head/helmet/space/plasmaman/librarian name = "librarian's plasma envirosuit helmet" - desc = "A slight modification on a tradiational voidsuit helmet, this helmet was Nano-Trasen's first solution to the *logistical problems* that come with employing plasmamen. Despite their limitations, these helmets still see use by historian and old-styled plasmamen alike." + desc = "A slight modification on a traditional voidsuit helmet, this helmet was Nanotrasen's first solution to the *logistical problems* that come with employing plasmamen. Despite their limitations, these helmets still see use by historian and old-styled plasmamen alike." icon_state = "prototype_envirohelm" item_state = "prototype_envirohelm" actions_types = list(/datum/action/item_action/toggle_welding_screen/plasmaman) @@ -218,7 +218,7 @@ /obj/item/clothing/head/helmet/space/plasmaman/botany name = "botany plasma envirosuit helmet" - desc = "A green and blue envirohelmet designating it's wearer as a botanist. While not specially designed for it, it would protect against minor planet-related injuries." + desc = "A green and blue envirohelmet designating its wearer as a botanist. While not specially designed for it, it would protect against minor plant-related injuries." icon_state = "botany_envirohelm" item_state = "botany_envirohelm" @@ -230,14 +230,14 @@ /obj/item/clothing/head/helmet/space/plasmaman/mime name = "mime envirosuit helmet" - desc = "The make-up is painted on, it's a miracle it doesn't chip. It's not very colourful." + desc = "The makeup is painted on, it's a miracle it doesn't chip. It's not very colourful." icon_state = "mime_envirohelm" item_state = "mime_envirohelm" visor_icon = "mime_envisor" /obj/item/clothing/head/helmet/space/plasmaman/clown name = "clown envirosuit helmet" - desc = "The make-up is painted on, it's a miracle it doesn't chip. 'HONK!'" + desc = "The makeup is painted on, it's a miracle it doesn't chip. 'HONK!'" icon_state = "clown_envirohelm" item_state = "clown_envirohelm" visor_icon = "clown_envisor" @@ -259,3 +259,14 @@ desc = "A plasmaman envirohelm designed for the blueshield." icon_state = "bs_envirohelm" item_state = "bs_envirohelm" + +/obj/item/clothing/head/helmet/space/plasmaman/wizard + name = "wizard plasma envirosuit helmet" + desc = "A magical plasmaman containment helmet designed to spread chaos in safety and comfort." + icon_state = "wizard_envirohelm" + item_state = "wizard_envirohelm" + gas_transfer_coefficient = 0.01 + permeability_coefficient = 0.01 + armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 100, "acid" = 100) + resistance_flags = FIRE_PROOF | ACID_PROOF + magical = TRUE diff --git a/code/modules/clothing/spacesuits/rig/modules/computer.dm b/code/modules/clothing/spacesuits/rig/modules/computer.dm index 74af696e76e..749e12e8053 100644 --- a/code/modules/clothing/spacesuits/rig/modules/computer.dm +++ b/code/modules/clothing/spacesuits/rig/modules/computer.dm @@ -23,7 +23,7 @@ to_chat(usr, "Your module is not installed in a hardsuit.") return - module.holder.ui_interact(usr, nano_state = contained_state) + module.holder.ui_interact(usr, state = GLOB.contained_state) /obj/item/rig_module/ai_container @@ -139,7 +139,7 @@ if(!target) if(ai_card) if(istype(ai_card,/obj/item/aicard)) - ai_card.ui_interact(H, state = deep_inventory_state) + ai_card.ui_interact(H, state = GLOB.deep_inventory_state) else eject_ai(H) update_verb_holder() diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 3167e68ca6f..cd4ac697406 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -522,7 +522,7 @@ cell.use(cost*10) return 1 -/obj/item/rig/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state) +/obj/item/rig/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.inventory_state) if(!user) return @@ -532,7 +532,7 @@ ui.open() ui.set_auto_update(1) -/obj/item/rig/ui_data(mob/user, ui_key = "main", datum/topic_state/state = inventory_state) +/obj/item/rig/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.inventory_state) var/data[0] data["primarysystem"] = null @@ -798,7 +798,7 @@ to_chat(wearer, "You are unable to deploy \the [piece] as \the [check_slot] [check_slot.gender == PLURAL ? "are" : "is"] in the way.") return use_obj.forceMove(wearer) - if(!wearer.equip_to_slot_if_possible(use_obj, equip_to, 0, 1)) + if(!wearer.equip_to_slot_if_possible(use_obj, equip_to, FALSE, TRUE)) use_obj.forceMove(src) else if(wearer) @@ -982,7 +982,7 @@ return 0 if(malfunctioning) - direction = pick(cardinal) + direction = pick(GLOB.cardinal) // Inside an object, tell it we moved. if(isobj(wearer.loc) || ismob(wearer.loc)) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index e9f78936cf7..6c4ace8c993 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -20,7 +20,6 @@ icon_state = "armor" item_state = "armor" blood_overlay_type = "armor" - flags_size = ONESIZEFITSALL dog_fashion = /datum/dog_fashion/back /obj/item/clothing/suit/armor/vest/jacket @@ -36,7 +35,6 @@ icon_state = "armor-combat" item_state = "bulletproof" blood_overlay_type = "armor" - flags_size = ONESIZEFITSALL /obj/item/clothing/suit/armor/vest/security name = "security armor" @@ -255,7 +253,6 @@ icon_state = "detective-armor" item_state = "armor" blood_overlay_type = "armor" - flags_size = ONESIZEFITSALL allowed = list(/obj/item/tank/emergency_oxygen,/obj/item/reagent_containers/spray/pepper,/obj/item/flashlight,/obj/item/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/storage/fancy/cigarettes,/obj/item/lighter,/obj/item/detective_scanner,/obj/item/taperecorder) resistance_flags = FLAMMABLE dog_fashion = null diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index 1b7100c02bc..eff7a9448ac 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -27,7 +27,6 @@ gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 flags = THICKMATERIAL - flags_size = ONESIZEFITSALL body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS slowdown = 1 allowed = list(/obj/item/tank/emergency_oxygen,/obj/item/pen,/obj/item/flashlight/pen) diff --git a/code/modules/clothing/suits/hood.dm b/code/modules/clothing/suits/hood.dm index 83f0fcfc211..be05ced4fd8 100644 --- a/code/modules/clothing/suits/hood.dm +++ b/code/modules/clothing/suits/hood.dm @@ -59,7 +59,7 @@ if(H.head) to_chat(H,"You're already wearing something on your head!") return - else if(H.equip_to_slot_if_possible(hood, slot_head, 0, 0, 1)) + else if(H.equip_to_slot_if_possible(hood, slot_head, FALSE, FALSE)) suit_adjusted = 1 icon_state = "[initial(icon_state)]_hood" H.update_inv_wear_suit() diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index bcb71edf356..a7bd3fb2627 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -7,7 +7,7 @@ desc = "A hazard vest used in the recovery of bodies." icon_state = "paramedic-vest" item_state = "paramedic-vest" - allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/syringe, \ + allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/applicator, /obj/item/reagent_containers/syringe, /obj/item/healthanalyzer, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/emergency_oxygen,/obj/item/rad_laser) armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 10, fire = 50, acid = 50) @@ -21,7 +21,7 @@ desc = "A vest often worn by doctors caring for inmates." icon_state = "brigphysician-vest" item_state = "brigphysician-vest" - allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/syringe, \ + allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/applicator, /obj/item/reagent_containers/syringe, /obj/item/healthanalyzer, /obj/item/flashlight, \ /obj/item/radio, /obj/item/tank/emergency_oxygen,/obj/item/rad_laser) armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 0, fire = 50, acid = 50) @@ -52,7 +52,6 @@ item_state = "bio_suit" body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS flags_inv = HIDEJUMPSUIT - flags_size = ONESIZEFITSALL allowed = list(/obj/item/disk, /obj/item/stamp, /obj/item/reagent_containers/food/drinks/flask, /obj/item/melee, /obj/item/storage/lockbox/medal, /obj/item/flash, /obj/item/storage/box/matches, /obj/item/lighter, /obj/item/clothing/mask/cigarette, /obj/item/storage/fancy/cigarettes, /obj/item/tank/emergency_oxygen) sprite_sheets = list( @@ -184,7 +183,6 @@ armor = list("melee" = 25, "bullet" = 10, "laser" = 25, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 45) cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_size = ONESIZEFITSALL sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' @@ -221,7 +219,6 @@ armor = list(melee = 25, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 45) cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS - flags_size = ONESIZEFITSALL sprite_sheets = list( "Vox" = 'icons/mob/species/vox/suit.dmi' @@ -341,7 +338,7 @@ icon_state = "fr_jacket_open" item_state = "fr_jacket_open" blood_overlay_type = "armor" - allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/syringe, \ + allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/applicator, /obj/item/reagent_containers/syringe, /obj/item/healthanalyzer, /obj/item/flashlight, /obj/item/radio, /obj/item/tank/emergency_oxygen,/obj/item/rad_laser) ignore_suitadjust = 0 suit_adjusted = 1 @@ -381,5 +378,5 @@ desc = "A tweed mantle, worn by the Research Director. Smells like science." icon_state = "rdmantle" item_state = "rdmantle" - allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/food/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/rad_laser) + allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/applicator, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/food/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/rad_laser) armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 50, rad = 0, fire = 50, acid = 50) diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm index 03df1bd74d8..5281a32676e 100644 --- a/code/modules/clothing/suits/labcoat.dm +++ b/code/modules/clothing/suits/labcoat.dm @@ -7,7 +7,7 @@ suit_adjusted = 1 blood_overlay_type = "coat" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - allowed = list(/obj/item/analyzer,/obj/item/stack/medical,/obj/item/dnainjector,/obj/item/reagent_containers/dropper,/obj/item/reagent_containers/syringe,/obj/item/reagent_containers/hypospray,/obj/item/healthanalyzer,/obj/item/flashlight/pen,/obj/item/reagent_containers/glass/bottle,/obj/item/reagent_containers/glass/beaker,/obj/item/reagent_containers/food/pill,/obj/item/storage/pill_bottle,/obj/item/paper,/obj/item/rad_laser) + allowed = list(/obj/item/analyzer,/obj/item/stack/medical,/obj/item/dnainjector,/obj/item/reagent_containers/dropper,/obj/item/reagent_containers/syringe,/obj/item/reagent_containers/hypospray,/obj/item/reagent_containers/applicator,/obj/item/healthanalyzer,/obj/item/flashlight/pen,/obj/item/reagent_containers/glass/bottle,/obj/item/reagent_containers/glass/beaker,/obj/item/reagent_containers/food/pill,/obj/item/storage/pill_bottle,/obj/item/paper,/obj/item/rad_laser) armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 50, "acid" = 50) species_exception = list(/datum/species/golem) sprite_sheets = list( diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 1a2cdbd31a2..7e9e698d185 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -383,7 +383,7 @@ name = "security winter coat" icon_state = "wintercoat_sec" item_state = "coatsecurity" - armor = list("melee" = 25, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 45) + armor = list("melee" = 15, "bullet" = 10, "laser" = 15, "energy" = 5, "bomb" = 15, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) allowed = list(/obj/item/gun/energy, /obj/item/reagent_containers/spray/pepper, /obj/item/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/flashlight/seclite, /obj/item/melee/classic_baton/telescopic) hoodtype = /obj/item/clothing/head/hooded/winterhood/security @@ -394,7 +394,7 @@ name = "medical winter coat" icon_state = "wintercoat_med" item_state = "coatmedical" - allowed = list(/obj/item/analyzer, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic) + allowed = list(/obj/item/analyzer, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/applicator,/obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic) armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 0, "acid" = 45) hoodtype = /obj/item/clothing/head/hooded/winterhood/medical @@ -405,7 +405,7 @@ name = "science winter coat" icon_state = "wintercoat_sci" item_state = "coatscience" - allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic) + allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/applicator,/obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic) armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 0, rad = 0, fire = 0, acid = 0) hoodtype = /obj/item/clothing/head/hooded/winterhood/science @@ -541,7 +541,6 @@ item_state = "straight_jacket" body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL - flags_size = ONESIZEFITSALL strip_delay = 60 breakouttime = 3000 @@ -690,7 +689,6 @@ item_state = "xenos_helm" body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT - flags_size = ONESIZEFITSALL //swimsuit /obj/item/clothing/under/swimsuit/ @@ -733,7 +731,6 @@ w_class = WEIGHT_CLASS_BULKY gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 - flags_size = ONESIZEFITSALL body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS allowed = list(/obj/item/tank/emergency_oxygen,/obj/item/pen,/obj/item/flashlight/pen) armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20, fire = 50, acid = 50) @@ -780,7 +777,6 @@ max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT strip_delay = 60 put_on_delay = 40 - flags_size = ONESIZEFITSALL armor = list(melee = 25, bullet = 15, laser = 25, energy = 10, bomb = 25, bio = 0, rad = 0, fire = 50, acid = 50) //End of inheritance from Security armour. @@ -958,7 +954,8 @@ if(linked_staff.faith >= 100) //if the linked staff is fully recharged, do nothing return - if(!linked_staff in range(3, get_turf(src))) //staff won't charge at range (to prevent it from being handed off / stolen and used) + // Do not allow the staff to recharge if it's more than 3 tiles away from the robe. If get_dist returns 0, the robe and the staff in the same tile. + if(!(get_dist(H, linked_staff) <= 3)) if(prob(10)) //10% chance per process should avoid being too spammy, can tweak if it ends up still being too frequent. to_chat(H, "Your staff is unable to charge at this range. Get closer!") return diff --git a/code/modules/clothing/suits/storage.dm b/code/modules/clothing/suits/storage.dm index 0c77183b578..9a675742b5e 100644 --- a/code/modules/clothing/suits/storage.dm +++ b/code/modules/clothing/suits/storage.dm @@ -25,8 +25,8 @@ return pockets.attackby(W, user, params) /obj/item/clothing/suit/storage/emp_act(severity) - pockets.emp_act(severity) ..() + pockets.emp_act(severity) /obj/item/clothing/suit/storage/hear_talk(mob/M, list/message_pieces) pockets.hear_talk(M, message_pieces) diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index c329d8a0033..7e1a993fca4 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -68,7 +68,7 @@ if(H.head) to_chat(H, "You're already wearing something on your head!") return - else if(H.equip_to_slot_if_possible(helmet, slot_head, 0 ,0, 1)) + else if(H.equip_to_slot_if_possible(helmet, slot_head, FALSE, FALSE)) to_chat(H, "You engage the helmet on the hardsuit.") suittoggled = TRUE H.update_inv_wear_suit() diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index d02c9b40105..0c3a0e92310 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -24,7 +24,6 @@ icon_state = "blackwizard" dog_fashion = null - /obj/item/clothing/head/wizard/clown name = "purple wizard hat" desc = "Strange-looking purple hat-wear that most certainly belongs to a real magic user." @@ -32,6 +31,18 @@ item_state = "wizhatclown" // cheating dog_fashion = null +/obj/item/clothing/head/wizard/mime + name = "magical beret" + desc = "A magical red beret." + icon_state = "wizhatmime" + item_state = "wizhatmime" + dog_fashion = null + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/head.dmi', + "Drask" = 'icons/mob/species/drask/head.dmi', + "Grey" = 'icons/mob/species/grey/head.dmi' + ) + /obj/item/clothing/head/wizard/fake name = "wizard hat" desc = "It has WIZZARD written across it in sequins. Comes with a cool beard." @@ -91,11 +102,22 @@ item_state = "blackwizrobe" /obj/item/clothing/suit/wizrobe/clown - name = "Clown Robe" + name = "clown robe" desc = "A set of armoured robes that seem to radiate a dark power. That, and bad fashion decisions." icon_state = "wizzclown" item_state = "wizzclown" +/obj/item/clothing/suit/wizrobe/mime + name = "mime robe" + desc = "Red, black, and white robes. There is not much else to say about them." + icon_state = "wizzmime" + item_state = "wizzmime" + sprite_sheets = list( + "Vox" = 'icons/mob/species/vox/suit.dmi', + "Drask" = 'icons/mob/species/drask/suit.dmi', + "Grey" = 'icons/mob/species/grey/suit.dmi' + ) + /obj/item/clothing/suit/wizrobe/marisa name = "Witch Robe" desc = "Magic is all about the spell power, ZE!" @@ -156,7 +178,7 @@ /obj/item/clothing/suit/space/hardsuit/shielded/wizard name = "battlemage armour" - desc = "Not all wizards are afraid of getting up close and personal." + desc = "Not all wizards are afraid of getting up close and personal. Not spaceproof despite its appearance." icon_state = "hardsuit-wiz" item_state = "wiz_hardsuit" recharge_rate = 0 @@ -172,6 +194,15 @@ resistance_flags = FIRE_PROOF | ACID_PROOF magical = TRUE +/obj/item/clothing/suit/space/hardsuit/shielded/wizard/arch + desc = "For the arch wizard in need of additional protection." + recharge_rate = 1 + recharge_cooldown = 0 + max_charges = 15 + min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT + max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT + helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard/arch + /obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard name = "battlemage helmet" desc = "A suitably impressive helmet." @@ -188,6 +219,11 @@ /obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard/attack_self(mob/user) return +/obj/item/clothing/head/helmet/space/hardsuit/shielded/wizard/arch + desc = "A truly protective helmet." + min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT + max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT + /obj/item/wizard_armour_charge name = "battlemage shield charges" desc = "A powerful rune that will increase the number of hits a suit of battlemage armour can take before failing.." diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm index 16eb1cd476a..727aba06b37 100644 --- a/code/modules/clothing/under/accessories/storage.dm +++ b/code/modules/clothing/under/accessories/storage.dm @@ -37,8 +37,8 @@ return hold.attackby(W, user, params) /obj/item/clothing/accessory/storage/emp_act(severity) - hold.emp_act(severity) ..() + hold.emp_act(severity) /obj/item/clothing/accessory/storage/hear_talk(mob/M, list/message_pieces, verb) hold.hear_talk(M, message_pieces, verb) diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm index 6b39191eb13..b57166d4909 100644 --- a/code/modules/clothing/under/color.dm +++ b/code/modules/clothing/under/color.dm @@ -16,7 +16,6 @@ icon_state = "black" item_state = "bl_suit" item_color = "black" - flags_size = ONESIZEFITSALL resistance_flags = NONE /obj/item/clothing/under/color/blackf @@ -31,18 +30,15 @@ icon_state = "blue" item_state = "b_suit" item_color = "blue" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/blue/dodgeball flags = NODROP - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/green name = "green jumpsuit" icon_state = "green" item_state = "g_suit" item_color = "green" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/grey name = "grey jumpsuit" @@ -50,11 +46,9 @@ icon_state = "grey" item_state = "gy_suit" item_color = "grey" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/grey/greytide flags = NODROP - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/grey/glorf name = "ancient jumpsuit" @@ -70,7 +64,6 @@ icon_state = "orange" item_state = "o_suit" item_color = "orange" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/orange/prison name = "orange jumpsuit" @@ -80,7 +73,6 @@ item_color = "orange" has_sensor = 2 sensor_mode = 3 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/pink name = "pink jumpsuit" @@ -88,32 +80,27 @@ icon_state = "pink" item_state = "p_suit" item_color = "pink" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/red name = "red jumpsuit" icon_state = "red" item_state = "r_suit" item_color = "red" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/red/dodgeball flags = NODROP - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/white name = "white jumpsuit" icon_state = "white" item_state = "w_suit" item_color = "white" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/yellow name = "yellow jumpsuit" icon_state = "yellow" item_state = "y_suit" item_color = "yellow" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/psyche name = "psychedelic jumpsuit" @@ -134,7 +121,6 @@ name = "aqua jumpsuit" icon_state = "aqua" item_color = "aqua" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/purple name = "purple jumpsuit" @@ -161,7 +147,6 @@ name = "light brown jumpsuit" icon_state = "lightbrown" item_color = "lightbrown" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/brown name = "brown jumpsuit" @@ -177,7 +162,6 @@ name = "dark blue jumpsuit" icon_state = "darkblue" item_color = "darkblue" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/lightred name = "light red jumpsuit" @@ -188,7 +172,6 @@ name = "dark red jumpsuit" icon_state = "darkred" item_color = "darkred" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/red/jersey name = "red team jersey" @@ -196,7 +179,6 @@ icon_state = "redjersey" item_state = "r_suit" item_color = "redjersey" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/color/blue/jersey name = "blue team jersey" @@ -204,4 +186,3 @@ icon_state = "bluejersey" item_state = "b_suit" item_color = "bluejersey" - flags_size = ONESIZEFITSALL diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm index 3850ce559df..faa9039c8c4 100644 --- a/code/modules/clothing/under/jobs/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian.dm @@ -6,7 +6,6 @@ icon_state = "ba_suit" item_state = "ba_suit" item_color = "ba_suit" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/captain //Alright, technically not a 'civilian' but its better then giving a .dm file for a single define. desc = "It's a blue jumpsuit with some gold markings denoting the rank of \"Captain\"." @@ -14,7 +13,6 @@ icon_state = "captain" item_state = "caparmor" item_color = "captain" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/cargo name = "quartermaster's jumpsuit" @@ -22,7 +20,6 @@ icon_state = "qm" item_state = "lb_suit" item_color = "qm" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/cargo/skirt name = "quartermaster's jumpskirt" @@ -30,7 +27,6 @@ icon_state = "qmf" item_color = "qmf" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - flags_size = null /obj/item/clothing/under/rank/cargotech name = "cargo technician's jumpsuit" @@ -38,14 +34,12 @@ icon_state = "cargotech" item_state = "lb_suit" item_color = "cargo" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/cargotech/skirt name = "cargo technician's jumpskirt" desc = "Skirrrrrts! They're comfy and easy to wear!" icon_state = "cargof" item_color = "cargof" - flags_size = null /obj/item/clothing/under/rank/chaplain desc = "It's a black jumpsuit, often worn by religious folk." @@ -53,14 +47,12 @@ icon_state = "chaplain" item_state = "bl_suit" item_color = "chapblack" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/chef desc = "It's an apron which is given only to the most hardcore chefs in space." name = "chef's uniform" icon_state = "chef" item_color = "chef" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/clown name = "clown suit" @@ -68,7 +60,6 @@ icon_state = "clown" item_state = "clown" item_color = "clown" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/clown/Initialize() . = ..() @@ -78,7 +69,7 @@ if(ishuman(loc)) var/mob/living/carbon/human/H = loc if(H.mind && H.mind.assigned_role == "Clown") - score_clownabuse++ + GLOB.score_clownabuse++ return ..() /obj/item/clothing/under/rank/clown/sexy @@ -97,7 +88,6 @@ icon_state = "hop" item_state = "b_suit" item_color = "hop" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/head_of_personnel_whimsy desc = "A blue jacket and red tie, with matching red cuffs! Snazzy. Wearing this makes you feel more important than your job title does." @@ -114,7 +104,6 @@ item_state = "g_suit" item_color = "hydroponics" permeability_coefficient = 0.50 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/internalaffairs desc = "The plain, professional attire of an Internal Affairs Agent. The collar is immaculately starched." @@ -122,7 +111,6 @@ icon_state = "internalaffairs" item_state = "internalaffairs" item_color = "internalaffairs" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/ntrep desc = "A well-ironed dress shirt and matching set of black pants." @@ -130,7 +118,6 @@ icon_state = "internalaffairs" item_state = "internalaffairs" item_color = "internalaffairs" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/ntrep/skirt desc = "A silky smooth black and gold representative uniform with blue markings." @@ -138,7 +125,6 @@ icon_state = "ntrepf" item_state = "ntrepf" item_color = "ntrepf" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/janitor desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." @@ -146,13 +132,11 @@ icon_state = "janitor" item_color = "janitor" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/lawyer desc = "Slick threads." name = "Lawyer suit" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/lawyer/black icon_state = "lawyer_black" @@ -201,7 +185,6 @@ icon_state = "red_suit" item_state = "red_suit" item_color = "red_suit" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/mime name = "mime's outfit" @@ -209,7 +192,6 @@ icon_state = "mime" item_state = "mime" item_color = "mime" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/mime/nodrop flags = NODROP @@ -220,7 +202,6 @@ icon_state = "miner" item_state = "miner" item_color = "miner" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/miner/lavaland desc = "A green uniform for operating in hazardous environments." diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index bdda81ad03d..aa70fc85db6 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -6,7 +6,6 @@ item_state = "chief" item_color = "chief" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 80, "acid" = 40) - flags_size = ONESIZEFITSALL resistance_flags = NONE /obj/item/clothing/under/rank/chief_engineer/skirt @@ -14,7 +13,6 @@ name = "chief engineer's jumpskirt" icon_state = "chieff" item_color = "chieff" - flags_size = null body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS /obj/item/clothing/under/rank/atmospheric_technician @@ -23,7 +21,6 @@ icon_state = "atmos" item_state = "atmos_suit" item_color = "atmos" - flags_size = ONESIZEFITSALL resistance_flags = NONE /obj/item/clothing/under/rank/atmospheric_technician/skirt @@ -31,7 +28,6 @@ name = "atmospheric technician's jumpskirt" icon_state = "atmosf" item_color = "atmosf" - flags_size = null body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS /obj/item/clothing/under/rank/engineer @@ -41,7 +37,6 @@ item_state = "engi_suit" item_color = "engine" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 60, "acid" = 20) - flags_size = ONESIZEFITSALL resistance_flags = NONE @@ -50,7 +45,6 @@ name = "engineer's jumpskirt" icon_state = "enginef" item_color = "enginef" - flags_size = null body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS /obj/item/clothing/under/rank/roboticist @@ -59,7 +53,6 @@ icon_state = "robotics" item_state = "robotics" item_color = "robotics" - flags_size = ONESIZEFITSALL resistance_flags = NONE /obj/item/clothing/under/rank/roboticist/skirt @@ -67,7 +60,6 @@ name = "roboticist's jumpskirt" icon_state = "roboticsf" item_color = "roboticsf" - flags_size = null /obj/item/clothing/under/rank/mechanic desc = "It's a pair of overalls worn by mechanics." diff --git a/code/modules/clothing/under/jobs/medsci.dm b/code/modules/clothing/under/jobs/medsci.dm index d3fcad16680..d8847741db3 100644 --- a/code/modules/clothing/under/jobs/medsci.dm +++ b/code/modules/clothing/under/jobs/medsci.dm @@ -8,7 +8,6 @@ item_state = "g_suit" item_color = "director" armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 35) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/scientist desc = "It's made of a special fiber that provides minor protection against biohazards. It has markings that denote the wearer as a scientist." @@ -18,14 +17,12 @@ item_color = "toxinswhite" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/scientist/skirt name = "scientist's jumpskirt" icon_state = "sciencewhitef" item_color = "sciencewhitef" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - flags_size = null /obj/item/clothing/under/rank/chemist desc = "It's made of a special fiber that gives special protection against biohazards. It has a chemist rank stripe on it." @@ -35,14 +32,12 @@ item_color = "chemistrywhite" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 65) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/chemist/skirt name = "chemist's jumpskirt" icon_state = "chemistrywhitef" item_color = "chemistrywhitef" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - flags_size = null /* * Medical @@ -55,7 +50,6 @@ item_color = "cmo" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/chief_medical_officer/skirt desc = "It's a jumpskirt worn by those with the experience to be \"Chief Medical Officer\". It provides minor biological protection." @@ -63,7 +57,6 @@ icon_state = "cmof" item_color = "cmof" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - flags_size = null /obj/item/clothing/under/rank/geneticist desc = "It's made of a special fiber that gives special protection against biohazards. It has a genetics rank stripe on it." @@ -73,14 +66,12 @@ item_color = "geneticswhite" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/geneticist/skirt name = "geneticist's jumpskirt" icon_state = "geneticswhitef" item_color = "geneticswhitef" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - flags_size = null /obj/item/clothing/under/rank/virologist desc = "It's made of a special fiber that gives special protection against biohazards. It has a virologist rank stripe on it." @@ -90,14 +81,12 @@ item_color = "virologywhite" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/virologist/skirt name = "virologist's jumpskirt" icon_state = "virologywhitef" item_color = "virologywhitef" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - flags_size = null /obj/item/clothing/under/rank/nursesuit desc = "It's a jumpsuit commonly worn by nursing staff in the medical department." @@ -107,7 +96,6 @@ item_color = "nursesuit" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/nurse desc = "A dress commonly worn by the nursing staff in the medical department." @@ -117,7 +105,6 @@ item_color = "nurse" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/orderly desc = "A white suit to be worn by orderly people who love orderly things." @@ -127,7 +114,6 @@ item_color = "orderly" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/medical desc = "It's made of a special fiber that provides minor protection against biohazards. It has a cross on the chest denoting that the wearer is trained medical personnel." @@ -137,42 +123,36 @@ item_color = "medical" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/medical/skirt name = "medical doctor's jumpskirt" icon_state = "medicalf" item_color = "medicalf" body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS - flags_size = null /obj/item/clothing/under/rank/medical/blue name = "medical scrubs" desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in baby blue." icon_state = "scrubsblue" item_color = "scrubsblue" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/medical/green name = "medical scrubs" desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in dark green." icon_state = "scrubsgreen" item_color = "scrubsgreen" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/medical/purple name = "medical scrubs" desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in deep purple." icon_state = "scrubspurple" item_color = "scrubspurple" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/medical/mortician name = "coroner's scrubs" desc = "It's made of a special fiber that provides minor protection against biohazards. This one is as dark as an emo's poetry." icon_state = "scrubsblack" item_color = "scrubsblack" - flags_size = ONESIZEFITSALL //paramedic /obj/item/clothing/under/rank/medical/paramedic @@ -183,7 +163,6 @@ item_color = "paramedic" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 10, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/psych desc = "A basic white jumpsuit. It has turqouise markings that denote the wearer as a psychiatrist." @@ -191,7 +170,6 @@ icon_state = "psych" item_state = "w_suit" item_color = "psych" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/psych/turtleneck desc = "A turqouise turtleneck and a pair of dark blue slacks, belonging to a psychologist." @@ -199,7 +177,6 @@ icon_state = "psychturtle" item_state = "b_suit" item_color = "psychturtle" - flags_size = ONESIZEFITSALL /* @@ -213,7 +190,6 @@ item_color = "genetics_new" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/chemist_new desc = "It's made of a special fiber which provides minor protection against biohazards." @@ -223,7 +199,6 @@ item_color = "chemist_new" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 65) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/scientist_new desc = "Made of a special fiber that gives special protection against biohazards and small explosions." @@ -233,7 +208,6 @@ item_color = "scientist_new" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/virologist_new desc = "Made of a special fiber that gives increased protection against biohazards." @@ -243,4 +217,3 @@ item_color = "virologist_new" permeability_coefficient = 0.50 armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - flags_size = ONESIZEFITSALL diff --git a/code/modules/clothing/under/jobs/plasmamen/antags.dm b/code/modules/clothing/under/jobs/plasmamen/antags.dm new file mode 100644 index 00000000000..c1ec8062825 --- /dev/null +++ b/code/modules/clothing/under/jobs/plasmamen/antags.dm @@ -0,0 +1,6 @@ +/obj/item/clothing/under/plasmaman/wizard + name = "wizard plasma envirosuit" + desc = "An envirosuit for plasmamen designed by the Wizard Federation. Still not spaceworthy..." + icon_state = "wizard_envirosuit" + item_state = "wizard_envirosuit" + item_color = "wizard_envirosuit" diff --git a/code/modules/clothing/under/jobs/plasmamen/civilian_service.dm b/code/modules/clothing/under/jobs/plasmamen/civilian_service.dm index 0ef8df4d57b..ea2f0db6812 100644 --- a/code/modules/clothing/under/jobs/plasmamen/civilian_service.dm +++ b/code/modules/clothing/under/jobs/plasmamen/civilian_service.dm @@ -1,13 +1,13 @@ /obj/item/clothing/under/plasmaman/cargo name = "cargo plasma envirosuit" - desc = "A joint envirosuit used by plasmamen quartermasters and cargo techs alike, due to the logistical problems of differenciating the two with the length of their pant legs." + desc = "An envirosuit used by plasmaman quartermasters and cargo techs alike, due to the logistical problems of differentiating the two by the length of their pant legs." icon_state = "cargo_envirosuit" item_state = "cargo_envirosuit" item_color = "cargo_envirosuit" /obj/item/clothing/under/plasmaman/mining name = "mining plasma envirosuit" - desc = "An air-tight khaki suit designed for operations on lavaland by plasmamen." + desc = "An airtight khaki suit designed for operations on Lavaland by plasmamen." icon_state = "explorer_envirosuit" item_state = "explorer_envirosuit" item_color = "explorer_envirosuit" @@ -15,14 +15,14 @@ /obj/item/clothing/under/plasmaman/chef name = "chef's plasma envirosuit" - desc = "A white plasmaman envirosuit designed for cullinary practices. One might question why a member of a species that doesn't need to eat would become a chef." + desc = "A white plasmaman envirosuit designed for culinary practices. One might question why a member of a species that doesn't need to eat would become a chef." icon_state = "chef_envirosuit" item_state = "chef_envirosuit" item_color = "chef_envirosuit" /obj/item/clothing/under/plasmaman/enviroslacks name = "enviroslacks" - desc = "The pet project of a particularly posh plasmaman, this custom suit was quickly appropriated by Nano-Trasen for it's detectives, lawyers, and bar-tenders alike." + desc = "The pet project of a particularly posh plasmaman, this custom suit was quickly appropriated by Nanotrasen for its detectives, lawyers, and bartenders alike." icon_state = "enviroslacks" item_state = "enviroslacks" item_color = "enviroslacks" @@ -36,14 +36,14 @@ /obj/item/clothing/under/plasmaman/librarian name = "librarian's plasma envirosuit" - desc = "Made out of a modified voidsuit, this suit was Nano-Trasen's first solution to the *logistical problems* that come with employing plasmamen. Due to the modifications, the suit is no longer space-worthy. Despite their limitations, these suits are still in used by historian and old-styled plasmamen alike." + desc = "Made out of a modified voidsuit, this suit was Nanotrasen's first solution to the *logistical problems* that come with employing plasmamen. Due to the modifications, the suit is no longer space-worthy. Despite their limitations, these suits are still in used by historian and old-styled plasmamen alike." icon_state = "prototype_envirosuit" item_state = "prototype_envirosuit" item_color = "prototype_envirosuit" /obj/item/clothing/under/plasmaman/janitor name = "janitor's plasma envirosuit" - desc = "A grey and purple envirosuit designated for plasmamen janitors." + desc = "A grey and purple envirosuit designated for plasmaman janitors." icon_state = "janitor_envirosuit" item_state = "janitor_envirosuit" item_color = "janitor_envirosuit" diff --git a/code/modules/clothing/under/jobs/plasmamen/engineering.dm b/code/modules/clothing/under/jobs/plasmamen/engineering.dm index 35f99558c1c..02a71afcaf6 100644 --- a/code/modules/clothing/under/jobs/plasmamen/engineering.dm +++ b/code/modules/clothing/under/jobs/plasmamen/engineering.dm @@ -1,6 +1,6 @@ /obj/item/clothing/under/plasmaman/engineering name = "engineering plasma envirosuit" - desc = "An air-tight suit designed to be used by plasmamen exployed as engineers, the usual purple stripes being replaced by engineer's orange. It protects the user from fire and acid damage." + desc = "An airtight suit designed to be used by plasmamen employed as engineers, the usual purple stripes being replaced by engineering's orange. It protects the user from fire and acid damage." icon_state = "engineer_envirosuit" item_state = "engineer_envirosuit" item_color = "engineer_envirosuit" @@ -8,14 +8,14 @@ /obj/item/clothing/under/plasmaman/engineering/ce name = "chief engineer plasma envirosuit" - desc = "An air-tight suit designed to be used by plasmamen exployed as the chief engineer" + desc = "An airtight suit designed to be used by plasmamen employed as the chief engineer." icon_state = "ce_envirosuit" item_state = "ce_envirosuit" item_color = "ce_envirosuit" /obj/item/clothing/under/plasmaman/atmospherics name = "atmospherics plasma envirosuit" - desc = "An air-tight suit designed to be used by plasmamen exployed as atmos technicians, the usual purple stripes being replaced by atmos's blue." + desc = "An airtight suit designed to be used by plasmamen employed as atmos technicians, the usual purple stripes being replaced by atmos' blue." icon_state = "atmos_envirosuit" item_state = "atmos_envirosuit" item_color = "atmos_envirosuit" diff --git a/code/modules/clothing/under/jobs/plasmamen/medsci.dm b/code/modules/clothing/under/jobs/plasmamen/medsci.dm index 69e14c0e878..531bc3fb124 100644 --- a/code/modules/clothing/under/jobs/plasmamen/medsci.dm +++ b/code/modules/clothing/under/jobs/plasmamen/medsci.dm @@ -20,7 +20,7 @@ item_color = "scientist_envirosuit" /obj/item/clothing/under/plasmaman/rd - name = "science plasma envirosuit" + name = "rd plasma envirosuit" desc = "A plasmaman envirosuit designed for the research director." icon_state = "rd_envirosuit" item_state = "rd_envirosuit" diff --git a/code/modules/clothing/under/jobs/plasmamen/security.dm b/code/modules/clothing/under/jobs/plasmamen/security.dm index 7060037bd90..427969307f4 100644 --- a/code/modules/clothing/under/jobs/plasmamen/security.dm +++ b/code/modules/clothing/under/jobs/plasmamen/security.dm @@ -8,7 +8,7 @@ /obj/item/clothing/under/plasmaman/security/warden name = "warden plasma envirosuit" - desc = "A plasmaman containment suit designed for the warden, white stripes being added to differeciate them from other members of security." + desc = "A plasmaman containment suit designed for the warden, white stripes being added to differentiate them from other members of security." icon_state = "warden_envirosuit" item_state = "warden_envirosuit" item_color = "warden_envirosuit" diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm index 2602c46d01d..0086ba96ef8 100644 --- a/code/modules/clothing/under/jobs/security.dm +++ b/code/modules/clothing/under/jobs/security.dm @@ -16,7 +16,6 @@ item_state = "r_suit" item_color = "warden" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) - flags_size = ONESIZEFITSALL strip_delay = 50 /obj/item/clothing/under/rank/warden/skirt @@ -25,7 +24,6 @@ icon_state = "wardenf" item_state = "r_suit" item_color = "wardenf" - flags_size = null /obj/item/clothing/under/rank/security name = "security officer's jumpsuit" @@ -34,7 +32,6 @@ item_state = "r_suit" item_color = "secred" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) - flags_size = ONESIZEFITSALL strip_delay = 50 /obj/item/clothing/under/rank/security/skirt @@ -43,7 +40,6 @@ icon_state = "secredf" item_state = "r_suit" item_color = "secredf" - flags_size = null /obj/item/clothing/under/rank/dispatch name = "dispatcher's uniform" @@ -52,7 +48,6 @@ item_state = "dispatch" item_color = "dispatch" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/security2 name = "security officer's uniform" @@ -61,7 +56,6 @@ item_state = "r_suit" item_color = "redshirt2" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/security/corp icon_state = "sec_corporate" @@ -83,7 +77,6 @@ item_state = "det" item_color = "detective" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) - flags_size = ONESIZEFITSALL strip_delay = 50 sprite_sheets = list( @@ -100,7 +93,6 @@ item_state = "r_suit" item_color = "hosred" armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) - flags_size = ONESIZEFITSALL strip_delay = 60 /obj/item/clothing/under/rank/head_of_security/skirt @@ -109,7 +101,6 @@ icon_state = "hosredf" item_state = "r_suit" item_color = "hosredf" - flags_size = null /obj/item/clothing/under/rank/head_of_security/corp icon_state = "hos_corporate" @@ -123,7 +114,6 @@ icon_state = "jensen" item_state = "jensen" item_color = "jensen" - flags_size = ONESIZEFITSALL //Paradise Station @@ -180,7 +170,6 @@ item_color = "brig_phys" permeability_coefficient = 0.50 armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 10, rad = 0, fire = 30, acid = 30) - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/security/brigphys/skirt desc = "A skirted Brig Physician uniform. It has both security and medical protection." @@ -189,7 +178,6 @@ item_state = "brig_physf" item_color = "brig_physf" permeability_coefficient = 0.50 - flags_size = ONESIZEFITSALL //Pod Pilot /obj/item/clothing/under/rank/security/pod_pilot diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 22a1d25ba22..a9b4eab329e 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -102,7 +102,6 @@ item_state = "navy_gold" item_color = "navy_gold" displays_id = 0 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/centcom/captain desc = "Gold trim on space-black cloth, this uniform displays the rank of \"Captain\" and bears \"N.A.S. Trurl \" on the left shoulder. Worn exclusively by officers of the Nanotrasen Navy. It's got exotic materials for protection." @@ -111,7 +110,6 @@ item_state = "navy_gold" item_color = "navy_gold" displays_id = 0 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/centcom/blueshield desc = "Gold trim on space-black cloth, this uniform bears \"Close Protection\" on the left shoulder." @@ -120,7 +118,6 @@ item_state = "g_suit" item_color = "officer" displays_id = 0 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/centcom/representative desc = "Gold trim on space-black cloth, this uniform bears \"N.S.S. Cyberiad\" on the left shoulder." @@ -129,7 +126,6 @@ item_state = "g_suit" item_color = "officer" displays_id = 0 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/centcom/representative/New() ..() @@ -142,7 +138,6 @@ item_state = "g_suit" item_color = "officer" displays_id = 0 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/rank/centcom/magistrate/New() ..() @@ -272,7 +267,6 @@ icon_state = "red_suit" item_state = "r_suit" item_color = "red_suit" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/suit_jacket/navy name = "navy suit" @@ -751,7 +745,6 @@ righthand_file = 'icons/goonstation/mob/inhands/clothing_righthand.dmi' flags = NODROP resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - flags_size = ONESIZEFITSALL has_sensor = 0 // HUNKE /obj/item/clothing/under/victdress @@ -809,7 +802,6 @@ icon_state = "hawaiianred" item_state = "hawaiianred" item_color = "hawaiianred" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/pinkhawaiianshirt name = "pink hawaiian shirt" @@ -817,7 +809,6 @@ icon_state = "hawaiianpink" item_state = "hawaiianpink" item_color = "hawaiianpink" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/orangehawaiianshirt name = "orange hawaiian shirt" @@ -825,7 +816,6 @@ icon_state = "hawaiianorange" item_state = "hawaiianorange" item_color = "hawaiianorange" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/bluehawaiianshirt name = "blue hawaiian shirt" @@ -833,7 +823,6 @@ icon_state = "hawaiianblue" item_state = "hawaiianblue" item_color = "hawaiianblue" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/misc/durathread name = "durathread jumpsuit" diff --git a/code/modules/clothing/under/oldstation_uni.dm b/code/modules/clothing/under/oldstation_uni.dm index f19b533ad24..97a3fa7614b 100644 --- a/code/modules/clothing/under/oldstation_uni.dm +++ b/code/modules/clothing/under/oldstation_uni.dm @@ -7,7 +7,6 @@ item_state = "retro_sec" item_color = "retro_sec" displays_id = 0 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/retro/medical desc = "A once biologically resistant medical uniform. The high-vis stripes are faded and unreflective." @@ -16,7 +15,6 @@ item_state = "retro_med" item_color = "retro_med" displays_id = 0 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/retro/engineering desc = "A faded grimy engineering jumpsuit and overall combo. It's coated with oil, dust, and grit." @@ -25,7 +23,6 @@ item_state = "retro_eng" item_color = "retro_eng" displays_id = 0 - flags_size = ONESIZEFITSALL /obj/item/clothing/under/retro/science desc = "A faded polo and set of distinct white slacks. What a ridiculous tie." @@ -34,4 +31,3 @@ item_state = "retro_sci" item_color = "retro_sci" displays_id = 0 - flags_size = ONESIZEFITSALL diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm index 40a8fe5f893..a9c47e760e7 100644 --- a/code/modules/crafting/craft.dm +++ b/code/modules/crafting/craft.dm @@ -103,7 +103,7 @@ if(RC.is_drainable()) for(var/datum/reagent/A in RC.reagents.reagent_list) .["other"][A.type] += A.volume - .["other"][I.type] += 1 + .["other"][I.type] += 1 .["toolsother"][I] += 1 /datum/personal_crafting/proc/check_tools(mob/user, datum/crafting_recipe/R, list/contents) @@ -135,13 +135,13 @@ /datum/personal_crafting/proc/check_pathtools(mob/user, datum/crafting_recipe/R, list/contents) if(!R.pathtools.len) //does not run if no tools are needed return TRUE - var/list/other_possible_tools = list() + var/list/other_possible_tools = list() for(var/obj/item/I in user.contents) // searchs the inventory of the mob if(istype(I, /obj/item/storage)) for(var/obj/item/SI in I.contents) other_possible_tools += SI.type // filters type paths other_possible_tools += I.type - + other_possible_tools |= contents["other"] // this adds contents to the other_possible_tools main_loop: // checks if all tools found are usable with the recipe for(var/A in R.pathtools) @@ -151,7 +151,7 @@ return FALSE return TRUE -/datum/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R) +/datum/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R) var/list/contents = get_surroundings(user) var/send_feedback = 1 if(check_contents(R, contents)) @@ -297,7 +297,7 @@ Deletion.Cut(Deletion.len) qdel(DL) -/datum/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, datum/topic_state/state = not_incapacitated_turf_state) +/datum/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, datum/topic_state/state = GLOB.not_incapacitated_turf_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "personal_crafting.tmpl", "Crafting Menu", 700, 800, state = state) @@ -356,6 +356,8 @@ var/fail_msg = construct_item(usr, TR) if(!fail_msg) to_chat(usr, "[TR.name] constructed.") + if(TR.alert_admins_on_craft) + message_admins("[usr.ckey] has created a [TR.name] at [ADMIN_COORDJMP(usr)]") else to_chat(usr, "Construction failed[fail_msg]") busy = FALSE diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm index ec334979cd2..35d2671cc13 100644 --- a/code/modules/crafting/recipes.dm +++ b/code/modules/crafting/recipes.dm @@ -11,6 +11,7 @@ var/category = CAT_NONE //where it shows up in the crafting UI var/subcategory = CAT_NONE var/always_availible = TRUE //Set to FALSE if it needs to be learned first. + var/alert_admins_on_craft = FALSE /datum/crafting_recipe/IED name = "IED" @@ -94,6 +95,7 @@ tools = list(TOOL_WELDER) time = 120 category = CAT_ROBOT + alert_admins_on_craft = TRUE /datum/crafting_recipe/cleanbot name = "Cleanbot" @@ -147,6 +149,7 @@ time = 10 category = CAT_WEAPONRY subcategory = CAT_WEAPON + alert_admins_on_craft = TRUE /datum/crafting_recipe/meteorshot name = "Meteorshot Shell" @@ -196,8 +199,7 @@ name = "Ion Scatter Shell" result = /obj/item/ammo_casing/shotgun/ion reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1, - /obj/item/stock_parts/micro_laser/ultra = 1, - /obj/item/stock_parts/subspace/crystal = 1) + /obj/item/stock_parts/micro_laser/ultra = 1) tools = list(TOOL_SCREWDRIVER) time = 5 category = CAT_WEAPONRY @@ -259,6 +261,7 @@ time = 50 category = CAT_WEAPONRY subcategory = CAT_WEAPON + alert_admins_on_craft = TRUE /datum/crafting_recipe/spear name = "Spear" @@ -378,6 +381,7 @@ time = 30 category = CAT_WEAPONRY subcategory = CAT_WEAPON + alert_admins_on_craft = TRUE /datum/crafting_recipe/chemical_payload2 name = "Chemical Payload (gibtonite)" @@ -391,6 +395,7 @@ time = 50 category = CAT_WEAPONRY subcategory = CAT_WEAPON + alert_admins_on_craft = TRUE /datum/crafting_recipe/toxins_payload name = "Toxins Payload Casing" @@ -503,6 +508,7 @@ reqs = list(/obj/item/grown/log = 5) result = /obj/structure/bonfire category = CAT_PRIMAL + alert_admins_on_craft = TRUE /datum/crafting_recipe/rake //Category resorting incoming name = "Rake" @@ -611,8 +617,8 @@ name = "Paper Jack o'Lantern" result = /obj/item/decorations/sticky_decorations/flammable/jack_o_lantern tools = list(TOOL_WIRECUTTER) - pathtools = list(/obj/item/pen, - /obj/item/toy/crayon/orange, + pathtools = list(/obj/item/pen, + /obj/item/toy/crayon/orange, /obj/item/toy/crayon/green)//pen ink is black category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -629,7 +635,7 @@ name = "Paper Spider" result = /obj/item/decorations/sticky_decorations/flammable/spider tools = list(TOOL_WIRECUTTER) - pathtools = list(/obj/item/pen, + pathtools = list(/obj/item/pen, /obj/item/toy/crayon/red) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -670,7 +676,7 @@ name = "Paper Snowman" result = /obj/item/decorations/sticky_decorations/flammable/snowman tools = list(TOOL_WIRECUTTER) - pathtools = list(/obj/item/pen, + pathtools = list(/obj/item/pen, /obj/item/toy/crayon/orange) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -687,9 +693,9 @@ name = "Paper Christmas Tree" result = /obj/item/decorations/sticky_decorations/flammable/christmas_tree tools = list(TOOL_WIRECUTTER) - pathtools = list(/obj/item/toy/crayon/red, - /obj/item/toy/crayon/yellow, - /obj/item/toy/crayon/blue, + pathtools = list(/obj/item/toy/crayon/red, + /obj/item/toy/crayon/yellow, + /obj/item/toy/crayon/blue, /obj/item/toy/crayon/green) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -714,7 +720,7 @@ name = "Paper Mistletoe" result = /obj/item/decorations/sticky_decorations/flammable/mistletoe tools = list(TOOL_WIRECUTTER) - pathtools = list(/obj/item/toy/crayon/red, + pathtools = list(/obj/item/toy/crayon/red, /obj/item/toy/crayon/green) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -723,7 +729,7 @@ name = "Paper Holly" result = /obj/item/decorations/sticky_decorations/flammable/holly tools = list(TOOL_WIRECUTTER) - pathtools = list(/obj/item/toy/crayon/red, + pathtools = list(/obj/item/toy/crayon/red, /obj/item/toy/crayon/green) category = CAT_DECORATIONS subcategory = CAT_HOLIDAY @@ -1012,7 +1018,7 @@ /obj/item/stack/rods = 4, /obj/item/stock_parts/cell = 1, /obj/item/stack/cable_coil = 4)//thing is a wireframe construct with an electro magnetic hover field - tools = list(TOOL_WIRECUTTER, + tools = list(TOOL_WIRECUTTER, TOOL_WELDER) pathtools = list(/obj/item/pen, /obj/item/toy/crayon/red) diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 983ce229d2c..f8d2029651d 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -1080,7 +1080,6 @@ icon_state = "counterfeitguise" item_state = "counterfeitguise" item_color = "counterfeitguise" - flags_size = ONESIZEFITSALL /obj/item/clothing/under/fluff/benjaminfallout // Benjaminfallout: Pretzel Brassheart icon = 'icons/obj/custom_items.dmi' @@ -1350,7 +1349,6 @@ icon = 'icons/obj/custom_items.dmi' icon_state = "chronx_robe" item_state = "chronx_robe" - flags_size = ONESIZEFITSALL actions_types = list(/datum/action/item_action/toggle) adjust_flavour = "untransform" ignore_suitadjust = 0 @@ -1658,13 +1656,16 @@ desc = "A small platinum ring with a large light blue diamond. Engraved inside the band are the words: 'To my lovely Pristine Princess. Forever yours, Savinien.'" icon_state = "benjaminfallout_ring" -/obj/item/clothing/under/fluff/voxbodysuit //Gangelwaefre: Kikeri - name = "Vox Bodysuit" - desc = "A shimmering bodysuit custom-fit to a vox. Has shorts sewn in." + +/obj/item/clothing/under/fluff/kikeridress //Gangelwaefre: Kikeri + name = "Kikeri's Dress" + desc = "A simple black dress with a white undercoat, tied with a blue ribbon." lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi' righthand_file = 'icons/mob/inhands/fluff_righthand.dmi' - icon = 'icons/mob/inhands/fluff_righthand.dmi' - icon_state = "voxbodysuit" - item_state = "voxbodysuit" - item_color = "voxbodysuit" - body_parts_covered = HEAD|UPPER_TORSO|LOWER_TORSO|LEGS|ARMS + sprite_sheets = list("Vox" = 'icons/mob/species/vox/uniform.dmi') + icon = 'icons/obj/custom_items.dmi' + icon_state = "kikeridress" + item_state = "kikeridress" + item_color = "kikeridress" + body_parts_covered = UPPER_TORSO|LOWER_TORSO + species_restricted = list("Vox") diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm index 5c1250ed355..8a8f44099ce 100644 --- a/code/modules/customitems/item_spawning.dm +++ b/code/modules/customitems/item_spawning.dm @@ -3,7 +3,7 @@ return // Grab the info we want. - var/DBQuery/query = dbcon.NewQuery("SELECT cuiPath, cuiPropAdjust, cuiJobMask, cuiDescription, cuiItemName FROM [format_table_name("customuseritems")] WHERE cuiCKey='[M.ckey]' AND (cuiRealName='[sanitizeSQL(M.real_name)]' OR cuiRealName='*')") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT cuiPath, cuiPropAdjust, cuiJobMask, cuiDescription, cuiItemName FROM [format_table_name("customuseritems")] WHERE cuiCKey='[M.ckey]' AND (cuiRealName='[sanitizeSQL(M.real_name)]' OR cuiRealName='*')") query.Execute() while(query.NextRow()) @@ -11,6 +11,9 @@ var/propadjust = query.item[2] var/jobmask = query.item[3] var/ok = 0 + if(!path || !ispath(path)) + log_debug("Incorrect database entry found in table 'customuseritems' path value = [path], cuiPath is null. cuiCKey='[M.ckey]' AND (cuiRealName='[sanitizeSQL(M.real_name)]' OR cuiRealName='*'") + continue if(jobmask != "*") var/list/allowed_jobs = splittext(jobmask,",") for(var/i = 1, i <= allowed_jobs.len, i++) diff --git a/code/modules/detective_work/footprints_and_rag.dm b/code/modules/detective_work/footprints_and_rag.dm index c636c3d01a7..2646d03fb0f 100644 --- a/code/modules/detective_work/footprints_and_rag.dm +++ b/code/modules/detective_work/footprints_and_rag.dm @@ -35,7 +35,7 @@ /obj/item/reagent_containers/glass/rag/afterattack(atom/A as obj|turf|area, mob/user as mob,proximity) if(!proximity) return - if(istype(A) && src in user) + if(istype(A) && (src in user)) user.visible_message("[user] starts to wipe down [A] with [src]!") if(do_after(user, wipespeed, target = A)) user.visible_message("[user] finishes wiping off the [A]!") diff --git a/code/modules/detective_work/scanner.dm b/code/modules/detective_work/scanner.dm index 64318877847..dea08c602f9 100644 --- a/code/modules/detective_work/scanner.dm +++ b/code/modules/detective_work/scanner.dm @@ -30,21 +30,21 @@ // I really, really wish I didn't have to split this into two seperate loops. But the datacore is awful. - for(var/record in data_core.general) + for(var/record in GLOB.data_core.general) var/datum/data/record/S = record if(S && (search == lowertext(S.fields["fingerprint"]) || search == lowertext(S.fields["name"]))) name = S.fields["name"] fingerprint = S.fields["fingerprint"] continue - for(var/record in data_core.medical) + for(var/record in GLOB.data_core.medical) var/datum/data/record/M = record if(M && ( search == lowertext(M.fields["b_dna"]) || name == M.fields["name"]) ) dna = M.fields["b_dna"] if(fingerprint == "FINGERPRINT NOT FOUND") // We have searched by DNA, and do not have the relevant information from the fingerprint records. name = M.fields["name"] - for(var/gen_record in data_core.general) + for(var/gen_record in GLOB.data_core.general) var/datum/data/record/S = gen_record if(S && (name == S.fields["name"])) fingerprint = S.fields["fingerprint"] diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm index df542964163..b094dded37e 100644 --- a/code/modules/economy/ATM.dm +++ b/code/modules/economy/ATM.dm @@ -36,7 +36,7 @@ log transactions /obj/machinery/atm/New() ..() - machine_id = "[station_name()] RT #[num_financial_terminals++]" + machine_id = "[station_name()] RT #[GLOB.num_financial_terminals++]" /obj/machinery/atm/Initialize() ..() @@ -127,7 +127,7 @@ log transactions ui = new(user, src, ui_key, "atm.tmpl", name, 550, 650) ui.open() -/obj/machinery/atm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/atm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["src"] = UID() data["view_screen"] = view_screen @@ -203,7 +203,7 @@ log transactions T.target_name = failed_account.owner_name T.purpose = "Unauthorised login attempt" T.source_terminal = machine_id - T.date = current_date_string + T.date = GLOB.current_date_string T.time = station_time_timestamp() failed_account.transaction_log.Add(T) else @@ -223,7 +223,7 @@ log transactions T.target_name = authenticated_account.owner_name T.purpose = "Remote terminal access" T.source_terminal = machine_id - T.date = current_date_string + T.date = GLOB.current_date_string T.time = station_time_timestamp() authenticated_account.transaction_log.Add(T) to_chat(usr, "[bicon(src)]Access granted. Welcome user '[authenticated_account.owner_name].'") @@ -237,9 +237,9 @@ log transactions playsound(src, 'sound/machines/chime.ogg', 50, 1) //remove the money - if(amount > 10000) // prevent crashes - to_chat(usr, "The ATM's screen flashes, 'Maximum single withdrawl limit reached, defaulting to 10,000.'") - amount = 10000 + if(amount > 100000) // prevent crashes + to_chat(usr, "The ATM's screen flashes, 'Maximum single withdrawl limit reached, defaulting to 100,000.'") + amount = 100000 withdraw_arbitrary_sum(amount) authenticated_account.charge(amount, null, "Credit withdrawal", machine_id, authenticated_account.owner_name) else @@ -257,7 +257,7 @@ log transactions Account holder: [authenticated_account.owner_name]
    Account number: [authenticated_account.account_number]
    Balance: $[authenticated_account.money]
    - Date and time: [station_time_timestamp()], [current_date_string]

    + Date and time: [station_time_timestamp()], [GLOB.current_date_string]

    Service terminal ID: [machine_id]
    "} //stamp the paper diff --git a/code/modules/economy/Accounts.dm b/code/modules/economy/Accounts.dm index 6001cf3f84e..0a2b500a0d3 100644 --- a/code/modules/economy/Accounts.dm +++ b/code/modules/economy/Accounts.dm @@ -4,33 +4,33 @@ #define STATION_SOURCE_TERMINAL "Biesel GalaxyNet Terminal #227" #define DEPARTMENT_START_CASH 5000 -var/global/num_financial_terminals = 1 -var/global/datum/money_account/station_account -var/global/list/datum/money_account/department_accounts = list() -var/global/next_account_number = 0 -var/global/obj/machinery/computer/account_database/centcomm_account_db -var/global/datum/money_account/vendor_account -var/global/list/all_money_accounts = list() +GLOBAL_VAR_INIT(num_financial_terminals, 1) +GLOBAL_DATUM(station_account, /datum/money_account) +GLOBAL_LIST_EMPTY(department_accounts) +GLOBAL_VAR_INIT(next_account_number, 0) +GLOBAL_DATUM(centcomm_account_db, /obj/machinery/computer/account_database) // this being an object hurts me deeply on the inside +GLOBAL_DATUM(vendor_account, /datum/money_account) +GLOBAL_LIST_EMPTY(all_money_accounts) /proc/create_station_account() - if(!station_account) - next_account_number = rand(111111, 999999) + if(!GLOB.station_account) + GLOB.next_account_number = rand(111111, 999999) - station_account = new() - station_account.owner_name = "[station_name()] Station Account" - station_account.account_number = rand(111111, 999999) - station_account.remote_access_pin = rand(1111, 111111) - station_account.money = STATION_START_CASH + GLOB.station_account = new() + GLOB.station_account.owner_name = "[station_name()] Station Account" + GLOB.station_account.account_number = rand(111111, 999999) + GLOB.station_account.remote_access_pin = rand(1111, 111111) + GLOB.station_account.money = STATION_START_CASH //create an entry in the account transaction log for when it was created - station_account.makeTransactionLog(STATION_START_CASH, "Account Creation", STATION_SOURCE_TERMINAL, station_account.owner_name, FALSE, + GLOB.station_account.makeTransactionLog(STATION_START_CASH, "Account Creation", STATION_SOURCE_TERMINAL, GLOB.station_account.owner_name, FALSE, STATION_CREATION_DATE, STATION_CREATION_TIME) //add the account - all_money_accounts.Add(station_account) + GLOB.all_money_accounts.Add(GLOB.station_account) /proc/create_department_account(department) - next_account_number = rand(111111, 999999) + GLOB.next_account_number = rand(111111, 999999) var/datum/money_account/department_account = new() department_account.owner_name = "[department] Account" @@ -43,9 +43,9 @@ var/global/list/all_money_accounts = list() STATION_CREATION_DATE, STATION_CREATION_TIME) //add the account - all_money_accounts.Add(department_account) + GLOB.all_money_accounts.Add(department_account) - department_accounts[department] = department_account + GLOB.department_accounts[department] = department_account //the current ingame time (hh:mm:ss) can be obtained by calling: //station_time_timestamp("hh:mm:ss") @@ -65,18 +65,18 @@ var/global/list/all_money_accounts = list() T.amount = starting_funds if(!source_db) //set a random date, time and location some time over the past few decades - T.date = "[num2text(rand(1,31))] [pick(GLOB.month_names)], [rand(game_year - 20,game_year - 1)]" + T.date = "[num2text(rand(1,31))] [pick(GLOB.month_names)], [rand(GLOB.game_year - 20,GLOB.game_year - 1)]" T.time = "[rand(0,23)]:[rand(0,59)]:[rand(0,59)]" T.source_terminal = "NTGalaxyNet Terminal #[rand(111,1111)]" M.account_number = rand(111111, 999999) else - T.date = current_date_string + T.date = GLOB.current_date_string T.time = station_time_timestamp() T.source_terminal = source_db.machine_id - M.account_number = next_account_number - next_account_number += rand(1,25) + M.account_number = GLOB.next_account_number + GLOB.next_account_number += rand(1,25) //create a sealed package containing the account details var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(source_db.loc) @@ -94,7 +94,7 @@ var/global/list/all_money_accounts = list() Account number: [M.account_number]
    Account pin: [M.remote_access_pin]
    Starting balance: $[M.money]
    - Date and time: [station_time_timestamp()], [current_date_string]

    + Date and time: [station_time_timestamp()], [GLOB.current_date_string]

    Creation terminal ID: [source_db.machine_id]
    Authorised NT officer overseeing creation: [overseer]
    "} @@ -109,7 +109,7 @@ var/global/list/all_money_accounts = list() //add the account M.transaction_log.Add(T) - all_money_accounts.Add(M) + GLOB.all_money_accounts.Add(M) return M @@ -138,7 +138,7 @@ var/global/list/all_money_accounts = list() /obj/machinery/computer/account_database/proc/charge_to_account(attempt_account_number, datum/money_account/source, purpose, terminal_id, amount) if(!activated) return 0 - for(var/datum/money_account/D in all_money_accounts) + for(var/datum/money_account/D in GLOB.all_money_accounts) if(D.account_number == attempt_account_number && !D.suspended) source.charge(amount, D, purpose, terminal_id, "Account #[D.account_number]", "Transfer from [source.owner_name]", "[D.owner_name]") @@ -148,18 +148,18 @@ var/global/list/all_money_accounts = list() //this returns the first account datum that matches the supplied accnum/pin combination, it returns null if the combination did not match any account /proc/attempt_account_access(var/attempt_account_number, var/attempt_pin_number, var/security_level_passed = 0,var/pin_needed=1) - for(var/datum/money_account/D in all_money_accounts) + for(var/datum/money_account/D in GLOB.all_money_accounts) if(D.account_number == attempt_account_number) if( D.security_level <= security_level_passed && (!D.security_level || D.remote_access_pin == attempt_pin_number || !pin_needed) ) return D /obj/machinery/computer/account_database/proc/get_account(var/account_number) - for(var/datum/money_account/D in all_money_accounts) + for(var/datum/money_account/D in GLOB.all_money_accounts) if(D.account_number == account_number) return D /proc/attempt_account_access_nosec(var/attempt_account_number) - for(var/datum/money_account/D in all_money_accounts) + for(var/datum/money_account/D in GLOB.all_money_accounts) if(D.account_number == attempt_account_number) return D diff --git a/code/modules/economy/Accounts_DB.dm b/code/modules/economy/Accounts_DB.dm index afb5fbff79a..6995e260500 100644 --- a/code/modules/economy/Accounts_DB.dm +++ b/code/modules/economy/Accounts_DB.dm @@ -1,4 +1,4 @@ -var/global/current_date_string +GLOBAL_VAR(current_date_string) /obj/machinery/computer/account_database name = "Accounts Uplink Terminal" @@ -17,20 +17,20 @@ var/global/current_date_string light_color = LIGHT_COLOR_GREEN /obj/machinery/computer/account_database/New() - if(!station_account) + if(!GLOB.station_account) create_station_account() - if(department_accounts.len == 0) - for(var/department in station_departments) + if(GLOB.department_accounts.len == 0) + for(var/department in GLOB.station_departments) create_department_account(department) - if(!vendor_account) + if(!GLOB.vendor_account) create_department_account("Vendor") - vendor_account = department_accounts["Vendor"] + GLOB.vendor_account = GLOB.department_accounts["Vendor"] - if(!current_date_string) - current_date_string = "[time2text(world.timeofday, "DD Month")], [game_year]" + if(!GLOB.current_date_string) + GLOB.current_date_string = "[time2text(world.timeofday, "DD Month")], [GLOB.game_year]" - machine_id = "[station_name()] Acc. DB #[num_financial_terminals++]" + machine_id = "[station_name()] Acc. DB #[GLOB.num_financial_terminals++]" ..() /obj/machinery/computer/account_database/proc/get_access_level(var/mob/user) @@ -40,7 +40,7 @@ var/global/current_date_string return 0 if(ACCESS_CENT_COMMANDER in held_card.access) return 2 - else if(ACCESS_HOP in held_card.access || ACCESS_CAPTAIN in held_card.access) + else if((ACCESS_HOP in held_card.access) || (ACCESS_CAPTAIN in held_card.access)) return 1 /obj/machinery/computer/account_database/proc/accounting_letterhead(report_name) @@ -74,7 +74,7 @@ var/global/current_date_string ui = new(user, src, ui_key, "accounts_terminal.tmpl", src.name, 400, 640) ui.open() -/obj/machinery/computer/account_database/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/account_database/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["src"] = UID() @@ -84,7 +84,7 @@ var/global/current_date_string data["machine_id"] = machine_id data["creating_new_account"] = creating_new_account data["detailed_account_view"] = !!detailed_account_view - data["station_account_number"] = station_account.account_number + data["station_account_number"] = GLOB.station_account.account_number data["transactions"] = null data["accounts"] = null @@ -108,8 +108,8 @@ var/global/current_date_string data["transactions"] = trx var/list/accounts[0] - for(var/i=1, i<=all_money_accounts.len, i++) - var/datum/money_account/D = all_money_accounts[i] + for(var/i=1, i<=GLOB.all_money_accounts.len, i++) + var/datum/money_account/D = GLOB.all_money_accounts[i] accounts.Add(list(list(\ "account_number"=D.account_number,\ "owner_name"=D.owner_name,\ @@ -159,12 +159,12 @@ var/global/current_date_string var/account_name = href_list["holder_name"] var/starting_funds = max(text2num(href_list["starting_funds"]), 0) - starting_funds = Clamp(starting_funds, 0, station_account.money) // Not authorized to put the station in debt. + starting_funds = Clamp(starting_funds, 0, GLOB.station_account.money) // Not authorized to put the station in debt. starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap. var/datum/money_account/M = create_account(account_name, starting_funds, src) if(starting_funds > 0) - station_account.charge(starting_funds, null, "New account activation", + GLOB.station_account.charge(starting_funds, null, "New account activation", "", "New account activation", M.owner_name) creating_new_account = 0 @@ -174,8 +174,8 @@ var/global/current_date_string if("view_account_detail") var/index = text2num(href_list["account_index"]) - if(index && index <= all_money_accounts.len) - detailed_account_view = all_money_accounts[index] + if(index && index <= GLOB.all_money_accounts.len) + detailed_account_view = GLOB.all_money_accounts[index] if("view_accounts_list") detailed_account_view = null @@ -240,8 +240,8 @@ var/global/current_date_string "} - for(var/i=1, i<=all_money_accounts.len, i++) - var/datum/money_account/D = all_money_accounts[i] + for(var/i=1, i<=GLOB.all_money_accounts.len, i++) + var/datum/money_account/D = GLOB.all_money_accounts[i] text += {" #[D.account_number] diff --git a/code/modules/economy/EFTPOS.dm b/code/modules/economy/EFTPOS.dm index 9a5faf8aa36..f84b40ebb10 100644 --- a/code/modules/economy/EFTPOS.dm +++ b/code/modules/economy/EFTPOS.dm @@ -14,7 +14,7 @@ /obj/item/eftpos/New() ..() - machine_name = "[station_name()] EFTPOS #[num_financial_terminals++]" + machine_name = "[station_name()] EFTPOS #[GLOB.num_financial_terminals++]" access_code = rand(1111,111111) reconnect_database() spawn(0) @@ -22,7 +22,7 @@ //by default, connect to the station account //the user of the EFTPOS device can change the target account though, and no-one will be the wiser (except whoever's being charged) - linked_account = station_account + linked_account = GLOB.station_account /obj/item/eftpos/proc/print_reference() playsound(loc, 'sound/goonstation/machines/printer_thermal.ogg', 50, 1) @@ -79,7 +79,7 @@ ui = new(user, src, ui_key, "eftpos.tmpl", name, 790, 310) ui.open() -/obj/item/eftpos/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/item/eftpos/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["machine_name"] = machine_name data["transaction_locked"] = transaction_locked @@ -150,7 +150,7 @@ var/obj/item/I = usr.get_active_hand() if(istype(I, /obj/item/card)) var/obj/item/card/id/C = I - if(ACCESS_CENT_COMMANDER in C.access || ACCESS_HOP in C.access || ACCESS_CAPTAIN in C.access) + if((ACCESS_CENT_COMMANDER in C.access) || (ACCESS_HOP in C.access) || (ACCESS_CAPTAIN in C.access)) access_code = 0 to_chat(usr, "[bicon(src)]Access code reset to 0.") else if(istype(I, /obj/item/card/emag)) @@ -190,8 +190,4 @@ playsound(src, 'sound/machines/chime.ogg', 50, 1) visible_message("[bicon(src)] The [src] chimes.") transaction_paid = 1 - - else - ..() - //emag? diff --git a/code/modules/economy/Economy.dm b/code/modules/economy/Economy.dm index eca0e08e359..8f06db02f34 100644 --- a/code/modules/economy/Economy.dm +++ b/code/modules/economy/Economy.dm @@ -63,9 +63,9 @@ //Destroyers are medium sized vessels, often used for escorting larger ships but able to go toe-to-toe with them if need be. //Frigates are medium sized vessels, often used for escorting larger ships. They will rapidly find themselves outclassed if forced to face heavy warships head on. -var/setup_economy = 0 +GLOBAL_VAR_INIT(setup_economy, 0) /proc/setup_economy() - if(setup_economy) + if(GLOB.setup_economy) return var/datum/feed_channel/newChannel = new /datum/feed_channel @@ -73,25 +73,25 @@ var/setup_economy = 0 newChannel.author = "Automated Announcement Listing" newChannel.locked = 1 newChannel.is_admin_channel = 1 - news_network.network_channels += newChannel + GLOB.news_network.network_channels += newChannel newChannel = new /datum/feed_channel newChannel.channel_name = "Nyx Daily" newChannel.author = "CentComm Minister of Information" newChannel.locked = 1 newChannel.is_admin_channel = 1 - news_network.network_channels += newChannel + GLOB.news_network.network_channels += newChannel newChannel = new /datum/feed_channel newChannel.channel_name = "The Gibson Gazette" newChannel.author = "Editor Mike Hammers" newChannel.locked = 1 newChannel.is_admin_channel = 1 - news_network.network_channels += newChannel + GLOB.news_network.network_channels += newChannel for(var/loc_type in subtypesof(/datum/trade_destination)) var/datum/trade_destination/D = new loc_type - weighted_randomevent_locations[D] = D.viable_random_events.len - weighted_mundaneevent_locations[D] = D.viable_mundane_events.len + GLOB.weighted_randomevent_locations[D] = D.viable_random_events.len + GLOB.weighted_mundaneevent_locations[D] = D.viable_mundane_events.len - setup_economy = 1 + GLOB.setup_economy = 1 diff --git a/code/modules/economy/Economy_Events.dm b/code/modules/economy/Economy_Events.dm index 10e0d574f98..d7754f122ea 100644 --- a/code/modules/economy/Economy_Events.dm +++ b/code/modules/economy/Economy_Events.dm @@ -8,10 +8,10 @@ var/datum/trade_destination/affected_dest /datum/event/economic_event/start() - if(!setup_economy) + if(!GLOB.setup_economy) setup_economy() - affected_dest = pickweight(weighted_randomevent_locations) + affected_dest = pickweight(GLOB.weighted_randomevent_locations) if(affected_dest.viable_random_events.len) endWhen = rand(60,300) event_type = pick(affected_dest.viable_random_events) @@ -94,11 +94,11 @@ if(FESTIVAL) newMsg.body = "A [pick("festival","week long celebration","day of revelry","planet-wide holiday")] has been declared on [affected_dest.name] by [pick("Governor","Commissioner","General","Commandant","Administrator")] [random_name(pick(MALE,FEMALE))] to celebrate [pick("the birth of their [pick("son","daughter")]","coming of age of their [pick("son","daughter")]","the pacification of rogue military cell","the apprehension of a violent criminal who had been terrorising the planet")]. Massive stocks of food and meat have been bought driving up prices across the planet." - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == "Nyx Daily") FC.messages += newMsg break - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters) NEWSCASTER.newsAlert("Nyx Daily") /datum/event/economic_event/end() diff --git a/code/modules/economy/Economy_Events_Mundane.dm b/code/modules/economy/Economy_Events_Mundane.dm index 1b5467a3a1c..cfabd6cdbe7 100644 --- a/code/modules/economy/Economy_Events_Mundane.dm +++ b/code/modules/economy/Economy_Events_Mundane.dm @@ -3,7 +3,7 @@ endWhen = 10 /datum/event/mundane_news/announce() - var/datum/trade_destination/affected_dest = pickweight(weighted_mundaneevent_locations) + var/datum/trade_destination/affected_dest = pickweight(GLOB.weighted_mundaneevent_locations) var/event_type = 0 if(affected_dest.viable_mundane_events.len) event_type = pick(affected_dest.viable_mundane_events) @@ -126,11 +126,11 @@ Nyx Daily is offering discount tickets for two to see [random_name(pick(MALE,FEMALE))] live in return for eyewitness reports and up to the minute coverage." - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == "Nyx Daily") FC.messages += newMsg break - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters) NEWSCASTER.newsAlert("Nyx Daily") /datum/event/trivial_news @@ -141,13 +141,13 @@ var/datum/feed_message/newMsg = new /datum/feed_message newMsg.author = "Editor Mike Hammers" //newMsg.is_admin_message = 1 - var/datum/trade_destination/affected_dest = pick(weighted_mundaneevent_locations) + var/datum/trade_destination/affected_dest = pick(GLOB.weighted_mundaneevent_locations) newMsg.body = pick(file2list("config/news/trivial.txt")) newMsg.body = replacetext(newMsg.body,"{{AFFECTED}}",affected_dest.name) - for(var/datum/feed_channel/FC in news_network.network_channels) + for(var/datum/feed_channel/FC in GLOB.news_network.network_channels) if(FC.channel_name == "The Gibson Gazette") FC.messages += newMsg break - for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) + for(var/obj/machinery/newscaster/NEWSCASTER in GLOB.allNewscasters) NEWSCASTER.newsAlert("The Gibson Gazette") diff --git a/code/modules/economy/Economy_TradeDestinations.dm b/code/modules/economy/Economy_TradeDestinations.dm index 09bbabdab37..74d005e3b3b 100644 --- a/code/modules/economy/Economy_TradeDestinations.dm +++ b/code/modules/economy/Economy_TradeDestinations.dm @@ -1,6 +1,6 @@ -var/list/weighted_randomevent_locations = list() -var/list/weighted_mundaneevent_locations = list() +GLOBAL_LIST_EMPTY(weighted_randomevent_locations) +GLOBAL_LIST_EMPTY(weighted_mundaneevent_locations) /datum/trade_destination var/name = "" diff --git a/code/modules/economy/Job_Departments.dm b/code/modules/economy/Job_Departments.dm index 77a938486dd..f2accab8541 100644 --- a/code/modules/economy/Job_Departments.dm +++ b/code/modules/economy/Job_Departments.dm @@ -1,4 +1,4 @@ -var/list/station_departments = list("Command", "Medical", "Engineering", "Science", "Security", "Cargo", "Support", "Civilian") +GLOBAL_LIST_INIT(station_departments, list("Command", "Medical", "Engineering", "Science", "Security", "Cargo", "Support", "Civilian")) // The department the job belongs to. /datum/job/var/department = null diff --git a/code/modules/economy/POS.dm b/code/modules/economy/POS.dm index cbf708f64ea..60b774a2a3d 100644 --- a/code/modules/economy/POS.dm +++ b/code/modules/economy/POS.dm @@ -11,8 +11,8 @@ var/price = 0 // Per unit var/units = 0 -var/global/current_pos_id = 1 -var/global/pos_sales = 0 +GLOBAL_VAR_INIT(current_pos_id, 1) +GLOBAL_VAR_INIT(pos_sales, 0) #define RECEIPT_HEADER {" @@ -142,11 +142,11 @@ var/global/pos_sales = 0 /obj/machinery/pos/New() ..() - id = current_pos_id++ + id = GLOB.current_pos_id++ if(department) - linked_account = department_accounts[department] + linked_account = GLOB.department_accounts[department] else - linked_account = station_account + linked_account = GLOB.station_account update_icon() /obj/machinery/pos/proc/AddToOrder(var/name, var/units) @@ -173,7 +173,7 @@ var/global/pos_sales = 0 receipt += myArea.name receipt += "
    " receipt += {"
    -
    [station_time_timestamp()], [current_date_string]
    +
    [station_time_timestamp()], [GLOB.current_date_string]
    @@ -369,7 +369,7 @@ var/global/pos_sales = 0 logindata={"[logged_in.name]"} var/dat = POS_HEADER + {"
    Item
    " - var/DBQuery/query = dbcon.NewQuery("SELECT id, title, flagged FROM [format_table_name("library")] WHERE flagged > 0 ORDER BY flagged DESC") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id, title, flagged FROM [format_table_name("library")] WHERE flagged > 0 ORDER BY flagged DESC") if(!query.Execute()) var/err = query.ErrorMsg() log_game("SQL ERROR getting flagged books. Error : \[[err]\]\n") diff --git a/code/modules/library/codex_gigas.dm b/code/modules/library/codex_gigas.dm index e908f35b60b..3e6ed79b040 100644 --- a/code/modules/library/codex_gigas.dm +++ b/code/modules/library/codex_gigas.dm @@ -45,7 +45,7 @@ if(!prob(correctness)) usedName += "x" var/datum/devilinfo/devil = devilInfo(usedName, 0) - user << browse("Information on [devilName]


    [lawlorify[LORE][devil.ban]]
    [lawlorify[LORE][devil.bane]]
    [lawlorify[LORE][devil.obligation]]
    [lawlorify[LORE][devil.banish]]", "window=book") + user << browse("Information on [devilName]


    [GLOB.lawlorify[LORE][devil.ban]]
    [GLOB.lawlorify[LORE][devil.bane]]
    [GLOB.lawlorify[LORE][devil.obligation]]
    [GLOB.lawlorify[LORE][devil.banish]]", "window=book") inUse = 0 sleep(10) if(!prob(willpower)) diff --git a/code/modules/library/computers/base.dm b/code/modules/library/computers/base.dm index 2b4bcd9f5a7..ff1e9bcb94f 100644 --- a/code/modules/library/computers/base.dm +++ b/code/modules/library/computers/base.dm @@ -47,7 +47,7 @@ var/sql = "SELECT id, author, title, category, ckey, flagged FROM [format_table_name("library")] [searchquery] LIMIT [(page_num - 1) * LIBRARY_BOOKS_PER_PAGE], [LIBRARY_BOOKS_PER_PAGE]" // Pagination - var/DBQuery/_query = dbcon.NewQuery(sql) + var/DBQuery/_query = GLOB.dbcon.NewQuery(sql) _query.Execute() if(_query.ErrorMsg()) log_world(_query.ErrorMsg()) @@ -69,7 +69,7 @@ /obj/machinery/computer/library/proc/get_num_results() var/sql = "SELECT COUNT(*) FROM [format_table_name("library")]" - var/DBQuery/_query = dbcon.NewQuery(sql) + var/DBQuery/_query = GLOB.dbcon.NewQuery(sql) _query.Execute() while(_query.NextRow()) return text2num(_query.item[1]) @@ -90,4 +90,4 @@ return pagelist /obj/machinery/computer/library/proc/getBookByID(var/id as text) - return library_catalog.getBookByID(id) + return GLOB.library_catalog.getBookByID(id) diff --git a/code/modules/library/computers/checkout.dm b/code/modules/library/computers/checkout.dm index e59c71392d3..31eebc5d05c 100644 --- a/code/modules/library/computers/checkout.dm +++ b/code/modules/library/computers/checkout.dm @@ -91,7 +91,7 @@ (Return to main menu)
    "} if(4) dat += "

    External Archive

    " - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance." else num_results = src.get_num_results() @@ -165,7 +165,7 @@ dat += "
    ISBNTitleTotal FlagsOptions
    " var/list/forbidden = list( - /obj/item/book/manual + /obj/item/book/manual/random ) if(!emagged) @@ -174,11 +174,12 @@ var/manualcount = 1 var/obj/item/book/manual/M = null - for(var/manual_type in (typesof(/obj/item/book/manual) - forbidden)) - M = new manual_type() - dat += "" + for(var/manual_type in subtypesof(/obj/item/book/manual)) + if(!(manual_type in forbidden)) + M = new manual_type() + dat += "" + QDEL_NULL(M) manualcount++ - QDEL_NULL(M) dat += "
    [M.title]
    [M.title]
    " dat += "
    (Return to main menu)
    " @@ -237,7 +238,7 @@ else query.title = null if(href_list["setcategory"]) - var/newcategory = input("Choose a category to search for:") in (list("Any") + library_section_names) + var/newcategory = input("Choose a category to search for:") in (list("Any") + GLOB.library_section_names) if(newcategory == "Any") query.category = null else if(newcategory) @@ -261,7 +262,7 @@ var/datum/cachedbook/target = getBookByID(href_list["del"]) // Sanitized in getBookByID var/ans = alert(usr, "Are you sure you wish to delete \"[target.title]\", by [target.author]? This cannot be undone.", "Library System", "Yes", "No") if(ans=="Yes") - var/DBQuery/query = dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[target.id]") + var/DBQuery/query = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[target.id]") var/response = query.Execute() if(!response) to_chat(usr, query.ErrorMsg()) @@ -277,7 +278,7 @@ var/tckey = ckey(href_list["delbyckey"]) var/ans = alert(usr,"Are you sure you wish to delete all books by [tckey]? This cannot be undone.", "Library System", "Yes", "No") if(ans=="Yes") - var/DBQuery/query = dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE ckey='[sanitizeSQL(tckey)]'") + var/DBQuery/query = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE ckey='[sanitizeSQL(tckey)]'") var/response = query.Execute() if(!response) to_chat(usr, query.ErrorMsg()) @@ -292,7 +293,7 @@ return if(href_list["flag"]) - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) alert("Connection to Archive has been severed. Aborting.") return var/id = href_list["flag"] @@ -300,7 +301,7 @@ var/datum/cachedbook/B = getBookByID(id) if(B) if((input(usr, "Are you sure you want to flag [B.title] as having inappropriate content?", "Flag Book #[B.id]") in list("Yes", "No")) == "Yes") - library_catalog.flag_book_by_id(usr, id) + GLOB.library_catalog.flag_book_by_id(usr, id) if(href_list["switchscreen"]) switch(href_list["switchscreen"]) @@ -378,14 +379,14 @@ var/choice = input("Are you certain you wish to upload this title to the Archive?") in list("Confirm", "Abort") if(choice == "Confirm") establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) alert("Connection to Archive has been severed. Aborting.") else var/sqltitle = sanitizeSQL(scanner.cache.name) var/sqlauthor = sanitizeSQL(scanner.cache.author) var/sqlcontent = sanitizeSQL(scanner.cache.dat) var/sqlcategory = sanitizeSQL(upload_category) - var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, flagged) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[ckey(usr.key)]', 0)") + var/DBQuery/query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("library")] (author, title, content, category, ckey, flagged) VALUES ('[sqlauthor]', '[sqltitle]', '[sqlcontent]', '[sqlcategory]', '[ckey(usr.key)]', 0)") var/response = query.Execute() if(!response) to_chat(usr, query.ErrorMsg()) @@ -399,7 +400,7 @@ if(!href_list["id"]) return - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) alert("Connection to Archive has been severed. Aborting.") return @@ -422,7 +423,7 @@ if(!href_list["manual"]) return var/bookid = href_list["manual"] - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) alert("Connection to Archive has been severed. Aborting.") return diff --git a/code/modules/library/computers/public.dm b/code/modules/library/computers/public.dm index 7793c9bb6f3..f94369b11b7 100644 --- a/code/modules/library/computers/public.dm +++ b/code/modules/library/computers/public.dm @@ -27,7 +27,7 @@ \[Start Search\]
    "} if(1) establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance.
    " else if(num_results == 0) dat += "No results found." @@ -84,7 +84,7 @@ else query.title = null if(href_list["setcategory"]) - var/newcategory = input("Choose a category to search for:") in (list("Any") + library_section_names) + var/newcategory = input("Choose a category to search for:") in (list("Any") + GLOB.library_section_names) if(newcategory == "Any") query.category = null else if(newcategory) @@ -113,7 +113,7 @@ screenstate = 0 if(href_list["flag"]) - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) alert("Connection to Archive has been severed. Aborting.") return var/id = href_list["flag"] @@ -121,7 +121,7 @@ var/datum/cachedbook/B = getBookByID(id) if(B) if((input(usr, "Are you sure you want to flag [B.title] as having inappropriate content?", "Flag Book #[B.id]") in list("Yes", "No")) == "Yes") - library_catalog.flag_book_by_id(usr, id) + GLOB.library_catalog.flag_book_by_id(usr, id) add_fingerprint(usr) updateUsrDialog() diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 5729d3d7fa5..65fadaa9b45 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -1,11 +1,11 @@ #define LIBRARY_BOOKS_PER_PAGE 25 -var/global/datum/library_catalog/library_catalog = new() -var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion") +GLOBAL_DATUM_INIT(library_catalog, /datum/library_catalog, new()) +GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion")) /hook/startup/proc/load_manuals() - library_catalog.initialize() + GLOB.library_catalog.initialize() return 1 /* @@ -98,7 +98,7 @@ var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "A var/sqlid = text2num(id) if(!sqlid) return - var/DBQuery/query = dbcon.NewQuery("UPDATE [format_table_name("library")] SET flagged = flagged + 1 WHERE id=[sqlid]") + var/DBQuery/query = GLOB.dbcon.NewQuery("UPDATE [format_table_name("library")] SET flagged = flagged + 1 WHERE id=[sqlid]") query.Execute() /datum/library_catalog/proc/rmBookByID(mob/user, id) @@ -111,7 +111,7 @@ var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "A var/sqlid = text2num(id) if(!sqlid) return - var/DBQuery/query = dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[sqlid]") + var/DBQuery/query = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("library")] WHERE id=[sqlid]") query.Execute() /datum/library_catalog/proc/getBookByID(id) @@ -121,7 +121,7 @@ var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "A var/sqlid = text2num(id) if(!sqlid) return - var/DBQuery/query = dbcon.NewQuery("SELECT id, author, title, category, content, ckey, flagged FROM [format_table_name("library")] WHERE id=[sqlid]") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id, author, title, category, content, ckey, flagged FROM [format_table_name("library")] WHERE id=[sqlid]") query.Execute() var/list/results=list() diff --git a/code/modules/library/random_books.dm b/code/modules/library/random_books.dm index 31d49489561..f571b3438e1 100644 --- a/code/modules/library/random_books.dm +++ b/code/modules/library/random_books.dm @@ -40,7 +40,7 @@ . = list() if(!isnum(amount) || amount<1) return - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) if(fail_loud || prob(5)) var/obj/item/paper/P = new(location) P.info = "There once was a book from Nantucket
    But the database failed us, so f*$! it.
    I tried to be good to you
    Now this is an I.O.U
    If you're feeling entitled, well, stuff it!

    ~" @@ -49,7 +49,7 @@ if(prob(25)) category = null var/c = category? " AND category='[sanitizeSQL(category)]'" :"" - var/DBQuery/query_get_random_books = dbcon.NewQuery("SELECT * FROM [format_table_name("library")] WHERE (isnull(flagged) OR flagged = 0)[c] GROUP BY title ORDER BY rand() LIMIT [amount];") + var/DBQuery/query_get_random_books = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("library")] WHERE (isnull(flagged) OR flagged = 0)[c] GROUP BY title ORDER BY rand() LIMIT [amount];") query_get_random_books.Execute() while(query_get_random_books.NextRow()) var/obj/item/book/B = new(location) diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 8e54531f901..fc87a855dc4 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -43,12 +43,10 @@ light_range = source_atom.light_range light_color = source_atom.light_color - parse_light_color() + PARSE_LIGHT_COLOR(src) update() - return ..() - /datum/light_source/Destroy(force) remove_lum() if(source_atom) @@ -94,17 +92,6 @@ /datum/light_source/proc/vis_update() EFFECT_UPDATE(LIGHTING_VIS_UPDATE) -// Decompile the hexadecimal colour into lumcounts of each perspective. -/datum/light_source/proc/parse_light_color() - if(light_color) - lum_r = GetRedPart (light_color) / 255 - lum_g = GetGreenPart (light_color) / 255 - lum_b = GetBluePart (light_color) / 255 - else - lum_r = 1 - lum_g = 1 - lum_b = 1 - // Macro that applies light to a new corner. // It is a macro in the interest of speed, yet not having to copy paste it. // If you're wondering what's with the backslashes, the backslashes cause BYOND to not automatically end the line. @@ -212,7 +199,7 @@ if(source_atom.light_color != light_color) light_color = source_atom.light_color - parse_light_color() + PARSE_LIGHT_COLOR(src) update = TRUE else if(applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b) @@ -233,7 +220,11 @@ var/oldlum = source_turf.luminosity source_turf.luminosity = CEILING(light_range, 1) for(T in view(CEILING(light_range, 1), source_turf)) - for (thing in T.get_corners(source_turf)) + if((!IS_DYNAMIC_LIGHTING(T) && !T.light_sources) || T.has_opaque_atom) + continue + if(!T.lighting_corners_initialised) + T.generate_missing_corners() + for(thing in T.corners) C = thing corners[C] = 0 turfs += T diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index c2198cea650..f368ff5ac4b 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -110,16 +110,6 @@ else lighting_clear_overlay() -/turf/proc/get_corners() - if(!IS_DYNAMIC_LIGHTING(src) && !light_sources) - return null - if(!lighting_corners_initialised) - generate_missing_corners() - if(has_opaque_atom) - return null // Since this proc gets used in a for loop, null won't be looped though. - - return corners - /turf/proc/generate_missing_corners() if(!IS_DYNAMIC_LIGHTING(src) && !light_sources) return @@ -132,4 +122,3 @@ continue corners[i] = new/datum/lighting_corner(src, GLOB.LIGHTING_CORNER_DIAGONAL[i]) - diff --git a/code/modules/map_fluff/maps.dm b/code/modules/map_fluff/maps.dm index b74ed7c9f3b..e2684d5c735 100644 --- a/code/modules/map_fluff/maps.dm +++ b/code/modules/map_fluff/maps.dm @@ -1,5 +1,3 @@ -var/datum/map/using_map = new USING_MAP_DATUM - /datum/map var/name = "Unnamed Map" var/full_name = "Unnamed Map" diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm index 64e7cba86cd..478438c47cb 100644 --- a/code/modules/martial_arts/martial.dm +++ b/code/modules/martial_arts/martial.dm @@ -227,7 +227,7 @@ /obj/item/twohanded/bostaff/attack(mob/target, mob/living/user) add_fingerprint(user) - if((CLUMSY in user.disabilities) && prob(50)) + if((CLUMSY in user.mutations) && prob(50)) to_chat(user, "You club yourself over the head with [src].") user.Weaken(3) if(ishuman(user)) diff --git a/code/modules/martial_arts/mimejutsu.dm b/code/modules/martial_arts/mimejutsu.dm index a6d6d9e3341..38904d407de 100644 --- a/code/modules/martial_arts/mimejutsu.dm +++ b/code/modules/martial_arts/mimejutsu.dm @@ -33,8 +33,8 @@ var/obj/item/organ/external/affecting = D.get_organ(ran_zone(A.zone_selected)) var/armor_block = D.run_armor_check(affecting, "melee") - D.visible_message("[A] has hit [D] with invisible nuncucks!", \ - "[A] has hit [D] with a with invisible nuncuck!") + D.visible_message("[A] has hit [D] with invisible nunchucks!", \ + "[A] has hit [D] with a with invisible nunchuck!") playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) D.apply_damage(damage, STAMINA, affecting, armor_block) diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm index 454b31b3b74..9b74c922a6b 100644 --- a/code/modules/mining/abandonedcrates.dm +++ b/code/modules/mining/abandonedcrates.dm @@ -82,7 +82,7 @@ new /obj/item/clothing/head/corgi(src) if(67 to 68) for(var/i in 1 to rand(4, 7)) - var /newitem = pick(subtypesof(/obj/item/stock_parts) - /obj/item/stock_parts/subspace) + var /newitem = pick(subtypesof(/obj/item/stock_parts)) new newitem(src) if(69 to 70) new /obj/item/stack/ore/bluespace_crystal(src, 5) diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index f21978db625..4af48e7050a 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -65,6 +65,8 @@ user.drop_l_hand() return var/datum/status_effect/crusher_damage/C = target.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) + if(!C) + C = target.apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) var/target_health = target.health ..() for(var/t in trophies) @@ -101,6 +103,8 @@ if(!CM || CM.hammer_synced != src || !L.remove_status_effect(STATUS_EFFECT_CRUSHERMARK)) return var/datum/status_effect/crusher_damage/C = L.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) + if(!C) + C = L.apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) var/target_health = L.health for(var/t in trophies) var/obj/item/crusher_trophy/T = t diff --git a/code/modules/mining/equipment/marker_beacons.dm b/code/modules/mining/equipment/marker_beacons.dm index e1456c475de..3df1699c7c1 100644 --- a/code/modules/mining/equipment/marker_beacons.dm +++ b/code/modules/mining/equipment/marker_beacons.dm @@ -58,10 +58,10 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list( transfer_fingerprints_to(M) /obj/item/stack/marker_beacon/AltClick(mob/living/user) - if(!istype(user) || CanUseTopic(user, physical_state) != STATUS_INTERACTIVE) + if(!istype(user) || CanUseTopic(user, GLOB.physical_state) != STATUS_INTERACTIVE) return var/input_color = input(user, "Choose a color.", "Beacon Color") as null|anything in GLOB.marker_beacon_colors - if(!istype(user) || CanUseTopic(user, physical_state) != STATUS_INTERACTIVE) + if(!istype(user) || CanUseTopic(user, GLOB.physical_state) != STATUS_INTERACTIVE) return if(input_color) picked_color = input_color @@ -130,10 +130,10 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list( /obj/structure/marker_beacon/AltClick(mob/living/user) ..() - if(!istype(user) || CanUseTopic(user, physical_state) != STATUS_INTERACTIVE) + if(!istype(user) || CanUseTopic(user, GLOB.physical_state) != STATUS_INTERACTIVE) return var/input_color = input(user, "Choose a color.", "Beacon Color") as null|anything in GLOB.marker_beacon_colors - if(!istype(user) || CanUseTopic(user, physical_state) != STATUS_INTERACTIVE) + if(!istype(user) || CanUseTopic(user, GLOB.physical_state) != STATUS_INTERACTIVE) return if(input_color) picked_color = input_color diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index bb2ce3a68f8..0c7b836b322 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -19,7 +19,7 @@ /obj/item/survivalcapsule/proc/get_template() if(template) return - template = shelter_templates[template_id] + template = GLOB.shelter_templates[template_id] if(!template) log_runtime("Shelter template ([template_id]) not found!", src) qdel(src) diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm index e9d04cc406b..dbb41229e27 100644 --- a/code/modules/mining/laborcamp/laborstacker.dm +++ b/code/modules/mining/laborcamp/laborstacker.dm @@ -58,7 +58,7 @@ GLOBAL_LIST(labor_sheet_values) /obj/machinery/mineral/labor_claim_console/attack_ghost(mob/user) attack_hand(user) -/obj/machinery/mineral/labor_claim_console/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/obj/machinery/mineral/labor_claim_console/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "labor_claim_console.tmpl", name, 450, 625, state) @@ -109,7 +109,7 @@ GLOBAL_LIST(labor_sheet_values) if(!alone_in_area(get_area(src), usr)) to_chat(usr, "Prisoners are only allowed to be released while alone.") else - switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE)) + switch(SSshuttle.moveShuttle("laborcamp", "laborcamp_home", TRUE, usr)) if(1) to_chat(usr, "Shuttle not found.") if(2) @@ -121,6 +121,7 @@ GLOBAL_LIST(labor_sheet_values) var/message = "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval." announcer.autosay(message, "Labor Camp Controller", "Security") to_chat(usr, "Shuttle received message and will be sent shortly.") + usr.create_log(MISC_LOG, "used [src] to call the laborcamp shuttle") return TRUE diff --git a/code/modules/mining/lavaland/loot/colossus_loot.dm b/code/modules/mining/lavaland/loot/colossus_loot.dm index 7b321474880..0bde4d95464 100644 --- a/code/modules/mining/lavaland/loot/colossus_loot.dm +++ b/code/modules/mining/lavaland/loot/colossus_loot.dm @@ -306,7 +306,7 @@ if(H.stat == DEAD) H.set_species(/datum/species/shadow) H.revive() - H.disabilities |= NOCLONE //Free revives, but significantly limits your options for reviving except via the crystal + H.mutations |= NOCLONE //Free revives, but significantly limits your options for reviving except via the crystal H.grab_ghost(force = TRUE) /obj/machinery/anomalous_crystal/helpers //Lets ghost spawn as helpful creatures that can only heal people slightly. Incredibly fragile and they can't converse with humans @@ -374,7 +374,7 @@ ..() verbs -= /mob/living/verb/pulled verbs -= /mob/verb/me_verb - var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] medsensor.add_hud_to(src) /mob/living/simple_animal/hostile/lightgeist/AttackingTarget() @@ -458,7 +458,7 @@ if(isliving(A) && holder_animal) var/mob/living/L = A L.notransform = 1 - L.disabilities |= MUTE + L.mutations |= MUTE L.status_flags |= GODMODE L.mind.transfer_to(holder_animal) var/obj/effect/proc_holder/spell/targeted/exit_possession/P = new /obj/effect/proc_holder/spell/targeted/exit_possession @@ -468,7 +468,7 @@ /obj/structure/closet/stasis/dump_contents(var/kill = 1) STOP_PROCESSING(SSobj, src) for(var/mob/living/L in src) - L.disabilities &= ~MUTE + L.mutations -=MUTE L.status_flags &= ~GODMODE L.notransform = 0 if(holder_animal && !QDELETED(holder_animal)) diff --git a/code/modules/mining/lavaland/loot/hierophant_loot.dm b/code/modules/mining/lavaland/loot/hierophant_loot.dm index bd06e2fe47a..a3f6e738380 100644 --- a/code/modules/mining/lavaland/loot/hierophant_loot.dm +++ b/code/modules/mining/lavaland/loot/hierophant_loot.dm @@ -254,7 +254,7 @@ var/obj/effect/temp_visual/hierophant/blast/B = new(T, user, friendly_fire_check) B.damage = HIEROPHANT_CLUB_CARDINAL_DAMAGE B.monster_damage_boost = FALSE - for(var/d in cardinal) + for(var/d in GLOB.cardinal) INVOKE_ASYNC(src, .proc/blast_wall, T, d, user) /obj/item/hierophant_club/proc/blast_wall(turf/T, dir, mob/living/user) //make a wall of blasts blast_range tiles long diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 50cb7d09801..579df861c19 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -98,7 +98,7 @@ /obj/machinery/mineral/processing_unit/Destroy() CONSOLE = null QDEL_NULL(files) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_all() return ..() @@ -120,7 +120,7 @@ CONSOLE.updateUsrDialog() /obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/material_amount = materials.get_item_material_amount(O) if(!materials.has_space(material_amount)) unload_mineral(O) @@ -132,7 +132,7 @@ /obj/machinery/mineral/processing_unit/proc/get_machine_data() var/dat = "Smelter control console

    " - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] dat += "[M.name]: [M.amount] cm³" @@ -165,7 +165,7 @@ return dat /obj/machinery/mineral/processing_unit/proc/smelt_ore() - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/datum/material/mat = materials.materials[selected_material] if(mat) var/sheets_to_remove = (mat.amount >= (MINERAL_MATERIAL_AMOUNT * SMELT_AMOUNT) ) ? SMELT_AMOUNT : round(mat.amount / MINERAL_MATERIAL_AMOUNT) @@ -187,7 +187,7 @@ on = FALSE return - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.use_amount(alloy.materials, amount) generate_mineral(alloy.build_path) @@ -198,7 +198,7 @@ var/build_amount = SMELT_AMOUNT - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in D.materials) var/M = D.materials[mat_id] diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index 20189c2793b..7f1b520e7f8 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -67,7 +67,7 @@ /obj/machinery/mineral/ore_redemption/Destroy() QDEL_NULL(files) - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) materials.retrieve_all() return ..() @@ -92,7 +92,7 @@ if(O && O.refined_type) points += O.points * point_upgrade * O.amount - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/material_amount = materials.get_item_material_amount(O) if(!material_amount) @@ -111,7 +111,7 @@ var/build_amount = 0 - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in D.materials) var/M = D.materials[mat_id] var/datum/material/redemption_mat = materials.materials[mat_id] @@ -147,7 +147,7 @@ var/has_minerals = FALSE var/mineral_name = null - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT @@ -159,7 +159,7 @@ if(!has_minerals) return - for(var/obj/machinery/requests_console/D in allConsoles) + for(var/obj/machinery/requests_console/D in GLOB.allRequestConsoles) if(D.department in src.supply_consoles) if(supply_consoles[D.department] == null || (mineral_name in supply_consoles[D.department])) D.createMessage("Ore Redemption Machine", "New Minerals Available!", msg, 1) @@ -251,7 +251,7 @@ else dat += "No ID inserted. Insert ID.

    " - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] if(M.amount) @@ -302,7 +302,7 @@ /obj/machinery/mineral/ore_redemption/Topic(href, href_list) if(..()) return - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) if(href_list["eject_id"]) usr.put_in_hands(inserted_id) inserted_id = null diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm index 9fb73229ba7..c6d23a1bbde 100644 --- a/code/modules/mining/mint.dm +++ b/code/modules/mining/mint.dm @@ -23,7 +23,7 @@ if(!T) return - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/obj/item/stack/sheet/O in T) materials.insert_stack(O, O.amount) @@ -32,7 +32,7 @@ return var/dat = "Coin Press
    " - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] if(!M.amount && chosen != mat_id) @@ -65,7 +65,7 @@ if(processing == 1) to_chat(usr, "The machine is processing.") return - GET_COMPONENT(materials, /datum/component/material_container) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) if(href_list["choose"]) if(materials.materials[href_list["choose"]]) chosen = href_list["choose"] diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 6f9572a8a0c..8737fdf21b3 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -14,12 +14,12 @@ var/points = 0 //How many points this ore gets you from the ore redemption machine var/refined_type = null //What this ore defaults to being refined into -/obj/item/stack/ore/New() +/obj/item/stack/ore/New(loc, new_amount, merge = TRUE) ..() pixel_x = rand(0, 16) - 8 pixel_y = rand(0, 8) - 8 if(is_mining_level(z)) - score_oremined++ //When ore spawns, increment score. Only include ore spawned on mining level (No Clown Planet) + GLOB.score_oremined++ //When ore spawns, increment score. Only include ore spawned on mining level (No Clown Planet) /obj/item/stack/ore/welder_act(mob/user, obj/item/I) . = TRUE diff --git a/code/modules/mob/abilities.dm b/code/modules/mob/abilities.dm deleted file mode 100644 index 8c4aabc4fc8..00000000000 --- a/code/modules/mob/abilities.dm +++ /dev/null @@ -1,5 +0,0 @@ -/* -Creature-level abilities. -*/ - -/var/global/list/ability_verbs = list( ) diff --git a/code/modules/mob/dead/observer/logout.dm b/code/modules/mob/dead/observer/logout.dm index a28bef6be5d..8622ba7c845 100644 --- a/code/modules/mob/dead/observer/logout.dm +++ b/code/modules/mob/dead/observer/logout.dm @@ -1,6 +1,6 @@ /mob/dead/observer/Logout() if(client) - client.images -= ghost_images + client.images -= GLOB.ghost_images ..() spawn(0) if(src && !key) //we've transferred to another mob. This ghost should be deleted. diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 98dcebdae49..dc7c2b4439e 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -1,7 +1,7 @@ #define GHOST_CAN_REENTER 1 #define GHOST_IS_OBSERVER 2 -var/list/image/ghost_images = list() +GLOBAL_LIST_EMPTY(ghost_images) GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) @@ -53,7 +53,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) var/turf/T if(ismob(body)) T = get_turf(body) //Where is the body located? - attack_log = body.attack_log //preserve our attack logs by copying them to our ghost + attack_log_old = body.attack_log_old //preserve our attack logs by copying them to our ghost + logs = body.logs.Copy() var/mutable_appearance/MA = copy_appearance(body) if(body.mind && body.mind.name) @@ -75,10 +76,10 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) ghostimage.appearance_flags |= KEEP_TOGETHER ghostimage.alpha = alpha appearance_flags |= KEEP_TOGETHER - ghost_images |= ghostimage + GLOB.ghost_images |= ghostimage updateallghostimages() - if(!T) - T = pick(latejoin) //Safety in case we cannot find the body's position + if(!T) + T = pick(GLOB.latejoin) //Safety in case we cannot find the body's position forceMove(T) if(!name) //To prevent nameless ghosts @@ -90,12 +91,8 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) ..() /mob/dead/observer/Destroy() - if(ismob(following)) - var/mob/M = following - M.following_mobs -= src - following = null if(ghostimage) - ghost_images -= ghostimage + GLOB.ghost_images -= ghostimage QDEL_NULL(ghostimage) updateallghostimages() return ..() @@ -116,7 +113,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) MA.blend_mode = COPY.blend_mode MA.color = COPY.color MA.dir = COPY.dir - MA.gender = COPY.gender MA.icon = COPY.icon MA.icon_state = COPY.icon_state MA.layer = COPY.layer @@ -130,7 +126,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) if(!isicon(MA.icon) && !LAZYLEN(MA.overlays)) // Gibbing/dusting/melting removes the icon before ghostize()ing the mob, so we need to account for that MA.icon = initial(icon) MA.icon_state = initial(icon_state) - MA.suffix = COPY.suffix MA.underlays = COPY.underlays . = MA @@ -143,13 +138,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) Transfer_mind is there to check if mob is being deleted/not going to have a body. Works together with spawning an observer, noted above. */ -/mob/dead/observer/Life(seconds, times_fired) - ..() - if(!loc) return - if(!client) return 0 - - - /mob/dead/proc/assess_targets(list/target_list, mob/dead/observer/U) var/client/C = U.client for(var/mob/living/carbon/human/target in target_list) @@ -319,11 +307,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp src << sound(sound) /mob/dead/observer/proc/show_me_the_hud(hud_index) - var/datum/atom_hud/H = huds[hud_index] + var/datum/atom_hud/H = GLOB.huds[hud_index] H.add_hud_to(src) /mob/dead/observer/proc/remove_the_hud(hud_index) //remove old huds - var/datum/atom_hud/H = huds[hud_index] + var/datum/atom_hud/H = GLOB.huds[hud_index] H.remove_hud_from(src) /mob/dead/observer/verb/toggle_medHUD() @@ -340,7 +328,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp show_me_the_hud(DATA_HUD_SECURITY_ADVANCED) show_me_the_hud(DATA_HUD_MEDICAL_ADVANCED) to_chat(src, "All HUDs enabled.") - if(DATA_HUD_DIAGNOSTIC + DATA_HUD_SECURITY_ADVANCED + DATA_HUD_MEDICAL_ADVANCED) + if(DATA_HUD_DIAGNOSTIC + DATA_HUD_SECURITY_ADVANCED + DATA_HUD_MEDICAL_ADVANCED) data_hud_seen = DATA_HUD_SECURITY_ADVANCED remove_the_hud(DATA_HUD_DIAGNOSTIC) remove_the_hud(DATA_HUD_MEDICAL_ADVANCED) @@ -386,7 +374,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp //var/datum/atom_hud/A = huds[DATA_HUD_SECURITY_ADVANCED] //var/adding_hud = (usr in A.hudusers) ? 0 : 1 - for(var/datum/atom_hud/antag/H in (huds)) + for(var/datum/atom_hud/antag/H in (GLOB.huds)) if(!M.antagHUD) H.add_hud_to(usr) else @@ -407,7 +395,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp to_chat(usr, "Not when you're not dead!") return - var/datum/async_input/A = input_autocomplete_async(usr, "Area to jump to: ", ghostteleportlocs) + var/datum/async_input/A = input_autocomplete_async(usr, "Area to jump to: ", GLOB.ghostteleportlocs) A.on_close(CALLBACK(src, .proc/teleport)) /mob/dead/observer/proc/teleport(area/thearea) @@ -431,7 +419,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set name = "Orbit" // "Haunt" set desc = "Follow and orbit a mob." - var/list/mobs = getpois(skip_mindless=1) + var/list/mobs = getpois(FALSE, TRUE, TRUE, TRUE) var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a mob: ", mobs) A.on_close(CALLBACK(src, .proc/ManualFollow)) @@ -478,35 +466,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp setDir(2)//reset dir so the right directional sprites show up return ..() -/mob/proc/update_following() - . = get_turf(src) - for(var/mob/dead/observer/M in following_mobs) - if(M.following != src) - following_mobs -= M - else - if(M.loc != .) - M.forceMove(.) - -/mob - var/list/following_mobs = list() - -/mob/Move() - . = ..() - if(.) - update_following() - -/mob/Life(seconds, times_fired) - // to catch teleports etc which directly set loc - update_following() - return ..() - /mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak set category = "Ghost" set name = "Jump to Mob" set desc = "Teleport to a mob" - if(isobserver(usr)) //Make sure they're an observer! - var/list/dest = getpois(mobs_only=1) //Fill list, prompt user with list + if(isobserver(usr)) //Make sure they're an observer! + var/list/dest = getpois(mobs_only=TRUE) //Fill list, prompt user with list var/datum/async_input/A = input_autocomplete_async(usr, "Enter a mob name: ", dest) A.on_close(CALLBACK(src, .proc/jump_to_mob)) @@ -616,7 +582,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp var/dat dat += "

    Crew Manifest

    " - dat += data_core.get_manifest() + dat += GLOB.data_core.get_manifest() src << browse(dat, "window=manifest;size=370x420;can_close=1") @@ -743,10 +709,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp if(!client) return if(seedarkness || !ghostvision) - client.images -= ghost_images + client.images -= GLOB.ghost_images else //add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now - client.images |= ghost_images + client.images |= GLOB.ghost_images if(ghostimage) client.images -= ghostimage //remove ourself diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 57232d74f44..5f18a27adc9 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -59,6 +59,7 @@ var/mob/living/L = src L.say_log += "EMOTE: [input]" //say log too so it is easier on admins instead of having to merge the two with timestamps etc L.emote_log += input //emote only log if an admin wants to search just for emotes they don't have to sift through the say + create_log(EMOTE_LOG, input) // TODO after #13047: Include the channel // Hearing gasp and such every five seconds is not good emotes were not global for a reason. // Maybe some people are okay with that. for(var/mob/M in GLOB.player_list) diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index cc497adc3e0..2b07e10291f 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -90,7 +90,7 @@ if(speaker_name != speaker.real_name && speaker.real_name) speaker_name = "[speaker.real_name] ([speaker_name])" track = "([ghost_follow_link(speaker, ghost=src)]) " - if(client.prefs.toggles & CHAT_GHOSTEARS && speaker in view(src)) + if(client.prefs.toggles & CHAT_GHOSTEARS && (speaker in view(src))) message = "[message]" if(!can_hear()) diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index ee9a3c3cca2..f89d19afaac 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -22,7 +22,6 @@ var/atom/movable/mob_container mob_container = M mob_container.forceMove(get_turf(src)) - M.reset_perspective() qdel(src) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 6d96d77c321..8f4f4dbb2da 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -214,9 +214,9 @@ if(M.equip_to_appropriate_slot(src)) if(M.hand) - M.update_inv_l_hand(0) + M.update_inv_l_hand() else - M.update_inv_r_hand(0) + M.update_inv_r_hand() return 1 if(M.s_active && M.s_active.can_be_inserted(src, 1)) //if storage active insert there diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 5936a0624d0..7f3a7049558 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -98,7 +98,9 @@ if(!check_can_speak(speaker)) return FALSE - log_say("([name]-HIVE) [message]", speaker) + var/log_message = "([name]-HIVE) [message]" + log_say(log_message, speaker) + speaker.create_log(SAY_LOG, log_message) if(!speaker_mask) speaker_mask = speaker.name @@ -605,7 +607,10 @@ if(!message) return - log_say("(ROBOT) [message]", speaker) + var/log_message = "(ROBOT) [message]" + log_say(log_message, speaker) + speaker.create_log(SAY_LOG, log_message) + var/message_start = "[name], [speaker.name]" var/message_body = "[speaker.say_quote(message)],\"[message]\"" @@ -614,7 +619,7 @@ var/message_start_dead = "[name], [speaker.name] ([ghost_follow_link(speaker, ghost=M)])" M.show_message("[message_start_dead] [message_body]", 2) - for(var/mob/living/S in GLOB.living_mob_list) + for(var/mob/living/S in GLOB.alive_mob_list) if(drone_only && !istype(S,/mob/living/silicon/robot/drone)) continue else if(isAI(S)) diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 1b85c3e5386..247e0bcbab2 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -26,6 +26,8 @@ var/death_sound = 'sound/voice/hiss6.ogg' /mob/living/carbon/alien/New() + ..() + create_reagents(1000) verbs += /mob/living/verb/mob_sleep verbs += /mob/living/verb/lay_down alien_organs += new /obj/item/organ/internal/brain/xeno @@ -33,7 +35,6 @@ alien_organs += new /obj/item/organ/internal/ears for(var/obj/item/organ/internal/I in alien_organs) I.insert(src) - ..() /mob/living/carbon/alien/get_default_language() if(default_language) @@ -67,18 +68,6 @@ /mob/living/carbon/alien/check_eye_prot() return 2 -/mob/living/carbon/alien/updatehealth(reason = "none given") - if(status_flags & GODMODE) - health = maxHealth - stat = CONSCIOUS - return - health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() - - update_stat("updatehealth([reason])") - med_hud_set_health() - med_hud_set_status() - handle_hud_icons_health() - /mob/living/carbon/alien/handle_environment(var/datum/gas_mixture/environment) if(!environment) @@ -118,12 +107,6 @@ else clear_alert("alien_fire") -/mob/living/carbon/alien/handle_fire()//Aliens on fire code - if(..()) - return - bodytemperature += BODYTEMP_HEATING_MAX //If you're on fire, you heat up! - return - /mob/living/carbon/alien/IsAdvancedToolUser() return has_fine_manipulation diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm index 2d894ee357e..99900183185 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm @@ -6,7 +6,6 @@ icon_state = "aliend_s" /mob/living/carbon/alien/humanoid/drone/New() - create_reagents(100) if(src.name == "alien drone") src.name = text("alien drone ([rand(1, 1000)])") src.real_name = src.name @@ -26,7 +25,7 @@ if(powerc(500)) // Queen check var/no_queen = 1 - for(var/mob/living/carbon/alien/humanoid/queen/Q in GLOB.living_mob_list) + for(var/mob/living/carbon/alien/humanoid/queen/Q in GLOB.alive_mob_list) if(!Q.key && Q.get_int_organ(/obj/item/organ/internal/brain/)) continue no_queen = 0 diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index 4cba49a2a03..f23f9b7aa42 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -6,7 +6,6 @@ icon_state = "alienh_s" /mob/living/carbon/alien/humanoid/hunter/New() - create_reagents(100) if(name == "alien hunter") name = text("alien hunter ([rand(1, 1000)])") real_name = name @@ -17,28 +16,6 @@ . = -1 //hunters are sanic . += ..() //but they still need to slow down on stun -/mob/living/carbon/alien/humanoid/hunter/handle_hud_icons_health() - ..() //-Yvarov - - if(healths) - if(stat != 2) - switch(health) - if(125 to INFINITY) - healths.icon_state = "health0" - if(100 to 125) - healths.icon_state = "health1" - if(50 to 100) - healths.icon_state = "health2" - if(25 to 50) - healths.icon_state = "health3" - if(0 to 25) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - - /mob/living/carbon/alien/humanoid/hunter/handle_environment() if(m_intent == MOVE_INTENT_RUN || resting) ..() @@ -83,7 +60,7 @@ else //Maybe uses plasma in the future, although that wouldn't make any sense... leaping = 1 update_icons() - throw_at(A, MAX_ALIEN_LEAP_DIST, 1, spin = 0, diagonals_first = 1, callback = CALLBACK(src, .leap_end)) + throw_at(A, MAX_ALIEN_LEAP_DIST, 1, spin = 0, diagonals_first = 1, callback = CALLBACK(src, .proc/leap_end)) /mob/living/carbon/alien/humanoid/hunter/proc/leap_end() leaping = 0 diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm index c436a43e4ff..4dd2d1b8569 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm @@ -33,7 +33,6 @@ overlays += I /mob/living/carbon/alien/humanoid/sentinel/New() - create_reagents(100) if(name == "alien sentinel") name = text("alien sentinel ([rand(1, 1000)])") real_name = name @@ -42,27 +41,6 @@ alien_organs += new /obj/item/organ/internal/xenos/neurotoxin ..() -/mob/living/carbon/alien/humanoid/sentinel/handle_hud_icons_health() - ..() //-Yvarov - - if(healths) - if(stat != 2) - switch(health) - if(150 to INFINITY) - healths.icon_state = "health0" - if(100 to 150) - healths.icon_state = "health1" - if(75 to 100) - healths.icon_state = "health2" - if(25 to 75) - healths.icon_state = "health3" - if(0 to 25) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - /* /mob/living/carbon/alien/humanoid/sentinel/verb/evolve() // -- TLE set name = "Evolve (250)" diff --git a/code/modules/mob/living/carbon/alien/humanoid/empress.dm b/code/modules/mob/living/carbon/alien/humanoid/empress.dm index a64602d030c..63514686f3d 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/empress.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/empress.dm @@ -30,17 +30,17 @@ overlays += I /mob/living/carbon/alien/humanoid/empress/New() - create_reagents(100) - //there should only be one queen - for(var/mob/living/carbon/alien/humanoid/empress/E in GLOB.living_mob_list) - if(E == src) continue - if(E.stat == DEAD) continue + for(var/mob/living/carbon/alien/humanoid/empress/E in GLOB.alive_mob_list) + if(E == src) + continue + if(E.stat == DEAD) + continue if(E.client) name = "alien grand princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it. break - real_name = src.name + real_name = name alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/queen alien_organs += new /obj/item/organ/internal/xenos/acidgland alien_organs += new /obj/item/organ/internal/xenos/eggsac @@ -48,27 +48,6 @@ alien_organs += new /obj/item/organ/internal/xenos/neurotoxin ..() -/mob/living/carbon/alien/humanoid/empress/handle_hud_icons_health() - ..() //-Yvarov - - if(healths) - if(stat != 2) - switch(health) - if(250 to INFINITY) - healths.icon_state = "health0" - if(175 to 250) - healths.icon_state = "health1" - if(100 to 175) - healths.icon_state = "health2" - if(50 to 100) - healths.icon_state = "health3" - if(0 to 50) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - /mob/living/carbon/alien/humanoid/empress/verb/lay_egg() set name = "Lay Egg (250)" set desc = "Lay an egg to produce huggers to impregnate prey with." diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index 29b37294cc4..e82488ee064 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -2,7 +2,7 @@ name = "alien" icon_state = "alien_s" - butcher_results = list(/obj/item/reagent_containers/food/snacks/xenomeat = 5, /obj/item/stack/sheet/animalhide/xeno = 1) + butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/xenomeat= 5, /obj/item/stack/sheet/animalhide/xeno = 1) var/obj/item/r_store = null var/obj/item/l_store = null var/caste = "" @@ -17,7 +17,6 @@ //This is fine right now, if we're adding organ specific damage this needs to be updated /mob/living/carbon/alien/humanoid/New() - create_reagents(1000) if(name == "alien") name = text("alien ([rand(1, 1000)])") real_name = name diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm index 646f069970b..071987f808e 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/life.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm @@ -2,27 +2,6 @@ . = ..() update_icons() - - -/mob/living/carbon/alien/humanoid/handle_disabilities() - if(disabilities & EPILEPSY) - if((prob(1) && paralysis < 10)) - to_chat(src, "You have a seizure!") - Paralyse(10) - if(disabilities & COUGHING) - if((prob(5) && paralysis <= 1)) - drop_item() - emote("cough") - return - if(disabilities & TOURETTES) - if((prob(10) && paralysis <= 1)) - Stun(10) - emote("twitch") - return - if(disabilities & NERVOUS) - if(prob(10)) - stuttering = max(10, stuttering) - /mob/living/carbon/alien/humanoid/proc/adjust_body_temperature(current, loc_temp, boost) var/temperature = current var/difference = abs(current-loc_temp) //get difference @@ -39,51 +18,3 @@ temperature = max(loc_temp, temperature-change) temp_change = (temperature - current) return temp_change - -/mob/living/carbon/alien/humanoid/handle_regular_status_updates() - updatehealth() - - if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP - SetSilence(0) - else //ALIVE. LIGHTS ARE ON - if(health < HEALTH_THRESHOLD_DEAD && check_death_method() || !get_int_organ(/obj/item/organ/internal/brain)) - death() - SetSilence(0) - return 1 - - //UNCONSCIOUS. NO-ONE IS HOME - if((getOxyLoss() > 50) || (HEALTH_THRESHOLD_CRIT >= health && check_death_method())) - if(health <= 20 && prob(1)) - emote("gasp") - if(!reagents.has_reagent("epinephrine")) - adjustOxyLoss(1) - Paralyse(3) - - if(paralysis) - stat = UNCONSCIOUS - else if(sleeping) - stat = UNCONSCIOUS - if(prob(10) && health) - emote("hiss") - //CONSCIOUS - else - stat = CONSCIOUS - - /* What in the living hell is this?*/ - if(move_delay_add > 0) - move_delay_add = max(0, move_delay_add - rand(1, 2)) - - if(eye_blind) //blindness, heals slowly over time - AdjustEyeBlind(-1) - else if(eye_blurry) //blurry eyes heal slowly - AdjustEyeBlurry(-1) - - if(stuttering) - AdjustStuttering(-1) - - if(silent) - AdjustSilence(-1) - - if(druggy) - AdjustDruggy(-1) - return 1 diff --git a/code/modules/mob/living/carbon/alien/humanoid/queen.dm b/code/modules/mob/living/carbon/alien/humanoid/queen.dm index 13eb62587be..3adb87ad505 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/queen.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/queen.dm @@ -11,12 +11,12 @@ pressure_resistance = 200 //Because big, stompy xenos should not be blown around like paper. /mob/living/carbon/alien/humanoid/queen/New() - create_reagents(100) - //there should only be one queen - for(var/mob/living/carbon/alien/humanoid/queen/Q in GLOB.living_mob_list) - if(Q == src) continue - if(Q.stat == DEAD) continue + for(var/mob/living/carbon/alien/humanoid/queen/Q in GLOB.alive_mob_list) + if(Q == src) + continue + if(Q.stat == DEAD) + continue if(Q.client) name = "alien princess ([rand(1, 999)])" //if this is too cutesy feel free to change it/remove it. break @@ -33,28 +33,7 @@ . = ..() . += 3 -/mob/living/carbon/alien/humanoid/queen/handle_hud_icons_health() - ..() //-Yvarov - - if(healths) - if(stat != DEAD) - switch(health) - if(250 to INFINITY) - healths.icon_state = "health0" - if(175 to 250) - healths.icon_state = "health1" - if(100 to 175) - healths.icon_state = "health2" - if(50 to 100) - healths.icon_state = "health3" - if(0 to 50) - healths.icon_state = "health4" - else - healths.icon_state = "health5" - else - healths.icon_state = "health6" - -/mob/living/carbon/alien/humanoid/queen/can_inject() +/mob/living/carbon/alien/humanoid/queen/can_inject(mob/user, error_msg, target_zone, penetrate_thick) return FALSE //Queen verbs diff --git a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm index 4b7845b0a0a..94c65095f01 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/update_icons.dm @@ -56,20 +56,21 @@ /mob/living/carbon/alien/humanoid/regenerate_icons() ..() - if(notransform) return + if(notransform) + return - update_inv_head(0,0) - update_inv_wear_suit(0,0) - update_inv_r_hand(0) - update_inv_l_hand(0) - update_inv_pockets(0) + update_inv_head() + update_inv_wear_suit() + update_inv_r_hand() + update_inv_l_hand() + update_inv_pockets() update_icons() update_fire() update_transform() /mob/living/carbon/alien/humanoid/update_transform() //The old method of updating lying/standing was update_icons(). Aliens still expect that. if(lying > 0) - lying = 90 //Anything else looks retarded + lying = 90 //Anything else looks lousy ..() update_icons() @@ -82,7 +83,7 @@ else overlays_standing[X_FIRE_LAYER] = null -/mob/living/carbon/alien/humanoid/update_inv_wear_suit(var/update_icons=1) +/mob/living/carbon/alien/humanoid/update_inv_wear_suit() if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_suit] inv.update_icon() @@ -110,10 +111,10 @@ overlays_standing[X_SUIT_LAYER] = standing else overlays_standing[X_SUIT_LAYER] = null - if(update_icons) update_icons() + update_icons() -/mob/living/carbon/alien/humanoid/update_inv_head(var/update_icons=1) +/mob/living/carbon/alien/humanoid/update_inv_head() if(head) var/t_state = head.item_state if(!t_state) t_state = head.icon_state @@ -124,17 +125,19 @@ overlays_standing[X_HEAD_LAYER] = standing else overlays_standing[X_HEAD_LAYER] = null - if(update_icons) update_icons() + update_icons() -/mob/living/carbon/alien/humanoid/update_inv_pockets(var/update_icons=1) - if(l_store) l_store.screen_loc = ui_storage1 - if(r_store) r_store.screen_loc = ui_storage2 - if(update_icons) update_icons() +/mob/living/carbon/alien/humanoid/update_inv_pockets() + if(l_store) + l_store.screen_loc = ui_storage1 + if(r_store) + r_store.screen_loc = ui_storage2 + update_icons() -/mob/living/carbon/alien/humanoid/update_inv_r_hand(var/update_icons=1) - ..(1) +/mob/living/carbon/alien/humanoid/update_inv_r_hand() + ..() if(r_hand) var/t_state = r_hand.item_state if(!t_state) t_state = r_hand.icon_state @@ -142,10 +145,10 @@ overlays_standing[X_R_HAND_LAYER] = image("icon" = r_hand.righthand_file, "icon_state" = t_state) else overlays_standing[X_R_HAND_LAYER] = null - if(update_icons) update_icons() + update_icons() -/mob/living/carbon/alien/humanoid/update_inv_l_hand(var/update_icons=1) - ..(1) +/mob/living/carbon/alien/humanoid/update_inv_l_hand() + ..() if(l_hand) var/t_state = l_hand.item_state if(!t_state) t_state = l_hand.icon_state @@ -153,7 +156,7 @@ overlays_standing[X_L_HAND_LAYER] = image("icon" = l_hand.lefthand_file, "icon_state" = t_state) else overlays_standing[X_L_HAND_LAYER] = null - if(update_icons) update_icons() + update_icons() //Xeno Overlays Indexes////////// diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index a55126ec045..aeee677b905 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -5,8 +5,8 @@ pass_flags = PASSTABLE | PASSMOB mob_size = MOB_SIZE_SMALL - maxHealth = 30 - health = 30 + maxHealth = 25 + health = 25 density = 0 var/amount_grown = 0 @@ -17,7 +17,6 @@ //This is fine right now, if we're adding organ specific damage this needs to be updated /mob/living/carbon/alien/larva/New() - create_reagents(100) if(name == "alien larva") name = "alien larva ([rand(1, 1000)])" real_name = name @@ -25,7 +24,6 @@ add_language("Xenomorph") add_language("Hivemind") alien_organs += new /obj/item/organ/internal/xenos/plasmavessel/larva - ..() //This needs to be fixed diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index fd1543673e6..496a12cbf82 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -1,57 +1,28 @@ /mob/living/carbon/alien/larva/Life(seconds, times_fired) - if(..()) //still breathing + set invisibility = 0 + if(notransform) + return + if(..()) //not dead and not in stasis // GROW! if(amount_grown < max_grown) amount_grown++ + update_icons() - //some kind of bug in canmove() isn't properly calling update_icons, so this is here as a placeholder - update_icons() - -/mob/living/carbon/alien/larva/handle_regular_status_updates() - updatehealth() - - if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP - SetSilence(0) - else //ALIVE. LIGHTS ARE ON - if(health < -25 || !get_int_organ(/obj/item/organ/internal/brain)) +/mob/living/carbon/alien/larva/update_stat(reason = "None given") + if(status_flags & GODMODE) + return + if(stat != DEAD) + if(health <= -maxHealth || !get_int_organ(/obj/item/organ/internal/brain)) death() - SetSilence(0) - return 1 + return - //UNCONSCIOUS. NO-ONE IS HOME - if((getOxyLoss() > 25) || (HEALTH_THRESHOLD_CRIT >= health && check_death_method())) - //if( health <= 20 && prob(1) ) - // spawn(0) - // emote("gasp") - if(!reagents.has_reagent("epinephrine")) - adjustOxyLoss(1) - Paralyse(3) - - if(paralysis) - stat = UNCONSCIOUS - else if(sleeping) - stat = UNCONSCIOUS - if(prob(10) && health) - emote("hiss_") - //CONSCIOUS + if(paralysis || sleeping || getOxyLoss() > 50 || (HEALTH_THRESHOLD_CRIT <= health && check_death_method())) + if(stat == CONSCIOUS) + KnockOut() + create_debug_log("fell unconscious, trigger reason: [reason]") else - stat = CONSCIOUS - - /* What in the living hell is this?*/ - if(move_delay_add > 0) - move_delay_add = max(0, move_delay_add - rand(1, 2)) - - if(eye_blind) //blindness, heals slowly over time - AdjustEyeBlind(-1) - else if(eye_blurry) //blurry eyes heal slowly - AdjustEyeBlurry(-1) - - if(stuttering) - AdjustStuttering(-1) - - if(silent) - AdjustSilence(-1) - - if(druggy) - AdjustDruggy(-1) - return 1 + if(stat == UNCONSCIOUS) + WakeUp() + create_debug_log("woke up, trigger reason: [reason]") + update_damage_hud() + update_health_hud() diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index a584f66dc97..5a1d08a010a 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -28,3 +28,15 @@ //BREATH TEMPERATURE handle_breath_temperature(breath) + +/mob/living/carbon/alien/handle_status_effects() + ..() + //natural reduction of movement delay due to stun. + if(move_delay_add > 0) + move_delay_add = max(0, move_delay_add - rand(1, 2)) + +/mob/living/carbon/alien/handle_fire()//Aliens on fire code + . = ..() + if(.) //if the mob isn't on fire anymore + return + adjust_bodytemperature(BODYTEMP_HEATING_MAX) //If you're on fire, you heat up! diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index 80f3c73d3d7..1dcd76c0358 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -83,7 +83,7 @@ return Attach(AM) return 0 -/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed) +/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force) if(!..()) return if(stat == CONSCIOUS) @@ -146,7 +146,7 @@ "[src] tears [W] off of [target]'s face!") src.loc = target - target.equip_to_slot(src, slot_wear_mask,,0) + target.equip_to_slot_if_possible(src, slot_wear_mask, FALSE, TRUE) if(!sterile) M.Paralyse(MAX_IMPREGNATION_TIME/6) //something like 25 ticks = 20 seconds with the default settings diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index 130a2e3a574..16014e7c353 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -49,7 +49,7 @@ brainmob.stat = CONSCIOUS GLOB.respawnable_list -= brainmob GLOB.dead_mob_list -= brainmob//Update dem lists - GLOB.living_mob_list += brainmob + GLOB.alive_mob_list += brainmob held_brain = B if(istype(O,/obj/item/organ/internal/brain/xeno)) // kept the type check, as it still does other weird stuff @@ -157,7 +157,7 @@ brainmob.container = null//Reset brainmob mmi var. brainmob.forceMove(held_brain) //Throw mob into brain. GLOB.respawnable_list += brainmob - GLOB.living_mob_list -= brainmob//Get outta here + GLOB.alive_mob_list -= brainmob//Get outta here held_brain.brainmob = brainmob//Set the brain to use the brainmob held_brain.brainmob.cancel_camera() brainmob = null//Set mmi brainmob var to null diff --git a/code/modules/mob/living/carbon/brain/brain.dm b/code/modules/mob/living/carbon/brain/brain.dm index ec80d6a44b4..386d5ae138f 100644 --- a/code/modules/mob/living/carbon/brain/brain.dm +++ b/code/modules/mob/living/carbon/brain/brain.dm @@ -7,9 +7,8 @@ icon_state = "brain1" /mob/living/carbon/brain/New() - create_reagents(330) - add_language("Galactic Common") ..() + add_language("Galactic Common") /mob/living/carbon/brain/Destroy() if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting. diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index 0b6bcededaf..93f31d0128c 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -26,11 +26,9 @@ mmi_icon = 'icons/mob/alien.dmi' mmi_icon_state = "AlienMMI" -/obj/item/organ/internal/brain/New() - ..() - spawn(5) - if(brainmob && brainmob.client) - brainmob.client.screen.len = null //clear the hud +/obj/item/organ/internal/brain/Destroy() + QDEL_NULL(brainmob) + return ..() /obj/item/organ/internal/brain/proc/transfer_identity(var/mob/living/carbon/H) brainmob = new(src) @@ -72,7 +70,7 @@ if(istype(owner,/mob/living/carbon/human)) var/mob/living/carbon/human/H = owner - H.update_hair(1) + H.update_hair() . = ..() /obj/item/organ/internal/brain/insert(var/mob/living/target,special = 0) @@ -84,7 +82,7 @@ brain_already_exists = 1 var/mob/living/carbon/human/H = target - H.update_hair(1) + H.update_hair() if(!brain_already_exists) if(brainmob) diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm index 6bd88e5e111..0faa238190e 100644 --- a/code/modules/mob/living/carbon/brain/life.dm +++ b/code/modules/mob/living/carbon/brain/life.dm @@ -28,13 +28,11 @@ var/discomfort = min( abs(exposed_temperature - bodytemperature)*(exposed_intensity)/2000000, 1.0) adjustFireLoss(5.0*discomfort) -/mob/living/carbon/brain/handle_regular_status_updates() +/mob/living/carbon/brain/Life() . = ..() - if(.) - if(!container && (health < HEALTH_THRESHOLD_DEAD && check_death_method() || ((world.time - timeofhostdeath) > config.revival_brain_life))) + if(!container && (world.time - timeofhostdeath) > config.revival_brain_life) death() - return 0 /mob/living/carbon/brain/breathe() return diff --git a/code/modules/mob/living/carbon/brain/robotic_brain.dm b/code/modules/mob/living/carbon/brain/robotic_brain.dm index b051fda9d89..908e905c1c8 100644 --- a/code/modules/mob/living/carbon/brain/robotic_brain.dm +++ b/code/modules/mob/living/carbon/brain/robotic_brain.dm @@ -110,7 +110,6 @@ if(imprinted_master) to_chat(H, "You are permanently imprinted to [imprinted_master], obey [imprinted_master]'s every order and assist [imprinted_master.p_them()] in completing [imprinted_master.p_their()] goals at any cost.") - /obj/item/mmi/robotic_brain/proc/transfer_personality(mob/candidate) searching = FALSE brainmob.key = candidate.key @@ -206,6 +205,10 @@ brainmob.container = src brainmob.stat = CONSCIOUS brainmob.SetSilence(0) + brainmob.dna = new(brainmob) + brainmob.dna.species = new /datum/species/machine() // Else it will default to human. And we don't want to clone IRC humans now do we? + brainmob.dna.ResetSE() + brainmob.dna.ResetUI() GLOB.dead_mob_list -= brainmob ..() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 598a533d2fa..4b6d6c68603 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -9,12 +9,18 @@ qdel(item) QDEL_LIST(internal_organs) QDEL_LIST(stomach_contents) + QDEL_LIST(processing_patches) var/mob/living/simple_animal/borer/B = has_brain_worms() if(B) B.leave_host() qdel(B) return ..() +/mob/living/carbon/handle_atom_del(atom/A) + if(A in processing_patches) + processing_patches -= A + return ..() + /mob/living/carbon/blob_act(obj/structure/blob/B) if(stat == DEAD) return @@ -126,7 +132,7 @@ if(isturf(loc)) I.remove(src) I.forceMove(get_turf(src)) - I.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),5) + I.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5) for(var/mob/M in src) if(M in src.stomach_contents) @@ -388,7 +394,7 @@ dna = newDNA -var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /obj/machinery/atmospherics/unary/vent_scrubber) +GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/vent_pump, /obj/machinery/atmospherics/unary/vent_scrubber)) /mob/living/handle_ventcrawl(var/atom/clicked_on) // -- TLE -- Merged by Carn if(!Adjacent(clicked_on)) @@ -432,13 +438,8 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, if(!vent_found) for(var/obj/machinery/atmospherics/machine in range(1,src)) - if(is_type_in_list(machine, ventcrawl_machinery)) + if(is_type_in_list(machine, GLOB.ventcrawl_machinery) && machine.can_crawl_through()) vent_found = machine - - if(!vent_found.can_crawl_through()) - vent_found = null - - if(vent_found) break if(vent_found) @@ -485,7 +486,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /mob/living/proc/add_ventcrawl(obj/machinery/atmospherics/starting_machine) - if(!istype(starting_machine) || !starting_machine.returnPipenet()) + if(!istype(starting_machine) || !starting_machine.returnPipenet() || !starting_machine.can_see_pipes()) return var/datum/pipeline/pipeline = starting_machine.returnPipenet() var/list/totalMembers = list() @@ -925,9 +926,10 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, return initial(pixel_y) /mob/living/carbon/emp_act(severity) - for(var/obj/item/organ/internal/O in internal_organs) - O.emp_act(severity) ..() + for(var/X in internal_organs) + var/obj/item/organ/internal/O = X + O.emp_act(severity) /mob/living/carbon/Stat() ..() @@ -975,25 +977,30 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /mob/living/carbon/proc/slip(description, stun, weaken, tilesSlipped, walkSafely, slipAny, slipVerb = "slip") if(flying || buckled || (walkSafely && m_intent == MOVE_INTENT_WALK)) - return 0 + return FALSE + if((lying) && (!(tilesSlipped))) - return 0 + return FALSE + if(!(slipAny)) if(istype(src, /mob/living/carbon/human)) var/mob/living/carbon/human/H = src if(isobj(H.shoes) && H.shoes.flags & NOSLIP) - return 0 + return FALSE + if(tilesSlipped) - for(var/t = 0, t<=tilesSlipped, t++) - spawn (t) step(src, src.dir) + for(var/i in 1 to tilesSlipped) + spawn(i) + step(src, dir) + stop_pulling() to_chat(src, "You [slipVerb]ped on [description]!") - playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + playsound(loc, 'sound/misc/slip.ogg', 50, 1, -3) // Something something don't run with scissors moving_diagonally = 0 //If this was part of diagonal move slipping will stop it. Stun(stun) Weaken(weaken) - return 1 + return TRUE /mob/living/carbon/proc/can_eat(flags = 255) return 1 @@ -1016,7 +1023,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, if(!forceFed(toEat, user, fullness)) return 0 consume(toEat, bitesize_override, can_taste_container = toEat.can_taste) - score_foodeaten++ + GLOB.score_foodeaten++ return 1 /mob/living/carbon/proc/selfFeed(var/obj/item/reagent_containers/food/toEat, fullness) @@ -1078,8 +1085,9 @@ so that different stomachs can handle things in different ways VB*/ if(can_taste_container) taste(toEat.reagents) var/fraction = min(this_bite/toEat.reagents.total_volume, 1) - toEat.reagents.reaction(src, toEat.apply_type, fraction) - toEat.reagents.trans_to(src, this_bite*toEat.transfer_efficiency) + if(fraction) + toEat.reagents.reaction(src, toEat.apply_type, fraction) + toEat.reagents.trans_to(src, this_bite*toEat.transfer_efficiency) /mob/living/carbon/get_access() . = ..() @@ -1103,7 +1111,7 @@ so that different stomachs can handle things in different ways VB*/ //to recalculate and update the mob's total tint from tinted equipment it's wearing. /mob/living/carbon/proc/update_tint() - if(!tinted_weldhelh) + if(!GLOB.tinted_weldhelh) return var/tinttotal = get_total_tint() if(tinttotal >= TINT_BLIND) diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 884ee802518..97ecf4dd08b 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -2,6 +2,7 @@ gender = MALE pressure_resistance = 15 var/list/stomach_contents = list() + var/list/processing_patches = list() var/list/internal_organs = list() var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access. var/antibodies = 0 diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index a0fd10e0610..58c6a39e6c1 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/human/proc/change_appearance(var/flags = APPEARANCE_ALL_HAIR, var/location = src, var/mob/user = src, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list(), var/datum/topic_state/state = default_state) +/mob/living/carbon/human/proc/change_appearance(var/flags = APPEARANCE_ALL_HAIR, var/location = src, var/mob/user = src, var/check_species_whitelist = 1, var/list/species_whitelist = list(), var/list/species_blacklist = list(), var/datum/topic_state/state = GLOB.default_state) var/datum/nano_module/appearance_changer/AC = new(location, src, check_species_whitelist, species_whitelist, species_blacklist) AC.flags = flags AC.ui_interact(user, state = state) @@ -104,9 +104,9 @@ if(!body_accessory_style || (body_accessory && body_accessory.name == body_accessory_style)) return - for(var/B in body_accessory_by_name) + for(var/B in GLOB.body_accessory_by_name) if(B == body_accessory_style) - body_accessory = body_accessory_by_name[body_accessory_style] + body_accessory = GLOB.body_accessory_by_name[body_accessory_style] found = 1 if(!found) @@ -131,7 +131,7 @@ m_styles["head"] = "None" update_markings() - update_body(1, 1) //Update the body and force limb icon regeneration to update the head with the new icon. + update_body(TRUE) //Update the body and force limb icon regeneration to update the head with the new icon. if(wear_mask) update_inv_wear_mask() return 1 @@ -340,7 +340,7 @@ if((H.gender == MALE && S.gender == FEMALE) || (H.gender == FEMALE && S.gender == MALE)) continue if(H.dna.species.bodyflags & ALL_RPARTS) //If the user is a species who can have a robotic head... - var/datum/robolimb/robohead = all_robolimbs[H.model] + var/datum/robolimb/robohead = GLOB.all_robolimbs[H.model] if((H.dna.species.name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_hairstyles += hairstyle //Give them their hairstyles if they do. else @@ -368,7 +368,7 @@ if((H.gender == MALE && S.gender == FEMALE) || (H.gender == FEMALE && S.gender == MALE)) continue if(H.dna.species.bodyflags & ALL_RPARTS) //If the user is a species who can have a robotic head... - var/datum/robolimb/robohead = all_robolimbs[H.model] + var/datum/robolimb/robohead = GLOB.all_robolimbs[H.model] if(H.dna.species.name in S.species_allowed) //If this is a facial hair style native to the user's species... if((H.dna.species.name in S.species_allowed) && robohead.is_monitor && ((S.models_allowed && (robohead.company in S.models_allowed)) || !S.models_allowed)) //If this is a facial hair style native to the user's species, check to see if they have a head with an ipc-style screen and that the head's company is in the screen style's allowed models list. valid_facial_hairstyles += facialhairstyle //Give them their facial hairstyles if they do. @@ -422,7 +422,7 @@ if(location == "head") var/datum/sprite_accessory/body_markings/head/M = GLOB.marking_styles_list[S.name] if(H.dna.species.bodyflags & ALL_RPARTS) //If the user is a species that can have a robotic head... - var/datum/robolimb/robohead = all_robolimbs[H.model] + var/datum/robolimb/robohead = GLOB.all_robolimbs[H.model] if(!(S.models_allowed && (robohead.company in S.models_allowed))) //Make sure they don't get markings incompatible with their head. continue else if(H.alt_head && H.alt_head != "None") //If the user's got an alt head, validate markings for that head. @@ -437,10 +437,10 @@ /mob/living/carbon/human/proc/generate_valid_body_accessories() var/list/valid_body_accessories = new() - for(var/B in body_accessory_by_name) - var/datum/body_accessory/A = body_accessory_by_name[B] + for(var/B in GLOB.body_accessory_by_name) + var/datum/body_accessory/A = GLOB.body_accessory_by_name[B] if(check_rights(R_ADMIN, 0, src)) - valid_body_accessories = body_accessory_by_name.Copy() + valid_body_accessories = GLOB.body_accessory_by_name.Copy() else if(!istype(A)) valid_body_accessories["None"] = "None" //The only null entry should be the "None" option. @@ -469,7 +469,7 @@ scramble(1, src, 100) real_name = random_name(gender, dna.species.name) //Give them a name that makes sense for their species. sync_organ_dna(assimilate = 1) - update_body(0) + update_body() reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover. reset_markings() //...Or markings. dna.ResetUIFrom(src) diff --git a/code/modules/mob/living/carbon/human/body_accessories.dm b/code/modules/mob/living/carbon/human/body_accessories.dm index 9c677444eb5..043a704ab0c 100644 --- a/code/modules/mob/living/carbon/human/body_accessories.dm +++ b/code/modules/mob/living/carbon/human/body_accessories.dm @@ -1,29 +1,29 @@ -var/global/list/body_accessory_by_name = list("None" = null) +GLOBAL_LIST_INIT(body_accessory_by_name, list("None" = null)) /hook/startup/proc/initalize_body_accessories() __init_body_accessory(/datum/body_accessory/body) __init_body_accessory(/datum/body_accessory/tail) - if(body_accessory_by_name.len) + if(GLOB.body_accessory_by_name.len) if(initialize_body_accessory_by_species()) return TRUE return FALSE //fail if no bodies are found -var/global/list/body_accessory_by_species = list("None" = null) +GLOBAL_LIST_INIT(body_accessory_by_species, list("None" = null)) /proc/initialize_body_accessory_by_species() - for(var/B in body_accessory_by_name) - var/datum/body_accessory/accessory = body_accessory_by_name[B] + for(var/B in GLOB.body_accessory_by_name) + var/datum/body_accessory/accessory = GLOB.body_accessory_by_name[B] if(!istype(accessory)) continue for(var/species in accessory.allowed_species) - if(!body_accessory_by_species["[species]"]) body_accessory_by_species["[species]"] = list() - body_accessory_by_species["[species]"] += accessory + if(!GLOB.body_accessory_by_species["[species]"]) GLOB.body_accessory_by_species["[species]"] = list() + GLOB.body_accessory_by_species["[species]"] += accessory - if(body_accessory_by_species.len) + if(GLOB.body_accessory_by_species.len) return TRUE return FALSE @@ -34,7 +34,7 @@ var/global/list/body_accessory_by_species = list("None" = null) for(var/A in subtypesof(ba_path)) var/datum/body_accessory/B = new A if(istype(B)) - body_accessory_by_name[B.name] += B + GLOB.body_accessory_by_name[B.name] += B ++_added_counter if(_added_counter) @@ -77,15 +77,6 @@ var/global/list/body_accessory_by_species = list("None" = null) /datum/body_accessory/body blend_mode = ICON_MULTIPLY -/datum/body_accessory/body/snake - name = "Snake" - - icon = 'icons/mob/body_accessory_64.dmi' - icon_state = "snake" - - pixel_x_offset = -16 - - //Tails /datum/body_accessory/tail icon = 'icons/mob/body_accessory.dmi' diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 2037f713c56..6b7a0a2b15d 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -21,7 +21,7 @@ var/atom/movable/thing = I.remove(src) if(thing) thing.forceMove(get_turf(src)) - thing.throw_at(get_edge_target_turf(src, pick(alldirs)), rand(1,3), 5) + thing.throw_at(get_edge_target_turf(src, pick(GLOB.alldirs)), rand(1,3), 5) for(var/obj/item/organ/external/E in bodyparts) if(istype(E, /obj/item/organ/external/chest)) @@ -103,7 +103,6 @@ set_heartattack(FALSE) SSmobs.cubemonkeys -= src if(dna.species) - dna.species.handle_hud_icons(src) //Handle species-specific deaths. dna.species.handle_death(gibbed, src) @@ -124,10 +123,10 @@ if(. && healthdoll) // We're alive again, so re-build the entire healthdoll healthdoll.cached_healthdoll_overlays.Cut() + update_health_hud() // Update healthdoll if(dna.species) dna.species.update_sight(src) - dna.species.handle_hud_icons(src) /mob/living/carbon/human/proc/makeSkeleton() var/obj/item/organ/external/head/H = get_organ("head") @@ -146,14 +145,14 @@ H.alt_head = initial(H.alt_head) H.handle_alt_icon() m_styles = DEFAULT_MARKING_STYLES - update_fhair(0) - update_hair(0) - update_head_accessory(0) - update_markings(0) + update_fhair() + update_hair() + update_head_accessory() + update_markings() mutations.Add(SKELETON) mutations.Add(NOCLONE) - update_body(0) + update_body() update_mutantrace() return @@ -172,11 +171,11 @@ H.f_style = "Shaved" //we only change the icon_state of the hair datum, so it doesn't mess up their UI/UE if(H.h_style) H.h_style = "Bald" - update_fhair(0) - update_hair(0) + update_fhair() + update_hair() mutations.Add(HUSK) - update_body(0) + update_body() update_mutantrace() return @@ -190,6 +189,6 @@ var/obj/item/organ/external/head/H = bodyparts_by_name["head"] if(istype(H)) H.disfigured = FALSE - update_body(0) - update_mutantrace(0) + update_body() + update_mutantrace() UpdateAppearance() // reset hair from DNA diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 1bb1a8cf536..a34f02bc868 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -256,12 +256,12 @@ if(body_accessory) if(body_accessory.try_restrictions(src)) message = "[src] starts wagging [p_their()] tail." - start_tail_wagging(1) + start_tail_wagging() else if(dna.species.bodyflags & TAIL_WAGGING) if(!wear_suit || !(wear_suit.flags_inv & HIDETAIL)) message = "[src] starts wagging [p_their()] tail." - start_tail_wagging(1) + start_tail_wagging() else return else @@ -271,7 +271,7 @@ if("swag", "swags") if(dna.species.bodyflags & TAIL_WAGGING || body_accessory) message = "[src] stops wagging [p_their()] tail." - stop_tail_wagging(1) + stop_tail_wagging() else return m_type = 1 @@ -400,7 +400,9 @@ var/turf/newloc = G.affecting.loc if(isturf(oldloc) && isturf(newloc)) SpinAnimation(5,1) + glide_for(6) // This and the glide_for below are purely arbitrary. Pick something that looks aesthetically pleasing. forceMove(newloc) + G.glide_for(6) G.affecting.forceMove(oldloc) message = "[src] flips over [G.affecting]!" else diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 845339917eb..b67e01924c8 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -290,13 +290,16 @@ if(5) msg += "[p_they(TRUE)] looks absolutely soaked.\n" - if(nutrition < NUTRITION_LEVEL_STARVING - 50) + if(nutrition < NUTRITION_LEVEL_HYPOGLYCEMIA) msg += "[p_they(TRUE)] [p_are()] severely malnourished.\n" - else if(nutrition >= NUTRITION_LEVEL_FAT) - if(user.nutrition < NUTRITION_LEVEL_STARVING - 50) + + if(FAT in mutations) + msg += "[p_they(TRUE)] [p_are()] morbidly obese.\n" + if(user.nutrition < NUTRITION_LEVEL_HYPOGLYCEMIA) msg += "[p_they(TRUE)] [p_are()] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n" - else - msg += "[p_they(TRUE)] [p_are()] quite chubby.\n" + + else if(nutrition >= NUTRITION_LEVEL_FAT) + msg += "[p_they(TRUE)] [p_are()] quite chubby.\n" if(!isSynthetic() && blood_volume < BLOOD_VOLUME_SAFE) msg += "[p_they(TRUE)] [p_have()] pale skin.\n" @@ -343,24 +346,32 @@ if(hasHUD(user,"security")) var/perpname = get_visible_name(TRUE) var/criminal = "None" + var/commentLatest = "ERROR: Unable to locate a data core entry for this person." //If there is no datacore present, give this if(perpname) - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in GLOB.data_core.security) if(R.fields["id"] == E.fields["id"]) criminal = R.fields["criminal"] + if(LAZYLEN(R.fields["comments"])) //if the commentlist is present + var/list/comments = R.fields["comments"] + commentLatest = LAZYACCESS(comments, comments.len) //get the latest entry from the comment log + else + commentLatest = "No entries." //If present but without entries (=target is recognized crew) + var/criminal_status = hasHUD(user, "read_only_security") ? "\[[criminal]\]" : "\[[criminal]\]" msg += "Criminal status: [criminal_status]\n" - msg += "Security records: \[View\] \[Add comment\]\n" + msg += "Security records: \[View comment log\] \[Add comment\]\n" + msg += "Latest entry: [commentLatest]\n" if(hasHUD(user,"medical")) var/perpname = get_visible_name(TRUE) var/medical = "None" - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.general) + for(var/datum/data/record/R in GLOB.data_core.general) if(R.fields["id"] == E.fields["id"]) medical = R.fields["p_stat"] @@ -395,17 +406,25 @@ if("medical") return istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(CIH,/obj/item/organ/internal/cyberimp/eyes/hud/medical) else - return 0 + return FALSE else if(isrobot(M) || isAI(M)) //Stand-in/Stopgap to prevent pAIs from freely altering records, pending a more advanced Records system switch(hudtype) if("security") - return 1 + return TRUE if("medical") - return 1 + return TRUE else - return 0 + return FALSE + else if(isobserver(M)) + var/mob/dead/observer/O = M + if(O.data_hud_seen == DATA_HUD_SECURITY_ADVANCED || O.data_hud_seen == DATA_HUD_DIAGNOSTIC + DATA_HUD_SECURITY_ADVANCED + DATA_HUD_MEDICAL_ADVANCED) + switch(hudtype) + if("security") + return TRUE + else + return FALSE else - return 0 + return FALSE // Ignores robotic limb branding prefixes like "Morpheus Cybernetics" /proc/ignore_limb_branding(limb_name) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 73b40652888..828dc25322c 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -18,10 +18,10 @@ dna = new /datum/dna(null) // Species name is handled by set_species() - set_species(new_species, 1, delay_icon_update = 1, skip_same_check = TRUE) - ..() + set_species(new_species, 1, delay_icon_update = 1, skip_same_check = TRUE) + if(dna.species) real_name = dna.species.get_random_name(gender) name = real_name @@ -30,7 +30,7 @@ create_reagents(330) - martial_art = default_martial_art + martial_art = GLOB.default_martial_art handcrafting = new() @@ -658,7 +658,7 @@ else if(place_item) usr.unEquip(place_item) - equip_to_slot_if_possible(place_item, pocket_id, 0, 1) + equip_to_slot_if_possible(place_item, pocket_id, FALSE, TRUE) add_attack_logs(usr, src, "Equipped with [place_item]", isLivingSSD(src) ? null : ATKLOG_ALL) // Update strip window @@ -710,19 +710,19 @@ var/perpname = get_visible_name(TRUE) if(perpname != "Unknown") - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in GLOB.data_core.security) if(R.fields["id"] == E.fields["id"]) - var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list("None", "*Arrest*", "Incarcerated", "Parolled", "Released", "Cancel") + var/setcriminal = input(usr, "Specify a new criminal status for this person.", "Security HUD", R.fields["criminal"]) in list(SEC_RECORD_STATUS_NONE, SEC_RECORD_STATUS_ARREST, SEC_RECORD_STATUS_SEARCH, SEC_RECORD_STATUS_MONITOR, SEC_RECORD_STATUS_DEMOTE, SEC_RECORD_STATUS_INCARCERATED, SEC_RECORD_STATUS_PAROLLED, SEC_RECORD_STATUS_RELEASED, "Cancel") var/t1 = copytext(trim(sanitize(input("Enter Reason:", "Security HUD", null, null) as text)), 1, MAX_MESSAGE_LEN) if(!t1) t1 = "(none)" if(hasHUD(usr, "security") && setcriminal != "Cancel") found_record = 1 - if(R.fields["criminal"] == "*Execute*") + if(R.fields["criminal"] == SEC_RECORD_STATUS_EXECUTE) to_chat(usr, "Unable to modify the sec status of a person with an active Execution order. Use a security computer instead.") else var/rank @@ -749,9 +749,9 @@ var/perpname = get_visible_name(TRUE) var/read = 0 - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in GLOB.data_core.security) if(R.fields["id"] == E.fields["id"]) if(hasHUD(usr,"security")) to_chat(usr, "Name: [R.fields["name"]] Criminal Status: [R.fields["criminal"]]") @@ -768,14 +768,14 @@ if(href_list["secrecordComment"]) if(hasHUD(usr,"security")) - if(usr.incapacitated()) + if(usr.incapacitated() && !isobserver(usr)) //give the ghosts access to "View Comment Log" while they can't manipulate it return var/perpname = get_visible_name(TRUE) var/read = 0 - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in GLOB.data_core.security) if(R.fields["id"] == E.fields["id"]) if(hasHUD(usr,"security")) read = 1 @@ -783,7 +783,7 @@ for(var/c in R.fields["comments"]) to_chat(usr, c) else - to_chat(usr, "No comment found") + to_chat(usr, "No comments found") to_chat(usr, "\[Add comment\]") if(!read) @@ -795,9 +795,9 @@ return var/perpname = get_visible_name(TRUE) - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in GLOB.data_core.security) if(R.fields["id"] == E.fields["id"]) if(hasHUD(usr,"security")) var/t1 = copytext(trim(sanitize(input("Add Comment:", "Sec. records", null, null) as message)), 1, MAX_MESSAGE_LEN) @@ -805,13 +805,13 @@ return if(ishuman(usr)) var/mob/living/carbon/human/U = usr - R.fields["comments"] += "Made by [U.get_authentification_name()] ([U.get_assignment()]) on [current_date_string] [station_time_timestamp()]
    [t1]" + R.fields["comments"] += "Made by [U.get_authentification_name()] ([U.get_assignment()]) on [GLOB.current_date_string] [station_time_timestamp()]
    [t1]" if(isrobot(usr)) var/mob/living/silicon/robot/U = usr - R.fields["comments"] += "Made by [U.name] ([U.modtype] [U.braintype]) on [current_date_string] [station_time_timestamp()]
    [t1]" + R.fields["comments"] += "Made by [U.name] ([U.modtype] [U.braintype]) on [GLOB.current_date_string] [station_time_timestamp()]
    [t1]" if(isAI(usr)) var/mob/living/silicon/ai/U = usr - R.fields["comments"] += "Made by [U.name] (artificial intelligence) on [current_date_string] [station_time_timestamp()]
    [t1]" + R.fields["comments"] += "Made by [U.name] (artificial intelligence) on [GLOB.current_date_string] [station_time_timestamp()]
    [t1]" if(href_list["medical"]) if(hasHUD(usr,"medical")) @@ -820,9 +820,9 @@ var/modified = 0 var/perpname = get_visible_name(TRUE) - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.general) + for(var/datum/data/record/R in GLOB.data_core.general) if(R.fields["id"] == E.fields["id"]) var/setmedical = input(usr, "Specify a new medical status for this person.", "Medical HUD", R.fields["p_stat"]) in list("*SSD*", "*Deceased*", "Physically Unfit", "Active", "Disabled", "Cancel") @@ -830,8 +830,8 @@ if(setmedical != "Cancel") R.fields["p_stat"] = setmedical modified = 1 - if(PDA_Manifest.len) - PDA_Manifest.Cut() + if(GLOB.PDA_Manifest.len) + GLOB.PDA_Manifest.Cut() spawn() sec_hud_set_security_status() @@ -846,9 +846,9 @@ var/read = 0 var/perpname = get_visible_name(TRUE) - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.medical) + for(var/datum/data/record/R in GLOB.data_core.medical) if(R.fields["id"] == E.fields["id"]) if(hasHUD(usr,"medical")) to_chat(usr, "Name: [R.fields["name"]] Blood Type: [R.fields["b_type"]]") @@ -871,9 +871,9 @@ var/perpname = get_visible_name(TRUE) var/read = 0 - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.medical) + for(var/datum/data/record/R in GLOB.data_core.medical) if(R.fields["id"] == E.fields["id"]) if(hasHUD(usr,"medical")) read = 1 @@ -892,9 +892,9 @@ if(usr.incapacitated()) return var/perpname = get_visible_name(TRUE) - for(var/datum/data/record/E in data_core.general) + for(var/datum/data/record/E in GLOB.data_core.general) if(E.fields["name"] == perpname) - for(var/datum/data/record/R in data_core.medical) + for(var/datum/data/record/R in GLOB.data_core.medical) if(R.fields["id"] == E.fields["id"]) if(hasHUD(usr,"medical")) var/t1 = copytext(trim(sanitize(input("Add Comment:", "Med. records", null, null) as message)), 1, MAX_MESSAGE_LEN) @@ -902,13 +902,13 @@ return if(ishuman(usr)) var/mob/living/carbon/human/U = usr - R.fields["comments"] += "Made by [U.get_authentification_name()] ([U.get_assignment()]) on [current_date_string] [station_time_timestamp()]
    [t1]" + R.fields["comments"] += "Made by [U.get_authentification_name()] ([U.get_assignment()]) on [GLOB.current_date_string] [station_time_timestamp()]
    [t1]" if(isrobot(usr)) var/mob/living/silicon/robot/U = usr - R.fields["comments"] += "Made by [U.name] ([U.modtype] [U.braintype]) on [current_date_string] [station_time_timestamp()]
    [t1]" + R.fields["comments"] += "Made by [U.name] ([U.modtype] [U.braintype]) on [GLOB.current_date_string] [station_time_timestamp()]
    [t1]" if(isAI(usr)) var/mob/living/silicon/ai/U = usr - R.fields["comments"] += "Made by [U.name] (artificial intelligence) on [current_date_string] [station_time_timestamp()]
    [t1]" + R.fields["comments"] += "Made by [U.name] (artificial intelligence) on [GLOB.current_date_string] [station_time_timestamp()]
    [t1]" if(href_list["lookitem"]) var/obj/item/I = locate(href_list["lookitem"]) @@ -1169,7 +1169,7 @@ qdel(feet_blood_DNA) bloody_feet = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_NOT_BLOODY = 0) blood_state = BLOOD_STATE_NOT_BLOODY - update_inv_shoes(1) + update_inv_shoes() return 1 /mob/living/carbon/human/cuff_resist(obj/item/I) @@ -1349,7 +1349,7 @@ dna.species.create_organs(src) for(var/obj/item/thing in kept_items) - equip_to_slot_if_possible(thing, kept_items[thing], redraw_mob = 0) + equip_to_slot_if_possible(thing, kept_items[thing]) thing.flags = item_flags[thing] // Reset the flags to the origional ones //Handle default hair/head accessories for created mobs. @@ -1399,7 +1399,7 @@ UpdateAppearance() overlays.Cut() - update_mutantrace(1) + update_mutantrace() regenerate_icons() if(dna.species) @@ -1551,16 +1551,16 @@ Eyes need to have significantly high darksight to shine unless the mob has the X //Check for arrest warrant if(judgebot.check_records) var/perpname = get_visible_name(TRUE) - var/datum/data/record/R = find_record("name", perpname, data_core.security) + var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security) if(R && R.fields["criminal"]) switch(R.fields["criminal"]) - if("*Execute*") + if(SEC_RECORD_STATUS_EXECUTE) threatcount += 7 - if("*Arrest*") + if(SEC_RECORD_STATUS_ARREST) threatcount += 5 - if("Incarcerated") + if(SEC_RECORD_STATUS_INCARCERATED) threatcount += 2 - if("Parolled") + if(SEC_RECORD_STATUS_PAROLLED) threatcount += 2 //Check for dresscode violations @@ -1962,3 +1962,6 @@ Eyes need to have significantly high darksight to shine unless the mob has the X if(O && O.glowing) O.toggle_biolum(TRUE) visible_message("[src] is engulfed in shadows and fades into the darkness.", "A sense of dread washes over you as you suddenly dim dark.") + +/mob/living/carbon/human/proc/get_perceived_trauma() + return min(health, maxHealth - getStaminaLoss()) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index a12ef49fb7f..89aa7854264 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -19,8 +19,6 @@ ChangeToHusk() update_stat("updatehealth([reason])") med_hud_set_health() - med_hud_set_status() - handle_hud_icons_health() /mob/living/carbon/human/adjustBrainLoss(amount, updating = TRUE, use_brain_mod = TRUE) if(status_flags & GODMODE) @@ -111,7 +109,7 @@ var/obj/item/organ/external/O = get_organ(organ_name) if(amount > 0) - O.receive_damage(amount, 0, sharp=is_sharp(damage_source), used_weapon=damage_source, list(), FALSE, updating_health) + O.receive_damage(amount, 0, sharp=is_sharp(damage_source), used_weapon=damage_source, forbidden_limbs = list(), ignore_resists=FALSE, updating_health=updating_health) else //if you don't want to heal robot organs, they you will have to check that yourself before using this proc. O.heal_damage(-amount, 0, internal = 0, robo_repair = O.is_robotic(), updating_health = updating_health) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index ad1d249439d..82b61a04391 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -206,12 +206,6 @@ emp_act if(martial_art && prob(martial_art.block_chance) && martial_art.can_use(src) && in_throw_mode && !incapacitated(FALSE, TRUE)) return TRUE -/mob/living/carbon/human/emp_act(severity) - for(var/obj/O in src) - if(!O) continue - O.emp_act(severity) - ..() - /mob/living/carbon/human/acid_act(acidpwr, acid_volume, bodyzone_hit) //todo: update this to utilize check_obscured_slots() //and make sure it's check_obscured_slots(TRUE) to stop aciding through visors etc var/list/damaged = list() var/list/inventory_items_to_kill = list() @@ -463,13 +457,13 @@ emp_act if(bloody)//Apply blood if(wear_mask) wear_mask.add_mob_blood(src) - update_inv_wear_mask(0) + update_inv_wear_mask() if(head) head.add_mob_blood(src) - update_inv_head(0,0) + update_inv_head() if(glasses && prob(33)) glasses.add_mob_blood(src) - update_inv_glasses(0) + update_inv_glasses() if("chest")//Easier to score a stun but lasts less time @@ -481,10 +475,10 @@ emp_act if(bloody) if(wear_suit) wear_suit.add_mob_blood(src) - update_inv_wear_suit(1) + update_inv_wear_suit() if(w_uniform) w_uniform.add_mob_blood(src) - update_inv_w_uniform(1) + update_inv_w_uniform() @@ -531,16 +525,16 @@ emp_act else add_mob_blood(source) bloody_hands = amount - update_inv_gloves(1) //updates on-mob overlays for bloody hands and/or bloody gloves + update_inv_gloves() //updates on-mob overlays for bloody hands and/or bloody gloves /mob/living/carbon/human/proc/bloody_body(var/mob/living/source) if(wear_suit) wear_suit.add_mob_blood(source) - update_inv_wear_suit(0) + update_inv_wear_suit() return if(w_uniform) w_uniform.add_mob_blood(source) - update_inv_w_uniform(1) + update_inv_w_uniform() /mob/living/carbon/human/proc/handle_suit_punctures(var/damtype, var/damage) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index c0d937a8118..60b6da987dd 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -1,4 +1,4 @@ -var/global/default_martial_art = new/datum/martial_art +GLOBAL_DATUM_INIT(default_martial_art, /datum/martial_art, new()) /mob/living/carbon/human hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPMINDSHIELD_HUD,IMPCHEM_HUD,IMPTRACK_HUD,SPECIALROLE_HUD,GLAND_HUD) @@ -23,7 +23,7 @@ var/global/default_martial_art = new/datum/martial_art var/backbag = 2 //Which backpack type the player has chosen. Nothing, Satchel or Backpack. //Equipment slots - var/obj/item/w_uniform = null + var/obj/item/clothing/under/w_uniform = null var/obj/item/shoes = null var/obj/item/belt = null var/obj/item/gloves = null diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 55228c51a51..b4a65b110a9 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -8,12 +8,15 @@ /mob/living/carbon/human/var/list/bodyparts_by_name = list() // map organ names to organs // Takes care of organ related updates, such as broken and missing limbs -/mob/living/carbon/human/proc/handle_organs() +/mob/living/carbon/human/handle_organs() + ..() //processing internal organs is pretty cheap, do that first. - for(var/obj/item/organ/internal/I in internal_organs) + for(var/X in internal_organs) + var/obj/item/organ/internal/I = X I.process() - for(var/obj/item/organ/external/E in bodyparts) + for(var/Y in bodyparts) + var/obj/item/organ/external/E = Y E.process() if(!lying && world.time - l_move_time < 15) @@ -109,35 +112,18 @@ do_sparks(5, 0, src) +/mob/living/carbon/human/handle_germs() + ..() + if(gloves && germ_level > gloves.germ_level && prob(10)) + gloves.germ_level += 1 + /mob/living/carbon/human/proc/becomeSlim() to_chat(src, "You feel fit again!") - var/obj/item/organ/external/chest/C = get_organ("chest") - if(istype(C)) - C.makeSlim(0) - else - to_chat(src, "Err, well, you *would*, but you don't have a torso. Yell at a coder.") - log_debug("[src] at ([x],[y],[z]) doesn't have a torso.") mutations.Remove(FAT) - update_mutantrace(0) - update_mutations(0) - update_body(0, 1) - update_inv_w_uniform(0) - update_inv_wear_suit() /mob/living/carbon/human/proc/becomeFat() to_chat(src, "You suddenly feel blubbery!") - var/obj/item/organ/external/chest/C = get_organ("chest") - if(istype(C)) - C.makeFat() - else - to_chat(src, "Err, well, you *would*, but you don't have a torso. Yell at a coder.") - log_debug("[src] at ([x],[y],[z]) doesn't have a torso.") mutations.Add(FAT) - update_mutantrace(0) - update_mutations(0) - update_body(0, 1) - update_inv_w_uniform(0) - update_inv_wear_suit() //Handles chem traces /mob/living/carbon/human/proc/handle_trace_chems() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 953ea6bae1d..954d4e8fa55 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -178,8 +178,7 @@ //This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() -//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc. -/mob/living/carbon/human/equip_to_slot(obj/item/I, slot, redraw_mob = 1) +/mob/living/carbon/human/equip_to_slot(obj/item/I, slot) if(!slot) return if(!istype(I)) @@ -203,40 +202,40 @@ switch(slot) if(slot_back) back = I - update_inv_back(redraw_mob) + update_inv_back() if(slot_wear_mask) wear_mask = I if((wear_mask.flags & BLOCKHAIR) || (wear_mask.flags & BLOCKHEADHAIR)) - update_hair(redraw_mob) //rebuild hair - update_fhair(redraw_mob) - update_head_accessory(redraw_mob) + update_hair() //rebuild hair + update_fhair() + update_head_accessory() if(hud_list.len) sec_hud_set_ID() wear_mask_update(I, toggle_off = TRUE) - update_inv_wear_mask(redraw_mob) + update_inv_wear_mask() if(slot_handcuffed) handcuffed = I - update_inv_handcuffed(redraw_mob) + update_inv_handcuffed() if(slot_legcuffed) legcuffed = I - update_inv_legcuffed(redraw_mob) + update_inv_legcuffed() if(slot_l_hand) l_hand = I - update_inv_l_hand(redraw_mob) + update_inv_l_hand() if(slot_r_hand) r_hand = I - update_inv_r_hand(redraw_mob) + update_inv_r_hand() if(slot_belt) belt = I - update_inv_belt(redraw_mob) + update_inv_belt() if(slot_wear_id) wear_id = I if(hud_list.len) sec_hud_set_ID() - update_inv_wear_id(redraw_mob) + update_inv_wear_id() if(slot_wear_pda) wear_pda = I - update_inv_wear_pda(redraw_mob) + update_inv_wear_pda() if(slot_l_ear) l_ear = I if(l_ear.slot_flags & SLOT_TWOEARS) @@ -245,7 +244,7 @@ r_ear = O O.layer = ABOVE_HUD_LAYER O.plane = ABOVE_HUD_PLANE - update_inv_ears(redraw_mob) + update_inv_ears() if(slot_r_ear) r_ear = I if(r_ear.slot_flags & SLOT_TWOEARS) @@ -254,7 +253,7 @@ l_ear = O O.layer = ABOVE_HUD_LAYER O.plane = ABOVE_HUD_PLANE - update_inv_ears(redraw_mob) + update_inv_ears() if(slot_glasses) glasses = I var/obj/item/clothing/glasses/G = I @@ -264,42 +263,42 @@ update_nearsighted_effects() if(G.vision_flags || G.see_in_dark || G.invis_override || G.invis_view || !isnull(G.lighting_alpha)) update_sight() - update_inv_glasses(redraw_mob) + update_inv_glasses() update_client_colour() if(slot_gloves) gloves = I - update_inv_gloves(redraw_mob) + update_inv_gloves() if(slot_head) head = I if((head.flags & BLOCKHAIR) || (head.flags & BLOCKHEADHAIR)) - update_hair(redraw_mob) //rebuild hair - update_fhair(redraw_mob) - update_head_accessory(redraw_mob) + update_hair() //rebuild hair + update_fhair() + update_head_accessory() // paper + bandanas if(istype(I, /obj/item/clothing/head)) var/obj/item/clothing/head/hat = I if(hat.vision_flags || hat.see_in_dark || !isnull(hat.lighting_alpha)) update_sight() head_update(I) - update_inv_head(redraw_mob) + update_inv_head() if(slot_shoes) shoes = I - update_inv_shoes(redraw_mob) + update_inv_shoes() if(slot_wear_suit) wear_suit = I - update_inv_wear_suit(redraw_mob) + update_inv_wear_suit() if(slot_w_uniform) w_uniform = I - update_inv_w_uniform(redraw_mob) + update_inv_w_uniform() if(slot_l_store) l_store = I - update_inv_pockets(redraw_mob) + update_inv_pockets() if(slot_r_store) r_store = I - update_inv_pockets(redraw_mob) + update_inv_pockets() if(slot_s_store) s_store = I - update_inv_s_store(redraw_mob) + update_inv_s_store() if(slot_in_backpack) if(get_active_hand() == I) unEquip(I) @@ -313,6 +312,11 @@ /mob/living/carbon/human/put_in_hands(obj/item/I) if(!I) return FALSE + if(istype(I, /obj/item/stack)) + var/obj/item/stack/S = I + if(S.amount == 0) + qdel(I) + return FALSE if(put_in_active_hand(I)) return TRUE else if(put_in_inactive_hand(I)) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index b46dff4718a..c74340d0901 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1,18 +1,26 @@ /mob/living/carbon/human/Life(seconds, times_fired) + set invisibility = 0 + if(notransform) + return + + . = ..() + + if(QDELETED(src)) + return FALSE + life_tick++ voice = GetVoice() - if(..()) + if(.) //not dead if(check_mutations) domutcheck(src,null) update_mutations() - check_mutations=0 + check_mutations = FALSE handle_pain() handle_heartbeat() - handle_drunk() dna.species.handle_life(src) if(!client) dna.species.handle_npc(src) @@ -24,45 +32,45 @@ if(stat == DEAD) handle_decay() - if(life_tick > 5 && timeofdeath && (timeofdeath < 5 || world.time - timeofdeath > 6000)) //We are long dead, or we're junk mobs spawned like the clowns on the clown shuttle - return //We go ahead and process them 5 times for HUD images and other stuff though. - //Update our name based on whether our face is obscured/disfigured name = get_visible_name() pulse = handle_pulse(times_fired) - if(mind && mind.vampire) + if(mind?.vampire) mind.vampire.handle_vampire() if(life_tick == 1) regenerate_icons() // Make sure the inventory updates - handle_ghosted() - handle_ssd() + if(player_ghosted > 0 && stat == CONSCIOUS && job && !restrained()) + handle_ghosted() + if(player_logged > 0 && stat != DEAD && job) + handle_ssd() + + if(stat != DEAD) + return TRUE /mob/living/carbon/human/proc/handle_ghosted() - if(player_ghosted > 0 && stat == CONSCIOUS && job && !restrained()) - if(key) - player_ghosted = 0 - else - player_ghosted++ - if(player_ghosted % 150 == 0) - force_cryo_human(src) + if(key) + player_ghosted = 0 + else + player_ghosted++ + if(player_ghosted % 150 == 0) + force_cryo_human(src) /mob/living/carbon/human/proc/handle_ssd() - if(player_logged > 0 && stat != DEAD && job) - player_logged++ - if(istype(loc, /obj/machinery/cryopod)) + player_logged++ + if(istype(loc, /obj/machinery/cryopod)) + return + if(config.auto_cryo_ssd_mins && (player_logged >= (config.auto_cryo_ssd_mins * 30)) && player_logged % 30 == 0) + var/turf/T = get_turf(src) + if(!is_station_level(T.z)) return - if(config.auto_cryo_ssd_mins && (player_logged >= (config.auto_cryo_ssd_mins * 30)) && player_logged % 30 == 0) - var/turf/T = get_turf(src) - if(!is_station_level(T.z)) - return - var/area/A = get_area(src) - if(cryo_ssd(src)) - var/obj/effect/portal/P = new /obj/effect/portal(T, null, null, 40) - P.name = "NT SSD Teleportation Portal" - if(A.fast_despawn) - force_cryo_human(src) + var/area/A = get_area(src) + if(cryo_ssd(src)) + var/obj/effect/portal/P = new /obj/effect/portal(T, null, null, 40) + P.name = "NT SSD Teleportation Portal" + if(A.fast_despawn) + force_cryo_human(src) /mob/living/carbon/human/calculate_affecting_pressure(var/pressure) ..() @@ -80,38 +88,35 @@ /mob/living/carbon/human/handle_disabilities() - if(disabilities & EPILEPSY) - if((prob(1) && paralysis < 1)) - visible_message("[src] starts having a seizure!","You have a seizure!") - Paralyse(10) - Jitter(1000) + //Vision //god knows why this is here + var/obj/item/organ/vision + if(dna.species.vision_organ) + vision = get_int_organ(dna.species.vision_organ) - // If we have the gene for being crazy, have random events. - if(dna.GetSEState(HALLUCINATIONBLOCK)) - if(prob(1)) - Hallucinate(20) + if(!dna.species.vision_organ) // Presumably if a species has no vision organs, they see via some other means. + SetEyeBlind(0) + SetEyeBlurry(0) - if(disabilities & COUGHING) - if((prob(5) && paralysis <= 1)) - drop_item() - emote("cough") - if(disabilities & TOURETTES) - if((prob(10) && paralysis <= 1)) - Stun(10) - switch(rand(1, 3)) - if(1) - emote("twitch") - if(2 to 3) - var/tourettes = pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS") - say("[prob(50) ? ";" : ""][tourettes]") - var/x_offset = pixel_x + rand(-2,2) //Should probably be moved into the twitch emote at some point. - var/y_offset = pixel_y + rand(-1,1) - animate(src, pixel_x = pixel_x + x_offset, pixel_y = pixel_y + y_offset, time = 1) - animate(pixel_x = initial(pixel_x) , pixel_y = initial(pixel_y), time = 1) + else if(!vision || vision.is_broken()) // Vision organs cut out or broken? Permablind. + EyeBlind(2) + EyeBlurry(2) - if(disabilities & NERVOUS) - if(prob(10)) - Stuttering(10) + else + //blindness + if(BLINDNESS in mutations) // Disabled-blind, doesn't get better on its own + + else if(eye_blind) // Blindness, heals slowly over time + AdjustEyeBlind(-1) + + else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold) && eye_blurry) //resting your eyes with a blindfold heals blurry eyes faster + AdjustEyeBlurry(-3) + + //blurry sight + if(vision.is_bruised()) // Vision organs impaired? Permablurry. + EyeBlurry(2) + + if(eye_blurry) // Blurry eyes heal slowly + AdjustEyeBlurry(-1) if(getBrainLoss() >= 60 && stat != DEAD) if(prob(3)) @@ -167,7 +172,7 @@ emote("drool") /mob/living/carbon/human/handle_mutations_and_radiation() - for(var/datum/dna/gene/gene in dna_genes) + for(var/datum/dna/gene/gene in GLOB.dna_genes) if(!gene.block) continue if(gene.is_active(src)) @@ -598,17 +603,16 @@ return 0 //godmode if(!(NO_HUNGER in dna.species.species_traits)) - //The fucking FAT mutation is the greatest shit ever. It makes everyone so hot and bothered. - if(CAN_BE_FAT in dna.species.species_traits) - if(FAT in mutations) - if(overeatduration < 100) - becomeSlim() - else - if(overeatduration > 500) - becomeFat() + if(FAT in mutations) + if(overeatduration < 100) + becomeSlim() + else + if(overeatduration > 500) + becomeFat() // nutrition decrease if(nutrition > 0 && stat != DEAD) + handle_nutrition_alerts() // THEY HUNGER var/hunger_rate = hunger_drain if(satiety > 0) @@ -631,6 +635,10 @@ else overeatduration -= 2 + if(!ismachine(src) && nutrition < NUTRITION_LEVEL_HYPOGLYCEMIA) //Gosh damn snowflakey IPCs + var/datum/disease/D = new /datum/disease/critical/hypoglycemia + ForceContractDisease(D) + //metabolism change if(nutrition > NUTRITION_LEVEL_FAT) metabolism_efficiency = 1 @@ -654,22 +662,25 @@ AdjustSleeping(1) Paralyse(5) - AdjustConfused(-1) + if(confused) + AdjustConfused(-1) // decrement dizziness counter, clamped to 0 if(resting) - AdjustDizzy(-15) - AdjustJitter(-15) + if(dizziness) + AdjustDizzy(-15) + if(jitteriness) + AdjustJitter(-15) else - AdjustDizzy(-3) - AdjustJitter(-3) + if(dizziness) + AdjustDizzy(-3) + if(jitteriness) + AdjustJitter(-3) if(NO_INTORGANS in dna.species.species_traits) return handle_trace_chems() - return //TODO: DEFERRED - /mob/living/carbon/human/handle_drunk() var/slur_start = 30 //12u ethanol, 30u whiskey FOR HUMANS var/confused_start = 40 @@ -681,55 +692,54 @@ var/collapse_start = 75 var/braindamage_start = 120 var/alcohol_strength = drunk - var/sober_str=!(SOBER in mutations)?1:2 + var/sober_str =! (SOBER in mutations) ? 1 : 2 - if(drunk) - alcohol_strength/=sober_str + alcohol_strength /= sober_str - var/obj/item/organ/internal/liver/L - if(!isSynthetic()) - L = get_int_organ(/obj/item/organ/internal/liver) + var/obj/item/organ/internal/liver/L + if(!isSynthetic()) + L = get_int_organ(/obj/item/organ/internal/liver) + if(L) + alcohol_strength *= L.alcohol_intensity + else + alcohol_strength *= 5 + + if(alcohol_strength >= slur_start) //slurring + Slur(drunk) + if(alcohol_strength >= brawl_start) //the drunken martial art + if(!istype(martial_art, /datum/martial_art/drunk_brawling)) + var/datum/martial_art/drunk_brawling/F = new + F.teach(src, 1) + if(alcohol_strength < brawl_start) //removing the art + if(istype(martial_art, /datum/martial_art/drunk_brawling)) + martial_art.remove(src) + if(alcohol_strength >= confused_start && prob(33)) //confused walking + if(!confused) + Confused(1) + AdjustConfused(3 / sober_str) + if(alcohol_strength >= blur_start) //blurry eyes + EyeBlurry(10 / sober_str) + if(!isSynthetic()) //stuff only for non-synthetics + if(alcohol_strength >= vomit_start) //vomiting + if(prob(8)) + fakevomit() + if(alcohol_strength >= pass_out) + Paralyse(5 / sober_str) + Drowsy(30 / sober_str) if(L) - alcohol_strength *= L.alcohol_intensity - else - alcohol_strength *= 5 - - if(alcohol_strength >= slur_start) //slurring - Slur(drunk) - if(alcohol_strength >= brawl_start) //the drunken martial art - if(!istype(martial_art, /datum/martial_art/drunk_brawling)) - var/datum/martial_art/drunk_brawling/F = new - F.teach(src,1) - if(alcohol_strength < brawl_start) //removing the art - if(istype(martial_art, /datum/martial_art/drunk_brawling)) - martial_art.remove(src) - if(alcohol_strength >= confused_start && prob(33)) //confused walking - if(!confused) Confused(1) - AdjustConfused(3/sober_str) - if(alcohol_strength >= blur_start) //blurry eyes - EyeBlurry(10/sober_str) - if(!isSynthetic()) //stuff only for non-synthetics - if(alcohol_strength >= vomit_start) //vomiting - if(prob(8)) - fakevomit() - if(alcohol_strength >= pass_out) - Paralyse(5/sober_str) - Drowsy(30/sober_str) - if(L) - L.receive_damage(0.1, 1) - adjustToxLoss(0.1) - else //stuff only for synthetics - if(alcohol_strength >= spark_start && prob(25)) - do_sparks(3, 1, src) - if(alcohol_strength >= collapse_start && prob(10)) - emote("collapse") - do_sparks(3, 1, src) - if(alcohol_strength >= braindamage_start && prob(10)) - adjustBrainLoss(1) + L.receive_damage(0.1, 1) + adjustToxLoss(0.1) + else //stuff only for synthetics + if(alcohol_strength >= spark_start && prob(25)) + do_sparks(3, 1, src) + if(alcohol_strength >= collapse_start && prob(10)) + emote("collapse") + do_sparks(3, 1, src) + if(alcohol_strength >= braindamage_start && prob(10)) + adjustBrainLoss(1) if(!has_booze()) AdjustDrunk(-0.5) - return /mob/living/carbon/human/proc/has_booze() //checks if the human has ethanol or its subtypes inside for(var/A in reagents.reagent_list) @@ -738,178 +748,154 @@ return 1 return 0 -/mob/living/carbon/human/handle_regular_status_updates() +/mob/living/carbon/human/handle_critical_condition() if(status_flags & GODMODE) return 0 - . = ..() + var/guaranteed_death_threshold = health + (getOxyLoss() * 0.5) - (getFireLoss() * 0.67) - (getBruteLoss() * 0.67) - if(.) //alive - if(REGEN in mutations) - heal_overall_damage(0.1, 0.1) + if(getBrainLoss() >= 120 || (guaranteed_death_threshold) <= -500) + death() + return - if(paralysis) - stat = UNCONSCIOUS + if(getBrainLoss() >= 100) // braindeath + AdjustLoseBreath(10, bound_lower = 0, bound_upper = 25) + Weaken(30) - else if(sleeping) + if(!check_death_method()) + if(health <= HEALTH_THRESHOLD_DEAD) + var/deathchance = min(99, ((getBrainLoss() * -5) + (health + (getOxyLoss() / 2))) * -0.01) + if(prob(deathchance)) + death() + return - stat = UNCONSCIOUS + if(health <= HEALTH_THRESHOLD_CRIT) + if(prob(5)) + emote(pick("faint", "collapse", "cry", "moan", "gasp", "shudder", "shiver")) + AdjustStuttering(5, bound_lower = 0, bound_upper = 5) + EyeBlurry(5) + if(prob(7)) + AdjustConfused(2) + if(prob(5)) + Paralyse(2) + switch(health) + if(-INFINITY to -100) + adjustOxyLoss(1) + if(prob(health * -0.1)) + if(ishuman(src)) + var/mob/living/carbon/human/H = src + H.set_heartattack(TRUE) + if(prob(health * -0.2)) + var/datum/disease/D = new /datum/disease/critical/heart_failure + ForceContractDisease(D) + Paralyse(5) + if(-99 to -80) + adjustOxyLoss(1) + if(prob(4)) + to_chat(src, "Your chest hurts...") + Paralyse(2) + var/datum/disease/D = new /datum/disease/critical/heart_failure + ForceContractDisease(D) + if(-79 to -50) + adjustOxyLoss(1) + if(prob(10)) + var/datum/disease/D = new /datum/disease/critical/shock + ForceContractDisease(D) + if(prob(health * -0.08)) + var/datum/disease/D = new /datum/disease/critical/heart_failure + ForceContractDisease(D) + if(prob(6)) + to_chat(src, "You feel [pick("horrible pain", "awful", "like shit", "absolutely awful", "like death", "like you are dying", "nothing", "warm", "sweaty", "tingly", "really, really bad", "horrible")]!") + Weaken(3) + if(prob(3)) + Paralyse(2) + if(-49 to 0) + adjustOxyLoss(1) + if(prob(3)) + var/datum/disease/D = new /datum/disease/critical/shock + ForceContractDisease(D) + if(prob(5)) + to_chat(src, "You feel [pick("terrible", "awful", "like shit", "sick", "numb", "cold", "sweaty", "tingly", "horrible")]!") + Weaken(3) - if(mind) - if(mind.vampire) - if(istype(loc, /obj/structure/closet/coffin)) - adjustBruteLoss(-1) - adjustFireLoss(-1) - adjustToxLoss(-1) - - else if(status_flags & FAKEDEATH) - stat = UNCONSCIOUS - - //Vision //god knows why this is here - var/obj/item/organ/vision - if(dna.species.vision_organ) - vision = get_int_organ(dna.species.vision_organ) - - if(!dna.species.vision_organ) // Presumably if a species has no vision organs, they see via some other means. - SetEyeBlind(0) - SetEyeBlurry(0) - - else if(!vision || vision.is_broken()) // Vision organs cut out or broken? Permablind. - EyeBlind(2) - EyeBlurry(2) - - else - //blindness - if(disabilities & BLIND) // Disabled-blind, doesn't get better on its own - - else if(eye_blind) // Blindness, heals slowly over time - AdjustEyeBlind(-1) - - else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster - AdjustEyeBlurry(-3) - - //blurry sight - if(vision.is_bruised()) // Vision organs impaired? Permablurry. - EyeBlurry(2) - - if(eye_blurry) // Blurry eyes heal slowly - AdjustEyeBlurry(-1) - - - if(flying) - animate(src, pixel_y = pixel_y + 5 , time = 10, loop = 1, easing = SINE_EASING) - animate(pixel_y = pixel_y - 5, time = 10, loop = 1, easing = SINE_EASING) - - // If you're dirty, your gloves will become dirty, too. - if(gloves && germ_level > gloves.germ_level && prob(10)) - gloves.germ_level += 1 - - handle_organs() - - if(getBrainLoss() >= 120 || (health + (getOxyLoss() / 2)) <= -500) - death() - return - - if(getBrainLoss() >= 100) // braindeath - AdjustLoseBreath(10, bound_lower = 0, bound_upper = 25) - Weaken(30) - - if(!check_death_method()) - if(health <= HEALTH_THRESHOLD_DEAD) - var/deathchance = min(99, ((getBrainLoss() * -5) + (health + (getOxyLoss() / 2))) * -0.01) - if(prob(deathchance)) - death() - return - - if(health <= HEALTH_THRESHOLD_CRIT) - if(prob(5)) - emote(pick("faint", "collapse", "cry", "moan", "gasp", "shudder", "shiver")) - AdjustStuttering(5, bound_lower = 0, bound_upper = 5) - EyeBlurry(5) - if(prob(7)) - AdjustConfused(2) - if(prob(5)) - Paralyse(2) - switch(health) - if(-INFINITY to -100) - adjustOxyLoss(1) - if(prob(health * -0.1)) - if(ishuman(src)) - var/mob/living/carbon/human/H = src - H.set_heartattack(TRUE) - if(prob(health * -0.2)) - var/datum/disease/D = new /datum/disease/critical/heart_failure - ForceContractDisease(D) - Paralyse(5) - if(-99 to -80) - adjustOxyLoss(1) - if(prob(4)) - to_chat(src, "Your chest hurts...") - Paralyse(2) - var/datum/disease/D = new /datum/disease/critical/heart_failure - ForceContractDisease(D) - if(-79 to -50) - adjustOxyLoss(1) - if(prob(10)) - var/datum/disease/D = new /datum/disease/critical/shock - ForceContractDisease(D) - if(prob(health * -0.08)) - var/datum/disease/D = new /datum/disease/critical/heart_failure - ForceContractDisease(D) - if(prob(6)) - to_chat(src, "You feel [pick("horrible pain", "awful", "like shit", "absolutely awful", "like death", "like you are dying", "nothing", "warm", "sweaty", "tingly", "really, really bad", "horrible")]!") - Weaken(3) - if(prob(3)) - Paralyse(2) - if(-49 to 0) - adjustOxyLoss(1) - if(prob(3)) - var/datum/disease/D = new /datum/disease/critical/shock - ForceContractDisease(D) - if(prob(5)) - to_chat(src, "You feel [pick("terrible", "awful", "like shit", "sick", "numb", "cold", "sweaty", "tingly", "horrible")]!") - Weaken(3) - - else //dead - SetSilence(0) - - -/mob/living/carbon/human/handle_vision() - if(machine) - if(!machine.check_eye(src)) - reset_perspective(null) +/mob/living/carbon/human/update_health_hud() + if(!client) + return + if(dna.species.update_health_hud()) + return else - var/isRemoteObserve = 0 - if((REMOTE_VIEW in mutations) && remoteview_target) - isRemoteObserve = 1 + if(healths) + var/health_amount = get_perceived_trauma() + if(..(health_amount)) //not dead + switch(hal_screwyhud) + if(SCREWYHUD_CRIT) + healths.icon_state = "health6" + if(SCREWYHUD_DEAD) + healths.icon_state = "health7" + if(SCREWYHUD_HEALTHY) + healths.icon_state = "health0" - if(remoteview_target.stat != CONSCIOUS) - to_chat(src, "Your psy-connection grows too faint to maintain!") - isRemoteObserve = 0 + if(healthdoll) + if(stat == DEAD) + healthdoll.icon_state = "healthdoll_DEAD" + if(healthdoll.overlays.len) + healthdoll.overlays.Cut() + else + var/list/new_overlays = list() + var/list/cached_overlays = healthdoll.cached_healthdoll_overlays + // Use the dead health doll as the base, since we have proper "healthy" overlays now + healthdoll.icon_state = "healthdoll_DEAD" + for(var/obj/item/organ/external/O in bodyparts) + var/damage = O.burn_dam + O.brute_dam + var/comparison = (O.max_damage/5) + var/icon_num = 0 + if(damage) + icon_num = 1 + if(damage > (comparison)) + icon_num = 2 + if(damage > (comparison*2)) + icon_num = 3 + if(damage > (comparison*3)) + icon_num = 4 + if(damage > (comparison*4)) + icon_num = 5 + new_overlays += "[O.limb_name][icon_num]" + healthdoll.overlays += (new_overlays - cached_overlays) + healthdoll.overlays -= (cached_overlays - new_overlays) + healthdoll.cached_healthdoll_overlays = new_overlays - if(PSY_RESIST in remoteview_target.mutations) - to_chat(src, "Your mind is shut out!") - isRemoteObserve = 0 +/mob/living/carbon/human/proc/handle_nutrition_alerts() //This is a terrible abuse of the alert system; something like this should be a HUD element + if(NO_HUNGER in dna.species.species_traits) + return + if(mind?.vampire && (mind in SSticker.mode.vampires)) //Vampires + switch(nutrition) + if(NUTRITION_LEVEL_FULL to INFINITY) + throw_alert("nutrition", /obj/screen/alert/fat/vampire) + if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL) + throw_alert("nutrition", /obj/screen/alert/full/vampire) + if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED) + throw_alert("nutrition", /obj/screen/alert/well_fed/vampire) + if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED) + throw_alert("nutrition", /obj/screen/alert/fed/vampire) + if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) + throw_alert("nutrition", /obj/screen/alert/hungry/vampire) + else + throw_alert("nutrition", /obj/screen/alert/starving/vampire) - // Not on the station or mining? - var/turf/temp_turf = get_turf(remoteview_target) - if(!temp_turf in config.contact_levels) - to_chat(src, "Your psy-connection grows too faint to maintain!") - isRemoteObserve = 0 - - if(remote_view) - isRemoteObserve = 1 - - if(!isRemoteObserve && client && !client.adminobs) - remoteview_target = null - reset_perspective(null) - -/mob/living/carbon/human/handle_hud_icons() - dna.species.handle_hud_icons(src) - -/mob/living/carbon/human/handle_hud_icons_health() - dna.species.handle_hud_icons_health(src) - handle_hud_icons_health_overlay() + else //Any other non-vampires + switch(nutrition) + if(NUTRITION_LEVEL_FULL to INFINITY) + throw_alert("nutrition", /obj/screen/alert/fat) + if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL) + throw_alert("nutrition", /obj/screen/alert/full) + if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED) + throw_alert("nutrition", /obj/screen/alert/well_fed) + if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED) + throw_alert("nutrition", /obj/screen/alert/fed) + if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) + throw_alert("nutrition", /obj/screen/alert/hungry) + else + throw_alert("nutrition", /obj/screen/alert/starving) /mob/living/carbon/human/handle_random_events() // Puke if toxloss is too high @@ -938,15 +924,14 @@ clear_alert("embeddedobject") /mob/living/carbon/human/handle_changeling() - if(mind) - if(mind.changeling) - mind.changeling.regenerate(src) - if(hud_used) - hud_used.lingchemdisplay.invisibility = 0 - hud_used.lingchemdisplay.maptext = "
    [round(mind.changeling.chem_charges)]
    " - else - if(hud_used) - hud_used.lingchemdisplay.invisibility = 101 + if(mind.changeling) + mind.changeling.regenerate(src) + if(hud_used) + hud_used.lingchemdisplay.invisibility = 0 + hud_used.lingchemdisplay.maptext = "
    [round(mind.changeling.chem_charges)]
    " + else + if(hud_used) + hud_used.lingchemdisplay.invisibility = 101 /mob/living/carbon/human/proc/handle_pulse(times_fired) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 40638a2110c..65b4585ff6b 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -138,7 +138,7 @@ span = mind.speech_span if((COMIC in mutations) \ || (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) \ - || GetComponent(/datum/component/jestosterone)) + || HAS_TRAIT(src, TRAIT_JESTER)) span = "sans" if(WINGDINGS in mutations) @@ -151,7 +151,7 @@ if(S.speaking && S.speaking.flags & NO_STUTTER) continue - if(silent || (disabilities & MUTE)) + if(silent || (MUTE in mutations)) S.message = "" if(istype(wear_mask, /obj/item/clothing/mask/horsehead)) @@ -161,7 +161,7 @@ verb = pick("whinnies", "neighs", "says") if(dna) - for(var/datum/dna/gene/gene in dna_genes) + for(var/datum/dna/gene/gene in GLOB.dna_genes) if(!gene.block) continue if(gene.is_active(src)) diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm index 6034a22139b..21695e25e78 100644 --- a/code/modules/mob/living/carbon/human/species/_species.dm +++ b/code/modules/mob/living/carbon/human/species/_species.dm @@ -84,6 +84,7 @@ var/single_gib_type = /obj/effect/decal/cleanable/blood/gibs var/remains_type = /obj/effect/decal/remains/human //What sort of remains is left behind when the species dusts var/base_color //Used when setting species. + var/list/inherent_factions //Used in icon caching. var/race_key = 0 @@ -272,8 +273,6 @@ if(H.status_flags & GOTTAGOFAST) . -= 1 - if(H.status_flags & GOTTAGOFAST_METH) - . -= 1 return . /datum/species/proc/on_species_gain(mob/living/carbon/human/H) //Handles anything not already covered by basic species assignment. @@ -285,11 +284,19 @@ H.hud_used.update_locked_slots() H.ventcrawler = ventcrawler + if(inherent_factions) + for(var/i in inherent_factions) + H.faction += i //Using +=/-= for this in case you also gain the faction from a different source. + /datum/species/proc/on_species_loss(mob/living/carbon/human/H) if(H.butcher_results) //clear it out so we don't butcher a actual human. H.butcher_results = null H.ventcrawler = initial(H.ventcrawler) + if(inherent_factions) + for(var/i in inherent_factions) + H.faction -= i + /datum/species/proc/updatespeciescolor(mob/living/carbon/human/H) //Handles changing icobase for species that have multiple skin colors. return @@ -347,7 +354,7 @@ if(H.LAssailant && ishuman(H.LAssailant)) //superheros still get the comical hit markers var/mob/living/carbon/human/A = H.LAssailant - if(A.mind && A.mind in (SSticker.mode.superheroes || SSticker.mode.supervillains || SSticker.mode.greyshirts)) + if(A.mind && (A.mind in (SSticker.mode.superheroes) || SSticker.mode.supervillains || SSticker.mode.greyshirts)) var/list/attack_bubble_recipients = list() var/mob/living/user for(var/mob/O in viewers(user, src)) @@ -609,13 +616,6 @@ if(!H.has_organ_for_slot(slot)) return FALSE - if(istype(I, /obj/item/clothing/under) || istype(I, /obj/item/clothing/suit)) - if(FAT in H.mutations) - if(!(I.flags_size & ONESIZEFITSALL)) - if(!disable_warning) - to_chat(H, "You're too fat to wear the [I].") - return FALSE - switch(slot) if(slot_l_hand) return !H.l_hand && !H.incapacitated() @@ -754,105 +754,8 @@ return FALSE //Unsupported slot -/datum/species/proc/get_perceived_trauma(mob/living/carbon/human/H) - return min(H.health, H.maxHealth - H.getStaminaLoss()) - -/datum/species/proc/handle_hud_icons(mob/living/carbon/human/H) - if(!H.client) - return - handle_hud_icons_health(H) - H.handle_hud_icons_health_overlay() - handle_hud_icons_nutrition(H) - -/datum/species/proc/handle_hud_icons_health(mob/living/carbon/H) - if(!H.client) - return - handle_hud_icons_health_side(H) - handle_hud_icons_health_doll(H) - -/datum/species/proc/handle_hud_icons_health_side(mob/living/carbon/human/H) - if(H.healths) - if(H.stat == DEAD || (H.status_flags & FAKEDEATH)) - H.healths.icon_state = "health7" - else - switch(H.hal_screwyhud) - if(SCREWYHUD_CRIT) H.healths.icon_state = "health6" - if(SCREWYHUD_DEAD) H.healths.icon_state = "health7" - if(SCREWYHUD_HEALTHY) H.healths.icon_state = "health0" - else - switch(get_perceived_trauma(H)) - if(100 to INFINITY) H.healths.icon_state = "health0" - if(80 to 100) H.healths.icon_state = "health1" - if(60 to 80) H.healths.icon_state = "health2" - if(40 to 60) H.healths.icon_state = "health3" - if(20 to 40) H.healths.icon_state = "health4" - if(0 to 20) H.healths.icon_state = "health5" - else H.healths.icon_state = "health6" - -/datum/species/proc/handle_hud_icons_health_doll(mob/living/carbon/human/H) - if(H.healthdoll) - if(H.stat == DEAD || (H.status_flags & FAKEDEATH)) - H.healthdoll.icon_state = "healthdoll_DEAD" - if(H.healthdoll.overlays.len) - H.healthdoll.overlays.Cut() - else - var/list/new_overlays = list() - var/list/cached_overlays = H.healthdoll.cached_healthdoll_overlays - // Use the dead health doll as the base, since we have proper "healthy" overlays now - H.healthdoll.icon_state = "healthdoll_DEAD" - for(var/obj/item/organ/external/O in H.bodyparts) - var/damage = O.burn_dam + O.brute_dam - var/comparison = (O.max_damage/5) - var/icon_num = 0 - if(damage) - icon_num = 1 - if(damage > (comparison)) - icon_num = 2 - if(damage > (comparison*2)) - icon_num = 3 - if(damage > (comparison*3)) - icon_num = 4 - if(damage > (comparison*4)) - icon_num = 5 - new_overlays += "[O.limb_name][icon_num]" - H.healthdoll.overlays += (new_overlays - cached_overlays) - H.healthdoll.overlays -= (cached_overlays - new_overlays) - H.healthdoll.cached_healthdoll_overlays = new_overlays - -/datum/species/proc/handle_hud_icons_nutrition(mob/living/carbon/human/H) - if(NO_HUNGER in species_traits) - return FALSE - if(H.mind && H.mind.vampire && (H.mind in SSticker.mode.vampires)) //Vampires - switch(H.nutrition) - if(NUTRITION_LEVEL_FULL to INFINITY) - H.throw_alert("nutrition", /obj/screen/alert/fat/vampire) - if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL) - H.throw_alert("nutrition", /obj/screen/alert/full/vampire) - if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED) - H.throw_alert("nutrition", /obj/screen/alert/well_fed/vampire) - if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED) - H.throw_alert("nutrition", /obj/screen/alert/fed/vampire) - if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) - H.throw_alert("nutrition", /obj/screen/alert/hungry/vampire) - else - H.throw_alert("nutrition", /obj/screen/alert/starving/vampire) - return 1 - - else ///Any other non-vampires - switch(H.nutrition) - if(NUTRITION_LEVEL_FULL to INFINITY) - H.throw_alert("nutrition", /obj/screen/alert/fat) - if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL) - H.throw_alert("nutrition", /obj/screen/alert/full) - if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED) - H.throw_alert("nutrition", /obj/screen/alert/well_fed) - if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED) - H.throw_alert("nutrition", /obj/screen/alert/fed) - if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY) - H.throw_alert("nutrition", /obj/screen/alert/hungry) - else - H.throw_alert("nutrition", /obj/screen/alert/starving) - return 1 +/datum/species/proc/update_health_hud(mob/living/carbon/human/H) + return FALSE /* Returns the path corresponding to the corresponding organ @@ -963,7 +866,7 @@ It'll return null if the organ doesn't correspond, so include null checks when u /datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H) -/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) +/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/organ/external/affecting, intent, mob/living/carbon/human/H) /proc/get_random_species(species_name = FALSE) // Returns a random non black-listed or hazardous species, either as a string or datum var/static/list/random_species = list() diff --git a/code/modules/mob/living/carbon/human/species/abductor.dm b/code/modules/mob/living/carbon/human/species/abductor.dm index 9571040fcec..d7220d3a3e9 100644 --- a/code/modules/mob/living/carbon/human/species/abductor.dm +++ b/code/modules/mob/living/carbon/human/species/abductor.dm @@ -37,10 +37,10 @@ H.gender = NEUTER H.languages.Cut() //Under no condition should you be able to speak any language H.add_language("Abductor Mindlink") //other than over the abductor's own mindlink - var/datum/atom_hud/abductor_hud = huds[DATA_HUD_ABDUCTOR] + var/datum/atom_hud/abductor_hud = GLOB.huds[DATA_HUD_ABDUCTOR] abductor_hud.add_hud_to(H) /datum/species/abductor/on_species_loss(mob/living/carbon/human/H) ..() - var/datum/atom_hud/abductor_hud = huds[DATA_HUD_ABDUCTOR] + var/datum/atom_hud/abductor_hud = GLOB.huds[DATA_HUD_ABDUCTOR] abductor_hud.remove_hud_from(H) diff --git a/code/modules/mob/living/carbon/human/species/diona.dm b/code/modules/mob/living/carbon/human/species/diona.dm index 22edf961270..a8639a1a948 100644 --- a/code/modules/mob/living/carbon/human/species/diona.dm +++ b/code/modules/mob/living/carbon/human/species/diona.dm @@ -108,13 +108,4 @@ /datum/species/diona/pod //Same name and everything; we want the same limitations on them; we just want their regeneration to kick in at all times and them to have special factions pod = TRUE - -/datum/species/diona/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species) - . = ..() - C.faction |= "plants" - C.faction |= "vines" - -/datum/species/diona/pod/on_species_loss(mob/living/carbon/C) - . = ..() - C.faction -= "plants" - C.faction -= "vines" + inherent_factions = list("plants", "vines") diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm index 157995e9549..7ff32e38644 100644 --- a/code/modules/mob/living/carbon/human/species/golem.dm +++ b/code/modules/mob/living/carbon/human/species/golem.dm @@ -474,7 +474,7 @@ if(P.is_reflectable) H.visible_message("The [P.name] gets reflected by [H]'s glass skin!", \ "The [P.name] gets reflected by [H]'s glass skin!") - + P.reflect_back(H) return FALSE @@ -534,7 +534,7 @@ if(world.time > last_teleport + teleport_cooldown && M != H && M.a_intent != INTENT_HELP) reactive_teleport(H) -/datum/species/golem/bluespace/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) +/datum/species/golem/bluespace/spec_attacked_by(obj/item/I, mob/living/user, obj/item/organ/external/affecting, intent, mob/living/carbon/human/H) ..() if(world.time > last_teleport + teleport_cooldown && user != H) reactive_teleport(H) @@ -636,12 +636,11 @@ H.mutations.Add(COMIC) H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(H), slot_r_store) H.equip_to_slot_or_del(new /obj/item/bikehorn(H), slot_l_store) - H.AddComponent(/datum/component/waddling) + H.AddElement(/datum/element/waddling) /datum/species/golem/bananium/on_species_loss(mob/living/carbon/C) . = ..() - GET_COMPONENT_FROM(waddling, /datum/component/waddling, C) - waddling.Destroy() + C.RemoveElement(/datum/element/waddling) /datum/species/golem/bananium/get_random_name() var/clown_name = pick(GLOB.clown_names) @@ -654,7 +653,7 @@ new/obj/item/grown/bananapeel/specialpeel(get_turf(H)) last_banana = world.time -/datum/species/golem/bananium/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) +/datum/species/golem/bananium/spec_attacked_by(obj/item/I, mob/living/user, obj/item/organ/external/affecting, intent, mob/living/carbon/human/H) ..() if(world.time > last_banana + banana_cooldown && user != H) new/obj/item/grown/bananapeel/specialpeel(get_turf(H)) diff --git a/code/modules/mob/living/carbon/human/species/grey.dm b/code/modules/mob/living/carbon/human/species/grey.dm index 502ce1a4ac0..790a7f75d3f 100644 --- a/code/modules/mob/living/carbon/human/species/grey.dm +++ b/code/modules/mob/living/carbon/human/species/grey.dm @@ -21,7 +21,7 @@ default_genes = list(REMOTE_TALK) - species_traits = list(LIPS, IS_WHITELISTED, CAN_BE_FAT, CAN_WINGDINGS) + species_traits = list(LIPS, IS_WHITELISTED, CAN_WINGDINGS) clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS bodyflags = HAS_BODY_MARKINGS dietflags = DIET_HERB @@ -32,9 +32,9 @@ /datum/species/grey/handle_dna(mob/living/carbon/human/H, remove) ..() - H.dna.SetSEState(REMOTETALKBLOCK, !remove, 1) - genemutcheck(H, REMOTETALKBLOCK, null, MUTCHK_FORCED) - H.dna.default_blocks.Add(REMOTETALKBLOCK) + H.dna.SetSEState(GLOB.remotetalkblock, !remove, 1) + genemutcheck(H, GLOB.remotetalkblock, null, MUTCHK_FORCED) + H.dna.default_blocks.Add(GLOB.remotetalkblock) /datum/species/grey/water_act(mob/living/carbon/human/H, volume, temperature, source, method = REAGENT_TOUCH) . = ..() diff --git a/code/modules/mob/living/carbon/human/species/human.dm b/code/modules/mob/living/carbon/human/species/human.dm index 6052e769c23..1d339917ad0 100644 --- a/code/modules/mob/living/carbon/human/species/human.dm +++ b/code/modules/mob/living/carbon/human/species/human.dm @@ -5,7 +5,7 @@ deform = 'icons/mob/human_races/r_def_human.dmi' primitive_form = /datum/species/monkey language = "Sol Common" - species_traits = list(LIPS, CAN_BE_FAT) + species_traits = list(LIPS) skinned_type = /obj/item/stack/sheet/animalhide/human clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS @@ -18,4 +18,4 @@ reagent_tag = PROCESS_ORG //Has standard darksight of 2. - + diff --git a/code/modules/mob/living/carbon/human/species/machine.dm b/code/modules/mob/living/carbon/human/species/machine.dm index e920cc38b90..ec37d3c6c9f 100644 --- a/code/modules/mob/living/carbon/human/species/machine.dm +++ b/code/modules/mob/living/carbon/human/species/machine.dm @@ -116,12 +116,12 @@ to_chat(H, "Where's your head at? Can't change your monitor/display without one.") return - var/datum/robolimb/robohead = all_robolimbs[head_organ.model] + var/datum/robolimb/robohead = GLOB.all_robolimbs[head_organ.model] if(!head_organ) return if(!robohead.is_monitor) //If they've got a prosthetic head and it isn't a monitor, they've no screen to adjust. Instead, let them change the colour of their optics! var/optic_colour = input(H, "Select optic colour", H.m_colours["head"]) as color|null - if(H.incapacitated()) + if(H.incapacitated(TRUE, TRUE, TRUE)) to_chat(H, "You were interrupted while changing the colour of your optics.") return if(optic_colour) @@ -149,7 +149,7 @@ var/new_style = input(H, "Select a monitor display", "Monitor Display", head_organ.h_style) as null|anything in hair var/new_color = input("Please select hair color.", "Monitor Color", head_organ.hair_colour) as null|color - if(H.incapacitated()) + if(H.incapacitated(TRUE, TRUE, TRUE)) to_chat(H, "You were interrupted while changing your monitor display.") return diff --git a/code/modules/mob/living/carbon/human/species/monkey.dm b/code/modules/mob/living/carbon/human/species/monkey.dm index b357d2c5345..9c5b51b743b 100644 --- a/code/modules/mob/living/carbon/human/species/monkey.dm +++ b/code/modules/mob/living/carbon/human/species/monkey.dm @@ -18,6 +18,7 @@ is_small = 1 has_fine_manipulation = 0 ventcrawler = VENTCRAWLER_NUDE + dietflags = DIET_OMNI show_ssd = 0 eyes = "blank_eyes" death_message = "lets out a faint chimper as it collapses and stops moving..." @@ -41,7 +42,7 @@ if(H.stat != CONSCIOUS) return if(prob(33) && H.canmove && isturf(H.loc) && !H.pulledby) //won't move if being pulled - step(H, pick(cardinal)) + step(H, pick(GLOB.cardinal)) if(prob(1)) H.emote(pick("scratch","jump","roll","tail")) @@ -57,8 +58,8 @@ /datum/species/monkey/handle_dna(mob/living/carbon/human/H, remove) ..() if(!remove) - H.dna.SetSEState(MONKEYBLOCK, TRUE) - genemutcheck(H, MONKEYBLOCK, null, MUTCHK_FORCED) + H.dna.SetSEState(GLOB.monkeyblock, TRUE) + genemutcheck(H, GLOB.monkeyblock, null, MUTCHK_FORCED) /datum/species/monkey/tajaran name = "Farwa" diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm index 7d1d4c26a61..63f062b8bc8 100644 --- a/code/modules/mob/living/carbon/human/species/shadow.dm +++ b/code/modules/mob/living/carbon/human/species/shadow.dm @@ -5,6 +5,7 @@ icobase = 'icons/mob/human_races/r_shadow.dmi' deform = 'icons/mob/human_races/r_shadow.dmi' dangerous_existence = TRUE + inherent_factions = list("faithless") unarmed_type = /datum/unarmed_attack/claws @@ -49,14 +50,12 @@ if(grant_vision_toggle) vision_toggle = new vision_toggle.Grant(H) - H.faction |= "faithless" /datum/species/shadow/on_species_loss(mob/living/carbon/human/H) ..() if(grant_vision_toggle && vision_toggle) H.vision_type = null vision_toggle.Remove(H) - H.faction -= "faithless" /datum/species/shadow/handle_life(mob/living/carbon/human/H) var/light_amount = 0 diff --git a/code/modules/mob/living/carbon/human/species/slime.dm b/code/modules/mob/living/carbon/human/species/slime.dm index d9fa1ccbf3c..60f972b69a4 100644 --- a/code/modules/mob/living/carbon/human/species/slime.dm +++ b/code/modules/mob/living/carbon/human/species/slime.dm @@ -13,6 +13,7 @@ icobase = 'icons/mob/human_races/r_slime.dmi' deform = 'icons/mob/human_races/r_slime.dmi' remains_type = /obj/effect/decal/remains/slime + inherent_factions = list("slime") // More sensitive to the cold cold_level_1 = 280 @@ -94,7 +95,7 @@ var/obj/item/organ/external/E = H.bodyparts_by_name[organname] if(istype(E) && E.dna && istype(E.dna.species, /datum/species/slime)) E.sync_colour_to_human(H) - H.update_hair(0) + H.update_hair() H.update_body() ..() @@ -146,11 +147,13 @@ return var/limb_select = input(H, "Choose a limb to regrow", "Limb Regrowth") as null|anything in missing_limbs + if(!limb_select) // If the user hit cancel on the popup, return + return var/chosen_limb = missing_limbs[limb_select] H.visible_message("[H] begins to hold still and concentrate on [H.p_their()] missing [limb_select]...", "You begin to focus on regrowing your missing [limb_select]... (This will take [round(SLIMEPERSON_REGROWTHDELAY/10)] seconds, and you must hold still.)") - if(do_after(H, SLIMEPERSON_REGROWTHDELAY, needhand = 0, target = H)) - if(H.incapacitated()) + if(do_after(H, SLIMEPERSON_REGROWTHDELAY, FALSE, H, extra_checks = list(CALLBACK(H, /mob.proc/IsStunned)), use_default_checks = FALSE)) // Override the check for weakness, only check for stunned + if(H.incapacitated(ignore_lying = TRUE, extra_checks = list(CALLBACK(H, /mob.proc/IsStunned)), use_default_checks = FALSE)) // Override the check for weakness, only check for stunned to_chat(H, "You cannot regenerate missing limbs in your current state.") return diff --git a/code/modules/mob/living/carbon/human/species/tajaran.dm b/code/modules/mob/living/carbon/human/species/tajaran.dm index 8a803aa3bd4..903e4a32332 100644 --- a/code/modules/mob/living/carbon/human/species/tajaran.dm +++ b/code/modules/mob/living/carbon/human/species/tajaran.dm @@ -24,7 +24,7 @@ primitive_form = /datum/species/monkey/tajaran - species_traits = list(LIPS, CAN_BE_FAT) + species_traits = list(LIPS) clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS bodyflags = HAS_TAIL | HAS_HEAD_ACCESSORY | HAS_MARKINGS | HAS_SKIN_COLOR | TAIL_WAGGING dietflags = DIET_OMNI @@ -56,4 +56,4 @@ "is holding their breath!") /datum/species/tajaran/handle_death(gibbed, mob/living/carbon/human/H) - H.stop_tail_wagging(1) + H.stop_tail_wagging() diff --git a/code/modules/mob/living/carbon/human/species/unathi.dm b/code/modules/mob/living/carbon/human/species/unathi.dm index 61c34ab41d9..d4e9b02cd9b 100644 --- a/code/modules/mob/living/carbon/human/species/unathi.dm +++ b/code/modules/mob/living/carbon/human/species/unathi.dm @@ -104,7 +104,7 @@ return /datum/species/unathi/handle_death(gibbed, mob/living/carbon/human/H) - H.stop_tail_wagging(1) + H.stop_tail_wagging() /datum/species/unathi/ashwalker name = "Ash Walker" diff --git a/code/modules/mob/living/carbon/human/species/vox.dm b/code/modules/mob/living/carbon/human/species/vox.dm index e803a33f3ec..6ac20e77b9b 100644 --- a/code/modules/mob/living/carbon/human/species/vox.dm +++ b/code/modules/mob/living/carbon/human/species/vox.dm @@ -76,7 +76,7 @@ speciesbox = /obj/item/storage/box/survival_vox /datum/species/vox/handle_death(gibbed, mob/living/carbon/human/H) - H.stop_tail_wagging(1) + H.stop_tail_wagging() /datum/species/vox/after_equip_job(datum/job/J, mob/living/carbon/human/H) if(!H.mind || !H.mind.assigned_role || H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime") diff --git a/code/modules/mob/living/carbon/human/species/vulpkanin.dm b/code/modules/mob/living/carbon/human/species/vulpkanin.dm index 9a313042d2d..920cd86659d 100644 --- a/code/modules/mob/living/carbon/human/species/vulpkanin.dm +++ b/code/modules/mob/living/carbon/human/species/vulpkanin.dm @@ -50,4 +50,4 @@ "is holding their breath!") /datum/species/vulpkanin/handle_death(gibbed, mob/living/carbon/human/H) - H.stop_tail_wagging(1) + H.stop_tail_wagging() diff --git a/code/modules/mob/living/carbon/human/species/wryn.dm b/code/modules/mob/living/carbon/human/species/wryn.dm index 9e02e2e28be..080a67a032b 100644 --- a/code/modules/mob/living/carbon/human/species/wryn.dm +++ b/code/modules/mob/living/carbon/human/species/wryn.dm @@ -50,7 +50,7 @@ /datum/species/wryn/handle_death(gibbed, mob/living/carbon/human/H) - for(var/mob/living/carbon/C in GLOB.living_mob_list) + for(var/mob/living/carbon/C in GLOB.alive_mob_list) if(C.get_int_organ(/obj/item/organ/internal/wryn/hivenode)) to_chat(C, "Your antennae tingle as you are overcome with pain...") to_chat(C, "It feels like part of you has died.") // This is bullshit diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 2ca0f47f7a7..2cce48d51c2 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1,10 +1,10 @@ /* Global associative list for caching humanoid icons. - Index format m or f, followed by a string of 0 and 1 to represent bodyparts followed by husk fat hulk skeleton 1 or 0. + Index format m or f, followed by a string of 0 and 1 to represent bodyparts followed by husk hulk skeleton 1 or 0. TODO: Proper documentation - icon_key is [species.race_key][g][husk][fat][hulk][skeleton][s_tone] + icon_key is [species.race_key][g][husk][hulk][skeleton][s_tone] */ -var/global/list/human_icon_cache = list() +GLOBAL_LIST_EMPTY(human_icon_cache) /////////////////////// //UPDATE_ICONS SYSTEM// @@ -77,14 +77,14 @@ There are several things that need to be remembered: If you wish to update several overlays at once, you can set the argument to 0 to disable the update and call it manually: e.g. - update_inv_head(0) - update_inv_l_hand(0) + update_inv_head() + update_inv_l_hand() update_inv_r_hand() //<---calls update_icons() or equivillantly: - update_inv_head(0) - update_inv_l_hand(0) - update_inv_r_hand(0) + update_inv_head() + update_inv_l_hand() + update_inv_r_hand() update_icons() > If you need to update all overlays you can use regenerate_icons(). it works exactly like update_clothing used to. @@ -120,11 +120,11 @@ Please contact me on #coderbus IRC. ~Carn x overlays_standing[cache_index] = null -var/global/list/damage_icon_parts = list() +GLOBAL_LIST_EMPTY(damage_icon_parts) //DAMAGE OVERLAYS //constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists -/mob/living/carbon/human/UpdateDamageIcon(var/update_icons=1) +/mob/living/carbon/human/UpdateDamageIcon() // first check whether something actually changed about damage appearance var/damage_appearance = "" @@ -151,20 +151,20 @@ var/global/list/damage_icon_parts = list() var/icon/DI var/cache_index = "[E.damage_state]/[E.icon_name]/[dna.species.blood_color]/[dna.species.name]" - if(damage_icon_parts[cache_index] == null) + if(GLOB.damage_icon_parts[cache_index] == null) DI = new /icon(dna.species.damage_overlays, E.damage_state) // the damage icon for whole human DI.Blend(new /icon(dna.species.damage_mask, E.icon_name), ICON_MULTIPLY) // mask with this organ's pixels DI.Blend(dna.species.blood_color, ICON_MULTIPLY) - damage_icon_parts[cache_index] = DI + GLOB.damage_icon_parts[cache_index] = DI else - DI = damage_icon_parts[cache_index] + DI = GLOB.damage_icon_parts[cache_index] damage_overlay.overlays += DI apply_overlay(H_DAMAGE_LAYER) //BASE MOB SPRITE -/mob/living/carbon/human/proc/update_body(var/update_icons=1, var/rebuild_base=0) +/mob/living/carbon/human/proc/update_body(rebuild_base = FALSE) remove_overlay(BODY_LAYER) remove_overlay(LIMBS_LAYER) // So we don't get the old species' sprite splatted on top of the new one's remove_overlay(UNDERWEAR_LAYER) @@ -191,8 +191,8 @@ var/global/list/damage_icon_parts = list() var/icon_key = generate_icon_render_key() var/mutable_appearance/base - if(human_icon_cache[icon_key] && !rebuild_base) - base = human_icon_cache[icon_key] + if(GLOB.human_icon_cache[icon_key] && !rebuild_base) + base = GLOB.human_icon_cache[icon_key] standing += base else var/icon/base_icon @@ -241,7 +241,7 @@ var/global/list/damage_icon_parts = list() base_icon.Blend(husk_over, ICON_OVERLAY) var/mutable_appearance/new_base = mutable_appearance(base_icon, layer = -LIMBS_LAYER) - human_icon_cache[icon_key] = new_base + GLOB.human_icon_cache[icon_key] = new_base standing += new_base //END CACHED ICON GENERATION. @@ -281,19 +281,19 @@ var/global/list/damage_icon_parts = list() overlays_standing[BODY_LAYER] = standing apply_overlay(BODY_LAYER) //tail - update_tail_layer(0) + update_tail_layer() update_int_organs() //head accessory - update_head_accessory(0) + update_head_accessory() //markings - update_markings(0) + update_markings() //hair - update_hair(0) - update_fhair(0) + update_hair() + update_fhair() //MARKINGS OVERLAY -/mob/living/carbon/human/proc/update_markings(var/update_icons=1) +/mob/living/carbon/human/proc/update_markings() //Reset our markings. remove_overlay(MARKINGS_LAYER) @@ -325,7 +325,7 @@ var/global/list/damage_icon_parts = list() apply_overlay(MARKINGS_LAYER) //HEAD ACCESSORY OVERLAY -/mob/living/carbon/human/proc/update_head_accessory(var/update_icons=1) +/mob/living/carbon/human/proc/update_head_accessory() //Reset our head accessory remove_overlay(HEAD_ACCESSORY_LAYER) remove_overlay(HEAD_ACC_OVER_LAYER) @@ -362,7 +362,7 @@ var/global/list/damage_icon_parts = list() //HAIR OVERLAY -/mob/living/carbon/human/proc/update_hair(var/update_icons=1) +/mob/living/carbon/human/proc/update_hair() //Reset our hair remove_overlay(HAIR_LAYER) @@ -403,7 +403,7 @@ var/global/list/damage_icon_parts = list() //FACIAL HAIR OVERLAY -/mob/living/carbon/human/proc/update_fhair(var/update_icons=1) +/mob/living/carbon/human/proc/update_fhair() //Reset our facial hair remove_overlay(FHAIR_LAYER) remove_overlay(FHAIR_OVER_LAYER) @@ -447,23 +447,19 @@ var/global/list/damage_icon_parts = list() -/mob/living/carbon/human/update_mutations(var/update_icons=1) +/mob/living/carbon/human/update_mutations() remove_overlay(MUTATIONS_LAYER) - var/fat - if(FAT in mutations) - fat = "fat" - var/mutable_appearance/standing = mutable_appearance('icons/effects/genetics.dmi', layer = -MUTATIONS_LAYER) var/add_image = 0 var/g = "m" if(gender == FEMALE) g = "f" // DNA2 - Drawing underlays. - for(var/datum/dna/gene/gene in dna_genes) + for(var/datum/dna/gene/gene in GLOB.dna_genes) if(!gene.block) continue if(gene.is_active(src)) - var/underlay = gene.OnDrawUnderlays(src, g, fat) + var/underlay = gene.OnDrawUnderlays(src, g) if(underlay) standing.underlays += underlay add_image = 1 @@ -473,16 +469,16 @@ var/global/list/damage_icon_parts = list() standing.overlays += "lasereyes_s" add_image = 1 if((COLDRES in mutations) && (HEATRES in mutations)) - standing.underlays -= "cold[fat]_s" - standing.underlays -= "fire[fat]_s" - standing.underlays += "coldfire[fat]_s" + standing.underlays -= "cold_s" + standing.underlays -= "fire_s" + standing.underlays += "coldfire_s" if(add_image) overlays_standing[MUTATIONS_LAYER] = standing apply_overlay(MUTATIONS_LAYER) -/mob/living/carbon/human/proc/update_mutantrace(var/update_icons=1) +/mob/living/carbon/human/proc/update_mutantrace() //BS12 EDIT var/skel = (SKELETON in mutations) if(skel) @@ -490,8 +486,8 @@ var/global/list/damage_icon_parts = list() else skeleton = null - update_hair(0) - update_fhair(0) + update_hair() + update_fhair() /mob/living/carbon/human/update_fire() @@ -505,41 +501,42 @@ var/global/list/damage_icon_parts = list() //For legacy support. /mob/living/carbon/human/regenerate_icons() ..() - if(notransform) return - update_mutations(0) - update_body(0, 1) //Update the body and force limb icon regeneration. - update_hair(0) - update_head_accessory(0) - update_fhair(0) - update_mutantrace(0) - update_inv_w_uniform(0,0) - update_inv_wear_id(0) - update_inv_gloves(0,0) - update_inv_glasses(0) - update_inv_ears(0) - update_inv_shoes(0,0) - update_inv_s_store(0) - update_inv_wear_mask(0) - update_inv_head(0,0) - update_inv_belt(0) - update_inv_back(0) - update_inv_wear_suit(0) - update_inv_r_hand(0) - update_inv_l_hand(0) - update_inv_handcuffed(0) - update_inv_legcuffed(0) - update_inv_pockets(0) - update_inv_wear_pda(0) - UpdateDamageIcon(0) + if(notransform) + return + update_mutations() + update_body(TRUE) //Update the body and force limb icon regeneration. + update_hair() + update_head_accessory() + update_fhair() + update_mutantrace() + update_inv_w_uniform() + update_inv_wear_id() + update_inv_gloves() + update_inv_glasses() + update_inv_ears() + update_inv_shoes() + update_inv_s_store() + update_inv_wear_mask() + update_inv_head() + update_inv_belt() + update_inv_back() + update_inv_wear_suit() + update_inv_r_hand() + update_inv_l_hand() + update_inv_handcuffed() + update_inv_legcuffed() + update_inv_pockets() + update_inv_wear_pda() + UpdateDamageIcon() force_update_limbs() - update_tail_layer(0) + update_tail_layer() overlays.Cut() // Force all overlays to regenerate update_fire() update_icons() /* --------------------------------------- */ //vvvvvv UPDATE_INV PROCS vvvvvv -/mob/living/carbon/human/update_inv_w_uniform(var/update_icons=1) +/mob/living/carbon/human/update_inv_w_uniform() remove_overlay(UNIFORM_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_w_uniform] @@ -557,13 +554,6 @@ var/global/list/damage_icon_parts = list() t_color = icon_state var/mutable_appearance/standing = mutable_appearance('icons/mob/uniform.dmi', "[t_color]_s", layer = -UNIFORM_LAYER) - if(FAT in mutations) - if(w_uniform.flags_size & ONESIZEFITSALL) - standing.icon = 'icons/mob/uniform_fat.dmi' - else - to_chat(src, "You burst out of \the [w_uniform]!") - unEquip(w_uniform) - return if(w_uniform.icon_override) standing.icon = w_uniform.icon_override @@ -575,7 +565,7 @@ var/global/list/damage_icon_parts = list() bloodsies.color = w_uniform.blood_color standing.overlays += bloodsies - if(w_uniform:accessories.len) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE. // oh my god kys whoever made this if statement jfc :gun: + if(w_uniform.accessories.len) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE. // oh my god kys whoever made this if statement jfc :gun: for(var/obj/item/clothing/accessory/A in w_uniform:accessories) var/tie_color = A.item_color if(!tie_color) @@ -604,7 +594,7 @@ var/global/list/damage_icon_parts = list() thing.plane = initial(thing.plane) apply_overlay(UNIFORM_LAYER) -/mob/living/carbon/human/update_inv_wear_id(var/update_icons=1) +/mob/living/carbon/human/update_inv_wear_id() remove_overlay(ID_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_id] @@ -620,7 +610,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[ID_LAYER] = mutable_appearance('icons/mob/mob.dmi', "id", layer = -ID_LAYER) apply_overlay(ID_LAYER) -/mob/living/carbon/human/update_inv_gloves(var/update_icons=1) +/mob/living/carbon/human/update_inv_gloves() remove_overlay(GLOVES_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_gloves] @@ -657,7 +647,7 @@ var/global/list/damage_icon_parts = list() apply_overlay(GLOVES_LAYER) -/mob/living/carbon/human/update_inv_glasses(var/update_icons=1) +/mob/living/carbon/human/update_inv_glasses() remove_overlay(GLASSES_LAYER) remove_overlay(GLASSES_OVER_LAYER) remove_overlay(OVER_MASK_LAYER) @@ -698,7 +688,7 @@ var/global/list/damage_icon_parts = list() update_misc_effects() -/mob/living/carbon/human/update_inv_ears(var/update_icons=1) +/mob/living/carbon/human/update_inv_ears() remove_overlay(EARS_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_l_ear] @@ -746,7 +736,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[EARS_LAYER] = mutable_appearance('icons/mob/ears.dmi', "[t_type]", layer = -EARS_LAYER) apply_overlay(EARS_LAYER) -/mob/living/carbon/human/update_inv_shoes(var/update_icons=1) +/mob/living/carbon/human/update_inv_shoes() remove_overlay(SHOES_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_shoes] @@ -782,7 +772,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[SHOES_LAYER] = bloodsies apply_overlay(SHOES_LAYER) -/mob/living/carbon/human/update_inv_s_store(var/update_icons=1) +/mob/living/carbon/human/update_inv_s_store() remove_overlay(SUIT_STORE_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_s_store] @@ -803,7 +793,7 @@ var/global/list/damage_icon_parts = list() apply_overlay(SUIT_STORE_LAYER) -/mob/living/carbon/human/update_inv_head(var/update_icons=1) +/mob/living/carbon/human/update_inv_head() ..() remove_overlay(HEAD_LAYER) if(client && hud_used) @@ -829,7 +819,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[HEAD_LAYER] = standing apply_overlay(HEAD_LAYER) -/mob/living/carbon/human/update_inv_belt(var/update_icons=1) +/mob/living/carbon/human/update_inv_belt() remove_overlay(BELT_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_belt] @@ -855,7 +845,7 @@ var/global/list/damage_icon_parts = list() apply_overlay(BELT_LAYER) -/mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1) +/mob/living/carbon/human/update_inv_wear_suit() remove_overlay(SUIT_LAYER) if(client && hud_used) var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_suit] @@ -873,13 +863,6 @@ var/global/list/damage_icon_parts = list() standing = mutable_appearance(wear_suit.icon_override, "[wear_suit.icon_state]", layer = -SUIT_LAYER) else if(wear_suit.sprite_sheets && wear_suit.sprite_sheets[dna.species.name]) standing = mutable_appearance(wear_suit.sprite_sheets[dna.species.name], "[wear_suit.icon_state]", layer = -SUIT_LAYER) - else if(FAT in mutations) - if(wear_suit.flags_size & ONESIZEFITSALL) - standing = mutable_appearance('icons/mob/suit_fat.dmi', "[wear_suit.icon_state]", layer = -SUIT_LAYER) - else - to_chat(src, "You burst out of \the [wear_suit]!") - unEquip(wear_suit) - return else standing = mutable_appearance('icons/mob/suit.dmi', "[wear_suit.icon_state]", layer = -SUIT_LAYER) @@ -903,8 +886,8 @@ var/global/list/damage_icon_parts = list() overlays_standing[SUIT_LAYER] = standing apply_overlay(SUIT_LAYER) - update_tail_layer(0) - update_collar(0) + update_tail_layer() + update_collar() /mob/living/carbon/human/update_inv_pockets() if(client && hud_used) @@ -937,7 +920,7 @@ var/global/list/damage_icon_parts = list() client.screen += wear_pda wear_pda.screen_loc = ui_pda -/mob/living/carbon/human/update_inv_wear_mask(var/update_icons = 1) +/mob/living/carbon/human/update_inv_wear_mask() ..() remove_overlay(FACEMASK_LAYER) if(client && hud_used) @@ -973,7 +956,7 @@ var/global/list/damage_icon_parts = list() apply_overlay(FACEMASK_LAYER) -/mob/living/carbon/human/update_inv_back(var/update_icons=1) +/mob/living/carbon/human/update_inv_back() ..() remove_overlay(BACK_LAYER) if(back) @@ -996,7 +979,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[BACK_LAYER] = standing apply_overlay(BACK_LAYER) -/mob/living/carbon/human/update_inv_handcuffed(var/update_icons=1) +/mob/living/carbon/human/update_inv_handcuffed() remove_overlay(HANDCUFF_LAYER) if(handcuffed) if(istype(handcuffed, /obj/item/restraints/handcuffs/pinkcuffs)) @@ -1005,7 +988,7 @@ var/global/list/damage_icon_parts = list() overlays_standing[HANDCUFF_LAYER] = mutable_appearance('icons/mob/mob.dmi', "handcuff1", layer = -HANDCUFF_LAYER) apply_overlay(HANDCUFF_LAYER) -/mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1) +/mob/living/carbon/human/update_inv_legcuffed() remove_overlay(LEGCUFF_LAYER) clear_alert("legcuffed") if(legcuffed) @@ -1018,7 +1001,7 @@ var/global/list/damage_icon_parts = list() apply_overlay(LEGCUFF_LAYER) -/mob/living/carbon/human/update_inv_r_hand(var/update_icons=1) +/mob/living/carbon/human/update_inv_r_hand() ..() remove_overlay(R_HAND_LAYER) if(r_hand) @@ -1037,7 +1020,7 @@ var/global/list/damage_icon_parts = list() apply_overlay(R_HAND_LAYER) -/mob/living/carbon/human/update_inv_l_hand(var/update_icons=1) +/mob/living/carbon/human/update_inv_l_hand() ..() remove_overlay(L_HAND_LAYER) if(l_hand) @@ -1078,7 +1061,7 @@ var/global/list/damage_icon_parts = list() client.screen += I -/mob/living/carbon/human/proc/update_tail_layer(var/update_icons=1) +/mob/living/carbon/human/proc/update_tail_layer() remove_overlay(TAIL_UNDERLIMBS_LAYER) // SEW direction icons, overlayed by LIMBS_LAYER. remove_overlay(TAIL_LAYER) /* This will be one of two things: If the species' tail is overlapped by limbs, this will be only the N direction icon so tails @@ -1153,7 +1136,7 @@ var/global/list/damage_icon_parts = list() apply_overlay(TAIL_LAYER) apply_overlay(TAIL_UNDERLIMBS_LAYER) -/mob/living/carbon/human/proc/start_tail_wagging(var/update_icons=1) +/mob/living/carbon/human/proc/start_tail_wagging() remove_overlay(TAIL_UNDERLIMBS_LAYER) // SEW direction icons, overlayed by LIMBS_LAYER. remove_overlay(TAIL_LAYER) /* This will be one of two things: If the species' tail is overlapped by limbs, this will be only the N direction icon so tails @@ -1229,10 +1212,10 @@ var/global/list/damage_icon_parts = list() apply_overlay(TAIL_LAYER) apply_overlay(TAIL_UNDERLIMBS_LAYER) -/mob/living/carbon/human/proc/stop_tail_wagging(var/update_icons=1) +/mob/living/carbon/human/proc/stop_tail_wagging() remove_overlay(TAIL_UNDERLIMBS_LAYER) remove_overlay(TAIL_LAYER) - update_tail_layer(update_icons) //just trigger a full update for normal stationary sprites + update_tail_layer() //just trigger a full update for normal stationary sprites /mob/living/carbon/human/proc/update_int_organs() remove_overlay(INTORGAN_LAYER) @@ -1254,7 +1237,7 @@ var/global/list/damage_icon_parts = list() //Adds a collar overlay above the helmet layer if the suit has one // Suit needs an identically named sprite in icons/mob/collar.dmi // For suits with sprite_sheets, an identically named sprite needs to exist in a file like this icons/mob/species/[species_name_here]/collar.dmi. -/mob/living/carbon/human/proc/update_collar(var/update_icons=1) +/mob/living/carbon/human/proc/update_collar() remove_overlay(COLLAR_LAYER) var/icon/C = new('icons/mob/collar.dmi') var/mutable_appearance/standing = null @@ -1290,20 +1273,17 @@ var/global/list/damage_icon_parts = list() apply_overlay(MISC_LAYER) -/mob/living/carbon/human/admin_Freeze(client/admin, skip_overlays = TRUE) - . = ..() - overlays_standing[FROZEN_LAYER] = mutable_appearance(frozen, layer = -FROZEN_LAYER) - apply_overlay(FROZEN_LAYER) - -/mob/living/carbon/human/admin_unFreeze(client/admin, skip_overlays = TRUE) - . = ..() - remove_overlay(FROZEN_LAYER) - +/mob/living/carbon/human/admin_Freeze(client/admin, skip_overlays = TRUE, mech = null) + if(..()) + overlays_standing[FROZEN_LAYER] = mutable_appearance(frozen, layer = -FROZEN_LAYER) + apply_overlay(FROZEN_LAYER) + else + remove_overlay(FROZEN_LAYER) /mob/living/carbon/human/proc/force_update_limbs() for(var/obj/item/organ/external/O in bodyparts) O.sync_colour_to_human(src) - update_body(0) + update_body() /mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers) var/list/out = new @@ -1316,7 +1296,6 @@ var/global/list/damage_icon_parts = list() /mob/living/carbon/human/proc/generate_icon_render_key() var/husk = (HUSK in mutations) - var/fat = (FAT in mutations) var/hulk = (HULK in mutations) var/skeleton = (SKELETON in mutations) @@ -1349,4 +1328,4 @@ var/global/list/damage_icon_parts = list() if(part.s_tone) . += "[part.s_tone]" - . = "[.][!!husk][!!fat][!!hulk][!!skeleton]" + . = "[.][!!husk][!!hulk][!!skeleton]" diff --git a/code/modules/mob/living/carbon/human/update_stat.dm b/code/modules/mob/living/carbon/human/update_stat.dm index 14c87e13722..d5d1801e1a7 100644 --- a/code/modules/mob/living/carbon/human/update_stat.dm +++ b/code/modules/mob/living/carbon/human/update_stat.dm @@ -12,7 +12,7 @@ /mob/living/carbon/human/update_nearsighted_effects() var/obj/item/clothing/glasses/G = glasses - if((disabilities & NEARSIGHTED) && (!istype(G) || !G.prescription)) + if((NEARSIGHTED in mutations) && (!istype(G) || !G.prescription)) overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1) else clear_fullscreen("nearsighted") diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 832260d3090..66e2e60f144 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -1,24 +1,35 @@ /mob/living/carbon/Life(seconds, times_fired) set invisibility = 0 - set background = BACKGROUND_ENABLED if(notransform) return - if(!loc) + + if(damageoverlaytemp) + damageoverlaytemp = 0 + update_damage_hud() + + if(stat != DEAD) + handle_organs() + + . = ..() + + if(QDELETED(src)) return - if(..()) - . = 1 + if(.) //not dead handle_blood() - for(var/obj/item/organ/internal/O in internal_organs) - O.on_life() - handle_changeling() + if(LAZYLEN(processing_patches)) + handle_patches() + if(mind) + handle_changeling() handle_wetness(times_fired) // Increase germ_level regularly - if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level - germ_level++ + handle_germs() + + if(stat != DEAD) + return TRUE /////////////// @@ -191,6 +202,11 @@ else update_action_buttons_icon() +/mob/living/carbon/proc/handle_organs() + for(var/thing in internal_organs) + var/obj/item/organ/internal/O = thing + O.on_life() + /mob/living/carbon/handle_diseases() for(var/thing in viruses) var/datum/disease/D = thing @@ -233,8 +249,7 @@ /mob/living/carbon/handle_chemicals_in_body() - if(reagents) - reagents.metabolize(src) + reagents.metabolize(src) /mob/living/carbon/proc/handle_wetness(times_fired) @@ -261,7 +276,9 @@ if(stam_regen_start_time <= world.time) if(stam_paralyzed) update_stamina() - setStaminaLoss(0, FALSE) + if(staminaloss) + setStaminaLoss(0, FALSE) + update_health_hud() var/restingpwr = 1 + 4 * resting @@ -319,8 +336,17 @@ AdjustHallucinate(-2) + // Keep SSD people asleep + if(player_logged) + Sleeping(2) + /mob/living/carbon/handle_sleeping() if(..()) + if(mind?.vampire) + if(istype(loc, /obj/structure/closet/coffin)) + adjustBruteLoss(-1, FALSE) + adjustFireLoss(-1, FALSE) + adjustToxLoss(-1) handle_dreams() adjustStaminaLoss(-10) var/comfort = 1 @@ -336,44 +362,42 @@ comfort += 1 //Aren't naps SO much better when drunk? AdjustDrunk(-0.2*comfort) //reduce drunkenness while sleeping. if(comfort > 1 && prob(3))//You don't heal if you're just sleeping on the floor without a blanket. - adjustBruteLoss(-1*comfort) - adjustFireLoss(-1*comfort) + adjustBruteLoss(-1 * comfort, FALSE) + adjustFireLoss(-1 * comfort) if(prob(10) && health && hal_screwyhud != SCREWYHUD_CRIT) emote("snore") - // Keep SSD people asleep - if(player_logged) - Sleeping(2) + return sleeping -/mob/living/carbon/handle_hud_icons() - return - -/mob/living/carbon/handle_hud_icons_health() +/mob/living/carbon/update_health_hud(shown_health_amount) if(!client) return if(healths) if(stat != DEAD) - switch(health) - if(100 to INFINITY) - healths.icon_state = "health0" - if(80 to 100) - healths.icon_state = "health1" - if(60 to 80) - healths.icon_state = "health2" - if(40 to 60) - healths.icon_state = "health3" - if(20 to 40) - healths.icon_state = "health4" - if(0 to 20) - healths.icon_state = "health5" - else - healths.icon_state = "health6" + . = TRUE + if(shown_health_amount == null) + shown_health_amount = health + if(shown_health_amount >= maxHealth) + healths.icon_state = "health0" + else if(shown_health_amount > maxHealth * 0.8) + healths.icon_state = "health1" + else if(shown_health_amount > maxHealth * 0.6) + healths.icon_state = "health2" + else if(shown_health_amount > maxHealth * 0.4) + healths.icon_state = "health3" + else if(shown_health_amount > maxHealth * 0.2) + healths.icon_state = "health4" + else if(shown_health_amount > 0) + healths.icon_state = "health5" + else + healths.icon_state = "health6" else healths.icon_state = "health7" - handle_hud_icons_health_overlay() -/mob/living/carbon/proc/handle_hud_icons_health_overlay() +/mob/living/carbon/update_damage_hud() + if(!client) + return if(stat == UNCONSCIOUS && health <= HEALTH_THRESHOLD_CRIT) if(check_death_method()) var/severity = 0 @@ -438,3 +462,25 @@ overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity) else clear_fullscreen("brute") + +/mob/living/carbon/proc/handle_patches() + var/multiple_patch_multiplier = processing_patches.len > 1 ? (processing_patches.len * 1.5) : 1 + var/applied_amount = 0.35 * multiple_patch_multiplier + + for(var/patch in processing_patches) + var/obj/item/reagent_containers/food/pill/patch/P = patch + + if(P.reagents && P.reagents.total_volume) + var/fractional_applied_amount = applied_amount / P.reagents.total_volume + P.reagents.reaction(src, REAGENT_TOUCH, fractional_applied_amount, P.needs_to_apply_reagents) + P.needs_to_apply_reagents = FALSE + P.reagents.trans_to(src, applied_amount * 0.5) + P.reagents.remove_any(applied_amount * 0.5) + else + if(!P.reagents || P.reagents.total_volume <= 0) + processing_patches -= P + qdel(P) + +/mob/living/carbon/proc/handle_germs() + if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level + germ_level++ diff --git a/code/modules/mob/living/carbon/update_status.dm b/code/modules/mob/living/carbon/update_status.dm index b67953c7e69..918968800ce 100644 --- a/code/modules/mob/living/carbon/update_status.dm +++ b/code/modules/mob/living/carbon/update_status.dm @@ -2,12 +2,10 @@ if(status_flags & GODMODE) return if(stat != DEAD) -// if(health <= min_health) if(health <= HEALTH_THRESHOLD_DEAD && check_death_method()) death() create_debug_log("died of damage, trigger reason: [reason]") return -// if(paralysis || sleeping || getOxyLoss() > low_oxy_ko || (status_flags & FAKEDEATH) || health <= crit_health) if(paralysis || sleeping || (check_death_method() && getOxyLoss() > 50) || (status_flags & FAKEDEATH) || health <= HEALTH_THRESHOLD_CRIT && check_death_method()) if(stat == CONSCIOUS) KnockOut() @@ -16,6 +14,9 @@ if(stat == UNCONSCIOUS) WakeUp() create_debug_log("woke up, trigger reason: [reason]") + update_damage_hud() + update_health_hud() + med_hud_set_status() /mob/living/carbon/update_stamina() var/stam = getStaminaLoss() @@ -24,7 +25,6 @@ else if(stam_paralyzed) stam_paralyzed = FALSE update_canmove() - handle_hud_icons_health() /mob/living/carbon/can_hear() . = FALSE diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index fa1c392334d..60f186631b7 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -269,6 +269,7 @@ if(amount > 0) stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME if(updating) + update_health_hud() update_stamina() /mob/living/proc/setStaminaLoss(amount, updating = TRUE) @@ -284,6 +285,7 @@ if(amount > 0) stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME if(updating) + update_health_hud() update_stamina() /mob/living/proc/getMaxHealth() diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 4d8aa1b776b..6af90792355 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -61,10 +61,13 @@ if(mind && suiciding) mind.suicided = TRUE + reset_perspective(null) clear_fullscreens() update_sight() update_action_buttons_icon() + update_damage_hud() + update_health_hud() med_hud_set_health() med_hud_set_status() if(!gibbed && !QDELETED(src)) @@ -81,8 +84,9 @@ update_canmove() timeofdeath = world.time + create_log(ATTACK_LOG, "died[gibbed ? " (Gibbed)": ""]") - GLOB.living_mob_list -= src + GLOB.alive_mob_list -= src GLOB.dead_mob_list += src if(mind) mind.store_memory("Time of death: [station_time_timestamp("hh:mm:ss", timeofdeath)]", 0) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 5ab604e5b3e..6d020ccdad1 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -1,12 +1,10 @@ -/mob/living/Life(seconds, times_fired) +/mob/living/proc/Life(seconds, times_fired) + set waitfor = FALSE set invisibility = 0 - set background = BACKGROUND_ENABLED - if(notransform) - return FALSE - if(!loc) - return FALSE - var/datum/gas_mixture/environment = loc.return_air() + if(flying) //TODO: Better floating + animate(src, pixel_y = pixel_y + 5 , time = 10, loop = 1, easing = SINE_EASING) + animate(pixel_y = pixel_y - 5, time = 10, loop = 1, easing = SINE_EASING) if(client || registered_z) // This is a temporary error tracker to make sure we've caught everything var/turf/T = get_turf(src) @@ -17,28 +15,44 @@ else if (!client && registered_z) log_game("Z-TRACKING: [src] of type [src.type] has a Z-registration despite not having a client.") update_z(null) + + if(notransform) + return FALSE + if(!loc) + return FALSE + if(stat != DEAD) //Chemicals in the body - handle_chemicals_in_body() + if(reagents) + handle_chemicals_in_body() + if(QDELETED(src)) // some chems can gib mobs + return + + if(stat != DEAD) //Mutations and radiation handle_mutations_and_radiation() + if(stat != DEAD) //Breathing, if applicable handle_breathing(times_fired) + if(stat != DEAD) //Random events (vomiting etc) handle_random_events() - . = 1 + if(LAZYLEN(viruses)) + handle_diseases() - handle_diseases() + if(QDELETED(src)) // diseases can qdel the mob via transformations + return //Heart Attack, if applicable if(stat != DEAD) handle_heartattack() //Handle temperature/pressure differences between body and environment + var/datum/gas_mixture/environment = loc.return_air() if(environment) handle_environment(environment) @@ -49,19 +63,38 @@ update_gravity(mob_has_gravity()) - update_pulling() + if(pulling) + update_pulling() for(var/obj/item/grab/G in src) G.process() - if(handle_regular_status_updates()) // Status & health update, are we dead or alive etc. + if(stat != DEAD) + handle_critical_condition() + + if(stat != DEAD) // Status & health update, are we dead or alive etc. handle_disabilities() // eye, ear, brain damages + + if(stat != DEAD) handle_status_effects() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc - if(client) - handle_regular_hud_updates() + if(stat != DEAD) + if(forced_look) + if(!isnum(forced_look)) + var/atom/A = locateUID(forced_look) + if(istype(A)) + var/view = client ? client.view : world.view + if(get_dist(src, A) > view || !(src in viewers(view, A))) + forced_look = null + to_chat(src, "Your direction target has left your view, you are no longer facing anything.") + return + setDir() - ..() + if(machine) + machine.check_eye(src) + + if(stat != DEAD) + return TRUE /mob/living/proc/handle_breathing(times_fired) return @@ -71,7 +104,6 @@ /mob/living/proc/handle_mutations_and_radiation() radiation = 0 //so radiation don't accumulate in simple animals - return /mob/living/proc/handle_chemicals_in_body() return @@ -89,122 +121,54 @@ return /mob/living/proc/update_pulling() - if(pulling) - if(incapacitated()) - stop_pulling() - -//This updates the health and status of the mob (conscious, unconscious, dead) -/mob/living/proc/handle_regular_status_updates() - return stat != DEAD + if(incapacitated()) + stop_pulling() //this updates all special effects: stunned, sleeping, weakened, druggy, stuttering, etc.. -/mob/living/proc/handle_status_effects() - handle_stunned() - handle_weakened() - handle_stuttering() - handle_silent() - handle_drugged() - handle_slurring() - handle_paralysed() - handle_sleeping() - handle_slowed() - handle_drunk() - handle_cultslurring() - - -/mob/living/proc/handle_stunned() +/mob/living/proc/handle_status_effects() // We check for the status effect in this proc as opposed to the procs below to avoid excessive proc call overhead if(stunned) AdjustStunned(-1, updating = 1, force = 1) - if(!stunned) - update_icons() - return stunned - -/mob/living/proc/handle_weakened() if(weakened) AdjustWeakened(-1, updating = 1, force = 1) - if(!weakened) - update_icons() - return weakened - -/mob/living/proc/handle_stuttering() if(stuttering) - stuttering = max(stuttering-1, 0) - return stuttering - -/mob/living/proc/handle_silent() + stuttering = max(stuttering - 1, 0) if(silent) AdjustSilence(-1) - return silent - -/mob/living/proc/handle_drugged() if(druggy) AdjustDruggy(-1) - return druggy - -/mob/living/proc/handle_slurring() if(slurring) AdjustSlur(-1) - return slurring - -/mob/living/proc/handle_cultslurring() - if(cultslurring) - AdjustCultSlur(-1) - return cultslurring - -/mob/living/proc/handle_paralysed() if(paralysis) AdjustParalysis(-1, updating = 1, force = 1) - return paralysis - -/mob/living/proc/handle_sleeping() if(sleeping) - AdjustSleeping(-1) - throw_alert("asleep", /obj/screen/alert/asleep) - else - clear_alert("asleep") - return sleeping - -/mob/living/proc/handle_slowed() + handle_sleeping() if(slowed) AdjustSlowed(-1) - return slowed + if(drunk) + handle_drunk() + if(cultslurring) + AdjustCultSlur(-1) + +/mob/living/proc/update_damage_hud() + return + +/mob/living/proc/handle_sleeping() + AdjustSleeping(-1) + return sleeping /mob/living/proc/handle_drunk() - if(drunk) - AdjustDrunk(-1) + AdjustDrunk(-1) return drunk /mob/living/proc/handle_disabilities() //Eyes - if(disabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own + if((BLINDNESS in mutations) || stat) //blindness from disability or unconsciousness doesn't get better on its own EyeBlind(1) else if(eye_blind) //blindness, heals slowly over time AdjustEyeBlind(-1) else if(eye_blurry) //blurry eyes heal slowly AdjustEyeBlurry(-1) -//this handles hud updates. Calls update_vision() and handle_hud_icons() -/mob/living/proc/handle_regular_hud_updates() - if(!client) return 0 - - handle_vision() - handle_hud_icons() - - return 1 - -/mob/living/proc/handle_vision() - update_sight() - - if(stat == DEAD) - return - - if(machine) - if(!machine.check_eye(src)) - reset_perspective(null) - else - if(!remote_view && !client.adminobs) - reset_perspective(null) - // Gives a mob the vision of being dead /mob/living/proc/grant_death_vision() sight |= SEE_TURFS @@ -215,9 +179,37 @@ see_invisible = SEE_INVISIBLE_OBSERVER sync_lighting_plane_alpha() -/mob/living/proc/handle_hud_icons() - handle_hud_icons_health() +/mob/living/proc/handle_critical_condition() return -/mob/living/proc/handle_hud_icons_health() - return +/mob/living/update_health_hud() + if(!client) + return + if(healths) + var/severity = 0 + var/healthpercent = (health / maxHealth) * 100 + switch(healthpercent) + if(100 to INFINITY) + healths.icon_state = "health0" + if(80 to 100) + healths.icon_state = "health1" + severity = 1 + if(60 to 80) + healths.icon_state = "health2" + severity = 2 + if(40 to 60) + healths.icon_state = "health3" + severity = 3 + if(20 to 40) + healths.icon_state = "health4" + severity = 4 + if(1 to 20) + healths.icon_state = "health5" + severity = 5 + else + healths.icon_state = "health7" + severity = 6 + if(severity > 0) + overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity) + else + clear_fullscreen("brute") diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b35556903f2..dfa4bb61c9d 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1,15 +1,15 @@ /mob/living/Initialize() . = ..() - var/datum/atom_hud/data/human/medical/advanced/medhud = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/data/human/medical/advanced/medhud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] medhud.add_to_hud(src) faction += "\ref[src]" + GLOB.mob_living_list += src /mob/living/prepare_huds() ..() prepare_data_huds() /mob/living/proc/prepare_data_huds() - ..() med_hud_set_health() med_hud_set_status() @@ -18,7 +18,7 @@ if(ranged_ability) ranged_ability.remove_ranged_ability(src) remove_from_all_data_huds() - + GLOB.mob_living_list -= src if(LAZYLEN(status_effects)) for(var/s in status_effects) var/datum/status_effect/S = s @@ -247,6 +247,7 @@ set hidden = 1 if(InCritical()) create_attack_log("[src] has ["succumbed to death"] with [round(health, 0.1)] points of health!") + create_log(MISC_LOG, "has succumbed to death with [round(health, 0.1)] points of health") adjustOxyLoss(health - HEALTH_THRESHOLD_DEAD) // super check for weird mobs, including ones that adjust hp // we don't want to go overboard and gib them, though @@ -285,8 +286,9 @@ health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() - getCloneLoss() update_stat("updatehealth([reason])") - handle_hud_icons_health() med_hud_set_health() + med_hud_set_status() + update_health_hud() //This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually @@ -374,7 +376,7 @@ return 0 // Living mobs use can_inject() to make sure that the mob is not syringe-proof in general. -/mob/living/proc/can_inject() +/mob/living/proc/can_inject(mob/user, error_msg, target_zone, penetrate_thick) return TRUE /mob/living/is_injectable(mob/user, allowmobs = TRUE) @@ -406,6 +408,8 @@ QDEL_LIST(C.reagents.addiction_list) C.reagents.addiction_threshold_accumulated.Cut() + QDEL_LIST(C.processing_patches) + // rejuvenate: Called by `revive` to get the mob into a revivable state // the admin "rejuvenate" command calls `revive`, not this proc. /mob/living/proc/rejuvenate() @@ -511,7 +515,7 @@ return -/mob/living/Move(atom/newloc, direct) +/mob/living/Move(atom/newloc, direct, movetime) if(buckled && buckled.loc != newloc) //not updating position if(!buckled.anchored) return buckled.Move(newloc, direct) @@ -544,7 +548,7 @@ var/mob/living/M = pulling if(M.lying && !M.buckled && (prob(M.getBruteLoss() * 200 / M.maxHealth))) M.makeTrail(T) - pulling.Move(T, get_dir(pulling, T)) // the pullee tries to reach our previous position + pulling.Move(T, get_dir(pulling, T), movetime) // the pullee tries to reach our previous position if(pulling && get_dist(src, pulling) > 1) // the pullee couldn't keep up stop_pulling() @@ -580,7 +584,7 @@ newdir = NORTH else if(newdir == 12) //E + W newdir = EAST - if((newdir in cardinal) && (prob(50))) + if((newdir in GLOB.cardinal) && (prob(50))) newdir = turn(get_dir(T, loc), 180) if(!blood_exists) new /obj/effect/decal/cleanable/trail_holder(loc) @@ -757,7 +761,7 @@ //called when the mob receives a bright flash /mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash) - if(check_eye_prot() < intensity && (override_blindness_check || !(disabilities & BLIND))) + if(check_eye_prot() < intensity && (override_blindness_check || !(BLINDNESS in mutations))) overlay_fullscreen("flash", type) addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25) return 1 @@ -800,7 +804,7 @@ if(do_mob(src, who, what.put_on_delay)) if(what && Adjacent(who) && !(what.flags & NODROP)) unEquip(what) - who.equip_to_slot_if_possible(what, where, 0, 1) + who.equip_to_slot_if_possible(what, where, FALSE, TRUE) add_attack_logs(src, who, "Equipped [what]") /mob/living/singularity_act() @@ -1023,9 +1027,9 @@ if("stat") if((stat == DEAD) && (var_value < DEAD))//Bringing the dead back to life GLOB.dead_mob_list -= src - GLOB.living_mob_list += src + GLOB.alive_mob_list += src if((stat < DEAD) && (var_value == DEAD))//Kill he - GLOB.living_mob_list -= src + GLOB.alive_mob_list -= src GLOB.dead_mob_list += src . = ..() switch(var_name) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 6e4f13d735f..604fd47de16 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -73,10 +73,9 @@ return shock_damage /mob/living/emp_act(severity) - var/list/L = src.get_contents() - for(var/obj/O in L) - O.emp_act(severity) ..() + for(var/obj/O in contents) + O.emp_act(severity) /obj/item/proc/get_volume_by_throwforce_and_or_w_class() if(throwforce && w_class) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 840f30c20ff..e230f7a2b99 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -28,13 +28,11 @@ var/on_fire = 0 //The "Are we on fire?" var var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20 - var/implanting = 0 //Used for the mind-slave implant var/floating = 0 var/mob_size = MOB_SIZE_HUMAN var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature.. var/digestion_ratio = 1 //controls how quickly reagents metabolize; largely governered by species attributes. - var/bloodcrawl = 0 //0 No blood crawling, 1 blood crawling, 2 blood crawling+mob devour var/holder = null //The holder for blood crawling var/ventcrawler = 0 //0 No vent crawling, 1 vent crawling in the nude, 2 vent crawling always @@ -61,7 +59,6 @@ var/list/say_log = list() //a log of what we've said, plain text, no spans or junk, essentially just each individual "message" var/list/emote_log = list() //like say_log but for emotes - var/list/recent_tastes = list() var/blood_volume = 0 //how much blood the mob has hud_possible = list(HEALTH_HUD,STATUS_HUD,SPECIALROLE_HUD) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 73ad5eabaca..c272952b6bf 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -1,4 +1,4 @@ -var/list/department_radio_keys = list( +GLOBAL_LIST_INIT(department_radio_keys, list( ":r" = "right ear", "#r" = "right ear", ".r" = "right ear", ":l" = "left ear", "#l" = "left ear", ".l" = "left ear", ":i" = "intercom", "#i" = "intercom", ".i" = "intercom", @@ -34,20 +34,20 @@ var/list/department_radio_keys = list( ":-" = "Special Ops", "#-" = "Special Ops", ".-" = "Special Ops", ":_" = "SyndTeam", "#_" = "SyndTeam", "._" = "SyndTeam", ":X" = "cords", "#X" = "cords", ".X" = "cords" -) +)) +GLOBAL_LIST_EMPTY(channel_to_radio_key) -var/list/channel_to_radio_key = new proc/get_radio_key_from_channel(var/channel) - var/key = channel_to_radio_key[channel] + var/key = GLOB.channel_to_radio_key[channel] if(!key) - for(var/radio_key in department_radio_keys) - if(department_radio_keys[radio_key] == channel) + for(var/radio_key in GLOB.department_radio_keys) + if(GLOB.department_radio_keys[radio_key] == channel) key = radio_key break if(!key) key = "" - channel_to_radio_key[channel] = key + GLOB.channel_to_radio_key[channel] = key return key @@ -172,11 +172,18 @@ proc/get_radio_key_from_channel(var/channel) var/list/hsp = handle_speech_problems(message_pieces, verb) verb = hsp["verb"] + // Do this so it gets logged for all types of communication + var/log_message = "[message_mode ? "([message_mode])" : ""] '[message]'" + create_log(SAY_LOG, log_message) var/list/used_radios = list() if(handle_message_mode(message_mode, message_pieces, verb, used_radios)) return 1 + // Log of what we've said, plain message, no spans or junk + // handle_message_mode should have logged this already if it handled it + say_log += log_message + log_say(log_message, src) var/list/handle_v = handle_speech_sound() var/sound/speech_sound = handle_v[1] @@ -274,9 +281,6 @@ proc/get_radio_key_from_channel(var/channel) if(O) //It's possible that it could be deleted in the meantime. O.hear_talk(src, message_pieces, verb) - //Log of what we've said, plain message, no spans or junk - say_log += message - log_say(message, src) return 1 /obj/effect/speech_bubble diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 41de195a9e0..85c4ceac427 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -1,5 +1,5 @@ -var/list/ai_list = list() -var/list/ai_verbs_default = list( +GLOBAL_LIST_EMPTY(ai_list) +GLOBAL_LIST_INIT(ai_verbs_default, list( /mob/living/silicon/ai/proc/announcement, /mob/living/silicon/ai/proc/ai_announcement_text, /mob/living/silicon/ai/proc/ai_call_shuttle, @@ -21,13 +21,13 @@ var/list/ai_verbs_default = list( /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/change_arrival_message -) +)) //Not sure why this is necessary... /proc/AutoUpdateAI(obj/subject) var/is_in_use = 0 if(subject!=null) - for(var/A in ai_list) + for(var/A in GLOB.ai_list) var/mob/living/silicon/ai/M = A if((M.client && M.machine == subject)) is_in_use = 1 @@ -112,11 +112,11 @@ var/list/ai_verbs_default = list( var/max_multicams = 6 /mob/living/silicon/ai/proc/add_ai_verbs() - verbs |= ai_verbs_default + verbs |= GLOB.ai_verbs_default verbs |= silicon_subsystems /mob/living/silicon/ai/proc/remove_ai_verbs() - verbs -= ai_verbs_default + verbs -= GLOB.ai_verbs_default verbs -= silicon_subsystems /mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/mmi/B, var/safety = 0) @@ -206,7 +206,7 @@ var/list/ai_verbs_default = list( builtInCamera.c_tag = name builtInCamera.network = list("SS13") - ai_list += src + GLOB.ai_list += src GLOB.shuttle_caller_list += src ..() @@ -271,7 +271,7 @@ var/list/ai_verbs_default = list( return TRUE /mob/living/silicon/ai/Destroy() - ai_list -= src + GLOB.ai_list -= src GLOB.shuttle_caller_list -= src SSshuttle.autoEvac() QDEL_NULL(eyeobj) // No AI, no Eye @@ -571,13 +571,13 @@ var/list/ai_verbs_default = list( return FALSE /mob/living/silicon/ai/emp_act(severity) + ..() if(prob(30)) switch(pick(1,2)) if(1) view_core() if(2) ai_call_shuttle() - ..() /mob/living/silicon/ai/ex_act(severity) ..() @@ -607,7 +607,7 @@ var/list/ai_verbs_default = list( unset_machine() src << browse(null, t1) if(href_list["switchcamera"]) - switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras + switchCamera(locate(href_list["switchcamera"])) in GLOB.cameranet.cameras if(href_list["showalerts"]) subsystem_alarm_monitor() if(href_list["show_paper"]) @@ -679,7 +679,7 @@ var/list/ai_verbs_default = list( if(controlled_mech) to_chat(src, "You are already loaded into an onboard computer!") return - if(!cameranet.checkCameraVis(M)) + if(!GLOB.cameranet.checkCameraVis(M)) to_chat(src, "Exosuit is no longer near active cameras.") return if(lacks_power()) @@ -768,7 +768,7 @@ var/list/ai_verbs_default = list( //The target must be in view of a camera or near the core. if(turf_check in range(get_turf(src))) call_bot(turf_check) - else if(cameranet && cameranet.checkTurfVis(turf_check)) + else if(GLOB.cameranet && GLOB.cameranet.checkTurfVis(turf_check)) call_bot(turf_check) else to_chat(src, "Selected location is not visible.") @@ -819,7 +819,7 @@ var/list/ai_verbs_default = list( var/mob/living/silicon/ai/U = usr - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in GLOB.cameranet.cameras) if(!C.can_use()) continue @@ -840,7 +840,7 @@ var/list/ai_verbs_default = list( if(isnull(network)) network = old_network // If nothing is selected else - for(var/obj/machinery/camera/C in cameranet.cameras) + for(var/obj/machinery/camera/C in GLOB.cameranet.cameras) if(!C.can_use()) continue if(network in C.network) @@ -916,7 +916,7 @@ var/list/ai_verbs_default = list( if("Crew Member") var/personnel_list[] = list() - for(var/datum/data/record/t in data_core.locked)//Look in data core locked. + for(var/datum/data/record/t in GLOB.data_core.locked)//Look in data core locked. personnel_list["[t.fields["name"]]: [t.fields["rank"]]"] = t.fields["image"]//Pull names, rank, and image. if(personnel_list.len) @@ -1203,7 +1203,7 @@ var/list/ai_verbs_default = list( //get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera //apc_override is needed here because AIs use their own APC when depowered var/turf/T = isturf(A) ? A : get_turf_pixel(A) - return (cameranet && cameranet.checkTurfVis(T)) || apc_override + return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(T)) || apc_override //AI is carded/shunted //view(src) returns nothing for carded/shunted AIs and they have x-ray vision so just use get_dist var/list/viewscale = getviewsize(client.view) @@ -1280,7 +1280,7 @@ var/list/ai_verbs_default = list( to_chat(src, "Target is not on or near any active cameras on the station.") /mob/living/silicon/ai/proc/camera_visibility(mob/camera/aiEye/moved_eye) - cameranet.visibility(moved_eye, client, all_eyes) + GLOB.cameranet.visibility(moved_eye, client, all_eyes) /mob/living/silicon/ai/forceMove(atom/destination) . = ..() diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index 2e35c437d45..641b1a2af0f 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -27,7 +27,7 @@ if(SSshuttle.emergency.mode == SHUTTLE_STRANDED) SSshuttle.emergency.mode = SHUTTLE_DOCKED SSshuttle.emergency.timer = world.time - priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg') + GLOB.priority_announcement.Announce("Hostile environment resolved. You have 3 minutes to board the Emergency Shuttle.", "Priority Announcement", 'sound/AI/shuttledock.ogg') qdel(doomsday_device) if(explosive) diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index fac6e3b518b..d9f4af600af 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -4,7 +4,7 @@ #define CHUNK_SIZE 16 // Only chunk sizes that are to the power of 2. E.g: 2, 4, 8, 16, etc.. -var/datum/cameranet/cameranet = new() +GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new()) /datum/cameranet var/name = "Camera Net" // Name to show for VV and stat() diff --git a/code/modules/mob/living/silicon/ai/latejoin.dm b/code/modules/mob/living/silicon/ai/latejoin.dm index 513b26ee558..75e8854b45c 100644 --- a/code/modules/mob/living/silicon/ai/latejoin.dm +++ b/code/modules/mob/living/silicon/ai/latejoin.dm @@ -1,4 +1,4 @@ -var/global/list/empty_playable_ai_cores = list() +GLOBAL_LIST_EMPTY(empty_playable_ai_cores) /hook/roundstart/proc/spawn_empty_ai() for(var/obj/effect/landmark/start/S in GLOB.landmarks_list) @@ -6,7 +6,7 @@ var/global/list/empty_playable_ai_cores = list() continue if(locate(/mob/living) in S.loc) continue - empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(get_turf(S)) + GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(get_turf(S)) return 1 @@ -21,8 +21,8 @@ var/global/list/empty_playable_ai_cores = list() return // We warned you. - empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(loc) - global_announcer.autosay("[src] has been moved to intelligence storage.", "Artificial Intelligence Oversight") + GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(loc) + GLOB.global_announcer.autosay("[src] has been moved to intelligence storage.", "Artificial Intelligence Oversight") //Handle job slot/tater cleanup. var/job = mind.assigned_role @@ -68,13 +68,13 @@ var/global/list/empty_playable_ai_cores = list() // Before calling this, make sure an empty core exists, or this will no-op /mob/living/silicon/ai/proc/moveToEmptyCore() - if(!empty_playable_ai_cores.len) + if(!GLOB.empty_playable_ai_cores.len) log_runtime(EXCEPTION("moveToEmptyCore called without any available cores"), src) return // IsJobAvailable for AI checks that there is an empty core available in this list - var/obj/structure/AIcore/deactivated/C = empty_playable_ai_cores[1] - empty_playable_ai_cores -= C + var/obj/structure/AIcore/deactivated/C = GLOB.empty_playable_ai_cores[1] + GLOB.empty_playable_ai_cores -= C forceMove(C.loc) view_core() diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 8d1555182a2..61151e35c92 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -37,7 +37,8 @@ else adjustOxyLoss(-1) - handle_stunned() + if(stunned) + AdjustStunned(-1, updating = 1, force = 1) var/area/my_area = get_area(src) @@ -140,7 +141,6 @@ else health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() update_stat("updatehealth([reason])") - diag_hud_set_status() diag_hud_set_health() diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index 254d5a9b794..d33e57ea971 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -135,7 +135,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room) if(screen && screen.ai) screen.ai.camera_visibility(src) else - cameranet.visibility(src) + GLOB.cameranet.visibility(src) update_camera_telegraphing() /mob/camera/aiEye/pic_in_pic/proc/update_camera_telegraphing() diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index 406b232681d..599063c2724 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -65,7 +65,7 @@ * AI VOX Announcements */ -var/announcing_vox = 0 // Stores the time of the last announcement +GLOBAL_VAR_INIT(announcing_vox, 0) // Stores the time of the last announcement #define VOX_DELAY 100 #define VOX_PATH "sound/vox_fem/" @@ -81,10 +81,10 @@ var/announcing_vox = 0 // Stores the time of the last announcement WARNING:
    Misuse of the announcement system will get you job banned.
    " var/index = 0 - for(var/word in vox_sounds) + for(var/word in GLOB.vox_sounds) index++ dat += "[capitalize(word)]" - if(index != vox_sounds.len) + if(index != GLOB.vox_sounds.len) dat += " / " var/datum/browser/popup = new(src, "announce_help", "Announcement Help", 500, 400) @@ -95,8 +95,8 @@ var/announcing_vox = 0 // Stores the time of the last announcement if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) return - if(announcing_vox > world.time) - to_chat(src, "Please wait [round((announcing_vox - world.time) / 10)] seconds.") + if(GLOB.announcing_vox > world.time) + to_chat(src, "Please wait [round((GLOB.announcing_vox - world.time) / 10)] seconds.") return var/message = clean_input("WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", last_announcement, src) @@ -106,7 +106,7 @@ var/announcing_vox = 0 // Stores the time of the last announcement if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) return - if(!message || announcing_vox > world.time) + if(!message || GLOB.announcing_vox > world.time) return var/list/words = splittext(trim(message), " ") @@ -120,14 +120,14 @@ var/announcing_vox = 0 // Stores the time of the last announcement if(!word) words -= word continue - if(!vox_sounds[word]) + if(!GLOB.vox_sounds[word]) incorrect_words += word if(incorrect_words.len) to_chat(src, "These words are not available on the announcement system: [english_list(incorrect_words)].") return - announcing_vox = world.time + VOX_DELAY + GLOB.announcing_vox = world.time + VOX_DELAY log_game("[key_name(src)] made a vocal announcement: [message].") message_admins("[key_name_admin(src)] made a vocal announcement: [message].") @@ -156,9 +156,9 @@ var/announcing_vox = 0 // Stores the time of the last announcement word = lowertext(word) - if(vox_sounds[word]) + if(GLOB.vox_sounds[word]) - var/sound_file = vox_sounds[word] + var/sound_file = GLOB.vox_sounds[word] var/sound/voice = sound(sound_file, wait = 1, channel = CHANNEL_VOX) voice.status = SOUND_STREAM diff --git a/code/modules/mob/living/silicon/ai/update_status.dm b/code/modules/mob/living/silicon/ai/update_status.dm index fd001956c67..8ee4a825631 100644 --- a/code/modules/mob/living/silicon/ai/update_status.dm +++ b/code/modules/mob/living/silicon/ai/update_status.dm @@ -9,7 +9,7 @@ else if(stat == UNCONSCIOUS) WakeUp() create_debug_log("woke up, trigger reason: [reason]") - //diag_hud_set_status() + diag_hud_set_status() /mob/living/silicon/ai/has_vision(information_only = FALSE) return ..() && !lacks_power() diff --git a/code/modules/mob/living/silicon/pai/life.dm b/code/modules/mob/living/silicon/pai/life.dm index d91b724370b..321362217a1 100644 --- a/code/modules/mob/living/silicon/pai/life.dm +++ b/code/modules/mob/living/silicon/pai/life.dm @@ -1,22 +1,18 @@ /mob/living/silicon/pai/Life(seconds, times_fired) . = ..() - if(.) - //if(secHUD == 1) - // process_sec_hud(src, 1) - ////if(medHUD == 1) - // process_med_hud(src, 1) - if(silence_time) - if(world.timeofday >= silence_time) - silence_time = null - to_chat(src, "Communication circuit reinitialized. Speech and messaging functionality restored.") + if(QDELETED(src) || stat == DEAD) + return + if(silence_time) + if(world.timeofday >= silence_time) + silence_time = null + to_chat(src, "Communication circuit reinitialized. Speech and messaging functionality restored.") - if(cable) - if(get_dist(src, cable) > 1) - var/turf/T = get_turf_or_move(loc) - for(var/mob/M in viewers(T)) - M.show_message("The data cable rapidly retracts back into its spool.", 3, "You hear a click and the sound of wire spooling rapidly.", 2) - qdel(src.cable) - cable = null + if(cable) + if(get_dist(src, cable) > 1) + var/turf/T = get_turf_or_move(loc) + for(var/mob/M in viewers(T)) + M.show_message("The data cable rapidly retracts back into its spool.", 3, "You hear a click and the sound of wire spooling rapidly.", 2) + QDEL_NULL(cable) /mob/living/silicon/pai/updatehealth(reason = "none given") if(status_flags & GODMODE) diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index fd4f04e8ec4..f52da9942e4 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -1,6 +1,6 @@ // Recruiting observers to play as pAIs -var/datum/paiController/paiController // Global handler for pAI candidates +GLOBAL_DATUM(paiController, /datum/paiController) // Global handler for pAI candidates /datum/paiCandidate var/name @@ -12,7 +12,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates /hook/startup/proc/paiControllerSetup() - paiController = new /datum/paiController() + GLOB.paiController = new /datum/paiController() return 1 @@ -252,7 +252,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates /datum/paiController/proc/findPAI(var/obj/item/paicard/p, var/mob/user) requestRecruits(p, user) var/list/available = list() - for(var/datum/paiCandidate/c in paiController.pai_candidates) + for(var/datum/paiCandidate/c in GLOB.paiController.pai_candidates) if(c.ready) var/found = 0 for(var/mob/o in GLOB.respawnable_list) diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 70117b4558c..3b51048452e 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -1,4 +1,4 @@ -var/list/pai_emotions = list( +GLOBAL_LIST_INIT(pai_emotions, list( "Happy" = 1, "Cat" = 2, "Extremely Happy" = 3, @@ -8,28 +8,28 @@ var/list/pai_emotions = list( "Sad" = 7, "Angry" = 8, "What" = 9 - ) +)) -var/global/list/pai_software_by_key = list() -var/global/list/default_pai_software = list() +GLOBAL_LIST_EMPTY(pai_software_by_key) +GLOBAL_LIST_EMPTY(default_pai_software) /hook/startup/proc/populate_pai_software_list() var/r = 1 // I would use ., but it'd sacrifice runtime detection for(var/type in subtypesof(/datum/pai_software)) var/datum/pai_software/P = new type() - if(pai_software_by_key[P.id]) - var/datum/pai_software/O = pai_software_by_key[P.id] + if(GLOB.pai_software_by_key[P.id]) + var/datum/pai_software/O = GLOB.pai_software_by_key[P.id] to_chat(world, "pAI software module [P.name] has the same key as [O.name]!") r = 0 continue - pai_software_by_key[P.id] = P + GLOB.pai_software_by_key[P.id] = P if(P.default) - default_pai_software[P.id] = P + GLOB.default_pai_software[P.id] = P return r /mob/living/silicon/pai/New() ..() - software = default_pai_software.Copy() + software = GLOB.default_pai_software.Copy() /mob/living/silicon/pai/verb/paiInterface() set category = "pAI Commands" @@ -37,7 +37,7 @@ var/global/list/default_pai_software = list() ui_interact(src) -/mob/living/silicon/pai/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, datum/topic_state/state = self_state) +/mob/living/silicon/pai/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1, datum/topic_state/state = GLOB.self_state) if(ui_key != "main") var/datum/pai_software/S = software[ui_key] if(S && !S.toggle) @@ -58,7 +58,7 @@ var/global/list/default_pai_software = list() ui.open() ui.set_auto_update(1) -/mob/living/silicon/pai/ui_data(mob/user, ui_key = "main", datum/topic_state/state = self_state) +/mob/living/silicon/pai/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.self_state) var/data[0] if(ui_key != "main") @@ -72,8 +72,8 @@ var/global/list/default_pai_software = list() // Software we have not bought var/not_bought_software[0] - for(var/key in pai_software_by_key) - var/datum/pai_software/S = pai_software_by_key[key] + for(var/key in GLOB.pai_software_by_key) + var/datum/pai_software/S = GLOB.pai_software_by_key[key] var/software_data[0] software_data["name"] = S.name software_data["id"] = S.id @@ -90,10 +90,10 @@ var/global/list/default_pai_software = list() // Emotions var/emotions[0] - for(var/name in pai_emotions) + for(var/name in GLOB.pai_emotions) var/emote[0] emote["name"] = name - emote["id"] = pai_emotions[name] + emote["id"] = GLOB.pai_emotions[name] emotions[++emotions.len] = emote data["emotions"] = emotions @@ -122,7 +122,7 @@ var/global/list/default_pai_software = list() else if(href_list["purchase"]) var/soft = href_list["purchase"] - var/datum/pai_software/S = pai_software_by_key[soft] + var/datum/pai_software/S = GLOB.pai_software_by_key[soft] if(S && (ram >= S.ram_cost)) ram -= S.ram_cost software[S.id] = S diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 84c467b1549..7161919df7f 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -19,7 +19,7 @@ var/ui_width = 450 var/ui_height = 600 -/datum/pai_software/proc/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/proc/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) return list() /datum/pai_software/proc/toggle(mob/living/silicon/pai/user) @@ -39,7 +39,7 @@ ui_title = "pAI Directives" autoupdate = 1 -/datum/pai_software/directives/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/directives/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] data["master"] = user.master @@ -94,7 +94,7 @@ ui_width = 300 ui_height = 150 -/datum/pai_software/radio_config/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/radio_config/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] data["listening"] = user.radio.broadcasting @@ -129,11 +129,11 @@ template_file = "pai_manifest.tmpl" ui_title = "Crew Manifest" -/datum/pai_software/crew_manifest/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/crew_manifest/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] - data_core.get_manifest_json() - data["manifest"] = PDA_Manifest + GLOB.data_core.get_manifest_json() + data["manifest"] = GLOB.PDA_Manifest return data @@ -147,7 +147,7 @@ template_file = "pai_messenger.tmpl" ui_title = "Digital Messenger" -/datum/pai_software/messenger/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/messenger/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] if(!user.pda) @@ -165,7 +165,7 @@ var/pdas[0] if(!M.toff) - for(var/obj/item/pda/P in PDAs) + for(var/obj/item/pda/P in GLOB.PDAs) var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) if(P == user.pda || !PM || !PM.can_receive()) @@ -237,11 +237,11 @@ ui_title = "Medical Records" -/datum/pai_software/med_records/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/med_records/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] var/records[0] - for(var/datum/data/record/general in sortRecord(data_core.general)) + for(var/datum/data/record/general in sortRecord(GLOB.data_core.general)) var/record[0] record["name"] = general.fields["name"] record["ref"] = "\ref[general]" @@ -266,11 +266,11 @@ if(record) var/datum/data/record/R = record var/datum/data/record/M = null - if(!( data_core.general.Find(R) )) + if(!( GLOB.data_core.general.Find(R) )) P.medical_cannotfind = 1 else P.medical_cannotfind = 0 - for(var/datum/data/record/E in data_core.medical) + for(var/datum/data/record/E in GLOB.data_core.medical) if((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) M = E P.medicalActive1 = R @@ -290,11 +290,11 @@ ui_title = "Security Records" -/datum/pai_software/sec_records/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/sec_records/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] var/records[0] - for(var/datum/data/record/general in sortRecord(data_core.general)) + for(var/datum/data/record/general in sortRecord(GLOB.data_core.general)) var/record[0] record["name"] = general.fields["name"] record["ref"] = "\ref[general]" @@ -319,13 +319,13 @@ if(record) var/datum/data/record/R = record var/datum/data/record/S = null - if(!( data_core.general.Find(R) )) + if(!( GLOB.data_core.general.Find(R) )) P.securityActive1 = null P.securityActive2 = null P.security_cannotfind = 1 else P.security_cannotfind = 0 - for(var/datum/data/record/E in data_core.security) + for(var/datum/data/record/E in GLOB.data_core.security) if((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) S = E P.securityActive1 = R @@ -348,7 +348,7 @@ ui_width = 300 ui_height = 150 -/datum/pai_software/door_jack/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/door_jack/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] data["cable"] = user.cable != null @@ -382,14 +382,6 @@ return 1 /mob/living/silicon/pai/proc/hackloop() - var/turf/T = get_turf_or_move(src.loc) - for(var/mob/living/silicon/ai/AI in GLOB.player_list) - if(!T || !is_station_contact(T.z)) - break - if(T.loc) - to_chat(AI, "Network Alert: Brute-force encryption crack in progress in [T.loc].") - else - to_chat(AI, "Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.") var/obj/machinery/door/D = cable.machine if(!istype(D)) hack_aborted = 1 @@ -424,7 +416,7 @@ ui_height = 300 -/datum/pai_software/atmosphere_sensor/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/atmosphere_sensor/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] var/turf/T = get_turf_or_move(user.loc) @@ -543,7 +535,7 @@ ui_width = 320 ui_height = 150 -/datum/pai_software/signaller/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/signaller/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] data["frequency"] = format_frequency(user.sradio.frequency) @@ -586,7 +578,7 @@ ui_width = 400 ui_height = 350 -/datum/pai_software/host_scan/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = self_state) +/datum/pai_software/host_scan/on_ui_data(mob/living/silicon/pai/user, datum/topic_state/state = GLOB.self_state) var/data[0] var/mob/living/held = user.loc var/count = 0 diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index 224c706f324..72d9b210712 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -18,7 +18,7 @@ flick("gibbed-r", animation) robogibs(loc) - GLOB.living_mob_list -= src + GLOB.alive_mob_list -= src GLOB.dead_mob_list -= src QDEL_IN(animation, 15) QDEL_IN(src, 15) diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index 7802f4c77d5..b181cec8ec0 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -18,6 +18,8 @@ magpulse = 1 mob_size = MOB_SIZE_SMALL + modules_break = FALSE + // We need to keep track of a few module items so we don't need to do list operations // every time we need them. These get set in New() after the module is chosen. var/obj/item/stack/sheet/metal/cyborg/stack_metal = null @@ -48,7 +50,7 @@ if(radio) radio.wires.CutWireIndex(RADIO_WIRE_TRANSMIT) - if(camera && "Robots" in camera.network) + if(camera && ("Robots" in camera.network)) camera.network.Add("Engineering") //They are unable to be upgraded, so let's give them a bit of a better battery. @@ -188,7 +190,7 @@ message_admins("[key_name_admin(user)] emagged drone [key_name_admin(src)]. Laws overridden.") log_game("[key_name(user)] emagged drone [key_name(src)]. Laws overridden.") var/time = time2text(world.realtime,"hh:mm:ss") - lawchanges.Add("[time] : [H.name]([H.key]) emagged [name]([key])") + GLOB.lawchanges.Add("[time] : [H.name]([H.key]) emagged [name]([key])") emagged_time = world.time emagged = 1 diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index d200bdb075a..7958f983805 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -30,29 +30,22 @@ /obj/item/circuitboard, /obj/item/stack/tile/light, /obj/item/stack/ore/bluespace_crystal - ) + ) //Item currently being held. - var/obj/item/wrapped = null - -/obj/item/gripper/paperwork - name = "paperwork gripper" - desc = "A simple grasping tool for clerical work." - - can_hold = list( - /obj/item/clipboard, - /obj/item/paper, - /obj/item/card/id - ) + var/obj/item/gripped_item = null /obj/item/gripper/medical name = "medical gripper" desc = "A grasping tool used to help patients up once surgery is complete." can_hold = list() -/obj/item/gripper/medical/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params) +/obj/item/gripper/medical/attack_self(mob/user) + return + +/obj/item/gripper/medical/afterattack(atom/target, mob/living/user, proximity, params) var/mob/living/carbon/human/H - if(!wrapped && proximity && target && ishuman(target)) + if(!gripped_item && proximity && target && ishuman(target)) H = target if(H.lying) H.AdjustSleeping(-5) @@ -71,98 +64,69 @@ ..() can_hold = typecacheof(can_hold) -/obj/item/gripper/attack_self(mob/user as mob) - if(wrapped) - wrapped.attack_self(user) - /obj/item/gripper/verb/drop_item() - set name = "Drop Gripped Item" set desc = "Release an item from your magnetic gripper." set category = "Drone" - drop_item_p() + drop_gripped_item() -// The "p" stands for proc, since I was having annoying weird stuff happening with this in the verb -// when trying to have default values for arguments and stuff -/obj/item/gripper/proc/drop_item_p(var/silent = 0) +/obj/item/gripper/attack_self(mob/user) + if(gripped_item) + gripped_item.attack_self(user) + else + to_chat(user, "[src] is empty.") - if(!wrapped) - //There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z - for(var/obj/item/thing in src.contents) - thing.forceMove(get_turf(src)) - return +/obj/item/gripper/proc/drop_gripped_item(silent = FALSE) + if(gripped_item) + if(!silent) + to_chat(loc, "You drop [gripped_item].") + gripped_item.forceMove(get_turf(src)) + gripped_item = null - if(wrapped.loc != src) - wrapped = null - return - - if(!silent) - to_chat(src.loc, "You drop \the [wrapped].") - wrapped.forceMove(get_turf(src)) - wrapped = null - -/obj/item/gripper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) +/obj/item/gripper/attack(mob/living/carbon/M, mob/living/carbon/user) return -/obj/item/gripper/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params) +/// Grippers are snowflakey so this is needed to to prevent forceMoving grippers after `if(!user.drop_item())` checks done in certain attackby's. +/obj/item/gripper/forceMove(atom/destination) + return + +/obj/item/gripper/afterattack(atom/target, mob/living/user, proximity, params) if(!target || !proximity) //Target is invalid or we are not adjacent. - return + return FALSE - //There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z - if(!wrapped) - for(var/obj/item/thing in src.contents) - wrapped = thing - break + if(gripped_item) //Already have an item. - if(wrapped) //Already have an item. - - //Temporary put wrapped into user so target's attackby() checks pass. - wrapped.forceMove(user) - - //Pass the attack on to the target. This might delete/relocate wrapped. - if(!target.attackby(wrapped, user, params) && target && wrapped) - // If the attackby didn't resolve or delete the target or wrapped, afterattack + //Pass the attack on to the target. This might delete/relocate gripped_item. + if(!target.attackby(gripped_item, user, params)) + // If the attackby didn't resolve or delete the target or gripped_item, afterattack // (Certain things, such as mountable frames, rely on afterattack) - wrapped.afterattack(target, user, 1, params) + gripped_item?.afterattack(target, user, 1, params) - //If wrapped did neither get deleted nor put into target, put it back into the gripper. - if(wrapped && user && (wrapped.loc == user)) - wrapped.forceMove(src) - else - wrapped = null - return - - else if(istype(target,/obj/item)) //Check that we're not pocketing a mob. - - //...and that the item is not in a container. - if(!isturf(target.loc)) - return + //If gripped_item either didn't get deleted, or it failed to be transfered to its target + if(!gripped_item && contents.len) + gripped_item = contents[1] + return FALSE + else if(gripped_item && !contents.len) + gripped_item = null + else if(istype(target, /obj/item)) //Check that we're not pocketing a mob. var/obj/item/I = target - - //Check if the item is blacklisted. - var/grab = 0 - if(can_hold.len) - if(is_type_in_typecache(I, can_hold)) - grab = 1 - - //We can grab the item, finally. - if(grab) - to_chat(user, "You collect \the [I].") + if(is_type_in_typecache(I, can_hold)) // Make sure the item is something the gripper can hold + to_chat(user, "You collect [I].") I.forceMove(src) - wrapped = I - return + gripped_item = I else - to_chat(user, "Your gripper cannot hold \the [target].") + to_chat(user, "Your gripper cannot hold [target].") + return FALSE else if(istype(target,/obj/machinery/power/apc)) var/obj/machinery/power/apc/A = target if(A.opened) if(A.cell) - wrapped = A.cell + gripped_item = A.cell A.cell.add_fingerprint(user) A.cell.update_icon() @@ -173,6 +137,7 @@ A.update_icon() user.visible_message("[user] removes the power cell from [A]!", "You remove the power cell.") + return TRUE //TODO: Matter decompiler. /obj/item/matter_decompiler diff --git a/code/modules/mob/living/silicon/robot/drone/update_status.dm b/code/modules/mob/living/silicon/robot/drone/update_status.dm index 80eac952966..d64824b1876 100644 --- a/code/modules/mob/living/silicon/robot/drone/update_status.dm +++ b/code/modules/mob/living/silicon/robot/drone/update_status.dm @@ -4,7 +4,7 @@ /mob/living/silicon/robot/drone/update_stat(reason = "none given") if(status_flags & GODMODE) return - if(health <= -35 && stat != DEAD) + if(health <= -maxHealth && stat != DEAD) gib() create_debug_log("died of damage, trigger reason: [reason]") return diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index 16d9080ef7e..f5b7048c3a8 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -78,6 +78,7 @@ set_actions(O) else to_chat(src, "You need to disable a module first!") + check_module_damage(FALSE) update_icons() /mob/living/silicon/robot/proc/set_actions(obj/item/I) @@ -115,11 +116,11 @@ return 0 /mob/living/silicon/robot/drop_item() - var/obj/item/I = get_active_hand() - if(istype(I, /obj/item/gripper)) - var/obj/item/gripper/G = I - G.drop_item_p(silent = 1) - return + var/obj/item/gripper/G = get_active_hand() + if(istype(G)) + G.drop_gripped_item(silent = TRUE) + return TRUE // The gripper is special because it has a normal item inside that we can drop. + return FALSE // All robot inventory items have NODROP, so they should return FALSE. //Helper procs for cyborg modules on the UI. //These are hackish but they help clean up code elsewhere. diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index d40e801ba5f..afdab2f5649 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -1,23 +1,20 @@ /mob/living/silicon/robot/Life(seconds, times_fired) set invisibility = 0 - set background = BACKGROUND_ENABLED - - if(src.notransform) + if(notransform) return - //Status updates, death etc. - clamp_values() + . = ..() - if(..()) + handle_equipment() + + // if Alive + if(.) + handle_robot_hud_updates() handle_robot_cell() process_locks() + update_items() process_queued_alarms() -/mob/living/silicon/robot/proc/clamp_values() - SetStunned(min(stunned, 30)) - SetParalysis(min(paralysis, 30)) - SetWeakened(min(weakened, 20)) - SetSleeping(0) /mob/living/silicon/robot/proc/handle_robot_cell() if(stat != DEAD) @@ -47,36 +44,13 @@ update_headlamp() diag_hud_set_borgcell() -/mob/living/silicon/robot/handle_regular_status_updates() - - . = ..() - +/mob/living/silicon/robot/proc/handle_equipment() if(camera && !scrambledcodes) if(stat == DEAD || wires.IsCameraCut()) camera.status = 0 else camera.status = 1 - if(sleeping) - AdjustSleeping(-1) - - if(.) //alive - if(!istype(src, /mob/living/silicon/robot/drone)) - if(health < 50) //Gradual break down of modules as more damage is sustained - if(uneq_module(module_state_3)) - to_chat(src, "SYSTEM ERROR: Module 3 OFFLINE.") - - if(health < 0) - if(uneq_module(module_state_2)) - to_chat(src, "SYSTEM ERROR: Module 2 OFFLINE.") - - if(health < -50) - if(uneq_module(module_state_1)) - to_chat(src, "CRITICAL ERROR: All modules OFFLINE.") - - diag_hud_set_health() - diag_hud_set_status() - //update the state of modules and components here if(stat != CONSCIOUS) uneq_all() @@ -86,18 +60,21 @@ else radio.on = 1 - return 1 - -/mob/living/silicon/robot/handle_hud_icons() - update_items() - update_cell() +/mob/living/silicon/robot/proc/SetEmagged(new_state) + emagged = new_state + update_icons() if(emagged) throw_alert("hacked", /obj/screen/alert/hacked) else clear_alert("hacked") - ..() -/mob/living/silicon/robot/handle_hud_icons_health() +/mob/living/silicon/robot/proc/handle_robot_hud_updates() + if(!client) + return + + update_cell_hud_icon() + +/mob/living/silicon/robot/update_health_hud() if(healths) if(stat != DEAD) if(health >= maxHealth) @@ -115,19 +92,7 @@ else healths.icon_state = "health7" - switch(bodytemperature) //310.055 optimal body temp - if(335 to INFINITY) - throw_alert("temp", /obj/screen/alert/hot/robot, 2) - if(320 to 335) - throw_alert("temp", /obj/screen/alert/hot/robot, 1) - if(300 to 320) - clear_alert("temp") - if(260 to 300) - throw_alert("temp", /obj/screen/alert/cold/robot, 1) - else - throw_alert("temp", /obj/screen/alert/cold/robot, 2) - -/mob/living/silicon/robot/proc/update_cell() +/mob/living/silicon/robot/proc/update_cell_hud_icon() if(cell) var/cellcharge = cell.charge/cell.maxcharge switch(cellcharge) @@ -146,7 +111,7 @@ -/mob/living/silicon/robot/proc/update_items() +/mob/living/silicon/robot/proc/update_items() // What in the Sam hell is this? if(client) for(var/obj/I in get_all_slots()) client.screen |= I diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index f0a49b47af1..2eb1e4669ab 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -1,6 +1,6 @@ -var/list/robot_verbs_default = list( +GLOBAL_LIST_INIT(robot_verbs_default, list( /mob/living/silicon/robot/proc/sensor_mode, -) +)) /mob/living/silicon/robot name = "Cyborg" @@ -87,6 +87,7 @@ var/list/robot_verbs_default = list( var/braintype = "Cyborg" var/base_icon = "" var/crisis = 0 + var/modules_break = TRUE var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting. var/lamp_intensity = 0 //Luminosity of the headlamp. 0 is off. Higher settings than the minimum require power. @@ -144,7 +145,7 @@ var/list/robot_verbs_default = list( if(!cell) // Make sure a new cell gets created *before* executing initialize_components(). The cell component needs an existing cell for it to get set up properly cell = new /obj/item/stock_parts/cell/high(src) - + initialize_components() //if(!unfinished) // Create all the robot parts. @@ -290,7 +291,7 @@ var/list/robot_verbs_default = list( var/list/modules = list("Standard", "Engineering", "Medical", "Miner", "Janitor", "Service", "Security") if(islist(force_modules) && force_modules.len) modules = force_modules.Copy() - if(security_level == (SEC_LEVEL_GAMMA || SEC_LEVEL_EPSILON) || crisis) + if(GLOB.security_level == (SEC_LEVEL_GAMMA || SEC_LEVEL_EPSILON) || crisis) to_chat(src, "Crisis mode active. The combat module is now available.") modules += "Combat" if(mmi != null && mmi.alien) @@ -328,7 +329,7 @@ var/list/robot_verbs_default = list( if("Miner") module = new /obj/item/robot_module/miner(src) module.channels = list("Supply" = 1) - if(camera && "Robots" in camera.network) + if(camera && ("Robots" in camera.network)) camera.network.Add("Mining Outpost") module_sprites["Basic"] = "Miner_old" module_sprites["Advanced Droid"] = "droid-miner" @@ -340,7 +341,7 @@ var/list/robot_verbs_default = list( if("Medical") module = new /obj/item/robot_module/medical(src) module.channels = list("Medical" = 1) - if(camera && "Robots" in camera.network) + if(camera && ("Robots" in camera.network)) camera.network.Add("Medical") module_sprites["Basic"] = "Medbot" module_sprites["Surgeon"] = "surgeon" @@ -366,7 +367,7 @@ var/list/robot_verbs_default = list( if("Engineering") module = new /obj/item/robot_module/engineering(src) module.channels = list("Engineering" = 1) - if(camera && "Robots" in camera.network) + if(camera && ("Robots" in camera.network)) camera.network.Add("Engineering") module_sprites["Basic"] = "Engineering" module_sprites["Antique"] = "engineerrobot" @@ -512,11 +513,11 @@ var/list/robot_verbs_default = list( toggle_sensor_mode() /mob/living/silicon/robot/proc/add_robot_verbs() - src.verbs |= robot_verbs_default + src.verbs |= GLOB.robot_verbs_default src.verbs |= silicon_subsystems /mob/living/silicon/robot/proc/remove_robot_verbs() - src.verbs -= robot_verbs_default + src.verbs -= GLOB.robot_verbs_default src.verbs -= silicon_subsystems /mob/living/silicon/robot/proc/ionpulse() @@ -840,7 +841,7 @@ var/list/robot_verbs_default = list( return else sleep(6) - emagged = 1 + SetEmagged(TRUE) SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown if(src.hud_used) src.hud_used.update_robot_modules_display() //Shows/hides the emag item if the inventory screen is already open. @@ -852,7 +853,7 @@ var/list/robot_verbs_default = list( clear_inherent_laws() laws = new /datum/ai_laws/syndicate_override var/time = time2text(world.realtime,"hh:mm:ss") - lawchanges.Add("[time] : [M.name]([M.key]) emagged [name]([key])") + GLOB.lawchanges.Add("[time] : [M.name]([M.key]) emagged [name]([key])") set_zeroth_law("Only [M.real_name] and people [M.p_they()] designate[M.p_s()] as being such are Syndicate Agents.") to_chat(src, "ALERT: Foreign software detected.") sleep(5) @@ -1133,8 +1134,8 @@ var/list/robot_verbs_default = list( if(!updating) updating = 1 spawn(BORG_CAMERA_BUFFER) - if(oldLoc != src.loc) - cameranet.updatePortableCamera(src.camera) + if(camera && oldLoc != src.loc) + GLOB.cameranet.updatePortableCamera(src.camera) updating = 0 if(module) if(module.type == /obj/item/robot_module/janitor) @@ -1157,16 +1158,16 @@ var/list/robot_verbs_default = list( if(cleaned_human.lying) if(cleaned_human.head) cleaned_human.head.clean_blood() - cleaned_human.update_inv_head(0,0) + cleaned_human.update_inv_head() if(cleaned_human.wear_suit) cleaned_human.wear_suit.clean_blood() - cleaned_human.update_inv_wear_suit(0,0) + cleaned_human.update_inv_wear_suit() else if(cleaned_human.w_uniform) cleaned_human.w_uniform.clean_blood() - cleaned_human.update_inv_w_uniform(0,0) + cleaned_human.update_inv_w_uniform() if(cleaned_human.shoes) cleaned_human.shoes.clean_blood() - cleaned_human.update_inv_shoes(0,0) + cleaned_human.update_inv_shoes() cleaned_human.clean_blood() to_chat(cleaned_human, "[src] cleans your face!") if(floor_only) @@ -1472,3 +1473,35 @@ var/list/robot_verbs_default = list( SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT) sync_lighting_plane_alpha() + +/// Used in `robot_bindings.dm` when the user presses "A" if on AZERTY mode, or "Q" on QWERTY mode. +/mob/living/silicon/robot/proc/on_drop_hotkey_press() + var/obj/item/gripper/G = get_active_hand() + if(istype(G) && G.gripped_item) + G.drop_gripped_item() // if the active module is a gripper, try to drop its held item. + else + uneq_active() // else unequip the module and put it back into the robot's inventory. + return + +/mob/living/silicon/robot/proc/check_module_damage(makes_sound = TRUE) + if(modules_break) + if(health < 50) //Gradual break down of modules as more damage is sustained + if(uneq_module(module_state_3)) + if(makes_sound) + audible_message("[src] sounds an alarm! \"SYSTEM ERROR: Module 3 OFFLINE.\"") + playsound(loc, 'sound/machines/warning-buzzer.ogg', 50, TRUE) + to_chat(src, "SYSTEM ERROR: Module 3 OFFLINE.") + + if(health < 0) + if(uneq_module(module_state_2)) + if(makes_sound) + audible_message("[src] sounds an alarm! \"SYSTEM ERROR: Module 2 OFFLINE.\"") + playsound(loc, 'sound/machines/warning-buzzer.ogg', 60, TRUE) + to_chat(src, "SYSTEM ERROR: Module 2 OFFLINE.") + + if(health < -50) + if(uneq_module(module_state_1)) + if(makes_sound) + audible_message("[src] sounds an alarm! \"CRITICAL ERROR: All modules OFFLINE.\"") + playsound(loc, 'sound/machines/warning-buzzer.ogg', 75, TRUE) + to_chat(src, "CRITICAL ERROR: All modules OFFLINE.") diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm index c73d566b729..f4290d764d6 100644 --- a/code/modules/mob/living/silicon/robot/robot_damage.dm +++ b/code/modules/mob/living/silicon/robot/robot_damage.dm @@ -1,12 +1,6 @@ /mob/living/silicon/robot/updatehealth(reason = "none given") - if(status_flags & GODMODE) - health = maxHealth - stat = CONSCIOUS - return - health = maxHealth - (getOxyLoss() + getFireLoss() + getBruteLoss()) - update_stat("updatehealth([reason])") - handle_hud_icons_health() - diag_hud_set_health() + ..(reason) + check_module_damage() /mob/living/silicon/robot/getBruteLoss(repairable_only = FALSE) var/amount = 0 @@ -72,7 +66,7 @@ /mob/living/silicon/robot/heal_organ_damage(brute, burn, updating_health = TRUE) var/list/datum/robot_component/parts = get_damaged_components(brute, burn) - if(!LAZYLEN(parts)) + if(!LAZYLEN(parts)) return var/datum/robot_component/picked = pick(parts) picked.heal_damage(brute, burn, updating_health) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 47dcb93cef5..3260775c674 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -230,7 +230,7 @@ /obj/item/robot_module/engineering/handle_death() var/obj/item/gripper/G = locate(/obj/item/gripper) in modules if(G) - G.drop_item() + G.drop_gripped_item(silent = TRUE) /obj/item/robot_module/security name = "security robot module" @@ -578,7 +578,7 @@ /obj/item/robot_module/drone/handle_death() var/obj/item/gripper/G = locate(/obj/item/gripper) in modules if(G) - G.drop_item() + G.drop_gripped_item(silent = TRUE) //checks whether this item is a module of the robot it is located in. /obj/item/proc/is_robot_module() diff --git a/code/modules/mob/living/silicon/robot/syndicate.dm b/code/modules/mob/living/silicon/robot/syndicate.dm index 2b5fd9bb702..f5ac3e5532b 100644 --- a/code/modules/mob/living/silicon/robot/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/syndicate.dm @@ -137,9 +137,9 @@ ..() /mob/living/silicon/robot/syndicate/saboteur/emp_act() + ..() if(cham_proj) cham_proj.disrupt(src) - ..() /mob/living/silicon/robot/syndicate/saboteur/bullet_act() if(cham_proj) diff --git a/code/modules/mob/living/silicon/robot/update_status.dm b/code/modules/mob/living/silicon/robot/update_status.dm index 63c13f97d24..91f9952c075 100644 --- a/code/modules/mob/living/silicon/robot/update_status.dm +++ b/code/modules/mob/living/silicon/robot/update_status.dm @@ -17,10 +17,12 @@ if(!is_component_functioning("actuator") || !is_component_functioning("power cell") || paralysis || sleeping || resting || stunned || IsWeakened() || getOxyLoss() > maxHealth * 0.5) if(stat == CONSCIOUS) KnockOut() + update_headlamp() create_debug_log("fell unconscious, trigger reason: [reason]") else if(stat == UNCONSCIOUS) WakeUp() + update_headlamp() create_debug_log("woke up, trigger reason: [reason]") else if(health > 0) @@ -30,9 +32,11 @@ to_chat(ghost, "Your cyborg shell has been repaired, re-enter if you want to continue! (Verbs -> Ghost -> Re-enter corpse)") ghost << sound('sound/effects/genetics.ogg') create_attack_log("revived, trigger reason: [reason]") - // diag_hud_set_status() - // diag_hud_set_health() - // update_health_hud() + create_log(MISC_LOG, "revived, trigger reason: [reason]") + + diag_hud_set_status() + diag_hud_set_health() + update_health_hud() /mob/living/silicon/robot/SetStunned(amount, updating = 1, force = 0) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned" . = STATUS_UPDATE_CANMOVE diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index ffbc375be04..6457afc87d4 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -38,7 +38,7 @@ /mob/living/silicon/New() GLOB.silicon_mob_list |= src ..() - var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC] + var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC] diag_hud.add_to_hud(src) diag_hud_set_status() diag_hud_set_health() @@ -76,23 +76,23 @@ return FALSE //So borgs they don't die trying to fix wiring /mob/living/silicon/emp_act(severity) + ..() switch(severity) if(1) - src.take_organ_damage(20) + take_organ_damage(20) Stun(8) if(2) - src.take_organ_damage(10) + take_organ_damage(10) Stun(3) flash_eyes(affect_silicon = 1) to_chat(src, "*BZZZT*") to_chat(src, "Warning: Electromagnetic pulse detected.") - ..() /mob/living/silicon/proc/damage_mob(var/brute = 0, var/fire = 0, var/tox = 0) return -/mob/living/silicon/can_inject(mob/user, error_msg) +/mob/living/silicon/can_inject(mob/user, error_msg, target_zone, penetrate_thick) if(error_msg) to_chat(user, "[p_their(TRUE)] outer shell is too tough.") return FALSE @@ -217,8 +217,8 @@ /mob/living/silicon/proc/show_station_manifest() var/dat dat += "

    Crew Manifest

    " - if(data_core) - dat += data_core.get_manifest(1) // make it monochrome + if(GLOB.data_core) + dat += GLOB.data_core.get_manifest(1) // make it monochrome dat += "
    " src << browse(dat, "window=airoster") onclose(src, "airoster") @@ -244,24 +244,24 @@ return 1 /mob/living/silicon/proc/remove_med_sec_hud() - var/datum/atom_hud/secsensor = huds[sec_hud] - var/datum/atom_hud/medsensor = huds[med_hud] - for(var/datum/atom_hud/data/diagnostic/diagsensor in huds) + var/datum/atom_hud/secsensor = GLOB.huds[sec_hud] + var/datum/atom_hud/medsensor = GLOB.huds[med_hud] + for(var/datum/atom_hud/data/diagnostic/diagsensor in GLOB.huds) diagsensor.remove_hud_from(src) secsensor.remove_hud_from(src) medsensor.remove_hud_from(src) /mob/living/silicon/proc/add_sec_hud() - var/datum/atom_hud/secsensor = huds[sec_hud] + var/datum/atom_hud/secsensor = GLOB.huds[sec_hud] secsensor.add_hud_to(src) /mob/living/silicon/proc/add_med_hud() - var/datum/atom_hud/medsensor = huds[med_hud] + var/datum/atom_hud/medsensor = GLOB.huds[med_hud] medsensor.add_hud_to(src) /mob/living/silicon/proc/add_diag_hud() - for(var/datum/atom_hud/data/diagnostic/diagsensor in huds) + for(var/datum/atom_hud/data/diagnostic/diagsensor in GLOB.huds) diagsensor.add_hud_to(src) diff --git a/code/modules/mob/living/silicon/subsystems.dm b/code/modules/mob/living/silicon/subsystems.dm index 8f7c2316768..5f00beff1e4 100644 --- a/code/modules/mob/living/silicon/subsystems.dm +++ b/code/modules/mob/living/silicon/subsystems.dm @@ -20,7 +20,7 @@ /mob/living/silicon/proc/subsystem_law_manager, /mob/living/silicon/proc/subsystem_power_monitor ) - + /mob/living/silicon/robot/drone silicon_subsystems = list( /mob/living/silicon/proc/subsystem_alarm_monitor, @@ -54,8 +54,8 @@ set name = "Alarm Monitor" set category = "Subsystems" - alarm_monitor.ui_interact(usr, state = self_state) - + alarm_monitor.ui_interact(usr, state = GLOB.self_state) + /******************** * Atmos Control * ********************/ @@ -63,7 +63,7 @@ set category = "Subsystems" set name = "Atmospherics Control" - atmos_control.ui_interact(usr, state = self_state) + atmos_control.ui_interact(usr, state = GLOB.self_state) /******************** * Crew Monitor * @@ -72,8 +72,8 @@ set category = "Subsystems" set name = "Crew Monitor" - crew_monitor.ui_interact(usr, state = self_state) - + crew_monitor.ui_interact(usr, state = GLOB.self_state) + /**************** * Law Manager * ****************/ @@ -81,8 +81,8 @@ set name = "Law Manager" set category = "Subsystems" - law_manager.ui_interact(usr, state = conscious_state) - + law_manager.ui_interact(usr, state = GLOB.conscious_state) + /******************** * Power Monitor * ********************/ @@ -90,5 +90,5 @@ set category = "Subsystems" set name = "Power Monitor" - power_monitor.ui_interact(usr, state = self_state) + power_monitor.ui_interact(usr, state = GLOB.self_state) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 98f5a3555f4..962b4722f39 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -94,6 +94,7 @@ /obj/item/radio/headset/bot subspace_transmission = 1 + requires_tcomms = FALSE canhear_range = 0 /obj/item/radio/headset/bot/recalculateChannels() @@ -160,7 +161,7 @@ SSradio.add_object(bot_core, control_freq, bot_filter) prepare_huds() - for(var/datum/atom_hud/data/diagnostic/diag_hud in huds) + for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) diag_hud.add_to_hud(src) diag_hud.add_hud_to(src) permanent_huds |= diag_hud @@ -391,7 +392,7 @@ pulse2.icon_state = "empdisable" pulse2.name = "emp sparks" pulse2.anchored = 1 - pulse2.dir = pick(cardinal) + pulse2.dir = pick(GLOB.cardinal) QDEL_IN(pulse2, 10) if(paicard) @@ -495,7 +496,7 @@ Pass a positive integer as an argument to override a bot's default speed. if(!path) return 0 if(path.len > 1) - step_towards(src, path[1]) + Move(path[1], get_dir(src, path[1]), BOT_STEP_DELAY) if(get_turf(src) == path[1]) //Successful move increment_path() tries = 0 @@ -1030,20 +1031,6 @@ Pass a positive integer as an argument to override a bot's default speed. Radio.talk_into(src, message, message_mode, verb, speaking) used_radios += Radio -/mob/living/simple_animal/bot/handle_hud_icons_health() - ..() - switch(bodytemperature) //310.055 optimal body temp - if(335 to INFINITY) - throw_alert("temp", /obj/screen/alert/hot/robot, 2) - if(320 to 335) - throw_alert("temp", /obj/screen/alert/hot/robot, 1) - if(300 to 320) - clear_alert("temp") - if(260 to 300) - throw_alert("temp", /obj/screen/alert/cold/robot, 1) - else - throw_alert("temp", /obj/screen/alert/cold/robot, 2) - /mob/living/simple_animal/bot/is_mechanical() return 1 @@ -1051,7 +1038,7 @@ Pass a positive integer as an argument to override a bot's default speed. path = newpath ? newpath : list() if(!path_hud) return - var/list/path_huds_watching_me = list(huds[DATA_HUD_DIAGNOSTIC_ADVANCED]) + var/list/path_huds_watching_me = list(GLOB.huds[DATA_HUD_DIAGNOSTIC_ADVANCED]) if(path_hud) path_huds_watching_me += path_hud for(var/V in path_huds_watching_me) @@ -1072,7 +1059,7 @@ Pass a positive integer as an argument to override a bot's default speed. var/turf/prevprevT = path[i - 2] var/prevDir = get_dir(prevprevT, prevT) var/mixDir = direction|prevDir - if(mixDir in diagonals) + if(mixDir in GLOB.diagonals) prevI.dir = mixDir if(prevDir & (NORTH|SOUTH)) var/matrix/ntransform = matrix() diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm index 27ecd8e1569..024e2b5f304 100644 --- a/code/modules/mob/living/simple_animal/bot/construction.dm +++ b/code/modules/mob/living/simple_animal/bot/construction.dm @@ -1,5 +1,4 @@ //Bot Construction -var/robot_arm = /obj/item/robot_parts/l_arm //Cleanbot assembly /obj/item/bucket_sensor @@ -13,6 +12,7 @@ var/robot_arm = /obj/item/robot_parts/l_arm throw_range = 5 w_class = WEIGHT_CLASS_NORMAL var/created_name = "Cleanbot" + var/robot_arm = /obj/item/robot_parts/l_arm /obj/item/bucket_sensor/attackby(obj/item/W, mob/user as mob, params) ..() @@ -350,6 +350,7 @@ var/robot_arm = /obj/item/robot_parts/l_arm var/treatment_fire = "salglu_solution" var/treatment_tox = "charcoal" var/treatment_virus = "spaceacillin" + var/robot_arm = /obj/item/robot_parts/l_arm /obj/item/firstaid_arm_assembly/New(loc, new_skin) ..() @@ -419,6 +420,7 @@ var/robot_arm = /obj/item/robot_parts/l_arm item_state = "helmet" var/created_name = "Securitron" //To preserve the name if it's a unique securitron I guess var/build_step = 0 + var/robot_arm = /obj/item/robot_parts/l_arm /obj/item/clothing/head/helmet/attackby(obj/item/assembly/signaler/S, mob/user, params) ..() @@ -596,6 +598,7 @@ var/robot_arm = /obj/item/robot_parts/l_arm req_one_access = list(ACCESS_CLOWN, ACCESS_ROBOTICS, ACCESS_MIME) var/build_step = 0 var/created_name = "Honkbot" //To preserve the name if it's a unique medbot I guess + var/robot_arm = /obj/item/robot_parts/l_arm /obj/item/honkbot_arm_assembly/attackby(obj/item/W, mob/user, params) ..() diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 410f9715325..faaa65a46c4 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -68,7 +68,7 @@ name = pick("RED RAMPAGE","RED ROVER","RED KILLDEATH MURDERBOT") //SECHUD - var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED] + var/datum/atom_hud/secsensor = GLOB.huds[DATA_HUD_SECURITY_ADVANCED] secsensor.add_hud_to(src) permanent_huds |= secsensor @@ -473,7 +473,7 @@ pulse2.icon_state = "empdisable" pulse2.name = "emp sparks" pulse2.anchored = 1 - pulse2.dir = pick(cardinal) + pulse2.dir = pick(GLOB.cardinal) spawn(10) qdel(pulse2) var/list/mob/living/carbon/targets = new diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index b7696236e38..5246a536d92 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -123,7 +123,7 @@ prev_access = access_card.access qdel(J) - var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] medsensor.add_hud_to(src) permanent_huds |= medsensor diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index c89b160bf0e..728b050dd54 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -391,8 +391,6 @@ passenger = M load = M can_buckle = FALSE - // Not sure why this is done - reset_perspective(src) return TRUE return FALSE @@ -417,9 +415,6 @@ overlays.Cut() - if(ismob(load)) - var/mob/M = load - M.reset_perspective(null) unbuckle_all_mobs() if(load) @@ -446,9 +441,6 @@ AM.layer = initial(AM.layer) AM.pixel_y = initial(AM.pixel_y) AM.plane = initial(AM.plane) - if(ismob(AM)) - var/mob/M = AM - M.reset_perspective(null) /mob/living/simple_animal/bot/mulebot/call_bot() ..() diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index eb629680a61..ecdb8e3f0fe 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -90,7 +90,7 @@ prev_access = access_card.access //SECHUD - var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED] + var/datum/atom_hud/secsensor = GLOB.huds[DATA_HUD_SECURITY_ADVANCED] secsensor.add_hud_to(src) permanent_huds |= secsensor diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index ee03c204d48..f150005116e 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -333,73 +333,116 @@ ///ui stuff -/mob/living/simple_animal/hostile/construct/armoured/handle_hud_icons_health() - ..() +/mob/living/simple_animal/hostile/construct/armoured/update_health_hud() + if(!client) + return if(healths) switch(health) - if(250 to INFINITY) healths.icon_state = "juggernaut_health0" - if(208 to 249) healths.icon_state = "juggernaut_health1" - if(167 to 207) healths.icon_state = "juggernaut_health2" - if(125 to 166) healths.icon_state = "juggernaut_health3" - if(84 to 124) healths.icon_state = "juggernaut_health4" - if(42 to 83) healths.icon_state = "juggernaut_health5" - if(1 to 41) healths.icon_state = "juggernaut_health6" - else healths.icon_state = "juggernaut_health7" + if(250 to INFINITY) + healths.icon_state = "juggernaut_health0" + if(208 to 249) + healths.icon_state = "juggernaut_health1" + if(167 to 207) + healths.icon_state = "juggernaut_health2" + if(125 to 166) + healths.icon_state = "juggernaut_health3" + if(84 to 124) + healths.icon_state = "juggernaut_health4" + if(42 to 83) + healths.icon_state = "juggernaut_health5" + if(1 to 41) + healths.icon_state = "juggernaut_health6" + else + healths.icon_state = "juggernaut_health7" -/mob/living/simple_animal/hostile/construct/behemoth/handle_hud_icons_health() - ..() +/mob/living/simple_animal/hostile/construct/behemoth/update_health_hud() + if(!client) + return if(healths) switch(health) - if(750 to INFINITY) healths.icon_state = "juggernaut_health0" - if(625 to 749) healths.icon_state = "juggernaut_health1" - if(500 to 624) healths.icon_state = "juggernaut_health2" - if(375 to 499) healths.icon_state = "juggernaut_health3" - if(250 to 374) healths.icon_state = "juggernaut_health4" - if(125 to 249) healths.icon_state = "juggernaut_health5" - if(1 to 124) healths.icon_state = "juggernaut_health6" - else healths.icon_state = "juggernaut_health7" + if(750 to INFINITY) + healths.icon_state = "juggernaut_health0" + if(625 to 749) + healths.icon_state = "juggernaut_health1" + if(500 to 624) + healths.icon_state = "juggernaut_health2" + if(375 to 499) + healths.icon_state = "juggernaut_health3" + if(250 to 374) + healths.icon_state = "juggernaut_health4" + if(125 to 249) + healths.icon_state = "juggernaut_health5" + if(1 to 124) + healths.icon_state = "juggernaut_health6" + else + healths.icon_state = "juggernaut_health7" -/mob/living/simple_animal/hostile/construct/builder/handle_hud_icons_health() - ..() +/mob/living/simple_animal/hostile/construct/builder/update_health_hud() + if(!client) + return if(healths) switch(health) - if(50 to INFINITY) healths.icon_state = "artificer_health0" - if(42 to 49) healths.icon_state = "artificer_health1" - if(34 to 41) healths.icon_state = "artificer_health2" - if(26 to 33) healths.icon_state = "artificer_health3" - if(18 to 25) healths.icon_state = "artificer_health4" - if(10 to 17) healths.icon_state = "artificer_health5" - if(1 to 9) healths.icon_state = "artificer_health6" - else healths.icon_state = "artificer_health7" + if(50 to INFINITY) + healths.icon_state = "artificer_health0" + if(42 to 49) + healths.icon_state = "artificer_health1" + if(34 to 41) + healths.icon_state = "artificer_health2" + if(26 to 33) + healths.icon_state = "artificer_health3" + if(18 to 25) + healths.icon_state = "artificer_health4" + if(10 to 17) + healths.icon_state = "artificer_health5" + if(1 to 9) + healths.icon_state = "artificer_health6" + else + healths.icon_state = "artificer_health7" -/mob/living/simple_animal/hostile/construct/wraith/handle_hud_icons_health() - - ..() +/mob/living/simple_animal/hostile/construct/wraith/update_health_hud() + if(!client) + return if(healths) switch(health) - if(75 to INFINITY) healths.icon_state = "wraith_health0" - if(62 to 74) healths.icon_state = "wraith_health1" - if(50 to 61) healths.icon_state = "wraith_health2" - if(37 to 49) healths.icon_state = "wraith_health3" - if(25 to 36) healths.icon_state = "wraith_health4" - if(12 to 24) healths.icon_state = "wraith_health5" - if(1 to 11) healths.icon_state = "wraith_health6" - else healths.icon_state = "wraith_health7" + if(75 to INFINITY) + healths.icon_state = "wraith_health0" + if(62 to 74) + healths.icon_state = "wraith_health1" + if(50 to 61) + healths.icon_state = "wraith_health2" + if(37 to 49) + healths.icon_state = "wraith_health3" + if(25 to 36) + healths.icon_state = "wraith_health4" + if(12 to 24) + healths.icon_state = "wraith_health5" + if(1 to 11) + healths.icon_state = "wraith_health6" + else + healths.icon_state = "wraith_health7" -/mob/living/simple_animal/hostile/construct/harvester/handle_hud_icons_health() - - ..() +/mob/living/simple_animal/hostile/construct/harvester/update_health_hud() + if(!client) + return if(healths) switch(health) - if(150 to INFINITY) healths.icon_state = "harvester_health0" - if(125 to 149) healths.icon_state = "harvester_health1" - if(100 to 124) healths.icon_state = "harvester_health2" - if(75 to 99) healths.icon_state = "harvester_health3" - if(50 to 74) healths.icon_state = "harvester_health4" - if(25 to 49) healths.icon_state = "harvester_health5" - if(1 to 24) healths.icon_state = "harvester_health6" - else healths.icon_state = "harvester_health7" + if(150 to INFINITY) + healths.icon_state = "harvester_health0" + if(125 to 149) + healths.icon_state = "harvester_health1" + if(100 to 124) + healths.icon_state = "harvester_health2" + if(75 to 99) + healths.icon_state = "harvester_health3" + if(50 to 74) + healths.icon_state = "harvester_health4" + if(25 to 49) + healths.icon_state = "harvester_health5" + if(1 to 24) + healths.icon_state = "harvester_health6" + else + healths.icon_state = "harvester_health7" diff --git a/code/modules/mob/living/simple_animal/friendly/diona.dm b/code/modules/mob/living/simple_animal/friendly/diona.dm index b4872c9ff87..7d6f90b7d0d 100644 --- a/code/modules/mob/living/simple_animal/friendly/diona.dm +++ b/code/modules/mob/living/simple_animal/friendly/diona.dm @@ -145,7 +145,7 @@ if((stat != CONSCIOUS) || !isdiona(loc)) return FALSE var/mob/living/carbon/human/D = loc - T = get_turf(src) + var/turf/T = get_turf(src) if(!T) return FALSE to_chat(loc, "You feel a pang of loss as [src] splits away from your biomass.") @@ -202,6 +202,20 @@ qdel(src) return TRUE +// Consumes plant matter other than weeds to evolve +/mob/living/simple_animal/diona/proc/consume(obj/item/reagent_containers/food/snacks/grown/G) + if(nutrition >= nutrition_need) // Prevents griefing by overeating plant items without evolving. + to_chat(src, "You're too full to consume this! Perhaps it's time to grow bigger...") + else + if(do_after_once(src, 20, target = G)) + visible_message("[src] ravenously consumes [G].", "You ravenously devour [G].") + playsound(loc, 'sound/items/eatfood.ogg', 30, 0, frequency = 1.5) + if(G.reagents.get_reagent_amount("nutriment") + G.reagents.get_reagent_amount("plantmatter") < 1) + adjust_nutrition(2) + else + adjust_nutrition((G.reagents.get_reagent_amount("nutriment") + G.reagents.get_reagent_amount("plantmatter")) * 2) + qdel(G) + /mob/living/simple_animal/diona/proc/steal_blood() if(stat != CONSCIOUS) return FALSE diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 77c2edbdd53..ea8e949f1c7 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -210,7 +210,7 @@ qdel(src) #define MAX_CHICKENS 50 -var/global/chicken_count = 0 +GLOBAL_VAR_INIT(chicken_count, 0) /mob/living/simple_animal/chicken name = "\improper chicken" @@ -258,14 +258,14 @@ var/global/chicken_count = 0 icon_dead = "[icon_prefix]_[body_color]_dead" pixel_x = rand(-6, 6) pixel_y = rand(0, 10) - chicken_count += 1 + GLOB.chicken_count += 1 /mob/living/simple_animal/chicken/death(gibbed) // Only execute the below if we successfully died . = ..(gibbed) if(!.) return - chicken_count -= 1 + GLOB.chicken_count -= 1 /mob/living/simple_animal/chicken/attackby(obj/item/O, mob/user, params) if(istype(O, food_type)) //feedin' dem chickens @@ -290,7 +290,7 @@ var/global/chicken_count = 0 E.pixel_x = rand(-6,6) E.pixel_y = rand(-6,6) if(eggsFertile) - if(chicken_count < MAX_CHICKENS && prob(25)) + if(GLOB.chicken_count < MAX_CHICKENS && prob(25)) START_PROCESSING(SSobj, E) /obj/item/reagent_containers/food/snacks/egg/var/amount_grown = 0 diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index 1446ef7d4bb..a48b36cb0c7 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -49,11 +49,11 @@ if(C.avail()) visible_message("[src] chews through [C]. It's toast!") playsound(src, 'sound/effects/sparks2.ogg', 100, 1) - C.deconstruct() toast() // mmmm toasty. else - C.deconstruct() visible_message("[src] chews through [C].") + investigate_log("was chewed through by a mouse in [get_area(F)]([F.x], [F.y], [F.z] - [ADMIN_JMP(F)])","wires") + C.deconstruct() /mob/living/simple_animal/mouse/handle_automated_speech() ..() diff --git a/code/modules/mob/living/simple_animal/friendly/penguin.dm b/code/modules/mob/living/simple_animal/friendly/penguin.dm index dc00e252661..08321b1bb5a 100644 --- a/code/modules/mob/living/simple_animal/friendly/penguin.dm +++ b/code/modules/mob/living/simple_animal/friendly/penguin.dm @@ -18,7 +18,7 @@ /mob/living/simple_animal/pet/penguin/Initialize(mapload) . = ..() - AddComponent(/datum/component/waddling) + AddElement(/datum/element/waddling) /mob/living/simple_animal/pet/penguin/emperor name = "Emperor penguin" diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index 5a369a043d7..038b3b3d221 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -11,7 +11,7 @@ response_disarm = "shoves" response_harm = "hits" speed = 0 - butcher_results = list(/obj/item/reagent_containers/food/snacks/xenomeat = 3, /obj/item/stack/sheet/animalhide/xeno = 1) + butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/xenomeat= 3, /obj/item/stack/sheet/animalhide/xeno = 1) maxHealth = 125 health = 125 harm_intent_damage = 5 @@ -83,7 +83,7 @@ retreat_distance = 5 minimum_distance = 5 move_to_delay = 4 - butcher_results = list(/obj/item/reagent_containers/food/snacks/xenomeat = 4, /obj/item/stack/sheet/animalhide/xeno = 1) + butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/xenomeat= 4, /obj/item/stack/sheet/animalhide/xeno = 1) projectiletype = /obj/item/projectile/neurotox projectilesound = 'sound/weapons/pierce.ogg' status_flags = 0 @@ -130,7 +130,7 @@ move_to_delay = 4 maxHealth = 400 health = 400 - butcher_results = list(/obj/item/reagent_containers/food/snacks/xenomeat = 10, /obj/item/stack/sheet/animalhide/xeno = 2) + butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/xenomeat= 10, /obj/item/stack/sheet/animalhide/xeno = 2) mob_size = MOB_SIZE_LARGE gold_core_spawnable = NO_SPAWN diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index 2530fb4b389..d5b7205f09c 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -13,7 +13,7 @@ speak_chance = 1 turns_per_move = 5 see_in_dark = 6 - butcher_results = list(/obj/item/reagent_containers/food/snacks/bearmeat = 5, /obj/item/clothing/head/bearpelt = 1) + butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/bearmeat= 5, /obj/item/clothing/head/bearpelt = 1) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "hits" diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index a0cb935ba25..7b0b52f0b4f 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -74,12 +74,11 @@ else our_color = pick(carp_colors) add_atom_colour(carp_colors[our_color], FIXED_COLOUR_PRIORITY) - add_carp_overlay() + regenerate_icons() /mob/living/simple_animal/hostile/carp/proc/add_carp_overlay() if(!random_color) return - cut_overlays() var/mutable_appearance/base_overlay = mutable_appearance(icon, "base_mouth") base_overlay.appearance_flags = RESET_COLOR add_overlay(base_overlay) @@ -87,7 +86,6 @@ /mob/living/simple_animal/hostile/carp/proc/add_dead_carp_overlay() if(!random_color) return - cut_overlays() var/mutable_appearance/base_dead_overlay = mutable_appearance(icon, "base_dead_mouth") base_dead_overlay.appearance_flags = RESET_COLOR add_overlay(base_dead_overlay) @@ -103,24 +101,22 @@ /mob/living/simple_animal/hostile/carp/death(gibbed) . = ..() - cut_overlays() if(!random_color || gibbed) return - add_dead_carp_overlay() + regenerate_icons() /mob/living/simple_animal/hostile/carp/revive() ..() regenerate_icons() /mob/living/simple_animal/hostile/carp/regenerate_icons() - cut_overlays() + ..() if(!random_color) return if(stat != DEAD) add_carp_overlay() else add_dead_carp_overlay() - ..() /mob/living/simple_animal/hostile/carp/holocarp icon_state = "holocarp" diff --git a/code/modules/mob/living/simple_animal/hostile/floorcluwne.dm b/code/modules/mob/living/simple_animal/hostile/floorcluwne.dm index 77d6807e086..cf55824542a 100644 --- a/code/modules/mob/living/simple_animal/hostile/floorcluwne.dm +++ b/code/modules/mob/living/simple_animal/hostile/floorcluwne.dm @@ -78,8 +78,8 @@ pixel_y = 8 if(is_type_in_typecache(get_area(loc), invalid_area_typecache)) - var/area = pick(teleportlocs) - var/area/tp = teleportlocs[area] + var/area = pick(GLOB.teleportlocs) + var/area/tp = GLOB.teleportlocs[area] forceMove(pick(get_area_turfs(tp.type))) if((!current_victim && !admincluwne) || QDELETED(current_victim)) @@ -285,7 +285,7 @@ if(prob(6)) for(var/turf/simulated/floor/O in range(src, 6)) - O.MakeSlippery(TURF_WET_WATER, 10) + O.MakeSlippery(TURF_WET_WATER, 10 SECONDS) playsound(src, 'sound/effects/clownstep1.ogg', 30, 1) if(prob(5)) @@ -323,7 +323,7 @@ if(!eating) addtimer(CALLBACK(src, /mob/living/simple_animal/hostile/floor_cluwne/.proc/Grab, H), 70) for(var/turf/simulated/floor/O in range(src, 6)) - O.MakeSlippery(TURF_WET_LUBE, 20) + O.MakeSlippery(TURF_WET_LUBE, 20 SECONDS) playsound(src, 'sound/effects/meteorimpact.ogg', 30, 1) eating = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index b456db6efaf..614e814fc25 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -18,7 +18,7 @@ turns_per_move = 5 see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE - butcher_results = list(/obj/item/reagent_containers/food/snacks/spidermeat = 2, /obj/item/reagent_containers/food/snacks/spiderleg = 8) + butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/spidermeat= 2, /obj/item/reagent_containers/food/snacks/monstermeat/spiderleg= 8) response_help = "pets" response_disarm = "gently pushes aside" response_harm = "hits" @@ -53,7 +53,7 @@ icon_state = "nurse" icon_living = "nurse" icon_dead = "nurse_dead" - butcher_results = list(/obj/item/reagent_containers/food/snacks/spidermeat = 2, /obj/item/reagent_containers/food/snacks/spiderleg = 8, /obj/item/reagent_containers/food/snacks/spidereggs = 4) + butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/spidermeat= 2, /obj/item/reagent_containers/food/snacks/monstermeat/spiderleg= 8, /obj/item/reagent_containers/food/snacks/monstermeat/spidereggs= 4) maxHealth = 40 health = 40 diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index ece990c7743..8d2ba52709f 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -25,23 +25,23 @@ var/list/human_overlays = list() /mob/living/simple_animal/hostile/headcrab/Life(seconds, times_fired) - if(!is_zombie && isturf(src.loc) && stat != DEAD) - for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile - if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD)) - Zombify(H) - break - var/cycles = 4 - if(cycles >= 4) - for(var/mob/living/simple_animal/K in oview(src, 1)) //Only for corpse right next to/on same tile - if(K.stat == DEAD || (!K.check_death_method() && K.health <= HEALTH_THRESHOLD_DEAD)) - visible_message("[src] consumes [target] whole!") - if(health < maxHealth) - health += 10 - qdel(K) - break - cycles = 0 - cycles++ - ..() + if(..()) + if(!is_zombie && isturf(src.loc)) + for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile + if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD)) + Zombify(H) + break + var/cycles = 4 + if(cycles >= 4) + for(var/mob/living/simple_animal/K in oview(src, 1)) //Only for corpse right next to/on same tile + if(K.stat == DEAD || (!K.check_death_method() && K.health <= HEALTH_THRESHOLD_DEAD)) + visible_message("[src] consumes [target] whole!") + if(health < maxHealth) + health += 10 + qdel(K) + break + cycles = 0 + cycles++ /mob/living/simple_animal/hostile/headcrab/OpenFire(atom/A) if(check_friendly_fire) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 2881a5945bb..d539721817a 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -455,8 +455,8 @@ EscapeConfinement() var/dir_to_target = get_dir(targets_from, target) var/dir_list = list() - if(dir_to_target in diagonals) //it's diagonal, so we need two directions to hit - for(var/direction in cardinal) + if(dir_to_target in GLOB.diagonals) //it's diagonal, so we need two directions to hit + for(var/direction in GLOB.cardinal) if(direction & dir_to_target) dir_list += direction else @@ -467,7 +467,7 @@ /mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with megafauna destroying everything around them if(environment_smash) EscapeConfinement() - for(var/dir in cardinal) + for(var/dir in GLOB.cardinal) DestroyObjectsInDirection(dir) /mob/living/simple_animal/hostile/proc/EscapeConfinement() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index 9fa5abe4695..c9139ea7bfd 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -79,7 +79,7 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/bubblegum/Initialize(mapload) . = ..() if(true_spawn) - for(var/mob/living/simple_animal/hostile/megafauna/bubblegum/B in GLOB.living_mob_list) + for(var/mob/living/simple_animal/hostile/megafauna/bubblegum/B in GLOB.alive_mob_list) if(B != src) qdel(src) //There can be only one return @@ -396,9 +396,9 @@ Difficulty: Hard if(. > 0 && prob(25)) var/obj/effect/decal/cleanable/blood/gibs/bubblegum/B = new /obj/effect/decal/cleanable/blood/gibs/bubblegum(loc) if(prob(40)) - step(B, pick(cardinal)) + step(B, pick(GLOB.cardinal)) else - B.setDir(pick(cardinal)) + B.setDir(pick(GLOB.cardinal)) /obj/effect/decal/cleanable/blood/gibs/bubblegum name = "thick blood" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 8eed750804f..7f1b3942d94 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -103,7 +103,7 @@ Difficulty: Very Hard visible_message("\"You can't dodge.\"") ranged_cooldown = world.time + 30 telegraph() - dir_shots(alldirs) + dir_shots(GLOB.alldirs) move_to_delay = 3 return else @@ -127,13 +127,13 @@ Difficulty: Very Hard /mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots() ranged_cooldown = world.time + 40 - dir_shots(diagonals) + dir_shots(GLOB.diagonals) SLEEP_CHECK_DEATH(10) - dir_shots(cardinal) + dir_shots(GLOB.cardinal) SLEEP_CHECK_DEATH(10) - dir_shots(diagonals) + dir_shots(GLOB.diagonals) SLEEP_CHECK_DEATH(10) - dir_shots(cardinal) + dir_shots(GLOB.cardinal) /mob/living/simple_animal/hostile/megafauna/colossus/proc/select_spiral_attack() telegraph() @@ -150,7 +150,7 @@ Difficulty: Very Hard INVOKE_ASYNC(src, .proc/spiral_shoot, TRUE) /mob/living/simple_animal/hostile/megafauna/colossus/proc/spiral_shoot(negative = pick(TRUE, FALSE), counter_start = 8) - var/turf/start_turf = get_step(src, pick(alldirs)) + var/turf/start_turf = get_step(src, pick(GLOB.alldirs)) var/counter = counter_start for(var/i in 1 to 80) if(negative) @@ -198,7 +198,7 @@ Difficulty: Very Hard /mob/living/simple_animal/hostile/megafauna/colossus/proc/dir_shots(list/dirs) if(!islist(dirs)) - dirs = alldirs.Copy() + dirs = GLOB.alldirs.Copy() playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 200, TRUE, 2) for(var/d in dirs) var/turf/E = get_step(src, d) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index e810222e1c4..e97b7671b67 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -366,7 +366,7 @@ Difficulty: Medium if(L && !QDELETED(L)) // Some mobs are deleted on death var/throw_dir = get_dir(src, L) if(L.loc == loc) - throw_dir = pick(alldirs) + throw_dir = pick(GLOB.alldirs) var/throwtarget = get_edge_target_turf(src, throw_dir) L.throw_at(throwtarget, 3) visible_message("[L] is thrown clear of [src]!") diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 24ee584b378..716f5436223 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -179,18 +179,18 @@ Difficulty: Hard if((prob(anger_modifier) || target.Adjacent(src)) && target != src) var/obj/effect/temp_visual/hierophant/chaser/OC = new(loc, src, target, chaser_speed * 1.5, FALSE) OC.moving = 4 - OC.moving_dir = pick(cardinal - C.moving_dir) + OC.moving_dir = pick(GLOB.cardinal - C.moving_dir) else if(prob(10 + (anger_modifier * 0.5)) && get_dist(src, target) > 2) blink(target) else if(prob(70 - anger_modifier)) //a cross blast of some type if(prob(anger_modifier * (2 / target_slowness)) && health < maxHealth * 0.5) //we're super angry do it at all dirs - INVOKE_ASYNC(src, .proc/blasts, target, alldirs) + INVOKE_ASYNC(src, .proc/blasts, target, GLOB.alldirs) else if(prob(60)) - INVOKE_ASYNC(src, .proc/blasts, target, cardinal) + INVOKE_ASYNC(src, .proc/blasts, target, GLOB.cardinal) else - INVOKE_ASYNC(src, .proc/blasts, target, diagonals) + INVOKE_ASYNC(src, .proc/blasts, target, GLOB.diagonals) else //just release a burst of power INVOKE_ASYNC(src, .proc/burst, get_turf(src)) @@ -226,9 +226,9 @@ Difficulty: Hard while(!QDELETED(target) && cross_counter) cross_counter-- if(prob(60)) - INVOKE_ASYNC(src, .proc/blasts, target, cardinal) + INVOKE_ASYNC(src, .proc/blasts, target, GLOB.cardinal) else - INVOKE_ASYNC(src, .proc/blasts, target, diagonals) + INVOKE_ASYNC(src, .proc/blasts, target, GLOB.diagonals) SLEEP_CHECK_DEATH(6 + target_slowness) animate(src, color = oldcolor, time = 8) addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8) @@ -244,7 +244,7 @@ Difficulty: Hard animate(src, color = "#660099", time = 6) SLEEP_CHECK_DEATH(6) var/list/targets = ListTargets() - var/list/cardinal_copy = cardinal.Copy() + var/list/cardinal_copy = GLOB.cardinal.Copy() while(targets.len && cardinal_copy.len) var/mob/living/pickedtarget = pick(targets) if(targets.len >= cardinal_copy.len) @@ -263,13 +263,13 @@ Difficulty: Hard SLEEP_CHECK_DEATH(8) blinking = FALSE -/mob/living/simple_animal/hostile/megafauna/hierophant/proc/blasts(mob/victim, var/list/directions = cardinal) //fires cross blasts with a delay +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/blasts(mob/victim, var/list/directions = GLOB.cardinal) //fires cross blasts with a delay var/turf/T = get_turf(victim) if(!T) return - if(directions == cardinal) + if(directions == GLOB.cardinal) new /obj/effect/temp_visual/hierophant/telegraph/cardinal(T, src) - else if(directions == diagonals) + else if(directions == GLOB.diagonals) new /obj/effect/temp_visual/hierophant/telegraph/diagonal(T, src) else new /obj/effect/temp_visual/hierophant/telegraph(T, src) @@ -295,7 +295,7 @@ Difficulty: Hard if((istype(get_area(T), /area/ruin/unpowered/hierophant) || istype(get_area(src), /area/ruin/unpowered/hierophant)) && victim != src) return arena_cooldown = world.time + initial(arena_cooldown) - for(var/d in cardinal) + for(var/d in GLOB.cardinal) INVOKE_ASYNC(src, .proc/arena_squares, T, d) for(var/t in RANGE_TURFS(11, T)) if(t && get_dist(t, T) == 11) @@ -565,7 +565,7 @@ Difficulty: Hard /obj/effect/temp_visual/hierophant/chaser/proc/get_target_dir() . = get_cardinal_dir(src, targetturf) if((. != previous_moving_dir && . == more_previouser_moving_dir) || . == 0) //we're alternating, recalculate - var/list/cardinal_copy = cardinal.Copy() + var/list/cardinal_copy = GLOB.cardinal.Copy() cardinal_copy -= more_previouser_moving_dir . = pick(cardinal_copy) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index b3618efff0a..eed05d55e91 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -43,7 +43,6 @@ . = ..() if(internal_type && true_spawn) internal = new internal_type(src) - apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) for(var/action_type in attack_action_types) var/datum/action/innate/megafauna_attack/attack_action = new action_type() attack_action.Grant(src) @@ -91,7 +90,7 @@ else devour(L) -/mob/living/simple_animal/hostile/megafauna/onShuttleMove() +/mob/living/simple_animal/hostile/megafauna/onShuttleMove(turf/oldT, turf/T1, rotation, mob/caller) var/turf/oldloc = loc . = ..() if(!.) @@ -100,7 +99,7 @@ message_admins("Megafauna [src] \ ([ADMIN_FLW(src,"FLW")]) \ moved via shuttle from ([oldloc.x], [oldloc.y], [oldloc.z]) to \ - ([newloc.x], [newloc.y], [newloc.z])") + ([newloc.x], [newloc.y], [newloc.z])[caller ? " called by [ADMIN_LOOKUP(caller)]" : ""]") /mob/living/simple_animal/hostile/megafauna/proc/devour(mob/living/L) if(!L) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm index 696c692a5dc..2515da9dff9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm @@ -66,7 +66,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa /mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/Initialize(mapload) . = ..() swarmer_caps = GLOB.AISwarmerCapsByType //for admin-edits - for(var/ddir in cardinal) + for(var/ddir in GLOB.cardinal) new /obj/structure/swarmer/blockade (get_step(src, ddir)) var/mob/living/simple_animal/hostile/swarmer/ai/resource/R = new(loc) step(R, ddir) //Step the swarmers, instead of spawning them there, incase the turf is solid diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 53f384aee0c..848a285abf4 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -101,7 +101,7 @@ // due to `del_on_death` return ..() -var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/cable, /obj/structure/window) +GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/cable, /obj/structure/window)) /mob/living/simple_animal/hostile/mimic/copy health = 100 @@ -141,7 +141,7 @@ var/global/list/protected_objects = list(/obj/structure/table, /obj/structure/ca faction |= "\ref[owner]" /mob/living/simple_animal/hostile/mimic/copy/proc/CheckObject(var/obj/O) - if((istype(O, /obj/item) || istype(O, /obj/structure)) && !is_type_in_list(O, protected_objects)) + if((istype(O, /obj/item) || istype(O, /obj/structure)) && !is_type_in_list(O, GLOB.protected_objects)) return 1 return 0 diff --git a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm index 490e056e62f..d052dd9bc23 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/goliath.dm @@ -89,7 +89,7 @@ throw_message = "does nothing to the tough hide of the" pre_attack_icon = "goliath2" crusher_loot = /obj/item/crusher_trophy/goliath_tentacle - butcher_results = list(/obj/item/reagent_containers/food/snacks/goliath = 2, /obj/item/stack/sheet/animalhide/goliath_hide = 1, /obj/item/stack/sheet/bone = 2) + butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/goliath= 2, /obj/item/stack/sheet/animalhide/goliath_hide = 1, /obj/item/stack/sheet/bone = 2) loot = list() stat_attack = UNCONSCIOUS robust_searching = TRUE @@ -113,7 +113,7 @@ pre_attack_icon = "Goliath_preattack" throw_message = "does nothing to the rocky hide of the" loot = list(/obj/item/stack/sheet/animalhide/goliath_hide) //A throwback to the asteroid days - butcher_results = list(/obj/item/reagent_containers/food/snacks/goliath = 2, /obj/item/stack/sheet/bone = 2) + butcher_results = list(/obj/item/reagent_containers/food/snacks/monstermeat/goliath= 2, /obj/item/stack/sheet/bone = 2) crusher_drop_mod = 30 wander = FALSE var/list/cached_tentacle_turfs @@ -164,7 +164,7 @@ /obj/effect/temp_visual/goliath_tentacle/original/Initialize(mapload, new_spawner) . = ..() - var/list/directions = cardinal.Copy() + var/list/directions = GLOB.cardinal.Copy() for(var/i in 1 to 3) var/spawndir = pick_n_take(directions) var/turf/T = get_step(src, spawndir) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm index 2f896f4adb0..fb2c741cb30 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/gutlunch.dm @@ -50,10 +50,9 @@ return ..() /mob/living/simple_animal/hostile/asteroid/gutlunch/regenerate_icons() - cut_overlays() + ..() if(udder.reagents.total_volume == udder.reagents.maximum_volume) add_overlay("gl_full") - ..() /mob/living/simple_animal/hostile/asteroid/gutlunch/attackby(obj/item/O, mob/user, params) if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass)) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm index 3d7da9d0fcc..ca9b632e06a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm @@ -327,9 +327,9 @@ /obj/effect/mob_spawn/human/corpse/damaged/legioninfested/dwarf/equip(mob/living/carbon/human/H) . = ..() - H.dna.SetSEState(SMALLSIZEBLOCK, 1, 1) + H.dna.SetSEState(GLOB.smallsizeblock, 1, 1) H.mutations.Add(DWARF) - genemutcheck(H, SMALLSIZEBLOCK, null, MUTCHK_FORCED) + genemutcheck(H, GLOB.smallsizeblock, null, MUTCHK_FORCED) H.update_mutations() /obj/effect/mob_spawn/human/corpse/damaged/legioninfested/Initialize(mapload) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm index 7c7200e8588..a888fa7ee9a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm @@ -23,10 +23,6 @@ var/icon_aggro = null var/crusher_drop_mod = 25 -/mob/living/simple_animal/hostile/asteroid/Initialize(mapload) - . = ..() - apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) - /mob/living/simple_animal/hostile/asteroid/Aggro() ..() if(vision_range != aggro_vision_range) diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index b32cae64675..105b9a02819 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -180,11 +180,11 @@ range = 10 /obj/effect/proc_holder/spell/aoe_turf/blindness/cast(list/targets, mob/user = usr) - for(var/mob/living/L in GLOB.living_mob_list) + for(var/mob/living/L in GLOB.alive_mob_list) if(L == user) continue var/turf/T = get_turf(L.loc) - if(T && T in targets) + if(T && (T in targets)) L.EyeBlind(4) return diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index f3389108498..23970e88826 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -281,7 +281,7 @@ /mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/LateInitialize() if(istype(depotarea)) var/list/key_candidates = list() - for(var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer/O in GLOB.living_mob_list) + for(var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer/O in GLOB.alive_mob_list) key_candidates += O if(key_candidates.len) var/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/officer/O = pick(key_candidates) diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm index 637c1833a89..2b15e584922 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/actions.dm @@ -58,7 +58,7 @@ if(feedings_left > 0) to_chat(user, "You must wrap [feedings_left] more humanoid prey before you can do this!") return - for(var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q in ts_spiderlist) + for(var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q in GLOB.ts_spiderlist) if(Q.spider_awaymission == user.spider_awaymission) to_chat(user, "The presence of another Queen in the area is preventing you from maturing.") return diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm index f6dffb79642..137d6739466 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/empress.dm @@ -96,13 +96,13 @@ S.amount_grown = 250 /mob/living/simple_animal/hostile/poison/terror_spider/queen/empress/proc/EraseBrood() - for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist) + for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist) if(T.spider_tier < spider_tier) T.degenerate = 1 to_chat(T, "Through the hivemind, the raw power of [src] floods into your body, burning it from the inside out!") - for(var/obj/structure/spider/eggcluster/terror_eggcluster/T in ts_egg_list) + for(var/obj/structure/spider/eggcluster/terror_eggcluster/T in GLOB.ts_egg_list) qdel(T) - for(var/obj/structure/spider/spiderling/terror_spiderling/T in ts_spiderling_list) + for(var/obj/structure/spider/spiderling/terror_spiderling/T in GLOB.ts_spiderling_list) qdel(T) to_chat(src, "All Terror Spiders, except yourself, will die off shortly.") diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/ghost.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/ghost.dm index 24e8012b5ee..daed363b8d9 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/ghost.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/ghost.dm @@ -14,7 +14,7 @@ var/error_on_humanize = "" var/humanize_prompt = "Take direct control of [src]?" humanize_prompt += " Role: [spider_role_summary]" - if(user.ckey in ts_ckey_blacklist) + if(user.ckey in GLOB.ts_ckey_blacklist) error_on_humanize = "You are not able to control any terror spider this round." else if(cannotPossess(user)) error_on_humanize = "You have enabled antag HUD and are unable to re-enter the round." diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/hive.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/hive.dm index aec7d9bb5ff..245ae95c5e9 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/hive.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/hive.dm @@ -4,7 +4,7 @@ /mob/living/simple_animal/hostile/poison/terror_spider/proc/DoHiveSense() var/hsline = "" to_chat(src, "Your Brood: ") - for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist) + for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist) if(T.spider_awaymission != spider_awaymission) continue hsline = "* [T] in [get_area(T)], " @@ -20,21 +20,21 @@ /mob/living/simple_animal/hostile/poison/terror_spider/proc/CountSpiders() var/numspiders = 0 - for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist) + for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist) if(T.stat != DEAD && !T.spider_placed && spider_awaymission == T.spider_awaymission) numspiders += 1 return numspiders /mob/living/simple_animal/hostile/poison/terror_spider/proc/CountSpidersType(specific_type) var/numspiders = 0 - for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist) + for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist) if(T.stat != DEAD && !T.spider_placed && spider_awaymission == T.spider_awaymission) if(T.type == specific_type) numspiders += 1 - for(var/obj/structure/spider/eggcluster/terror_eggcluster/E in ts_egg_list) + for(var/obj/structure/spider/eggcluster/terror_eggcluster/E in GLOB.ts_egg_list) if(E.spiderling_type == specific_type && E.z == z) numspiders += E.spiderling_number - for(var/obj/structure/spider/spiderling/terror_spiderling/L in ts_spiderling_list) + for(var/obj/structure/spider/spiderling/terror_spiderling/L in GLOB.ts_spiderling_list) if(!L.stillborn && L.grow_as == specific_type && L.z == z) numspiders += 1 return numspiders diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm index 828e0e5f8f6..047219a151b 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm @@ -38,9 +38,12 @@ evolvequeen_action.Grant(src) /mob/living/simple_animal/hostile/poison/terror_spider/princess/proc/evolve_to_queen() - var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q = new /mob/living/simple_animal/hostile/poison/terror_spider/queen(loc) + var/mob/living/simple_animal/hostile/poison/terror_spider/queen/Q = new(loc) if(mind) mind.transfer_to(Q) + // Calling `transfer_to()` removes our new body (the Queen's) ability to see the med hud, so we have to re-add the queen here. + var/datum/atom_hud/U = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + U.add_hud_to(Q) qdel(src) /mob/living/simple_animal/hostile/poison/terror_spider/princess/DoWrap() diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm index cd5322a58a1..241cceb3d2c 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm @@ -88,7 +88,7 @@ if(spider_uo71) UnlockBlastDoors("UO71_Caves") // When a queen dies, so do her player-controlled purple-type guardians. Intended as a motivator for purples to ensure they guard her. - for(var/mob/living/simple_animal/hostile/poison/terror_spider/purple/P in ts_spiderlist) + for(var/mob/living/simple_animal/hostile/poison/terror_spider/purple/P in GLOB.ts_spiderlist) if(ckey) P.visible_message("\The [src] writhes in pain!") to_chat(P,"\The [src] has died. Without her hivemind link, purple terrors like yourself cannot survive more than a few minutes!") @@ -97,7 +97,7 @@ /mob/living/simple_animal/hostile/poison/terror_spider/queen/Retaliate() ..() - for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist) + for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist) T.enemies |= enemies /mob/living/simple_animal/hostile/poison/terror_spider/queen/proc/ai_nest_is_full() diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm index 0cf8355e06e..a889bc6d328 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/reproduction.dm @@ -23,12 +23,12 @@ /obj/structure/spider/spiderling/terror_spiderling/New() ..() - ts_spiderling_list += src + GLOB.ts_spiderling_list += src if(is_away_level(z)) spider_awaymission = TRUE /obj/structure/spider/spiderling/terror_spiderling/Destroy() - ts_spiderling_list -= src + GLOB.ts_spiderling_list -= src return ..() /obj/structure/spider/spiderling/terror_spiderling/Bump(obj/O) @@ -205,7 +205,7 @@ /obj/structure/spider/eggcluster/terror_eggcluster/New() ..() - ts_egg_list += src + GLOB.ts_egg_list += src spawn(50) if(spiderling_type == /mob/living/simple_animal/hostile/poison/terror_spider/red) name = "red terror eggs" @@ -227,7 +227,7 @@ name = "queen of terror eggs" /obj/structure/spider/eggcluster/terror_eggcluster/Destroy() - ts_egg_list -= src + GLOB.ts_egg_list -= src return ..() /obj/structure/spider/eggcluster/terror_eggcluster/process() diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_ai.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_ai.dm index 8d18471b1cb..11e4cac3e4a 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_ai.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_ai.dm @@ -103,8 +103,8 @@ return if(!target) var/my_ventcrawl_freq = freq_ventcrawl_idle - if(ts_count_dead > 0) - if(world.time < (ts_death_last + ts_death_window)) + if(GLOB.ts_count_dead > 0) + if(world.time < (GLOB.ts_death_last + GLOB.ts_death_window)) my_ventcrawl_freq = freq_ventcrawl_combat // First, check for general actions that any spider could take. if(path_to_vent) @@ -267,7 +267,7 @@ /mob/living/simple_animal/hostile/poison/terror_spider/proc/ClearObstacle(turf/target_turf) var/list/valid_obstacles = list(/obj/structure/window, /obj/structure/closet, /obj/structure/table, /obj/structure/grille, /obj/structure/rack, /obj/machinery/door/window) - for(var/dir in cardinal) // North, South, East, West + for(var/dir in GLOB.cardinal) // North, South, East, West var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir)) if(is_type_in_list(obstacle, valid_obstacles)) obstacle.attack_animal(src) diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm index d6d64096ff1..520143d71d0 100644 --- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm +++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/terror_spiders.dm @@ -1,12 +1,12 @@ -var/global/list/ts_ckey_blacklist = list() -var/global/ts_count_dead = 0 -var/global/ts_count_alive_awaymission = 0 -var/global/ts_count_alive_station = 0 -var/global/ts_death_last = 0 -var/global/ts_death_window = 9000 // 15 minutes -var/global/list/ts_spiderlist = list() -var/global/list/ts_egg_list = list() -var/global/list/ts_spiderling_list = list() +GLOBAL_LIST_EMPTY(ts_ckey_blacklist) +GLOBAL_VAR_INIT(ts_count_dead, 0) +GLOBAL_VAR_INIT(ts_count_alive_awaymission, 0) +GLOBAL_VAR_INIT(ts_count_alive_station, 0) +GLOBAL_VAR_INIT(ts_death_last, 0) +GLOBAL_VAR_INIT(ts_death_window, 9000) // 15 minutes +GLOBAL_LIST_EMPTY(ts_spiderlist) +GLOBAL_LIST_EMPTY(ts_egg_list) +GLOBAL_LIST_EMPTY(ts_spiderling_list) // -------------------------------------------------------------------------------- // --------------------- TERROR SPIDERS: DEFAULTS --------------------------------- @@ -245,7 +245,7 @@ var/global/list/ts_spiderling_list = list() /mob/living/simple_animal/hostile/poison/terror_spider/New() ..() - ts_spiderlist += src + GLOB.ts_spiderlist += src add_language("Spider Hivemind") if(spider_tier >= TS_TIER_2) add_language("Galactic Common") @@ -262,7 +262,7 @@ var/global/list/ts_spiderling_list = list() msg_terrorspiders("[src] has grown in [get_area(src)].") if(is_away_level(z)) spider_awaymission = 1 - ts_count_alive_awaymission++ + GLOB.ts_count_alive_awaymission++ if(spider_tier >= 3) ai_ventcrawls = FALSE // means that pre-spawned bosses on away maps won't ventcrawl. Necessary to keep prince/mother in one place. if(istype(get_area(src), /area/awaymission/UO71)) // if we are playing the away mission with our special spiders... @@ -272,11 +272,11 @@ var/global/list/ts_spiderling_list = list() ai_ventcrawls = FALSE spider_placed = 1 else - ts_count_alive_station++ + GLOB.ts_count_alive_station++ // after 3 seconds, assuming nobody took control of it yet, offer it to ghosts. addtimer(CALLBACK(src, .proc/CheckFaction), 20) addtimer(CALLBACK(src, .proc/announcetoghosts), 30) - var/datum/atom_hud/U = huds[DATA_HUD_MEDICAL_ADVANCED] + var/datum/atom_hud/U = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] U.add_hud_to(src) /mob/living/simple_animal/hostile/poison/terror_spider/proc/announcetoghosts() @@ -292,7 +292,7 @@ var/global/list/ts_spiderling_list = list() notify_ghosts("[src] has appeared in [get_area(src)].", enter_link = "(Click to control)", source = src, alert_overlay = alert_overlay, action = NOTIFY_ATTACK) /mob/living/simple_animal/hostile/poison/terror_spider/Destroy() - ts_spiderlist -= src + GLOB.ts_spiderlist -= src handle_dying() return ..() @@ -322,12 +322,12 @@ var/global/list/ts_spiderling_list = list() /mob/living/simple_animal/hostile/poison/terror_spider/proc/handle_dying() if(!hasdied) hasdied = 1 - ts_count_dead++ - ts_death_last = world.time + GLOB.ts_count_dead++ + GLOB.ts_death_last = world.time if(spider_awaymission) - ts_count_alive_awaymission-- + GLOB.ts_count_alive_awaymission-- else - ts_count_alive_station-- + GLOB.ts_count_alive_station-- /mob/living/simple_animal/hostile/poison/terror_spider/death(gibbed) if(can_die()) @@ -352,7 +352,7 @@ var/global/list/ts_spiderling_list = list() . = ..() /mob/living/simple_animal/hostile/poison/terror_spider/proc/msg_terrorspiders(msgtext) - for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in ts_spiderlist) + for(var/mob/living/simple_animal/hostile/poison/terror_spider/T in GLOB.ts_spiderlist) if(T.stat != DEAD) to_chat(T, "TerrorSense: [msgtext]") diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index d159f8160c6..41786017ea2 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -79,7 +79,7 @@ var/obj/desired_perches = list(/obj/structure/computerframe, /obj/structure/displaycase, \ /obj/structure/filingcabinet, /obj/machinery/teleport, \ /obj/machinery/suit_storage_unit, /obj/machinery/clonepod, \ - /obj/machinery/dna_scannernew, /obj/machinery/telecomms, \ + /obj/machinery/dna_scannernew, /obj/machinery/tcomms, \ /obj/machinery/nuclearbomb, /obj/machinery/particle_accelerator, \ /obj/machinery/recharge_station, /obj/machinery/smartfridge, \ /obj/machinery/computer) @@ -357,7 +357,7 @@ //Wander around aimlessly. This will help keep the loops from searches down //and possibly move the mob into a new are in view of something they can use if(prob(90)) - step(src, pick(cardinal)) + step(src, pick(GLOB.cardinal)) return if(!held_item && !parrot_perch) //If we've got nothing to do.. look for something to do. @@ -374,11 +374,11 @@ return return - if(parrot_interest && parrot_interest in view(src)) + if(parrot_interest && (parrot_interest in view(src))) parrot_state = PARROT_SWOOP | PARROT_STEAL return - if(parrot_perch && parrot_perch in view(src)) + if(parrot_perch && (parrot_perch in view(src))) parrot_state = PARROT_SWOOP | PARROT_RETURN return diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 7665d20f932..ada8ed9896b 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -145,7 +145,7 @@ /mob/living/simple_animal/updatehealth(reason = "none given") ..(reason) health = Clamp(health, 0, maxHealth) - med_hud_set_status() + med_hud_set_health() /mob/living/simple_animal/StartResting(updating = 1) ..() @@ -166,12 +166,14 @@ /mob/living/simple_animal/update_stat(reason = "none given") if(status_flags & GODMODE) return - - ..(reason) if(stat != DEAD) - if(health < 1) + if(health <= 0) death() create_debug_log("died of damage, trigger reason: [reason]") + else + WakeUp() + create_debug_log("woke up, trigger reason: [reason]") + med_hud_set_status() /mob/living/simple_animal/proc/handle_automated_action() set waitfor = FALSE @@ -184,7 +186,7 @@ turns_since_move++ if(turns_since_move >= turns_per_move) if(!(stop_automated_movement_when_pulled && pulledby)) //Soma animals don't move when pulled - var/anydir = pick(cardinal) + var/anydir = pick(GLOB.cardinal) if(Process_Spacemove(anydir)) Move(get_step(src,anydir), anydir) turns_since_move = 0 @@ -594,7 +596,7 @@ toggle_ai(initial(AIStatus)) /mob/living/simple_animal/proc/add_collar(obj/item/clothing/accessory/petcollar/P, mob/user) - if(QDELETED(P) || pcollar) + if(!istype(P) || QDELETED(P) || pcollar) return if(user && !user.unEquip(P)) return @@ -609,7 +611,7 @@ real_name = P.tagname /mob/living/simple_animal/regenerate_icons() + cut_overlays() if(pcollar && collar_type) - cut_overlays() add_overlay("[collar_type]collar") add_overlay("[collar_type]tag") diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index deb9981645f..4e1aee2c822 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -314,7 +314,7 @@ for(var/mob/living/L in view(7,src)) - if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs + if(L.stat == DEAD) // Ignore dead mobs continue if(L in Friends) // No eating friends! @@ -368,7 +368,7 @@ if (holding_still) holding_still = max(holding_still - hungry, 0) else if(canmove && isturf(loc) && prob(50)) - step(src, pick(cardinal)) + step(src, pick(GLOB.cardinal)) else if(holding_still) @@ -376,7 +376,7 @@ else if (docile && pulledby) holding_still = 10 else if(canmove && isturf(loc) && prob(33)) - step(src, pick(cardinal)) + step(src, pick(GLOB.cardinal)) else if(!AIproc) INVOKE_ASYNC(src, .proc/AIprocess) diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 339240af529..8c7d14b23f4 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -121,7 +121,7 @@ set_colour(pick(slime_colours)) /mob/living/simple_animal/slime/regenerate_icons() - cut_overlays() + ..() var/icon_text = "[colour] [is_adult ? "adult" : "baby"] slime" icon_dead = "[icon_text] dead" if(stat != DEAD) @@ -130,7 +130,6 @@ add_overlay("aslime-[mood]") else icon_state = icon_dead - ..() /mob/living/simple_animal/slime/movement_delay() if(bodytemperature >= 330.23) // 135 F or 57.08 C @@ -157,7 +156,7 @@ . += config.slime_delay -/mob/living/simple_animal/slime/handle_hud_icons_health() +/mob/living/simple_animal/slime/update_health_hud() if(hud_used) if(!client) return @@ -262,7 +261,7 @@ Feedon(Food) return ..() -/mob/living/simple_animal/slime/unEquip(obj/item/I) +/mob/living/simple_animal/slime/unEquip(obj/item/I, force) return /mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) diff --git a/code/modules/mob/living/simple_animal/tribbles.dm b/code/modules/mob/living/simple_animal/tribbles.dm index b916fa801f0..e5ebfb2ff61 100644 --- a/code/modules/mob/living/simple_animal/tribbles.dm +++ b/code/modules/mob/living/simple_animal/tribbles.dm @@ -1,4 +1,4 @@ -var/global/totaltribbles = 0 //global variable so it updates for all tribbles, not just the new one being made. +GLOBAL_VAR_INIT(totaltribbles, 0) //global variable so it updates for all tribbles, not just the new one being made. /mob/living/simple_animal/tribble @@ -35,7 +35,7 @@ var/global/totaltribbles = 0 //global variable so it updates for all tribbles, //random pixel offsets so they cover the floor src.pixel_x = rand(-5.0, 5) src.pixel_y = rand(-5.0, 5) - totaltribbles += 1 + GLOB.totaltribbles += 1 /mob/living/simple_animal/tribble/attack_hand(mob/user as mob) @@ -60,8 +60,7 @@ var/global/totaltribbles = 0 //global variable so it updates for all tribbles, /mob/living/simple_animal/tribble/proc/procreate() - ..() - if(totaltribbles <= maxtribbles) + if(GLOB.totaltribbles <= maxtribbles) for(var/mob/living/simple_animal/tribble/F in src.loc) if(!F || F == src) new /mob/living/simple_animal/tribble(src.loc) @@ -84,7 +83,7 @@ var/global/totaltribbles = 0 //global variable so it updates for all tribbles, . = ..(gibbed) if(!.) return FALSE - totaltribbles -= 1 + GLOB.totaltribbles -= 1 //||Item version of the trible || diff --git a/code/modules/mob/living/stat_states.dm b/code/modules/mob/living/stat_states.dm index 57fd6e17cbc..eab88b5ec4d 100644 --- a/code/modules/mob/living/stat_states.dm +++ b/code/modules/mob/living/stat_states.dm @@ -7,6 +7,7 @@ else if(stat == UNCONSCIOUS) return 0 create_attack_log("Fallen unconscious at [atom_loc_line(get_turf(src))]") + add_attack_logs(src, null, "Fallen unconscious", ATKLOG_ALL) log_game("[key_name(src)] fell unconscious at [atom_loc_line(get_turf(src))]") stat = UNCONSCIOUS if(updating) @@ -22,6 +23,7 @@ else if(stat == CONSCIOUS) return 0 create_attack_log("Woken up at [atom_loc_line(get_turf(src))]") + add_attack_logs(src, null, "Woken up", ATKLOG_ALL) log_game("[key_name(src)] woke up at [atom_loc_line(get_turf(src))]") stat = CONSCIOUS if(updating) @@ -45,10 +47,11 @@ if(!can_be_revived()) return 0 create_attack_log("Came back to life at [atom_loc_line(get_turf(src))]") + add_attack_logs(src, null, "Came back to life", ATKLOG_ALL) log_game("[key_name(src)] came back to life at [atom_loc_line(get_turf(src))]") stat = CONSCIOUS GLOB.dead_mob_list -= src - GLOB.living_mob_list += src + GLOB.alive_mob_list += src if(mind) GLOB.respawnable_list -= src timeofdeath = null diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 2e5c6e66137..7cd2b4414f7 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -125,10 +125,6 @@ var/stuttering = 0 var/weakened = 0 -/mob/living - // Bitfields - var/disabilities = 0 - // RESTING /mob/living/proc/StartResting(updating = 1) @@ -467,90 +463,90 @@ // Blind /mob/living/proc/BecomeBlind(updating = TRUE) - var/val_change = !(disabilities & BLIND) + var/val_change = !(BLINDNESS in mutations) . = val_change ? STATUS_UPDATE_BLIND : STATUS_UPDATE_NONE - disabilities |= BLIND + mutations |= BLINDNESS if(val_change && updating) update_blind_effects() /mob/living/proc/CureBlind(updating = TRUE) - var/val_change = !!(disabilities & BLIND) + var/val_change = !!(BLINDNESS in mutations) . = val_change ? STATUS_UPDATE_BLIND : STATUS_UPDATE_NONE - disabilities &= ~BLIND + mutations -= BLINDNESS if(val_change && updating) - CureIfHasDisability(BLINDBLOCK) + CureIfHasDisability(GLOB.blindblock) update_blind_effects() // Coughing /mob/living/proc/BecomeCoughing() - disabilities |= COUGHING + mutations |= COUGHING /mob/living/proc/CureCoughing() - disabilities &= ~COUGHING - CureIfHasDisability(COUGHBLOCK) + mutations -= COUGHING + CureIfHasDisability(GLOB.coughblock) // Deaf /mob/living/proc/BecomeDeaf() - disabilities |= DEAF + mutations |= DEAF /mob/living/proc/CureDeaf() - disabilities &= ~DEAF - CureIfHasDisability(DEAFBLOCK) + mutations -= DEAF + CureIfHasDisability(GLOB.deafblock) // Epilepsy /mob/living/proc/BecomeEpilepsy() - disabilities |= EPILEPSY + mutations |= EPILEPSY /mob/living/proc/CureEpilepsy() - disabilities &= ~EPILEPSY - CureIfHasDisability(EPILEPSYBLOCK) + mutations -= EPILEPSY + CureIfHasDisability(GLOB.epilepsyblock) // Mute /mob/living/proc/BecomeMute() - disabilities |= MUTE + mutations |= MUTE /mob/living/proc/CureMute() - disabilities &= ~MUTE - CureIfHasDisability(MUTEBLOCK) + mutations -= MUTE + CureIfHasDisability(GLOB.muteblock) // Nearsighted /mob/living/proc/BecomeNearsighted(updating = TRUE) - var/val_change = !(disabilities & NEARSIGHTED) + var/val_change = !(NEARSIGHTED in mutations) . = val_change ? STATUS_UPDATE_NEARSIGHTED : STATUS_UPDATE_NONE - disabilities |= NEARSIGHTED + mutations |= NEARSIGHTED if(val_change && updating) update_nearsighted_effects() /mob/living/proc/CureNearsighted(updating = TRUE) - var/val_change = !!(disabilities & NEARSIGHTED) + var/val_change = !!(NEARSIGHTED in mutations) . = val_change ? STATUS_UPDATE_NEARSIGHTED : STATUS_UPDATE_NONE - disabilities &= ~NEARSIGHTED + mutations -= NEARSIGHTED if(val_change && updating) - CureIfHasDisability(GLASSESBLOCK) + CureIfHasDisability(GLOB.glassesblock) update_nearsighted_effects() // Nervous /mob/living/proc/BecomeNervous() - disabilities |= NERVOUS + mutations |= NERVOUS /mob/living/proc/CureNervous() - disabilities &= ~NERVOUS - CureIfHasDisability(NERVOUSBLOCK) + mutations -= NERVOUS + CureIfHasDisability(GLOB.nervousblock) // Tourettes /mob/living/proc/BecomeTourettes() - disabilities |= TOURETTES + mutations |= TOURETTES /mob/living/proc/CureTourettes() - disabilities &= ~TOURETTES - CureIfHasDisability(TWITCHBLOCK) + mutations -= TOURETTES + CureIfHasDisability(GLOB.twitchblock) /mob/living/proc/CureIfHasDisability(block) if(dna && dna.GetSEState(block)) diff --git a/code/modules/mob/living/update_status.dm b/code/modules/mob/living/update_status.dm index 20cc969119f..8ef178918b4 100644 --- a/code/modules/mob/living/update_status.dm +++ b/code/modules/mob/living/update_status.dm @@ -25,7 +25,7 @@ clear_alert("high") /mob/living/update_nearsighted_effects() - if(disabilities & NEARSIGHTED) + if(NEARSIGHTED in mutations) overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1) else clear_fullscreen("nearsighted") @@ -41,17 +41,17 @@ // Whether the mob can hear things /mob/living/can_hear() - . = !(disabilities & DEAF) + . = !(DEAF in mutations) // Whether the mob is able to see // `information_only` is for stuff that's purely informational - like blindness overlays // This flag exists because certain things like angel statues expect this to be false for dead people /mob/living/has_vision(information_only = FALSE) - return (information_only && stat == DEAD) || !(eye_blind || (disabilities & BLIND) || stat) + return (information_only && stat == DEAD) || !(eye_blind || (BLINDNESS in mutations) || stat) // Whether the mob is capable of talking /mob/living/can_speak() - if(!(silent || (disabilities & MUTE))) + if(!(silent || (MUTE in mutations))) if(is_muzzled()) var/obj/item/clothing/mask/muzzle/M = wear_mask if(M.mute >= MUZZLE_MUTE_MUFFLE) @@ -65,8 +65,14 @@ return !(IsWeakened() || paralysis || stat || (status_flags & FAKEDEATH)) // Whether the mob is capable of actions or not -/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, ignore_lying = FALSE) - if(stat || paralysis || stunned || IsWeakened() || (!ignore_restraints && restrained()) || (!ignore_lying && lying)) +/mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, ignore_lying = FALSE, list/extra_checks = list(), use_default_checks = TRUE) + // By default, checks for weakness and stunned get added to the extra_checks list. + // Setting `use_default_checks` to FALSE means that you don't want it checking for these statuses or you are supplying your own checks. + if(use_default_checks) + extra_checks += CALLBACK(src, /mob.proc/IsWeakened) + extra_checks += CALLBACK(src, /mob.proc/IsStunned) + + if(stat || paralysis || (!ignore_restraints && restrained()) || (!ignore_lying && lying) || check_for_true_callbacks(extra_checks)) return TRUE // wonderful proc names, I know - used to check whether the blur overlay @@ -106,22 +112,6 @@ /mob/living/proc/update_stamina() return -/mob/living/update_stat(reason = "None given") - if(status_flags & GODMODE) - return - if(stat != DEAD) - if(health <= HEALTH_THRESHOLD_DEAD && check_death_method()) - death() - create_debug_log("died of damage, trigger reason: [reason]") - else if(paralysis || status_flags & FAKEDEATH) - if(stat == CONSCIOUS) - KnockOut() - create_debug_log("fell unconscious, trigger reason: [reason]") - else - if(stat == UNCONSCIOUS) - WakeUp() - create_debug_log("woke up, trigger reason: [reason]") - /mob/living/vv_edit_var(var_name, var_value) . = ..() switch(var_name) diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index ada7669a520..5345bda5b94 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -5,6 +5,7 @@ computer_id = client.computer_id log_access_in(client) create_attack_log("Logged in at [atom_loc_line(get_turf(src))]") + create_log(MISC_LOG, "Logged in") if(config.log_access) for(var/mob/M in GLOB.player_list) if(M == src) continue @@ -51,7 +52,7 @@ verbs += /client/proc/readmin //Clear ability list and update from mob. - client.verbs -= ability_verbs + client.verbs -= GLOB.ability_verbs if(abilities) client.verbs |= abilities diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index 1e019d16529..8bdb0d89332 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -4,10 +4,11 @@ GLOB.player_list -= src log_access_out(src) create_attack_log("Logged out at [atom_loc_line(get_turf(src))]") + create_log(MISC_LOG, "Logged out") // `holder` is nil'd out by now, so we check the `admin_datums` array directly //Only report this stuff if we are currently playing. - if(admin_datums[ckey] && SSticker && SSticker.current_state == GAME_STATE_PLAYING) - var/datum/admins/temp_admin = admin_datums[ckey] + if(GLOB.admin_datums[ckey] && SSticker && SSticker.current_state == GAME_STATE_PLAYING) + var/datum/admins/temp_admin = GLOB.admin_datums[ckey] // Triggers on people with banhammer power only - no mentors tripping the alarm if(temp_admin.rights & R_BAN) message_admins("Admin logout: [key_name_admin(src)]") diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 65d2cb4788e..46f80bc1919 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1,7 +1,7 @@ /mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game. GLOB.mob_list -= src GLOB.dead_mob_list -= src - GLOB.living_mob_list -= src + GLOB.alive_mob_list -= src focus = null QDEL_NULL(hud_used) if(mind && mind.current == src) @@ -9,9 +9,6 @@ mobspellremove(src) QDEL_LIST(viruses) ghostize() - for(var/mob/dead/observer/M in following_mobs) - M.following = null - following_mobs = null QDEL_LIST_ASSOC_VAL(tkgrabbed_objects) for(var/I in tkgrabbed_objects) qdel(tkgrabbed_objects[I]) @@ -22,6 +19,7 @@ for(var/datum/alternate_appearance/AA in viewing_alternate_appearances) AA.viewers -= src viewing_alternate_appearances = null + logs.Cut() ..() return QDEL_HINT_HARDDEL @@ -30,7 +28,7 @@ if(stat == DEAD) GLOB.dead_mob_list += src else - GLOB.living_mob_list += src + GLOB.alive_mob_list += src set_focus(src) prepare_huds() ..() @@ -44,6 +42,7 @@ hud_list[hud] = list() else var/image/I = image('icons/mob/hud.dmi', src, "") + I.appearance_flags = RESET_COLOR | RESET_TRANSFORM hud_list[hud] = I /mob/proc/generate_name() @@ -173,21 +172,6 @@ /mob/proc/movement_delay() return 0 -/mob/proc/Life(seconds, times_fired) - set waitfor = FALSE - if(forced_look) - if(!isnum(forced_look)) - var/atom/A = locateUID(forced_look) - if(istype(A)) - var/view = client ? client.view : world.view - if(get_dist(src, A) > view || !(src in viewers(view, A))) - forced_look = null - to_chat(src, "Your direction target has left your view, you are no longer facing anything.") - return - setDir() -// handle_typing_indicator() - return - //This proc is called whenever someone clicks an inventory ui slot. /mob/proc/attack_ui(slot) var/obj/item/W = get_active_hand() @@ -203,10 +187,10 @@ src:update_hair() src:update_fhair() -/mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1, redraw_mob = 1) - if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning, redraw_mob)) +/mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1) + if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning)) return 1 - else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning, redraw_mob)) + else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning)) return 1 return 0 @@ -215,8 +199,7 @@ //This is a SAFE proc. Use this instead of equip_to_slot()! //set del_on_fail to have it delete W if it fails to equip //set disable_warning to disable the 'you are unable to equip that' warning. -//unset redraw_mob to prevent the mob from being redrawn at the end. -/mob/proc/equip_to_slot_if_possible(obj/item/W as obj, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1) +/mob/proc/equip_to_slot_if_possible(obj/item/W, slot, del_on_fail = 0, disable_warning = 0) if(!istype(W)) return 0 if(!W.mob_can_equip(src, slot, disable_warning)) @@ -228,17 +211,17 @@ return 0 - equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail. + equip_to_slot(W, slot) //This proc should not ever fail. return 1 //This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't eqip need to be done before! Use mob_can_equip() for that task. //In most cases you will want to use equip_to_slot_if_possible() -/mob/proc/equip_to_slot(obj/item/W as obj, slot) +/mob/proc/equip_to_slot(obj/item/W, slot) return //This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the rounds tarts and when events happen and such. /mob/proc/equip_to_slot_or_del(obj/item/W as obj, slot) - return equip_to_slot_if_possible(W, slot, 1, 1, 0) + return equip_to_slot_if_possible(W, slot, TRUE, TRUE) // Convinience proc. Collects crap that fails to equip either onto the mob's back, or drops it. // Used in job equipping so shit doesn't pile up at the start loc. @@ -261,7 +244,7 @@ //The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot. -var/list/slot_equipment_priority = list( \ +GLOBAL_LIST_INIT(slot_equipment_priority, list( \ slot_back,\ slot_wear_pda,\ slot_wear_id,\ @@ -279,17 +262,17 @@ var/list/slot_equipment_priority = list( \ slot_tie,\ slot_l_store,\ slot_r_store\ - ) + )) //puts the item "W" into an appropriate slot in a human's inventory //returns 0 if it cannot, 1 if successful /mob/proc/equip_to_appropriate_slot(obj/item/W) if(!istype(W)) return 0 - for(var/slot in slot_equipment_priority) + for(var/slot in GLOB.slot_equipment_priority) if(istype(W,/obj/item/storage/) && slot == slot_head) // Storage items should be put on the belt before the head continue - if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //del_on_fail = 0; disable_warning = 0; redraw_mob = 1 + if(equip_to_slot_if_possible(W, slot, FALSE, TRUE)) //del_on_fail = 0; disable_warning = 0 return 1 return 0 @@ -297,7 +280,7 @@ var/list/slot_equipment_priority = list( \ /mob/proc/check_for_open_slot(obj/item/W) if(!istype(W)) return 0 var/openslot = 0 - for(var/slot in slot_equipment_priority) + for(var/slot in GLOB.slot_equipment_priority) if(W.mob_check_equip(src, slot, 1) == 1) openslot = 1 break @@ -413,8 +396,6 @@ var/list/slot_equipment_priority = list( \ if(slot_w_uniform) if( !(slot_flags & SLOT_ICLOTHING) ) return 0 - if((FAT in H.mutations) && !(flags_size & ONESIZEFITSALL)) - return 0 if(H.w_uniform) if(!(H.w_uniform.flags & NODROP)) return 2 @@ -528,12 +509,6 @@ var/list/slot_equipment_priority = list( \ update_pipe_vision() /mob/dead/reset_perspective(atom/A) - if(client) - if(ismob(client.eye) && (client.eye != src)) - // Note to self: Use `client.eye` for ghost following in place - // of periodic ghost updates - var/mob/target = client.eye - target.following_mobs -= src . = ..() if(.) // Allows sharing HUDs with ghosts @@ -741,7 +716,7 @@ var/list/slot_equipment_priority = list( \ set name = "Respawn" set category = "OOC" - if(!abandon_allowed) + if(!GLOB.abandon_allowed) to_chat(usr, "Respawning is disabled.") return @@ -840,10 +815,6 @@ var/list/slot_equipment_priority = list( \ if(client && mob_eye) client.eye = mob_eye - if(is_admin) - client.adminobs = 1 - if(mob_eye == client.mob || client.eye == client.mob) - client.adminobs = 0 /mob/verb/cancel_camera() set name = "Cancel Camera View" @@ -963,8 +934,8 @@ var/list/slot_equipment_priority = list( \ for(var/obj/effect/proc_holder/spell/S in mind.spell_list) add_spell_to_statpanel(S) - - if(is_admin(src)) + // Allow admins + PR reviewers to VIEW the panel. Doesnt mean they can click things. + if(is_admin(src) || check_rights(R_VIEWRUNTIMES, FALSE)) if(statpanel("MC")) //looking at that panel var/turf/T = get_turf(client.eye) stat("Location:", COORD(T)) @@ -1093,7 +1064,7 @@ var/list/slot_equipment_priority = list( \ if((usr in GLOB.respawnable_list) && (stat==2 || istype(usr,/mob/dead/observer))) var/list/creatures = list("Mouse") - for(var/mob/living/L in GLOB.living_mob_list) + for(var/mob/living/L in GLOB.alive_mob_list) if(safe_respawn(L.type) && L.stat!=2) if(!L.key) creatures += L @@ -1118,10 +1089,10 @@ var/list/slot_equipment_priority = list( \ /mob/proc/become_mouse() var/timedifference = world.time - client.time_died_as_mouse - if(client.time_died_as_mouse && timedifference <= mouse_respawn_time * 600) + if(client.time_died_as_mouse && timedifference <= GLOB.mouse_respawn_time * 600) var/timedifference_text - timedifference_text = time2text(mouse_respawn_time * 600 - timedifference,"mm:ss") - to_chat(src, "You may only spawn again as a mouse more than [mouse_respawn_time] minutes after your death. You have [timedifference_text] left.") + timedifference_text = time2text(GLOB.mouse_respawn_time * 600 - timedifference,"mm:ss") + to_chat(src, "You may only spawn again as a mouse more than [GLOB.mouse_respawn_time] minutes after your death. You have [timedifference_text] left.") return //find a viable mouse candidate @@ -1257,14 +1228,20 @@ var/list/slot_equipment_priority = list( \ return list() //must return list or IGNORE_ACCESS /mob/proc/create_attack_log(text, collapse = TRUE) - LAZYINITLIST(attack_log) - create_log_in_list(attack_log, text, collapse, last_log) + LAZYINITLIST(attack_log_old) + create_log_in_list(attack_log_old, text, collapse, last_log) last_log = world.timeofday /mob/proc/create_debug_log(text, collapse = TRUE) LAZYINITLIST(debug_log) create_log_in_list(debug_log, text, collapse, world.timeofday) +/mob/proc/create_log(log_type, what, target = null, turf/where = get_turf(src)) + LAZYINITLIST(logs[log_type]) + var/list/log_list = logs[log_type] + var/datum/log_record/record = new(log_type, src, what, target, where, world.time) + log_list.Add(record) + /proc/create_log_in_list(list/target, text, collapse = TRUE, last_log)//forgive me code gods for this shitcode proc //this proc enables lovely stuff like an attack log that looks like this: "[18:20:29-18:20:45]21x John Smith attacked Andrew Jackson with a crowbar." //That makes the logs easier to read, but because all of this is stored in strings, weird things have to be used to get it all out. diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 5d63b7b4ad9..dc77610b97e 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -33,15 +33,17 @@ var/computer_id = null var/lastattacker = null var/lastattacked = null - var/list/attack_log = list( ) + var/list/attack_log_old = list( ) var/list/debug_log = null + + var/list/logs = list() // Logs for each log type defined in __DEFINES/logs.dm + var/last_log = 0 var/obj/machinery/machine = null var/other_mobs = null var/memory = "" var/next_move = null var/notransform = null //Carbon - var/other = 0.0 var/hand = null var/real_name = null var/flavor_text = "" @@ -60,12 +62,10 @@ var/name_archive //For admin things like possession var/timeofdeath = 0.0//Living - var/cpr_time = 1.0//Carbon var/bodytemperature = 310.055 //98.7 F var/flying = 0 - var/charges = 0.0 var/nutrition = NUTRITION_LEVEL_FED + 50 //Carbon var/satiety = 0 //Carbon var/hunger_drain = HUNGER_FACTOR // how quickly the mob gets hungry; largely utilized by species. @@ -88,8 +88,6 @@ var/obj/item/storage/s_active = null//Carbon var/obj/item/clothing/mask/wear_mask = null//Carbon - var/seer = 0 //for cult//Carbon, probably Human - var/datum/hud/hud_used = null hud_possible = list(SPECIALROLE_HUD) @@ -162,10 +160,7 @@ var/atom/movable/remote_control //Calls relaymove() to whatever it is - var/remote_view = 0 // Set to 1 to prevent view resets on Life - var/obj/control_object //Used by admins to possess objects. All mobs should have this var - var/datum/visibility_interface/visibility_interface = null // used by the visibility system to provide an interface for the visibility networks //Whether or not mobs can understand other mobtypes. These stay in /mob so that ghosts can hear everything. var/universal_speak = 0 // Set to 1 to enable the mob to speak to everyone -- TLE diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index a894ad7cd07..df2a39c0930 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -358,7 +358,7 @@ proc/muffledspeech(phrase) return 0 //converts intent-strings into numbers and back -var/list/intents = list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM) +GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM)) /proc/intent_numeric(argument) if(istext(argument)) switch(argument) @@ -521,11 +521,11 @@ var/list/intents = list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM) alert_overlay.plane = FLOAT_PLANE A.overlays += alert_overlay -/mob/proc/switch_to_camera(var/obj/machinery/camera/C) - if(!C.can_use() || stat || (get_dist(C, src) > 1 || machine != src || !has_vision() || !canmove)) - return 0 +/mob/proc/switch_to_camera(obj/machinery/camera/C) + if(!C.can_use() || incapacitated() || (get_dist(C, src) > 1 || machine != src || !has_vision())) + return FALSE check_eye(src) - return 1 + return TRUE /mob/proc/rename_character(oldname, newname) if(!newname) @@ -539,7 +539,7 @@ var/list/intents = list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM) if(oldname) //update the datacore records! This is goig to be a bit costly. - for(var/list/L in list(data_core.general,data_core.medical,data_core.security,data_core.locked)) + for(var/list/L in list(GLOB.data_core.general, GLOB.data_core.medical, GLOB.data_core.security, GLOB.data_core.locked)) for(var/datum/data/record/R in L) if(R.fields["name"] == oldname) R.fields["name"] = newname diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 48f149fa096..471ddc42557 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -143,8 +143,10 @@ move_delay = world.time mob.last_movement = world.time + delay = TICKS2DS(-round(-(DS2TICKS(delay)))) //Rounded to the next tick in equivalent ds + if(locate(/obj/item/grab, mob)) - move_delay = max(move_delay, world.time + 7) + delay += 7 var/list/L = mob.ret_grab() if(istype(L, /list)) if(L.len == 2) @@ -153,14 +155,14 @@ if(M) if((get_dist(mob, M) <= 1 || M.loc == mob.loc)) var/turf/prev_loc = mob.loc - . = ..() + . = mob.SelfMove(n, direct, delay) if(M && isturf(M.loc)) // Mob may get deleted during parent call var/diag = get_dir(mob, M) if((diag - 1) & diag) else diag = null if((get_dist(mob, M) > 1 || diag)) - step(M, get_dir(M.loc, prev_loc)) + M.Move(prev_loc, get_dir(M.loc, prev_loc), delay) else for(var/mob/M in L) M.other_mobs = 1 @@ -168,17 +170,15 @@ M.animate_movement = 3 for(var/mob/M in L) spawn(0) - step(M, direct) - return + M.Move(get_step(M,direct), direct, delay) spawn(1) M.other_mobs = null M.animate_movement = 2 - return else if(mob.confused) var/newdir = 0 if(mob.confused > 40) - newdir = pick(alldirs) + newdir = pick(GLOB.alldirs) else if(prob(mob.confused * 1.5)) newdir = angle2dir(dir2angle(direct) + pick(90, -90)) else if(prob(mob.confused * 3)) @@ -186,19 +186,22 @@ if(newdir) direct = newdir n = get_step(mob, direct) - - . = ..() + + . = mob.SelfMove(n, direct, delay) mob.setDir(direct) + if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully + delay = mob.movement_delay() * 2 //Will prevent mob diagonal moves from smoothing accurately, sadly + + move_delay += delay + for(var/obj/item/grab/G in mob) if(G.state == GRAB_NECK) mob.setDir(angle2dir((dir2angle(direct) + 202.5) % 365)) G.adjust_position() for(var/obj/item/grab/G in mob.grabbed_by) G.adjust_position() - if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully - delay = mob.movement_delay() * 2 - move_delay += delay + moving = 0 if(mob && .) if(mob.throwing) @@ -208,8 +211,8 @@ O.on_mob_move(direct, mob) - - +/mob/proc/SelfMove(turf/n, direct, movetime) + return Move(n, direct, movetime) ///Process_Grab() ///Called by client/Move() diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm index d8e6a239a9a..7a0462fd00f 100644 --- a/code/modules/mob/new_player/login.dm +++ b/code/modules/mob/new_player/login.dm @@ -1,15 +1,15 @@ /mob/new_player/Login() update_Login_details() //handles setting lastKnownIP and computer_id for use by the ban systems as well as checking for multikeying - if(join_motd) - to_chat(src, "
    [join_motd]
    ") + if(GLOB.join_motd) + to_chat(src, "
    [GLOB.join_motd]
    ") if(!mind) mind = new /datum/mind(key) mind.active = 1 mind.current = src - if(length(newplayer_start)) - loc = pick(newplayer_start) + if(length(GLOB.newplayer_start)) + loc = pick(GLOB.newplayer_start) else loc = locate(1,1,1) lastarea = loc @@ -29,11 +29,11 @@ spawn(30) // Annoy the player with polls. establish_db_connection() - if(dbcon.IsConnected() && client && client.can_vote()) + if(GLOB.dbcon.IsConnected() && client && client.can_vote()) var/isadmin = 0 if(client && client.holder) isadmin = 1 - var/DBQuery/query = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")") query.Execute() var/newpoll = 0 while(query.NextRow()) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 6c9c04fded8..af3d439df59 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -27,11 +27,11 @@ return TRUE establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) tos_consent = TRUE return TRUE - var/DBQuery/query = dbcon.NewQuery("SELECT * FROM [format_table_name("privacy")] WHERE ckey='[src.ckey]' AND consent=1") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT * FROM [format_table_name("privacy")] WHERE ckey='[src.ckey]' AND consent=1") query.Execute() while(query.NextRow()) tos_consent = TRUE @@ -80,11 +80,11 @@ if(!IsGuestKey(src.key)) establish_db_connection() - if(dbcon.IsConnected() && client.can_vote()) + if(GLOB.dbcon.IsConnected() && client.can_vote()) var/isadmin = 0 if(src.client && src.client.holder) isadmin = 1 - var/DBQuery/query = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")") query.Execute() var/newpoll = 0 while(query.NextRow()) @@ -111,13 +111,13 @@ stat("Game Mode:", "Secret") else if(SSticker.hide_mode == 0) - stat("Game Mode:", "[master_mode]") // Old setting for showing the game mode + stat("Game Mode:", "[GLOB.master_mode]") // Old setting for showing the game mode else stat("Game Mode: ", "Secret") - if((SSticker.current_state == GAME_STATE_PREGAME) && going) + if((SSticker.current_state == GAME_STATE_PREGAME) && SSticker.ticker_going) stat("Time To Start:", round(SSticker.pregame_timeleft/10)) - if((SSticker.current_state == GAME_STATE_PREGAME) && !going) + if((SSticker.current_state == GAME_STATE_PREGAME) && !SSticker.ticker_going) stat("Time To Start:", "DELAYED") if(SSticker.current_state == GAME_STATE_PREGAME) @@ -143,7 +143,7 @@ if(href_list["consent_signed"]) var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES ('[ckey]', '[sqltime]', 1)") + var/DBQuery/query = GLOB.dbcon.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES ('[ckey]', '[sqltime]', 1)") query.Execute() src << browse(null, "window=privacy_consent") tos_consent = 1 @@ -152,7 +152,7 @@ tos_consent = 0 to_chat(usr, "You must consent to the terms of service before you can join!") var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss") - var/DBQuery/query = dbcon.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES ('[ckey]', '[sqltime]', 0)") + var/DBQuery/query = GLOB.dbcon.NewQuery("REPLACE INTO [format_table_name("privacy")] (ckey, datetime, consent) VALUES ('[ckey]', '[sqltime]', 0)") query.Execute() if(href_list["show_preferences"]) @@ -232,7 +232,7 @@ if(href_list["SelectedJob"]) - if(!enter_allowed) + if(!GLOB.enter_allowed) to_chat(usr, "There is an administrative lock on entering the game!") return @@ -304,7 +304,7 @@ if(!SSticker || SSticker.current_state != GAME_STATE_PLAYING) to_chat(usr, "The round is either not ready, or has already finished...") return 0 - if(!enter_allowed) + if(!GLOB.enter_allowed) to_chat(usr, "There is an administrative lock on entering the game!") return 0 if(!IsJobAvailable(rank)) @@ -338,25 +338,25 @@ if(IsAdminJob(rank)) if(IsERTSpawnJob(rank)) - character.loc = pick(ertdirector) + character.loc = pick(GLOB.ertdirector) else if(IsSyndicateCommand(rank)) - character.loc = pick(syndicateofficer) + character.loc = pick(GLOB.syndicateofficer) else - character.forceMove(pick(aroomwarp)) + character.forceMove(pick(GLOB.aroomwarp)) join_message = "has arrived" else if(spawning_at) - S = spawntypes[spawning_at] + S = GLOB.spawntypes[spawning_at] if(S && istype(S)) if(S.check_job_spawning(rank)) character.forceMove(pick(S.turfs)) join_message = S.msg else to_chat(character, "Your chosen spawnpoint ([S.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead.") - character.forceMove(pick(latejoin)) + character.forceMove(pick(GLOB.latejoin)) join_message = "has arrived on the station" else - character.forceMove(pick(latejoin)) + character.forceMove(pick(GLOB.latejoin)) join_message = "has arrived on the station" character.lastarea = get_area(loc) @@ -375,7 +375,7 @@ else SSticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn if(!IsAdminJob(rank)) - data_core.manifest_inject(character) + GLOB.data_core.manifest_inject(character) AnnounceArrival(character, rank, join_message) AddEmploymentContract(character) @@ -384,7 +384,7 @@ if(GLOB.summon_magic_triggered) give_magic(character) - if(!thisjob.is_position_available() && thisjob in SSjobs.prioritized_jobs) + if(!thisjob.is_position_available() && (thisjob in SSjobs.prioritized_jobs)) SSjobs.prioritized_jobs -= thisjob qdel(src) @@ -392,7 +392,7 @@ /mob/new_player/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message) if(SSticker.current_state == GAME_STATE_PLAYING) var/ailist[] = list() - for(var/mob/living/silicon/ai/A in GLOB.living_mob_list) + for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list) ailist += A if(ailist.len) var/mob/living/silicon/ai/announcer = pick(ailist) @@ -412,11 +412,11 @@ if((character.mind.assigned_role != "Cyborg") && (character.mind.assigned_role != character.mind.special_role)) if(character.mind.role_alt_title) rank = character.mind.role_alt_title - global_announcer.autosay("[character.real_name],[rank ? " [rank]," : " visitor," ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") + GLOB.global_announcer.autosay("[character.real_name],[rank ? " [rank]," : " visitor," ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") /mob/new_player/proc/AddEmploymentContract(mob/living/carbon/human/employee) spawn(30) - for(var/C in employmentCabinets) + for(var/C in GLOB.employmentCabinets) var/obj/structure/filingcabinet/employment/employmentCabinet = C if(!employmentCabinet.virgin) employmentCabinet.addFile(employee) @@ -424,7 +424,7 @@ /mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message) if(SSticker.current_state == GAME_STATE_PLAYING) var/ailist[] = list() - for(var/mob/living/silicon/ai/A in GLOB.living_mob_list) + for(var/mob/living/silicon/ai/A in GLOB.alive_mob_list) ailist += A if(ailist.len) var/mob/living/silicon/ai/announcer = pick(ailist) @@ -436,7 +436,7 @@ if(character.mind) if(character.mind.assigned_role != character.mind.special_role) // can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc. - global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") + GLOB.global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") /mob/new_player/proc/LateChoices() var/mills = ROUND_TIME // 1/10 of a second, not real milliseconds but whatever @@ -467,15 +467,15 @@ var/num_jobs_available = 0 var/list/activePlayers = list() var/list/categorizedJobs = list( - "Command" = list(jobs = list(), titles = command_positions, color = "#aac1ee"), - "Engineering" = list(jobs = list(), titles = engineering_positions, color = "#ffd699"), - "Security" = list(jobs = list(), titles = security_positions, color = "#ff9999"), + "Command" = list(jobs = list(), titles = GLOB.command_positions, color = "#aac1ee"), + "Engineering" = list(jobs = list(), titles = GLOB.engineering_positions, color = "#ffd699"), + "Security" = list(jobs = list(), titles = GLOB.security_positions, color = "#ff9999"), "Miscellaneous" = list(jobs = list(), titles = list(), color = "#ffffff", colBreak = 1), - "Synthetic" = list(jobs = list(), titles = nonhuman_positions, color = "#ccffcc"), - "Support / Service" = list(jobs = list(), titles = service_positions, color = "#cccccc"), - "Medical" = list(jobs = list(), titles = medical_positions, color = "#99ffe6", colBreak = 1), - "Science" = list(jobs = list(), titles = science_positions, color = "#e6b3e6"), - "Supply" = list(jobs = list(), titles = supply_positions, color = "#ead4ae"), + "Synthetic" = list(jobs = list(), titles = GLOB.nonhuman_positions, color = "#ccffcc"), + "Support / Service" = list(jobs = list(), titles = GLOB.service_positions, color = "#cccccc"), + "Medical" = list(jobs = list(), titles = GLOB.medical_positions, color = "#99ffe6", colBreak = 1), + "Science" = list(jobs = list(), titles = GLOB.science_positions, color = "#e6b3e6"), + "Supply" = list(jobs = list(), titles = GLOB.supply_positions, color = "#ead4ae"), ) for(var/datum/job/job in SSjobs.occupations) if(job && IsJobAvailable(job.title) && !job.barred_by_disability(client)) @@ -495,7 +495,7 @@ else jobs += job else // Put heads at top of non-command jobs - if(job.title in command_positions) + if(job.title in GLOB.command_positions) jobs.Insert(1, job) else jobs += job @@ -584,7 +584,7 @@ /mob/new_player/proc/ViewManifest() var/dat = "" dat += "

    Crew Manifest

    " - dat += data_core.get_manifest(OOC = 1) + dat += GLOB.data_core.get_manifest(OOC = 1) src << browse(dat, "window=manifest;size=370x420;can_close=1") diff --git a/code/modules/mob/new_player/poll.dm b/code/modules/mob/new_player/poll.dm index ad73451b645..f67c53c9941 100644 --- a/code/modules/mob/new_player/poll.dm +++ b/code/modules/mob/new_player/poll.dm @@ -12,12 +12,12 @@ /client/proc/handle_player_polling() establish_db_connection() - if(dbcon.IsConnected()) + if(GLOB.dbcon.IsConnected()) var/isadmin = 0 if(holder) isadmin = 1 - var/DBQuery/select_query = dbcon.NewQuery("SELECT id, question, (id IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = '[ckey]') OR id IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = '[ckey]')) AS voted FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT id, question, (id IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = '[ckey]') OR id IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = '[ckey]')) AS voted FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime") select_query.Execute() var/output = "
    Player polls" @@ -29,7 +29,7 @@ var/color1 = "#ececec" var/color2 = "#e2e2e2" var/i = 0 - + output += "Active Polls" while(select_query.NextRow()) var/pollid = select_query.item[1] @@ -39,14 +39,14 @@ if(can_vote() && !voted) output += "[poll_player(pollid, 1)]" i++ - - // Show expired polls. Non admins can view admin polls at this stage + + // Show expired polls. Non admins can view admin polls at this stage // (just like tgstation's web interface so don't complain) - // (Also why was there no ingame interface tg not having an ingame - // interface is retarded because it cucks downstreams) - select_query = dbcon.NewQuery("SELECT id, question FROM [format_table_name("poll_question")] WHERE Now() > endtime ORDER BY id DESC") + // (Also why was there no ingame interface? tg not having an ingame + // interface is a pain in the neck because it means downstreams have to roll their own) + select_query = GLOB.dbcon.NewQuery("SELECT id, question FROM [format_table_name("poll_question")] WHERE Now() > endtime ORDER BY id DESC") select_query.Execute() - + output += "Expired Polls" while(select_query.NextRow()) var/pollid = select_query.item[1] @@ -61,9 +61,9 @@ if(pollid == -1) return establish_db_connection() - if(!dbcon.IsConnected()) + if(!GLOB.dbcon.IsConnected()) return - var/DBQuery/select_query = dbcon.NewQuery("SELECT polltype, question, adminonly, multiplechoiceoptions, starttime, endtime FROM [format_table_name("poll_question")] WHERE id = [pollid] AND endtime < Now()") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT polltype, question, adminonly, multiplechoiceoptions, starttime, endtime FROM [format_table_name("poll_question")] WHERE id = [pollid] AND endtime < Now()") select_query.Execute() var/question = "" var/polltype = "" @@ -84,15 +84,15 @@ if(!found) to_chat(src, "Poll question details not found. (Maybe the poll isn't expired yet?)") return - + if(polltype == POLLTYPE_MULTI) question += " (Choose up to [multiplechoiceoptions] options)" if(adminonly) question = "(Admin only poll) " + question - + var output = "" if(polltype == POLLTYPE_MULTI || polltype == POLLTYPE_OPTION) - select_query = dbcon.NewQuery("SELECT text, percentagecalc, (SELECT COUNT(optionid) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id GROUP BY optionid) AS votecount FROM [format_table_name("poll_option")] WHERE pollid = [pollid]"); + select_query = GLOB.dbcon.NewQuery("SELECT text, percentagecalc, (SELECT COUNT(optionid) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id GROUP BY optionid) AS votecount FROM [format_table_name("poll_option")] WHERE pollid = [pollid]"); select_query.Execute() var/list/options = list() var/total_votes = 1 @@ -140,7 +140,7 @@ [question]
    [starttime] - [endtime] "} - select_query = dbcon.NewQuery("SELECT id, text, (SELECT AVG(rating) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id AND rating != 'abstain') AS avgrating, (SELECT COUNT(rating) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id AND rating != 'abstain') AS countvotes, minval, maxval FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") + select_query = GLOB.dbcon.NewQuery("SELECT id, text, (SELECT AVG(rating) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id AND rating != 'abstain') AS avgrating, (SELECT COUNT(rating) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id AND rating != 'abstain') AS countvotes, minval, maxval FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") select_query.Execute() while(select_query.NextRow()) output += {" @@ -156,7 +156,7 @@ var/maxvote = 1 var/list/votecounts = list() for(var/I in minval to maxval) - var/DBQuery/rating_query = dbcon.NewQuery("SELECT COUNT(rating) AS countrating FROM [format_table_name("poll_vote")] WHERE optionid = [optionid] AND rating = [I] GROUP BY rating") + var/DBQuery/rating_query = GLOB.dbcon.NewQuery("SELECT COUNT(rating) AS countrating FROM [format_table_name("poll_vote")] WHERE optionid = [optionid] AND rating = [I] GROUP BY rating") rating_query.Execute() var/votecount = 0 while(rating_query.NextRow()) @@ -177,7 +177,7 @@ output += "" output += "" if(polltype == POLLTYPE_TEXT) - select_query = dbcon.NewQuery("SELECT replytext, COUNT(replytext) AS countresponse, GROUP_CONCAT(DISTINCT ckey SEPARATOR ', ') as ckeys FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] GROUP BY replytext ORDER BY countresponse DESC"); + select_query = GLOB.dbcon.NewQuery("SELECT replytext, COUNT(replytext) AS countresponse, GROUP_CONCAT(DISTINCT ckey SEPARATOR ', ') as ckeys FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] GROUP BY replytext ORDER BY countresponse DESC"); select_query.Execute() output += {" @@ -195,15 +195,15 @@ "} output += "
    " output += "" - + src << browse(output,"window=pollresults;size=950x500") /client/proc/poll_player(var/pollid = -1, var/inline = 0) if(pollid == -1) return establish_db_connection() - if(dbcon.IsConnected()) + if(GLOB.dbcon.IsConnected()) - var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]") select_query.Execute() var/pollstarttime = "" @@ -229,7 +229,7 @@ switch(polltype) //Polls that have enumerated options if(POLLTYPE_OPTION) - var/DBQuery/voted_query = dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") + var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") voted_query.Execute() var/voted = 0 // If the can't vote then consider them voted @@ -241,21 +241,21 @@ var/list/datum/polloption/options = list() - var/DBQuery/options_query = dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") + var/DBQuery/options_query = GLOB.dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") options_query.Execute() while(options_query.NextRow()) var/datum/polloption/PO = new() PO.optionid = text2num(options_query.item[1]) PO.optiontext = options_query.item[2] options += PO - + var/output if(!inline) output += "
    Player poll" output +="
    " output += "Question: [pollquestion]
    " output += "Poll runs from [pollstarttime] until [pollendtime]

    " - + if(canvote && !voted) //Only make this a form if we have not voted yet output += "" output += "" @@ -278,7 +278,7 @@ output += "" output += "

    " - + if(inline) return output else @@ -286,7 +286,7 @@ //Polls with a text input if(POLLTYPE_TEXT) - var/DBQuery/voted_query = dbcon.NewQuery("SELECT replytext FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] AND ckey = '[ckey]'") + var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT replytext FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] AND ckey = '[ckey]'") voted_query.Execute() var/voted = 0 @@ -296,7 +296,7 @@ voted = 1 break - + var/output if(!inline) output += "
    Player poll" @@ -323,7 +323,7 @@ output += "" else output += "[vote_text]" - + if(inline) return output else @@ -331,9 +331,9 @@ //Polls with a text input if(POLLTYPE_RATING) - var/DBQuery/voted_query = dbcon.NewQuery("SELECT o.text, v.rating FROM [format_table_name("poll_option")] o, erro_poll_vote v WHERE o.pollid = [pollid] AND v.ckey = '[ckey]' AND o.id = v.optionid") + var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT o.text, v.rating FROM [format_table_name("poll_option")] o, erro_poll_vote v WHERE o.pollid = [pollid] AND v.ckey = '[ckey]' AND o.id = v.optionid") voted_query.Execute() - + var/output if(!inline) output += "
    Player poll" @@ -358,7 +358,7 @@ var/minid = 999999 var/maxid = 0 - var/DBQuery/option_query = dbcon.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") + var/DBQuery/option_query = GLOB.dbcon.NewQuery("SELECT id, text, minval, maxval, descmin, descmid, descmax FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") option_query.Execute() while(option_query.NextRow()) var/optionid = text2num(option_query.item[1]) @@ -404,7 +404,7 @@ else src << browse(output,"window=playerpoll;size=500x500") if(POLLTYPE_MULTI) - var/DBQuery/voted_query = dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") + var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT optionid FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") voted_query.Execute() var/list/votedfor = list() @@ -417,7 +417,7 @@ var/maxoptionid = 0 var/minoptionid = 0 - var/DBQuery/options_query = dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") + var/DBQuery/options_query = GLOB.dbcon.NewQuery("SELECT id, text FROM [format_table_name("poll_option")] WHERE pollid = [pollid]") options_query.Execute() while(options_query.NextRow()) var/datum/polloption/PO = new() @@ -478,9 +478,9 @@ if(!isnum(pollid) || !isnum(optionid)) return establish_db_connection() - if(dbcon.IsConnected()) + if(GLOB.dbcon.IsConnected()) - var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT starttime, endtime, question, polltype, multiplechoiceoptions FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]") select_query.Execute() var/validpoll = 0 @@ -498,7 +498,7 @@ to_chat(usr, "Poll is not valid.") return - var/DBQuery/select_query2 = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE id = [optionid] AND pollid = [pollid]") + var/DBQuery/select_query2 = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE id = [optionid] AND pollid = [pollid]") select_query2.Execute() var/validoption = 0 @@ -513,7 +513,7 @@ var/alreadyvoted = 0 - var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") + var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE pollid = [pollid] AND ckey = '[ckey]'") voted_query.Execute() while(voted_query.NextRow()) @@ -534,7 +534,7 @@ adminrank = usr.client.holder.rank - var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank) VALUES (null, Now(), [pollid], [optionid], '[ckey]', '[usr.client.address]', '[adminrank]')") + var/DBQuery/insert_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank) VALUES (null, Now(), [pollid], [optionid], '[ckey]', '[usr.client.address]', '[adminrank]')") insert_query.Execute() to_chat(usr, "Vote successful.") @@ -548,9 +548,9 @@ if(!isnum(pollid) || !istext(replytext)) return establish_db_connection() - if(dbcon.IsConnected()) + if(GLOB.dbcon.IsConnected()) - var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]") select_query.Execute() var/validpoll = 0 @@ -567,7 +567,7 @@ var/alreadyvoted = 0 - var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] AND ckey = '[ckey]'") + var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_textreply")] WHERE pollid = [pollid] AND ckey = '[ckey]'") voted_query.Execute() while(voted_query.NextRow()) @@ -592,7 +592,7 @@ to_chat(usr, "The text you entered was blank, contained illegal characters or was too long. Please correct the text and submit again.") return - var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO [format_table_name("poll_textreply")] (id ,datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (null, Now(), [pollid], '[ckey]', '[usr.client.address]', '[replytext]', '[adminrank]')") + var/DBQuery/insert_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_textreply")] (id ,datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (null, Now(), [pollid], '[ckey]', '[usr.client.address]', '[replytext]', '[adminrank]')") insert_query.Execute() to_chat(usr, "Feedback logging successful.") @@ -606,9 +606,9 @@ if(!isnum(pollid) || !isnum(optionid)) return establish_db_connection() - if(dbcon.IsConnected()) + if(GLOB.dbcon.IsConnected()) - var/DBQuery/select_query = dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]") + var/DBQuery/select_query = GLOB.dbcon.NewQuery("SELECT starttime, endtime, question, polltype FROM [format_table_name("poll_question")] WHERE id = [pollid] AND Now() BETWEEN starttime AND endtime [holder ? "AND adminonly = 0" : ""]") select_query.Execute() var/validpoll = 0 @@ -623,7 +623,7 @@ to_chat(usr, "Poll is not valid.") return - var/DBQuery/select_query2 = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE id = [optionid] AND pollid = [pollid]") + var/DBQuery/select_query2 = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_option")] WHERE id = [optionid] AND pollid = [pollid]") select_query2.Execute() var/validoption = 0 @@ -638,7 +638,7 @@ var/alreadyvoted = 0 - var/DBQuery/voted_query = dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE optionid = [optionid] AND ckey = '[ckey]'") + var/DBQuery/voted_query = GLOB.dbcon.NewQuery("SELECT id FROM [format_table_name("poll_vote")] WHERE optionid = [optionid] AND ckey = '[ckey]'") voted_query.Execute() while(voted_query.NextRow()) @@ -654,7 +654,7 @@ adminrank = usr.client.holder.rank - var/DBQuery/insert_query = dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (null, Now(), [pollid], [optionid], '[ckey]', '[usr.client.address]', '[adminrank]', [(isnull(rating)) ? "null" : rating])") + var/DBQuery/insert_query = GLOB.dbcon.NewQuery("INSERT INTO [format_table_name("poll_vote")] (id ,datetime ,pollid ,optionid ,ckey ,ip ,adminrank, rating) VALUES (null, Now(), [pollid], [optionid], '[ckey]', '[usr.client.address]', '[adminrank]', [(isnull(rating)) ? "null" : rating])") insert_query.Execute() to_chat(usr, "Vote successful.") diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 3489e56be54..77f8cc40da9 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -9,7 +9,7 @@ if(S.bodyflags & ALL_RPARTS) var/head_model = "[!rlimb_data["head"] ? "Morpheus Cyberkinetics" : rlimb_data["head"]]" - robohead = all_robolimbs[head_model] + robohead = GLOB.all_robolimbs[head_model] if(gender_override) gender = gender_override else @@ -17,7 +17,7 @@ underwear = random_underwear(gender, species) undershirt = random_undershirt(gender, species) socks = random_socks(gender, species) - if(body_accessory_by_species[species]) + if(GLOB.body_accessory_by_species[species]) body_accessory = random_body_accessory(species) if(body_accessory == "None") //Required to prevent a bug where the information/icons in the character preferences screen wouldn't update despite the data being changed. body_accessory = null @@ -237,10 +237,7 @@ else icobase = 'icons/mob/human_races/r_human.dmi' - var/fat="" - if(disabilities & DISABILITY_FLAG_FAT && (CAN_BE_FAT in current_species.species_traits)) - fat="_fat" - preview_icon = new /icon(icobase, "torso_[g][fat]") + preview_icon = new /icon(icobase, "torso_[g]") preview_icon.Blend(new /icon(icobase, "groin_[g]"), ICON_OVERLAY) var/head = "head" if(alt_head && current_species.bodyflags & HAS_ALT_HEADS) @@ -253,8 +250,8 @@ if(organ_data[name] == "amputated") continue if(organ_data[name] == "cyborg") var/datum/robolimb/R - if(rlimb_data[name]) R = all_robolimbs[rlimb_data[name]] - if(!R) R = basic_robolimb + if(rlimb_data[name]) R = GLOB.all_robolimbs[rlimb_data[name]] + if(!R) R = GLOB.basic_robolimb if(name == "chest") name = "torso" preview_icon.Blend(icon(R.icon, "[name]"), ICON_OVERLAY) // This doesn't check gendered_icon. Not an issue while only limbs can be robotic. @@ -281,7 +278,7 @@ var/blend_mode = ICON_ADD if(body_accessory) - var/datum/body_accessory/accessory = body_accessory_by_name[body_accessory] + var/datum/body_accessory/accessory = GLOB.body_accessory_by_name[body_accessory] tail_icon = accessory.icon tail_icon_state = accessory.icon_state if(accessory.blend_mode) @@ -404,8 +401,6 @@ var/icon/clothes_s = null var/uniform_dmi='icons/mob/uniform.dmi' - if(disabilities&DISABILITY_FLAG_FAT) - uniform_dmi='icons/mob/uniform_fat.dmi' if(job_support_low & JOB_CIVILIAN)//This gives the preview icon clothes depending on which job(if any) is set to 'high' clothes_s = new /icon(uniform_dmi, "grey_s") clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY) @@ -926,7 +921,7 @@ if(4) clothes_s.Blend(new /icon('icons/mob/back.dmi', "satchel"), ICON_OVERLAY) - if(disabilities & NEARSIGHTED) + if(disabilities & DISABILITY_FLAG_NEARSIGHTED) preview_icon.Blend(new /icon('icons/mob/eyes.dmi', "glasses"), ICON_OVERLAY) // Observers get tourist outfit. diff --git a/code/modules/mob/new_player/sprite_accessories/human/human_hair.dm b/code/modules/mob/new_player/sprite_accessories/human/human_hair.dm index f9e1ee1cc49..0dd6910e591 100644 --- a/code/modules/mob/new_player/sprite_accessories/human/human_hair.dm +++ b/code/modules/mob/new_player/sprite_accessories/human/human_hair.dm @@ -200,7 +200,7 @@ name = "Emo" icon_state = "emo" -/datum/sprite_accessory/hair/fag +/datum/sprite_accessory/hair/flow name = "Flow Hair" icon_state = "flow" diff --git a/code/modules/mob/new_player/sprite_accessories/ipc/ipc_face.dm b/code/modules/mob/new_player/sprite_accessories/ipc/ipc_face.dm index 8910a8f5229..6868521f9c2 100644 --- a/code/modules/mob/new_player/sprite_accessories/ipc/ipc_face.dm +++ b/code/modules/mob/new_player/sprite_accessories/ipc/ipc_face.dm @@ -4,6 +4,10 @@ glasses_over = 1 models_allowed = list("Bishop Cybernetics mtr.", "Hesphiastos Industries mtr.", "Morpheus Cyberkinetics", "Ward-Takahashi mtr.", "Xion Manufacturing Group mtr.", "Shellguard Munitions Monitor Series") +/datum/sprite_accessory/hair/ipc/ipc_screen_blank + name = "Blank IPC Screen" + icon_state = "blank" + /datum/sprite_accessory/hair/ipc/ipc_screen_pink name = "Pink IPC Screen" icon_state = "pink" diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index e218ce3c25d..81d22e40a0b 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -1,5 +1,5 @@ -#define ILLEGAL_CHARACTERS_LIST list("<" = "", ">" = "", "^" = "", \ +#define ILLEGAL_CHARACTERS_LIST list("<" = "", ">" = "", \ "\[" = "", "]" = "", "{" = "", "}" = "") /mob/proc/say() @@ -131,7 +131,7 @@ if(length(message) >= 2) var/channel_prefix = copytext(message, 1 ,3) - return department_radio_keys[channel_prefix] + return GLOB.department_radio_keys[channel_prefix] return null diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index 0aeb9beef84..b61ce171194 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -173,6 +173,9 @@ /mob/proc/Stun() return +/mob/proc/IsStunned() + return stunned + /mob/proc/SetStunned() return diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index fe19d366550..2ee4a9d2a9c 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -1,7 +1,7 @@ /mob/living/carbon/human/proc/monkeyize() var/mob/H = src - H.dna.SetSEState(MONKEYBLOCK,1) - genemutcheck(H,MONKEYBLOCK,null,MUTCHK_FORCED) + H.dna.SetSEState(GLOB.monkeyblock,1) + genemutcheck(H,GLOB.monkeyblock,null,MUTCHK_FORCED) /mob/new_player/AIize() spawning = 1 diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm index 1dd4c9f8ccb..4dfbddc2d84 100644 --- a/code/modules/mob/typing_indicator.dm +++ b/code/modules/mob/typing_indicator.dm @@ -5,31 +5,31 @@ mob/var/typing mob/var/last_typed mob/var/last_typed_time -var/global/image/typing_indicator +GLOBAL_DATUM(typing_indicator, /image) /mob/proc/set_typing_indicator(var/state) - if(!typing_indicator) - typing_indicator = image('icons/mob/talk.dmi', null, "typing", MOB_LAYER + 1) - typing_indicator.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA + if(!GLOB.typing_indicator) + GLOB.typing_indicator = image('icons/mob/talk.dmi', null, "typing", MOB_LAYER + 1) + GLOB.typing_indicator.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA if(ishuman(src)) var/mob/living/carbon/human/H = src - if(H.disabilities & MUTE || H.silent) - overlays -= typing_indicator + if((MUTE in H.mutations) || H.silent) + overlays -= GLOB.typing_indicator return if(client) if((client.prefs.toggles & SHOW_TYPING) || stat != CONSCIOUS || is_muzzled()) - overlays -= typing_indicator + overlays -= GLOB.typing_indicator else if(state) if(!typing) - overlays += typing_indicator + overlays += GLOB.typing_indicator typing = 1 else if(typing) - overlays -= typing_indicator + overlays -= GLOB.typing_indicator typing = 0 return state @@ -49,7 +49,7 @@ var/global/image/typing_indicator set name = ".Me" set hidden = 1 - + set_typing_indicator(1) hud_typing = 1 var/message = typing_input(src, "", "me (text)") diff --git a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm index 33a94cc31a5..948824fa32e 100644 --- a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm +++ b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm @@ -1,4 +1,4 @@ -var/global/static/ntnrc_uid = 0 +GLOBAL_VAR_INIT(ntnrc_uid, 0) /datum/ntnet_conversation var/id = null @@ -9,15 +9,15 @@ var/global/static/ntnrc_uid = 0 var/password /datum/ntnet_conversation/New() - id = ntnrc_uid - ntnrc_uid++ - if(ntnet_global) - ntnet_global.chat_channels.Add(src) + id = GLOB.ntnrc_uid + GLOB.ntnrc_uid++ + if(GLOB.ntnet_global) + GLOB.ntnet_global.chat_channels.Add(src) ..() /datum/ntnet_conversation/Destroy() - if(ntnet_global) - ntnet_global.chat_channels.Remove(src) + if(GLOB.ntnet_global) + GLOB.ntnet_global.chat_channels.Remove(src) return ..() /datum/ntnet_conversation/proc/add_message(message, username) diff --git a/code/modules/modular_computers/NTNet/NTNet.dm b/code/modules/modular_computers/NTNet/NTNet.dm index 000131d6c03..2f9aa3f2e7d 100644 --- a/code/modules/modular_computers/NTNet/NTNet.dm +++ b/code/modules/modular_computers/NTNet/NTNet.dm @@ -1,4 +1,4 @@ -var/global/datum/ntnet/ntnet_global = new() +GLOBAL_DATUM_INIT(ntnet_global, /datum/ntnet, new()) // This is the NTNet datum. There can be only one NTNet datum in game at once. Modular computers read data from this. @@ -26,8 +26,8 @@ var/global/datum/ntnet/ntnet_global = new() // If new NTNet datum is spawned, it replaces the old one. /datum/ntnet/New() - if(ntnet_global && (ntnet_global != src)) - ntnet_global = src // There can be only one. + if(GLOB.ntnet_global && (GLOB.ntnet_global != src)) + GLOB.ntnet_global = src // There can be only one. for(var/obj/machinery/ntnet_relay/R in GLOB.machines) relays.Add(R) R.NTNet = src diff --git a/code/modules/modular_computers/NTNet/NTNet_relay.dm b/code/modules/modular_computers/NTNet/NTNet_relay.dm index 436070470ea..97ddcfb69c0 100644 --- a/code/modules/modular_computers/NTNet/NTNet_relay.dm +++ b/code/modules/modular_computers/NTNet/NTNet_relay.dm @@ -3,7 +3,7 @@ name = "NTNet Quantum Relay" desc = "A very complex router and transmitter capable of connecting electronic devices together. Looks fragile." use_power = ACTIVE_POWER_USE - active_power_usage = 10000 //10kW, apropriate for machine that keeps massive cross-Zlevel wireless network operational. Used to be 20 but that actually drained the smes one round + active_power_usage = 100 // 100 watts. Yes I know this is a high power machine but this fucking obliterates an unpowered smes (AI sat) idle_power_usage = 100 icon = 'icons/obj/stationobjs.dmi' icon_state = "bus" @@ -51,12 +51,12 @@ if((dos_overload > dos_capacity) && !dos_failure) dos_failure = 1 update_icon() - ntnet_global.add_log("Quantum relay switched from normal operation mode to overload recovery mode.") + GLOB.ntnet_global.add_log("Quantum relay switched from normal operation mode to overload recovery mode.") // If the DoS buffer reaches 0 again, restart. if((dos_overload == 0) && dos_failure) dos_failure = 0 update_icon() - ntnet_global.add_log("Quantum relay switched from overload recovery mode to normal operation mode.") + GLOB.ntnet_global.add_log("Quantum relay switched from overload recovery mode to normal operation mode.") ..() /obj/machinery/ntnet_relay/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) @@ -82,10 +82,10 @@ dos_overload = 0 dos_failure = 0 update_icon() - ntnet_global.add_log("Quantum relay manually restarted from overload recovery mode to normal operation mode.") + GLOB.ntnet_global.add_log("Quantum relay manually restarted from overload recovery mode to normal operation mode.") if("toggle") enabled = !enabled - ntnet_global.add_log("Quantum relay manually [enabled ? "enabled" : "disabled"].") + GLOB.ntnet_global.add_log("Quantum relay manually [enabled ? "enabled" : "disabled"].") update_icon() return 1 @@ -99,18 +99,17 @@ component_parts = list() component_parts += new /obj/item/circuitboard/machine/ntnet_relay(null) component_parts += new /obj/item/stack/cable_coil(null, 2) - component_parts += new /obj/item/stock_parts/subspace/filter(null) - if(ntnet_global) - ntnet_global.relays.Add(src) - NTNet = ntnet_global - ntnet_global.add_log("New quantum relay activated. Current amount of linked relays: [NTNet.relays.len]") + if(GLOB.ntnet_global) + GLOB.ntnet_global.relays.Add(src) + NTNet = GLOB.ntnet_global + GLOB.ntnet_global.add_log("New quantum relay activated. Current amount of linked relays: [NTNet.relays.len]") ..() /obj/machinery/ntnet_relay/Destroy() - if(ntnet_global) - ntnet_global.relays.Remove(src) - ntnet_global.add_log("Quantum relay connection severed. Current amount of linked relays: [NTNet.relays.len]") + if(GLOB.ntnet_global) + GLOB.ntnet_global.relays.Remove(src) + GLOB.ntnet_global.add_log("Quantum relay connection severed. Current amount of linked relays: [NTNet.relays.len]") NTNet = null for(var/datum/computer_file/program/ntnet_dos/D in dos_sources) @@ -123,6 +122,4 @@ name = "NTNet Relay (Machine Board)" build_path = /obj/machinery/ntnet_relay origin_tech = "programming=3;bluespace=3;magnets=2" - req_components = list( - /obj/item/stack/cable_coil = 2, - /obj/item/stock_parts/subspace/filter = 1) + req_components = list(/obj/item/stack/cable_coil = 2) diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index 1e43884df9a..1dd45a33603 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -289,7 +289,7 @@ if(!get_ntnet_status()) return FALSE var/obj/item/computer_hardware/network_card/network_card = all_components[MC_NET] - return ntnet_global.add_log(text, network_card) + return GLOB.ntnet_global.add_log(text, network_card) /obj/item/modular_computer/proc/shutdown_computer(loud = 1) if(enabled) diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm index 7b025087a8b..223627bd69e 100644 --- a/code/modules/modular_computers/computers/item/laptop.dm +++ b/code/modules/modular_computers/computers/item/laptop.dm @@ -89,11 +89,13 @@ /obj/item/modular_computer/laptop/proc/toggle_open(mob/living/user=null) if(screen_on) - to_chat(user, "You close \the [src].") + if(user) + to_chat(user, "You close \the [src].") slowdown = initial(slowdown) w_class = initial(w_class) else - to_chat(user, "You open \the [src].") + if(user) + to_chat(user, "You open \the [src].") slowdown = slowdown_open w_class = w_class_open diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index 61e26ed9899..391396a7d75 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -1,5 +1,5 @@ // Global var to track modular computers -var/list/global_modular_computers = list() +GLOBAL_LIST_EMPTY(global_modular_computers) // Modular Computer - device that runs various programs and operates with hardware // DO NOT SPAWN THIS TYPE. Use /laptop/ or /console/ instead. @@ -34,7 +34,7 @@ var/list/global_modular_computers = list() ..() cpu = new(src) cpu.physical = src - global_modular_computers.Add(src) + GLOB.global_modular_computers.Add(src) /obj/machinery/modular_computer/Destroy() QDEL_NULL(cpu) diff --git a/code/modules/modular_computers/file_system/computer_file.dm b/code/modules/modular_computers/file_system/computer_file.dm index a93aaf2412e..b3f8064b72a 100644 --- a/code/modules/modular_computers/file_system/computer_file.dm +++ b/code/modules/modular_computers/file_system/computer_file.dm @@ -1,4 +1,4 @@ -var/global/file_uid = 0 +GLOBAL_VAR_INIT(file_uid, 0) /datum/computer_file var/filename = "NewFile" // Placeholder. No spacebars @@ -12,8 +12,8 @@ var/global/file_uid = 0 /datum/computer_file/New() ..() - uid = file_uid - file_uid++ + uid = GLOB.file_uid + GLOB.file_uid++ /datum/computer_file/Destroy() if(!holder) diff --git a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm index 22b0fa1a511..f6bc293db7d 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm @@ -51,7 +51,7 @@ return 1 switch(href_list["action"]) if("PRG_target_relay") - for(var/obj/machinery/ntnet_relay/R in ntnet_global.relays) + for(var/obj/machinery/ntnet_relay/R in GLOB.ntnet_global.relays) if("[R.uid]" == href_list["targid"]) target = R return 1 @@ -66,14 +66,14 @@ if(target) executed = 1 target.dos_sources.Add(src) - if(ntnet_global.intrusion_detection_enabled) + if(GLOB.ntnet_global.intrusion_detection_enabled) var/obj/item/computer_hardware/network_card/network_card = computer.all_components[MC_NET] - ntnet_global.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [network_card.get_network_tag()]") - ntnet_global.intrusion_detection_alarm = 1 + GLOB.ntnet_global.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [network_card.get_network_tag()]") + GLOB.ntnet_global.intrusion_detection_alarm = 1 return 1 /datum/computer_file/program/ntnet_dos/ui_data(mob/user) - if(!ntnet_global) + if(!GLOB.ntnet_global) return var/list/data = get_header_data() @@ -96,7 +96,7 @@ data["dos_strings"] += list(list("nums" = string)) else data["relays"] = list() - for(var/obj/machinery/ntnet_relay/R in ntnet_global.relays) + for(var/obj/machinery/ntnet_relay/R in GLOB.ntnet_global.relays) data["relays"] += list(list("id" = R.uid)) data["focus"] = target ? target.uid : null diff --git a/code/modules/modular_computers/file_system/programs/command/card.dm b/code/modules/modular_computers/file_system/programs/command/card.dm index f211ee6fd49..b85fb710e38 100644 --- a/code/modules/modular_computers/file_system/programs/command/card.dm +++ b/code/modules/modular_computers/file_system/programs/command/card.dm @@ -35,7 +35,8 @@ /datum/job/ntnavyofficer, /datum/job/ntspecops, /datum/job/civilian, - /datum/job/syndicateofficer + /datum/job/syndicateofficer, + /datum/job/explorer // blacklisted so that HOPs don't try prioritizing it, then wonder why that doesn't work ) //The scaling factor of max total positions in relation to the total amount of people on board the station in % @@ -105,7 +106,7 @@ if(job) if(!job_blacklisted(job)) if((job.total_positions <= GLOB.player_list.len * (max_relative_positions / 100))) - var/delta = (world.time / 10) - time_last_changed_position + var/delta = (world.time / 10) - GLOB.time_last_changed_position if((change_position_cooldown < delta) || (opened_positions[job.title] < 0)) return 1 return -2 @@ -117,7 +118,7 @@ if(job) if(!job_blacklisted(job)) if(job.total_positions > job.current_positions) - var/delta = (world.time / 10) - time_last_changed_position + var/delta = (world.time / 10) - GLOB.time_last_changed_position if((change_position_cooldown < delta) || (opened_positions[job.title] > 0)) return 1 return -2 @@ -180,7 +181,7 @@ switch(href_list["action"]) if("PRG_modify") if(modify) - data_core.manifest_modify(modify.registered_name, modify.assignment) + GLOB.data_core.manifest_modify(modify.registered_name, modify.assignment) modify.name = "[modify.registered_name]'s ID Card ([modify.assignment])" card_slot.try_eject(1, user) else @@ -302,7 +303,7 @@ var/content if(mode == 2) title = "crew manifest ([station_time_timestamp()])" - content = "

    Crew Manifest


    [data_core ? data_core.get_manifest(0) : ""]" + content = "

    Crew Manifest


    [GLOB.data_core ? GLOB.data_core.get_manifest(0) : ""]" else if(modify && !mode) title = "access report" content = {"

    Access Report

    @@ -346,7 +347,7 @@ if(can_open_job(j) != 1) return 1 if(opened_positions[edit_job_target] >= 0) - time_last_changed_position = world.time / 10 + GLOB.time_last_changed_position = world.time / 10 j.total_positions++ opened_positions[edit_job_target]++ log_game("[key_name(usr)] has opened a job slot for job \"[j]\".") @@ -362,7 +363,7 @@ return 1 //Allow instant closing without cooldown if a position has been opened before if(opened_positions[edit_job_target] <= 0) - time_last_changed_position = world.time / 10 + GLOB.time_last_changed_position = world.time / 10 j.total_positions-- opened_positions[edit_job_target]-- log_game("[key_name(usr)] has closed a job slot for job \"[j]\".") @@ -413,7 +414,7 @@ data["mode"] = mode data["printing"] = printing data["printer"] = printer ? TRUE : FALSE - data["manifest"] = data_core ? data_core.get_manifest(0) : null + data["manifest"] = GLOB.data_core ? GLOB.data_core.get_manifest(0) : null data["target_name"] = modify ? modify.name : "-----" data["target_owner"] = modify && modify.registered_name ? modify.registered_name : "-----" data["target_rank"] = get_target_rank() @@ -429,19 +430,19 @@ var/list/job_formats = SSjobs.format_jobs_for_id_computer(modify) data["top_jobs"] = format_jobs(list("Captain", "Custom"), data["target_rank"], job_formats) - data["engineering_jobs"] = format_jobs(engineering_positions, data["target_rank"], job_formats) - data["medical_jobs"] = format_jobs(medical_positions, data["target_rank"], job_formats) - data["science_jobs"] = format_jobs(science_positions, data["target_rank"], job_formats) - data["security_jobs"] = format_jobs(security_positions, data["target_rank"], job_formats) - data["support_jobs"] = format_jobs(support_positions, data["target_rank"], job_formats) - data["civilian_jobs"] = format_jobs(civilian_positions, data["target_rank"], job_formats) - data["special_jobs"] = format_jobs(whitelisted_positions, data["target_rank"], job_formats) + data["engineering_jobs"] = format_jobs(GLOB.engineering_positions, data["target_rank"], job_formats) + data["medical_jobs"] = format_jobs(GLOB.medical_positions, data["target_rank"], job_formats) + data["science_jobs"] = format_jobs(GLOB.science_positions, data["target_rank"], job_formats) + data["security_jobs"] = format_jobs(GLOB.security_positions, data["target_rank"], job_formats) + data["support_jobs"] = format_jobs(GLOB.support_positions, data["target_rank"], job_formats) + data["civilian_jobs"] = format_jobs(GLOB.civilian_positions, data["target_rank"], job_formats) + data["special_jobs"] = format_jobs(GLOB.whitelisted_positions, data["target_rank"], job_formats) data["centcom_jobs"] = format_jobs(get_all_centcom_jobs(), data["target_rank"], job_formats) data["card_skins"] = format_card_skins(get_station_card_skins()) data["job_slots"] = format_job_slots() - var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - time_last_changed_position), 1) + var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) var/mins = round(time_to_wait / 60) var/seconds = time_to_wait - (60*mins) data["cooldown_mins"] = mins diff --git a/code/modules/modular_computers/file_system/programs/command/comms.dm b/code/modules/modular_computers/file_system/programs/command/comms.dm index eb6f079d078..c23f0c9e3c7 100644 --- a/code/modules/modular_computers/file_system/programs/command/comms.dm +++ b/code/modules/modular_computers/file_system/programs/command/comms.dm @@ -50,7 +50,7 @@ /datum/computer_file/program/comm/proc/change_security_level(mob/user, new_level) tmp_alertlevel = new_level - var/old_level = security_level + var/old_level = GLOB.security_level if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN if(tmp_alertlevel < SEC_LEVEL_GREEN) @@ -58,10 +58,10 @@ if(tmp_alertlevel > SEC_LEVEL_BLUE) tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this set_security_level(tmp_alertlevel) - if(security_level != old_level) + if(GLOB.security_level != old_level) log_game("[key_name(user)] has changed the security level to [get_security_level()].") message_admins("[key_name_admin(user)] has changed the security level to [get_security_level()].") - switch(security_level) + switch(GLOB.security_level) if(SEC_LEVEL_GREEN) feedback_inc("alert_comms_green", 1) if(SEC_LEVEL_BLUE) @@ -101,7 +101,7 @@ ui.set_layout_key("program") ui.open() -/datum/computer_file/program/comm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/datum/computer_file/program/comm/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/list/data = get_header_data() data["is_ai"] = isAI(user) || isrobot(user) data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state @@ -128,7 +128,7 @@ ) ) - data["security_level"] = security_level + data["security_level"] = GLOB.security_level data["str_security_level"] = capitalize(get_security_level()) data["levels"] = list( list("id" = SEC_LEVEL_GREEN, "name" = "Green"), @@ -326,7 +326,7 @@ Nuke_request(input, usr) to_chat(usr, "Request sent.") log_game("[key_name(usr)] has requested the nuclear codes from Centcomm") - priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg') + GLOB.priority_announcement.Announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/AI/commandreport.ogg') centcomm_message_cooldown = 1 spawn(6000)//10 minute cooldown centcomm_message_cooldown = 0 diff --git a/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm index 0695c496541..0763d527345 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm @@ -43,6 +43,6 @@ data["poweravail"] = powernet.avail data["powerload"] = powernet.viewload data["powerdemand"] = powernet.load - data["apcs"] = apc_repository.apc_data(powernet) + data["apcs"] = GLOB.apc_repository.apc_data(powernet) return data diff --git a/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm index c0447b591bf..b4e5ab4674c 100644 --- a/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm +++ b/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm @@ -21,7 +21,7 @@ if(downloaded_file) return 0 - var/datum/computer_file/program/PRG = ntnet_global.find_ntnet_file_by_name(filename) + var/datum/computer_file/program/PRG = GLOB.ntnet_global.find_ntnet_file_by_name(filename) if(!PRG || !istype(PRG)) return 0 @@ -37,10 +37,10 @@ ui_header = "downloader_running.gif" - if(PRG in ntnet_global.available_station_software) + if(PRG in GLOB.ntnet_global.available_station_software) generate_network_log("Began downloading file [PRG.filename].[PRG.filetype] from NTNet Software Repository.") hacked_download = 0 - else if(PRG in ntnet_global.available_antag_software) + else if(PRG in GLOB.ntnet_global.available_antag_software) generate_network_log("Began downloading file **ENCRYPTED**.[PRG.filetype] from unspecified server.") hacked_download = 1 else @@ -135,7 +135,7 @@ data["disk_size"] = hard_drive.max_capacity data["disk_used"] = hard_drive.used_capacity var/list/all_entries[0] - for(var/A in ntnet_global.available_station_software) + for(var/A in GLOB.ntnet_global.available_station_software) var/datum/computer_file/program/P = A // Only those programs our user can run will show in the list if(!P.can_run(user,transfer = 1)) @@ -151,7 +151,7 @@ data["hackedavailable"] = 0 if(computer.emagged) // If we are running on emagged computer we have access to some "bonus" software var/list/hacked_programs[0] - for(var/S in ntnet_global.available_antag_software) + for(var/S in GLOB.ntnet_global.available_antag_software) var/datum/computer_file/program/P = S data["hackedavailable"] = 1 hacked_programs.Add(list(list( diff --git a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm index 5a6affbb0a0..517c8f99ebe 100644 --- a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm @@ -52,7 +52,7 @@ /datum/computer_file/program/chatclient/ui_data(mob/user) - if(!ntnet_global || !ntnet_global.chat_channels) + if(!GLOB.ntnet_global || !GLOB.ntnet_global.chat_channels) return var/list/data = get_header_data() @@ -78,7 +78,7 @@ else // Channel selection screen var/list/all_channels[0] - for(var/C in ntnet_global.chat_channels) + for(var/C in GLOB.ntnet_global.chat_channels) var/datum/ntnet_conversation/conv = C if(conv && conv.title) all_channels.Add(list(list( @@ -108,7 +108,7 @@ if("PRG_joinchannel") . = 1 var/datum/ntnet_conversation/C - for(var/datum/ntnet_conversation/chan in ntnet_global.chat_channels) + for(var/datum/ntnet_conversation/chan in GLOB.ntnet_global.chat_channels) if(chan.id == text2num(href_list["id"])) C = chan break diff --git a/code/modules/modular_computers/file_system/programs/generic/nttransfer.dm b/code/modules/modular_computers/file_system/programs/generic/nttransfer.dm index 184b2cf300f..1ccefa9311a 100644 --- a/code/modules/modular_computers/file_system/programs/generic/nttransfer.dm +++ b/code/modules/modular_computers/file_system/programs/generic/nttransfer.dm @@ -1,4 +1,4 @@ -var/global/nttransfer_uid = 0 +GLOBAL_VAR_INIT(nttransfer_uid, 0) /datum/computer_file/program/nttransfer filename = "nttransfer" @@ -24,8 +24,8 @@ var/global/nttransfer_uid = 0 var/upload_menu = 0 // Whether we show the program list and upload menu /datum/computer_file/program/nttransfer/New() - unique_token = nttransfer_uid - nttransfer_uid++ + unique_token = GLOB.nttransfer_uid + GLOB.nttransfer_uid++ ..() /datum/computer_file/program/nttransfer/process_tick() @@ -100,7 +100,7 @@ var/global/nttransfer_uid = 0 return 1 switch(href_list["action"]) if("PRG_downloadfile") - for(var/datum/computer_file/program/nttransfer/P in ntnet_global.fileservers) + for(var/datum/computer_file/program/nttransfer/P in GLOB.ntnet_global.fileservers) if("[P.unique_token]" == href_list["id"]) remote = P break @@ -118,8 +118,8 @@ var/global/nttransfer_uid = 0 error = "" upload_menu = 0 finalize_download() - if(src in ntnet_global.fileservers) - ntnet_global.fileservers.Remove(src) + if(src in GLOB.ntnet_global.fileservers) + GLOB.ntnet_global.fileservers.Remove(src) for(var/datum/computer_file/program/nttransfer/T in connected_clients) T.crash_download("Remote server has forcibly closed the connection") provided_file = null @@ -145,7 +145,7 @@ var/global/nttransfer_uid = 0 if(!P.can_run(usr,transfer = 1)) error = "Access Error: Insufficient rights to upload file." provided_file = F - ntnet_global.fileservers.Add(src) + GLOB.ntnet_global.fileservers.Add(src) return error = "I/O Error: Unable to locate file on hard drive." return 1 @@ -183,7 +183,7 @@ var/global/nttransfer_uid = 0 data["upload_filelist"] = all_files else var/list/all_servers[0] - for(var/datum/computer_file/program/nttransfer/P in ntnet_global.fileservers) + for(var/datum/computer_file/program/nttransfer/P in GLOB.ntnet_global.fileservers) all_servers.Add(list(list( "uid" = P.unique_token, "filename" = "[P.provided_file.filename].[P.provided_file.filetype]", diff --git a/code/modules/modular_computers/file_system/programs/research/airestorer.dm b/code/modules/modular_computers/file_system/programs/research/airestorer.dm index d5ff31af66b..a87a2cd87b4 100644 --- a/code/modules/modular_computers/file_system/programs/research/airestorer.dm +++ b/code/modules/modular_computers/file_system/programs/research/airestorer.dm @@ -78,7 +78,7 @@ A.stat = CONSCIOUS A.lying = 0 GLOB.dead_mob_list -= A - GLOB.living_mob_list += A + GLOB.alive_mob_list += A // Finished restoring if(A.health >= 100) ai_slot.locked = FALSE diff --git a/code/modules/modular_computers/file_system/programs/research/ntmonitor.dm b/code/modules/modular_computers/file_system/programs/research/ntmonitor.dm index 6f3f41df272..0a839a6d13f 100644 --- a/code/modules/modular_computers/file_system/programs/research/ntmonitor.dm +++ b/code/modules/modular_computers/file_system/programs/research/ntmonitor.dm @@ -24,22 +24,22 @@ switch(href_list["action"]) if("resetIDS") . = 1 - if(ntnet_global) - ntnet_global.resetIDS() + if(GLOB.ntnet_global) + GLOB.ntnet_global.resetIDS() return 1 if("toggleIDS") . = 1 - if(ntnet_global) - ntnet_global.toggleIDS() + if(GLOB.ntnet_global) + GLOB.ntnet_global.toggleIDS() return 1 if("toggleWireless") . = 1 - if(!ntnet_global) + if(!GLOB.ntnet_global) return 1 // NTNet is disabled. Enabling can be done without user prompt - if(ntnet_global.setting_disabled) - ntnet_global.setting_disabled = 0 + if(GLOB.ntnet_global.setting_disabled) + GLOB.ntnet_global.setting_disabled = 0 return 1 // NTNet is enabled and user is about to shut it down. Let's ask them if they really want to do it, as wirelessly connected computers won't connect without NTNet being enabled (which may prevent people from turning it back on) @@ -48,43 +48,43 @@ return 1 var/response = alert(user, "Really disable NTNet wireless? If your computer is connected wirelessly you won't be able to turn it back on! This will affect all connected wireless devices.", "NTNet shutdown", "Yes", "No") if(response == "Yes") - ntnet_global.setting_disabled = 1 + GLOB.ntnet_global.setting_disabled = 1 return 1 if("purgelogs") . = 1 - if(ntnet_global) - ntnet_global.purge_logs() + if(GLOB.ntnet_global) + GLOB.ntnet_global.purge_logs() if("updatemaxlogs") . = 1 var/mob/user = usr var/logcount = text2num(input(user,"Enter amount of logs to keep in memory ([MIN_NTNET_LOGS]-[MAX_NTNET_LOGS]):")) - if(ntnet_global) - ntnet_global.update_max_log_count(logcount) + if(GLOB.ntnet_global) + GLOB.ntnet_global.update_max_log_count(logcount) if("toggle_function") . = 1 - if(!ntnet_global) + if(!GLOB.ntnet_global) return 1 - ntnet_global.toggle_function(text2num(href_list["id"])) + GLOB.ntnet_global.toggle_function(text2num(href_list["id"])) /datum/computer_file/program/ntnetmonitor/ui_data(mob/user) - if(!ntnet_global) + if(!GLOB.ntnet_global) return var/list/data = get_header_data() - data["ntnetstatus"] = ntnet_global.check_function() - data["ntnetrelays"] = ntnet_global.relays.len - data["idsstatus"] = ntnet_global.intrusion_detection_enabled - data["idsalarm"] = ntnet_global.intrusion_detection_alarm + data["ntnetstatus"] = GLOB.ntnet_global.check_function() + data["ntnetrelays"] = GLOB.ntnet_global.relays.len + data["idsstatus"] = GLOB.ntnet_global.intrusion_detection_enabled + data["idsalarm"] = GLOB.ntnet_global.intrusion_detection_alarm - data["config_softwaredownload"] = ntnet_global.setting_softwaredownload - data["config_peertopeer"] = ntnet_global.setting_peertopeer - data["config_communication"] = ntnet_global.setting_communication - data["config_systemcontrol"] = ntnet_global.setting_systemcontrol + data["config_softwaredownload"] = GLOB.ntnet_global.setting_softwaredownload + data["config_peertopeer"] = GLOB.ntnet_global.setting_peertopeer + data["config_communication"] = GLOB.ntnet_global.setting_communication + data["config_systemcontrol"] = GLOB.ntnet_global.setting_systemcontrol data["ntnetlogs"] = list() - for(var/i in ntnet_global.logs) + for(var/i in GLOB.ntnet_global.logs) data["ntnetlogs"] += list(list("entry" = i)) - data["ntnetmaxlogs"] = ntnet_global.setting_maxlogcount + data["ntnetmaxlogs"] = GLOB.ntnet_global.setting_maxlogcount return data diff --git a/code/modules/modular_computers/hardware/network_card.dm b/code/modules/modular_computers/hardware/network_card.dm index 4768a63b9cb..3e5409b5d61 100644 --- a/code/modules/modular_computers/hardware/network_card.dm +++ b/code/modules/modular_computers/hardware/network_card.dm @@ -1,4 +1,4 @@ -var/global/ntnet_card_uid = 1 +GLOBAL_VAR_INIT(ntnet_card_uid, 1) /obj/item/computer_hardware/network_card name = "network card" @@ -26,8 +26,8 @@ var/global/ntnet_card_uid = 1 /obj/item/computer_hardware/network_card/New(var/l) ..(l) - identification_id = ntnet_card_uid - ntnet_card_uid++ + identification_id = GLOB.ntnet_card_uid + GLOB.ntnet_card_uid++ // Returns a string identifier of this network card /obj/item/computer_hardware/network_card/proc/get_network_tag() @@ -44,7 +44,7 @@ var/global/ntnet_card_uid = 1 if(ethernet) // Computer is connected via wired connection. return 3 - if(!ntnet_global || !ntnet_global.check_function(specific_action)) // NTNet is down and we are not connected via wired connection. No signal. + if(!GLOB.ntnet_global || !GLOB.ntnet_global.check_function(specific_action)) // NTNet is down and we are not connected via wired connection. No signal. return 0 if(holder) diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm index b2066285dea..aa69b85b1df 100644 --- a/code/modules/modular_computers/laptop_vendor.dm +++ b/code/modules/modular_computers/laptop_vendor.dm @@ -283,7 +283,7 @@ obj/machinery/lapvend/attackby(obj/item/I, mob/user) atom_say("Insufficient funds in account.") return 0 else - customer_account.charge(total_price, vendor_account, + customer_account.charge(total_price, GLOB.vendor_account, "Purchase of [(devtype == 1) ? "laptop computer" : "tablet microcomputer"].", name, customer_account.owner_name, "Sale of [(devtype == 1) ? "laptop computer" : "tablet microcomputer"].", customer_account.owner_name) diff --git a/code/modules/nano/interaction/admin.dm b/code/modules/nano/interaction/admin.dm index 412ebbc1260..9223e1e0763 100644 --- a/code/modules/nano/interaction/admin.dm +++ b/code/modules/nano/interaction/admin.dm @@ -1,7 +1,7 @@ /* This state checks that the user is an admin, end of story */ -/var/global/datum/topic_state/admin_state/admin_state = new() +GLOBAL_DATUM_INIT(admin_state, /datum/topic_state/admin_state, new()) /datum/topic_state/admin_state/can_use_topic(var/src_object, var/mob/user) return check_rights(R_ADMIN, 0, user) ? STATUS_INTERACTIVE : STATUS_CLOSE diff --git a/code/modules/nano/interaction/conscious.dm b/code/modules/nano/interaction/conscious.dm index 143bc24956f..e4b478dced6 100644 --- a/code/modules/nano/interaction/conscious.dm +++ b/code/modules/nano/interaction/conscious.dm @@ -1,7 +1,7 @@ /* This state only checks if user is conscious. */ -/var/global/datum/topic_state/conscious_state/conscious_state = new() +GLOBAL_DATUM_INIT(conscious_state, /datum/topic_state/conscious_state, new()) /datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user) return user.stat == CONSCIOUS ? STATUS_INTERACTIVE : STATUS_CLOSE diff --git a/code/modules/nano/interaction/contained.dm b/code/modules/nano/interaction/contained.dm index 3c84734104a..03ac30d07ad 100644 --- a/code/modules/nano/interaction/contained.dm +++ b/code/modules/nano/interaction/contained.dm @@ -1,7 +1,7 @@ /* This state checks if user is somewhere within src_object, as well as the default NanoUI interaction. */ -/var/global/datum/topic_state/contained_state/contained_state = new() +GLOBAL_DATUM_INIT(contained_state, /datum/topic_state/contained_state, new()) /datum/topic_state/contained_state/can_use_topic(var/atom/src_object, var/mob/user) if(!src_object.contains(user)) diff --git a/code/modules/nano/interaction/default.dm b/code/modules/nano/interaction/default.dm index e5062bc0b12..ca42220204d 100644 --- a/code/modules/nano/interaction/default.dm +++ b/code/modules/nano/interaction/default.dm @@ -1,4 +1,4 @@ -/var/global/datum/topic_state/default/default_state = new() +GLOBAL_DATUM_INIT(default_state, /datum/topic_state/default, new()) /datum/topic_state/default/href_list(var/mob/user) return list() @@ -51,7 +51,7 @@ // If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view if(is_in_chassis()) //stop AIs from leaving windows open and using then after they lose vision - if(cameranet && !cameranet.checkTurfVis(get_turf(src_object))) + if(GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf(src_object))) return STATUS_CLOSE return STATUS_INTERACTIVE else if(get_dist(src_object, src) <= client.view) // View does not return what one would expect while installed in an inteliCard diff --git a/code/modules/nano/interaction/ghost.dm b/code/modules/nano/interaction/ghost.dm index 6b0aa3db1ca..bb435b33896 100644 --- a/code/modules/nano/interaction/ghost.dm +++ b/code/modules/nano/interaction/ghost.dm @@ -1,9 +1,9 @@ /* - This checks that the user is a ghost or alternatively an admin. Used for the mob spawner. + This checks that the user is a ghost or alternatively an admin. Used for the mob spawner. We don't want any living people somehow getting the menu open and reincarnating while alive */ -/var/global/datum/topic_state/ghost_state/ghost_state = new() +GLOBAL_DATUM_INIT(ghost_state, /datum/topic_state/ghost_state, new()) /datum/topic_state/ghost_state/can_use_topic(var/src_object, var/mob/user) if(user.stat == DEAD) diff --git a/code/modules/nano/interaction/inventory.dm b/code/modules/nano/interaction/inventory.dm index cbe5165e5ff..bd0e12ea5a1 100644 --- a/code/modules/nano/interaction/inventory.dm +++ b/code/modules/nano/interaction/inventory.dm @@ -1,7 +1,7 @@ /* This state checks that the src_object is somewhere in the user's first-level inventory (in hands, on ear, etc.), but not further down (such as in bags). */ -/var/global/datum/topic_state/inventory_state/inventory_state = new() +GLOBAL_DATUM_INIT(inventory_state, /datum/topic_state/inventory_state, new()) /datum/topic_state/inventory_state/can_use_topic(var/src_object, var/mob/user) if(!((src_object in user) || user.is_in_active_hand(src_object) || user.is_in_inactive_hand(src_object))) diff --git a/code/modules/nano/interaction/inventory_deep.dm b/code/modules/nano/interaction/inventory_deep.dm index 98078c02c1d..6d6e3667675 100644 --- a/code/modules/nano/interaction/inventory_deep.dm +++ b/code/modules/nano/interaction/inventory_deep.dm @@ -1,7 +1,7 @@ /* This state checks if src_object is contained anywhere in the user's inventory, including bags, etc. */ -/var/global/datum/topic_state/deep_inventory_state/deep_inventory_state = new() +GLOBAL_DATUM_INIT(deep_inventory_state, /datum/topic_state/deep_inventory_state, new()) /datum/topic_state/deep_inventory_state/can_use_topic(var/src_object, var/mob/user) if(!user.contains(src_object)) diff --git a/code/modules/nano/interaction/not_incapacitated.dm b/code/modules/nano/interaction/not_incapacitated.dm index db12edf3119..8539315f3c6 100644 --- a/code/modules/nano/interaction/not_incapacitated.dm +++ b/code/modules/nano/interaction/not_incapacitated.dm @@ -2,13 +2,12 @@ * This state only checks if the user isn't incapacitated **/ -/var/global/datum/topic_state/not_incapacitated_state/not_incapacitated_state = new() +GLOBAL_DATUM_INIT(not_incapacitated_state, /datum/topic_state/not_incapacitated_state, new()) /** * This state checks if the user isn't incapacitated and that their loc is a turf **/ - -/var/global/datum/topic_state/not_incapacitated_state/not_incapacitated_turf_state = new(no_turfs = TRUE) +GLOBAL_DATUM_INIT(not_incapacitated_turf_state, /datum/topic_state/not_incapacitated_state, new(no_turfs = TRUE)) /datum/topic_state/not_incapacitated_state var/turf_check = FALSE diff --git a/code/modules/nano/interaction/physical.dm b/code/modules/nano/interaction/physical.dm index 424ea3a6304..193f8c094c1 100644 --- a/code/modules/nano/interaction/physical.dm +++ b/code/modules/nano/interaction/physical.dm @@ -1,4 +1,4 @@ -/var/global/datum/topic_state/physical/physical_state = new() +GLOBAL_DATUM_INIT(physical_state, /datum/topic_state/physical, new()) /datum/topic_state/physical/can_use_topic(var/src_object, var/mob/user) . = user.shared_nano_interaction(src_object) diff --git a/code/modules/nano/interaction/self.dm b/code/modules/nano/interaction/self.dm index a4ae5050347..a3d94457135 100644 --- a/code/modules/nano/interaction/self.dm +++ b/code/modules/nano/interaction/self.dm @@ -1,7 +1,7 @@ /* This state checks that the src_object is the same the as user */ -/var/global/datum/topic_state/self_state/self_state = new() +GLOBAL_DATUM_INIT(self_state, /datum/topic_state/self_state, new()) /datum/topic_state/self_state/can_use_topic(var/src_object, var/mob/user) if(src_object != user) diff --git a/code/modules/nano/interaction/zlevel.dm b/code/modules/nano/interaction/zlevel.dm index 15052bc6636..feeb617cd49 100644 --- a/code/modules/nano/interaction/zlevel.dm +++ b/code/modules/nano/interaction/zlevel.dm @@ -2,7 +2,7 @@ This state checks that the user is on the same Z-level as src_object */ -/var/global/datum/topic_state/z_state/z_state = new() +GLOBAL_DATUM_INIT(z_state, /datum/topic_state/z_state, new()) /datum/topic_state/z_state/can_use_topic(var/src_object, var/mob/user) var/turf/turf_obj = get_turf(src_object) diff --git a/code/modules/nano/modules/alarm_monitor.dm b/code/modules/nano/modules/alarm_monitor.dm index dc52841a367..cee3820b102 100644 --- a/code/modules/nano/modules/alarm_monitor.dm +++ b/code/modules/nano/modules/alarm_monitor.dm @@ -48,21 +48,21 @@ if(..()) return 1 if(href_list["switchTo"]) - var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.cameras + var/obj/machinery/camera/C = locate(href_list["switchTo"]) in GLOB.cameranet.cameras if(!C || !isAI(usr)) return usr.switch_to_camera(C) return 1 -/datum/nano_module/alarm_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) +/datum/nano_module/alarm_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "alarm_monitor.tmpl", "Alarm Monitoring Console", 800, 800, state = state) ui.open() ui.set_auto_update(1) -/datum/nano_module/alarm_monitor/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/datum/nano_module/alarm_monitor/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/categories[0] diff --git a/code/modules/nano/modules/atmos_control.dm b/code/modules/nano/modules/atmos_control.dm index 3b61ea0f557..2c74a1ce844 100644 --- a/code/modules/nano/modules/atmos_control.dm +++ b/code/modules/nano/modules/atmos_control.dm @@ -12,7 +12,7 @@ if(monitored_alarm_ids) for(var/obj/machinery/alarm/alarm in GLOB.machines) - if(alarm.alarm_id && alarm.alarm_id in monitored_alarm_ids) + if(alarm.alarm_id && (alarm.alarm_id in monitored_alarm_ids)) monitored_alarms += alarm // machines may not yet be ordered at this point monitored_alarms = dd_sortedObjectList(monitored_alarms) @@ -28,7 +28,7 @@ var/datum/topic_state/air_alarm/TS = generate_state(alarm) alarm.ui_interact(usr, master_ui = ui_ref, state = TS) -/datum/nano_module/atmos_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state) +/datum/nano_module/atmos_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/master_ui = null, var/datum/topic_state/state = GLOB.default_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "atmos_control.tmpl", src.name, 900, 800, state = state) @@ -39,9 +39,9 @@ ui.set_auto_update(1) ui_ref = ui -/datum/nano_module/atmos_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/datum/nano_module/atmos_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] - data["alarms"] = air_alarm_repository.air_alarm_data(monitored_alarms) + data["alarms"] = GLOB.air_alarm_repository.air_alarm_data(monitored_alarms) return data diff --git a/code/modules/nano/modules/crew_monitor.dm b/code/modules/nano/modules/crew_monitor.dm index 755009ac0be..4ed7fc03de1 100644 --- a/code/modules/nano/modules/crew_monitor.dm +++ b/code/modules/nano/modules/crew_monitor.dm @@ -16,7 +16,7 @@ AI.ai_actual_track(H) return 1 -/datum/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) +/datum/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800) @@ -31,11 +31,11 @@ // should make the UI auto-update; doesn't seem to? ui.set_auto_update(1) -/datum/nano_module/crew_monitor/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/datum/nano_module/crew_monitor/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/turf/T = get_turf(nano_host()) data["isAI"] = isAI(user) - data["crewmembers"] = crew_repository.health_data(T) + data["crewmembers"] = GLOB.crew_repository.health_data(T) return data diff --git a/code/modules/nano/modules/ert_manager.dm b/code/modules/nano/modules/ert_manager.dm index e218ad2ae68..98a3e19d052 100644 --- a/code/modules/nano/modules/ert_manager.dm +++ b/code/modules/nano/modules/ert_manager.dm @@ -11,7 +11,7 @@ var/autoclose = 0 -/datum/nano_module/ert_manager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = admin_state) +/datum/nano_module/ert_manager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.admin_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(ui && autoclose) ui.close() @@ -50,7 +50,7 @@ cyborg_slots = text2num(href_list["set_cyb"]) if(href_list["dispatch_ert"]) - ert_request_answered = TRUE + GLOB.ert_request_answered = TRUE var/slots_list = list() if(commander_slots > 0) slots_list += "commander: [commander_slots]" @@ -70,7 +70,7 @@ notify_ghosts("An ERT is being dispatched. Open positions: [slot_text]") message_admins("[key_name_admin(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]", 1) log_admin("[key_name(usr)] dispatched a [ert_type] ERT. Slots: [slot_text]") - event_announcement.Announce("Attention, [station_name()]. We are attempting to assemble an ERT. Standby.", "ERT Protocol Activated") + GLOB.event_announcement.Announce("Attention, [station_name()]. We are attempting to assemble an ERT. Standby.", "ERT Protocol Activated") autoclose = 1 ui_interact(usr) trigger_armed_response_team(convert_ert_string(ert_type), commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots) diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index 07810eb92a0..485fee0acb8 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -25,7 +25,7 @@ src.whitelist = species_whitelist src.blacklist = species_blacklist -/datum/nano_module/appearance_changer/Topic(ref, href_list, var/nowindow, var/datum/topic_state/state = default_state) +/datum/nano_module/appearance_changer/Topic(ref, href_list, var/nowindow, var/datum/topic_state/state = GLOB.default_state) if(..()) return 1 @@ -173,14 +173,14 @@ return 0 -/datum/nano_module/appearance_changer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) +/datum/nano_module/appearance_changer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "appearance_changer.tmpl", "[src]", 800, 450, state = state) ui.open() ui.set_auto_update(1) -/datum/nano_module/appearance_changer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/datum/nano_module/appearance_changer/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) generate_data(check_whitelist, whitelist, blacklist) var/data[0] diff --git a/code/modules/nano/modules/law_manager.dm b/code/modules/nano/modules/law_manager.dm index a8a8d5e688a..f2423e57c2f 100644 --- a/code/modules/nano/modules/law_manager.dm +++ b/code/modules/nano/modules/law_manager.dm @@ -152,14 +152,14 @@ return 0 -/datum/nano_module/law_manager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) +/datum/nano_module/law_manager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "law_manager.tmpl", sanitize("[src] - [owner.name]"), 800, is_malf(user) ? 600 : 400, state = state) ui.open() ui.set_auto_update(1) -/datum/nano_module/law_manager/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/datum/nano_module/law_manager/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] owner.lawsync() diff --git a/code/modules/nano/modules/nano_module.dm b/code/modules/nano/modules/nano_module.dm index c62067bfaf8..a9afc94f69b 100644 --- a/code/modules/nano/modules/nano_module.dm +++ b/code/modules/nano/modules/nano_module.dm @@ -12,5 +12,5 @@ if(host) host.on_ui_close(user) -/datum/nano_module/proc/can_still_topic(var/datum/topic_state/state = default_state) +/datum/nano_module/proc/can_still_topic(var/datum/topic_state/state = GLOB.default_state) return CanUseTopic(usr, state) == STATUS_INTERACTIVE diff --git a/code/modules/nano/modules/power_monitor.dm b/code/modules/nano/modules/power_monitor.dm index 00dcf9819ec..66948243035 100644 --- a/code/modules/nano/modules/power_monitor.dm +++ b/code/modules/nano/modules/power_monitor.dm @@ -11,20 +11,20 @@ if(!select_monitor) powermonitor = nano_host() -/datum/nano_module/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state) +/datum/nano_module/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state) ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "power_monitor.tmpl", "Power Monitoring Console", 800, 700, state = state) ui.open() ui.set_auto_update(1) -/datum/nano_module/power_monitor/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/datum/nano_module/power_monitor/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["powermonitor"] = powermonitor if(select_monitor) data["select_monitor"] = 1 - data["powermonitors"] = powermonitor_repository.powermonitor_data() + data["powermonitors"] = GLOB.powermonitor_repository.powermonitor_data() if(powermonitor && !isnull(powermonitor.powernet)) if(select_monitor && (powermonitor.stat & (NOPOWER|BROKEN))) @@ -33,7 +33,7 @@ data["poweravail"] = powermonitor.powernet.avail data["powerload"] = powermonitor.powernet.viewload data["powerdemand"] = powermonitor.powernet.load - data["apcs"] = apc_repository.apc_data(powermonitor.powernet) + data["apcs"] = GLOB.apc_repository.apc_data(powermonitor.powernet) return data diff --git a/code/modules/nano/nanoexternal.dm b/code/modules/nano/nanoexternal.dm index 8e7269972fd..f57014496fd 100644 --- a/code/modules/nano/nanoexternal.dm +++ b/code/modules/nano/nanoexternal.dm @@ -37,7 +37,7 @@ * * @return nothing */ -/datum/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nano_ui/master_ui = null, var/datum/topic_state/state = default_state) +/datum/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = GLOB.default_state) return /** @@ -57,7 +57,7 @@ * * @return list() */ -/datum/proc/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/datum/proc/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) return list() // Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index 0df04d27928..526ca1ffe04 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -71,7 +71,7 @@ nanoui is used to open and update nano browser uis * * @return /nanoui new nanoui object */ -/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = default_state) +/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/state = GLOB.default_state) user = nuser src_object = nsrc_object ui_key = nui_key @@ -176,7 +176,7 @@ nanoui is used to open and update nano browser uis var/name = "[src_object]" var/list/config_data = list( "title" = title, - "map" = (using_map && using_map.name) ? using_map.name : "Unknown", + "map" = (GLOB.using_map && GLOB.using_map.name) ? GLOB.using_map.name : "Unknown", "srcObject" = list("name" = name), "stateKey" = state_key, "status" = status, diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm index cf694e59d83..741f0399922 100644 --- a/code/modules/ninja/energy_katana.dm +++ b/code/modules/ninja/energy_katana.dm @@ -52,7 +52,7 @@ if(user.put_in_hands(src)) msg = "Your Energy Katana teleports into your hand!" - else if(user.equip_to_slot_if_possible(src, slot_belt, 0, 1, 1)) + else if(user.equip_to_slot_if_possible(src, slot_belt, FALSE, TRUE)) msg = "Your Energy Katana teleports back to you, sheathing itself as it does so!" else loc = get_turf(user) diff --git a/code/modules/paperwork/contract.dm b/code/modules/paperwork/contract.dm index 25e72610237..b1fe71db72e 100644 --- a/code/modules/paperwork/contract.dm +++ b/code/modules/paperwork/contract.dm @@ -265,8 +265,8 @@ /obj/item/paper/contract/infernal/power/FulfillContract(mob/living/carbon/human/user = target.current, blood = 0) if(!user.dna) return -1 - user.dna.SetSEState(HULKBLOCK,1) - genemutcheck(user, HULKBLOCK,null,MUTCHK_FORCED) + user.dna.SetSEState(GLOB.hulkblock,1) + genemutcheck(user, GLOB.hulkblock,null,MUTCHK_FORCED) // Demonic power gives you consequenceless hulk user.gene_stability += GENE_INSTABILITY_MAJOR if(ishuman(user)) diff --git a/code/modules/paperwork/fax.dm b/code/modules/paperwork/fax.dm index 4b8d4f9db6e..360b5a78500 100644 --- a/code/modules/paperwork/fax.dm +++ b/code/modules/paperwork/fax.dm @@ -1,6 +1,6 @@ // Fax datum - holds all faxes sent during the round -var/list/faxes = list() -var/list/adminfaxes = list() +GLOBAL_LIST_EMPTY(faxes) +GLOBAL_LIST_EMPTY(adminfaxes) /datum/fax var/name = "fax" @@ -12,13 +12,13 @@ var/list/adminfaxes = list() var/sent_at = null /datum/fax/New() - faxes += src + GLOB.faxes += src /datum/fax/admin var/list/reply_to = null /datum/fax/admin/New() - adminfaxes += src + GLOB.adminfaxes += src // Fax panel - lets admins check all faxes sent during the round /client/proc/fax_panel() @@ -37,7 +37,7 @@ var/list/adminfaxes = list() html += "

    Admin Faxes

    " html += "" html += "" - for(var/datum/fax/admin/A in adminfaxes) + for(var/datum/fax/admin/A in GLOB.adminfaxes) html += "" html += "" html += "" @@ -66,7 +66,7 @@ var/list/adminfaxes = list() html += "

    Departmental Faxes

    " html += "
    NameFrom DepartmentTo DepartmentSent AtSent ByViewReplyReplied To
    [A.name][A.from_department]
    " html += "" - for(var/datum/fax/F in faxes) + for(var/datum/fax/F in GLOB.faxes) html += "" html += "" html += "" diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm index 2f3088c5484..09858073142 100644 --- a/code/modules/paperwork/faxmachine.dm +++ b/code/modules/paperwork/faxmachine.dm @@ -1,9 +1,9 @@ -var/list/obj/machinery/photocopier/faxmachine/allfaxes = list() -var/list/admin_departments = list("Central Command") -var/list/hidden_admin_departments = list("Syndicate") -var/list/alldepartments = list() -var/list/hidden_departments = list() -var/global/list/fax_blacklist = list() +GLOBAL_LIST_EMPTY(allfaxes) +GLOBAL_LIST_INIT(admin_departments, list("Central Command")) +GLOBAL_LIST_INIT(hidden_admin_departments, list("Syndicate")) +GLOBAL_LIST_EMPTY(alldepartments) +GLOBAL_LIST_EMPTY(hidden_departments) +GLOBAL_LIST_EMPTY(fax_blacklist) /obj/machinery/photocopier/faxmachine name = "fax machine" @@ -33,13 +33,13 @@ var/global/list/fax_blacklist = list() /obj/machinery/photocopier/faxmachine/New() ..() - allfaxes += src + GLOB.allfaxes += src update_network() /obj/machinery/photocopier/faxmachine/proc/update_network() if(department != "Unknown") - if(!(("[department]" in alldepartments) || ("[department]" in hidden_departments) || ("[department]" in admin_departments) || ("[department]" in hidden_admin_departments))) - alldepartments |= department + if(!(("[department]" in GLOB.alldepartments) || ("[department]" in GLOB.hidden_departments) || ("[department]" in GLOB.admin_departments) || ("[department]" in GLOB.hidden_admin_departments))) + GLOB.alldepartments |= department /obj/machinery/photocopier/faxmachine/longrange name = "long range fax machine" @@ -55,7 +55,7 @@ var/global/list/fax_blacklist = list() /obj/machinery/photocopier/faxmachine/longrange/syndie/update_network() if(department != "Unknown") - hidden_departments |= department + GLOB.hidden_departments |= department /obj/machinery/photocopier/faxmachine/attack_hand(mob/user) ui_interact(user) @@ -86,7 +86,7 @@ var/global/list/fax_blacklist = list() ui = new(user, src, ui_key, "faxmachine.tmpl", "Fax Machine UI", 540, 450) ui.open() -/obj/machinery/photocopier/faxmachine/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/photocopier/faxmachine/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/is_authenticated = is_authenticated(user) @@ -109,7 +109,7 @@ var/global/list/fax_blacklist = list() data["paperinserted"] = 0 data["destination"] = destination data["cooldown"] = sendcooldown - if((destination in admin_departments) || (destination in hidden_admin_departments)) + if((destination in GLOB.admin_departments) || (destination in GLOB.hidden_admin_departments)) data["respectcooldown"] = 1 else data["respectcooldown"] = 0 @@ -130,7 +130,7 @@ var/global/list/fax_blacklist = list() var/is_authenticated = is_authenticated(usr) if(href_list["send"]) if(copyitem && is_authenticated) - if((destination in admin_departments) || (destination in hidden_admin_departments)) + if((destination in GLOB.admin_departments) || (destination in GLOB.hidden_admin_departments)) send_admin_fax(usr, destination) else sendfax(destination, usr) @@ -163,18 +163,18 @@ var/global/list/fax_blacklist = list() if(href_list["dept"]) if(is_authenticated) var/lastdestination = destination - var/list/combineddepartments = alldepartments.Copy() + var/list/combineddepartments = GLOB.alldepartments.Copy() if(long_range_enabled) - combineddepartments += admin_departments.Copy() + combineddepartments += GLOB.admin_departments.Copy() if(emagged) - combineddepartments += hidden_admin_departments.Copy() - combineddepartments += hidden_departments.Copy() + combineddepartments += GLOB.hidden_admin_departments.Copy() + combineddepartments += GLOB.hidden_departments.Copy() if(syndie_restricted) - combineddepartments = hidden_admin_departments.Copy() - combineddepartments += hidden_departments.Copy() - for(var/obj/machinery/photocopier/faxmachine/F in allfaxes) + combineddepartments = GLOB.hidden_admin_departments.Copy() + combineddepartments += GLOB.hidden_departments.Copy() + for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes) if(F.emagged)//we can contact emagged faxes on the station combineddepartments |= F.department @@ -184,7 +184,7 @@ var/global/list/fax_blacklist = list() if(href_list["auth"]) if(!is_authenticated && scan) - if(scan.registered_name in fax_blacklist) + if(scan.registered_name in GLOB.fax_blacklist) playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0) else if(check_access(scan)) authenticated = 1 @@ -252,7 +252,7 @@ var/global/list/fax_blacklist = list() use_power(200) var/success = 0 - for(var/obj/machinery/photocopier/faxmachine/F in allfaxes) + for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes) if(F.department == destination) success = F.receivefax(copyitem) @@ -324,7 +324,7 @@ var/global/list/fax_blacklist = list() message_admins(sender, "CENTCOM FAX", destination, copyitem, "#006100") if("Syndicate") message_admins(sender, "SYNDICATE FAX", destination, copyitem, "#DC143C") - for(var/obj/machinery/photocopier/faxmachine/F in allfaxes) + for(var/obj/machinery/photocopier/faxmachine/F in GLOB.allfaxes) if(F.department == destination) F.receivefax(copyitem) sendcooldown = cooldown_time diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index 7d6144bee1b..eb350f5e29a 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -119,9 +119,9 @@ /obj/structure/filingcabinet/security/proc/populate() if(virgin) - for(var/datum/data/record/G in data_core.general) + for(var/datum/data/record/G in GLOB.data_core.general) var/datum/data/record/S - for(var/datum/data/record/R in data_core.security) + for(var/datum/data/record/R in GLOB.data_core.security) if(R.fields["name"] == G.fields["name"] || R.fields["id"] == G.fields["id"]) S = R break @@ -135,7 +135,6 @@ P.name = "paper - '[G.fields["name"]]'" virgin = 0 //tabbing here is correct- it's possible for people to try and use it //before the records have been generated, so we do this inside the loop. - ..() /obj/structure/filingcabinet/security/attack_hand() populate() @@ -153,9 +152,9 @@ /obj/structure/filingcabinet/medical/proc/populate() if(virgin) - for(var/datum/data/record/G in data_core.general) + for(var/datum/data/record/G in GLOB.data_core.general) var/datum/data/record/M - for(var/datum/data/record/R in data_core.medical) + for(var/datum/data/record/R in GLOB.data_core.medical) if(R.fields["name"] == G.fields["name"] || R.fields["id"] == G.fields["id"]) M = R break @@ -169,7 +168,6 @@ P.name = "paper - '[G.fields["name"]]'" virgin = 0 //tabbing here is correct- it's possible for people to try and use it //before the records have been generated, so we do this inside the loop. - ..() /obj/structure/filingcabinet/medical/attack_hand() populate() @@ -183,7 +181,7 @@ * Employment contract Cabinets */ -var/list/employmentCabinets = list() +GLOBAL_LIST_EMPTY(employmentCabinets) /obj/structure/filingcabinet/employment var/cooldown = 0 @@ -191,16 +189,16 @@ var/list/employmentCabinets = list() var/virgin = 1 /obj/structure/filingcabinet/employment/New() - employmentCabinets += src + GLOB.employmentCabinets += src return ..() /obj/structure/filingcabinet/employment/Destroy() - employmentCabinets -= src + GLOB.employmentCabinets -= src return ..() /obj/structure/filingcabinet/employment/proc/fillCurrent() //This proc fills the cabinet with the current crew. - for(var/record in data_core.locked) + for(var/record in GLOB.data_core.locked) var/datum/data/record/G = record if(!G) continue diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm index de894e80106..eefb4d299a4 100644 --- a/code/modules/paperwork/folders.dm +++ b/code/modules/paperwork/folders.dm @@ -7,6 +7,12 @@ pressure_resistance = 2 resistance_flags = FLAMMABLE +/obj/item/folder/emp_act(severity) + ..() + for(var/i in contents) + var/atom/A = i + A.emp_act(severity) + /obj/item/folder/blue desc = "A blue folder." icon_state = "folder_blue" diff --git a/code/modules/paperwork/handlabeler.dm b/code/modules/paperwork/handlabeler.dm index 74bee9867ab..7722dd2b53f 100644 --- a/code/modules/paperwork/handlabeler.dm +++ b/code/modules/paperwork/handlabeler.dm @@ -1,11 +1,12 @@ /obj/item/hand_labeler name = "hand labeler" + desc = "A combined label printer, applicator, and remover, all in a single portable device. Designed to be easy to operate and use." icon = 'icons/obj/bureaucracy.dmi' icon_state = "labeler0" item_state = "flight" var/label = null var/labels_left = 30 - var/mode = 0 //off or on. + var/mode = 0 /obj/item/hand_labeler/afterattack(atom/A, mob/user, proximity) if(!proximity) @@ -29,7 +30,9 @@ user.visible_message("[user] labels [A] as [label].", \ "You label [A] as [label].") investigate_log("[key_name(user)] labelled [A] as [label].", INVESTIGATE_LABEL) // Investigate goes BEFORE rename so the original name is preserved in the log - A.name = "[A.name] ([label])" + A.AddComponent(/datum/component/label, label) + playsound(A, 'sound/items/handling/component_pickup.ogg', 20, TRUE) + labels_left-- /obj/item/hand_labeler/attack_self(mob/user as mob) mode = !mode @@ -45,3 +48,20 @@ to_chat(user, "You set the text to '[str]'.") else to_chat(user, "You turn off \the [src].") + +/obj/item/hand_labeler/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/hand_labeler_refill)) + to_chat(user, "You insert [I] into [src].") + user.drop_item() + qdel(I) + labels_left = initial(labels_left) //Yes, it's capped at its initial value + else + return ..() + +/obj/item/hand_labeler_refill + name = "hand labeler paper roll" + icon = 'icons/obj/bureaucracy.dmi' + desc = "A roll of paper. Use it on a hand labeler to refill it." + icon_state = "labeler_refill" + item_state = "electropack" + w_class = WEIGHT_CLASS_TINY diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 46376c1828d..d80b175e757 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -21,7 +21,9 @@ max_integrity = 50 attack_verb = list("bapped") dog_fashion = /datum/dog_fashion/head + var/header //Above the main body, displayed at the top var/info //What's actually written on the paper. + var/footer //The bottom stuff before the stamp but after the body var/info_links //A different version of the paper which includes html links at fields and EOF var/stamps //The (text for the) stamps on the paper. var/fields //Amount of user created fields @@ -76,15 +78,16 @@ var/data var/stars = (!user.say_understands(null, GLOB.all_languages["Galactic Common"]) && !forceshow) || forcestars if(stars) //assuming all paper is written in common is better than hardcoded type checks - data = "[stars(info)][stamps]" + data = "[header][stars(info)][footer][stamps]" else - data = "
    [infolinks ? info_links : info]
    [stamps]" + data = "[header]
    [infolinks ? info_links : info]
    [footer][stamps]" if(view) var/datum/browser/popup = new(user, "Paper[UID()]", , paper_width, paper_height) popup.stylesheets = list() popup.set_content(data) if(!stars) popup.add_script("marked.js", 'html/browser/marked.js') + popup.add_script("marked-paradise.js", 'html/browser/marked-paradise.js') popup.add_head_content("[name]") popup.open() return data @@ -560,10 +563,6 @@ name = "paper- 'Holodeck Disclaimer'" info = "Brusies sustained in the holodeck can be healed simply by sleeping." -/obj/item/paper/spells - name = "paper- 'List of Available Spells (READ)'" - info = "

    LIST OF SPELLS AVAILABLE

    Magic Missile:
    This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage.

    Fireball:
    This spell fires a fireball at a target and does not require wizard garb. Be careful not to fire it at people that are standing next to you.

    Disintegrate:
    This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown.

    Disable Technology:
    This spell disables all weapons, cameras and most other technology in range.

    Smoke:
    This spell spawns a cloud of choking smoke at your location and does not require wizard garb.

    Blind:
    This spell temporarly blinds a single person and does not require wizard garb.

    Forcewall:
    This spell creates an unbreakable wall that lasts for 30 seconds and does not require wizard garb.

    Blink:
    This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience.

    Teleport:
    This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable.

    Mutate:
    This spell causes you to turn into a hulk, and gain telekinesis for a short while.

    Ethereal Jaunt:
    This spell creates your ethereal form, temporarily making you invisible and able to pass through walls.

    Knock:
    This spell opens nearby doors and does not require wizard garb.

    " - /obj/item/paper/syndimemo name = "paper- 'Memo'" info = "GET DAT FUKKEN DISK" @@ -588,6 +587,23 @@ name = "paper scrap" icon_state = "scrap" +/obj/item/paper/syndicate + name = "paper" + header = "


    " + info = "" + +/obj/item/paper/nanotrasen + name = "paper" + header = "


    " + info = "" + +/obj/item/paper/central_command + name = "paper" + header ="


    Nanotrasen Central Command

    Official Expedited Memorandum


    " + info = "" + footer = "

    Failure to adhere appropriately to orders that may be contained herein is in violation of Space Law, and punishments may be administered appropriately upon return to Central Command.
    The recipient(s) of this memorandum acknowledge by reading it that they are liable for any and all damages to crew or station that may arise from ignoring suggestions or advice given herein.

    " + + /obj/item/paper/crumpled/update_icon() return @@ -677,19 +693,25 @@ to_chat(H, "You feel surrounded by sadness. Sadness... and HONKS!") H.makeCluwne() else if(myeffect == "Demote") - event_announcement.Announce("[target.real_name] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order") - else if(myeffect == "Demote with Bot") - event_announcement.Announce("[target.real_name] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order") - for(var/datum/data/record/R in sortRecord(data_core.security)) + GLOB.event_announcement.Announce("[target.real_name] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order") + for(var/datum/data/record/R in sortRecord(GLOB.data_core.security)) if(R.fields["name"] == target.real_name) - R.fields["criminal"] = "*Arrest*" + R.fields["criminal"] = SEC_RECORD_STATUS_DEMOTE + R.fields["comments"] += "Central Command Demotion Order, given on [GLOB.current_date_string] [station_time_timestamp()]
    Process this demotion immediately. Failure to comply with these orders is grounds for termination." + update_all_mob_security_hud() + else if(myeffect == "Demote with Bot") + GLOB.event_announcement.Announce("[target.real_name] is hereby demoted to the rank of Civilian. Process this demotion immediately. Failure to comply with these orders is grounds for termination.","CC Demotion Order") + for(var/datum/data/record/R in sortRecord(GLOB.data_core.security)) + if(R.fields["name"] == target.real_name) + R.fields["criminal"] = SEC_RECORD_STATUS_ARREST + R.fields["comments"] += "Central Command Demotion Order, given on [GLOB.current_date_string] [station_time_timestamp()]
    Process this demotion immediately. Failure to comply with these orders is grounds for termination." update_all_mob_security_hud() if(fax) var/turf/T = get_turf(fax) new /obj/effect/portal(T) new /mob/living/simple_animal/bot/secbot(T) else if(myeffect == "Revoke Fax Access") - fax_blacklist += target.real_name + GLOB.fax_blacklist += target.real_name if(fax) fax.authenticated = 0 else if(myeffect == "Angry Fax Machine") diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index 68afe9fbd12..d76765b61a7 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -10,7 +10,8 @@ pressure_resistance = 8 var/amount = 30 //How much paper is in the bin. var/list/papers = list() //List of papers put in the bin for reference. - + var/letterhead_type + /obj/item/paper_bin/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE) if(amount) amount = 0 @@ -71,7 +72,10 @@ P = papers[papers.len] papers.Remove(P) else - P = new /obj/item/paper + if(letterhead_type && alert("Choose a style",,"Letterhead","Blank")=="Letterhead") + P = new letterhead_type + else + P = new /obj/item/paper if(SSholiday.holidays && SSholiday.holidays[APRIL_FOOLS]) if(prob(30)) P.info = "HONK HONK HONK HONK HONK HONK HONK
    HOOOOOOOOOOOOOOOOOOOOOONK
    APRIL FOOLS
    " @@ -139,3 +143,13 @@ add_fingerprint(user) return + + +/obj/item/paper_bin/nanotrasen + name = "nanotrasen paper bin" + letterhead_type = /obj/item/paper/nanotrasen + +/obj/item/paper_bin/syndicate + name = "syndicate paper bin" + letterhead_type = /obj/item/paper/syndicate + diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index 7fac0e3386a..aa2a033f130 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -72,7 +72,7 @@ update_icon() else if(is_hot(P)) - if(user.disabilities & CLUMSY && prob(10)) + if((CLUMSY in user.mutations) && prob(10)) user.visible_message("[user] accidentally ignites [user.p_them()]self!", \ "You miss [src] and accidentally light yourself on fire!") user.unEquip(P) diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 0954127b00a..5ca53396253 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -64,14 +64,14 @@ if(toner <= 0) break - if(copier_items_printed >= copier_max_items) //global vars defined in misc.dm + if(GLOB.copier_items_printed >= GLOB.copier_max_items) //global vars defined in misc.dm if(prob(10)) visible_message("The printer screen reads \"PC LOAD LETTER\".") else visible_message("The printer screen reads \"PHOTOCOPIER NETWORK OFFLINE, PLEASE CONTACT SYSTEM ADMINISTRATOR\".") - if(!copier_items_printed_logged) - message_admins("Photocopier cap of [copier_max_items] papers reached, all photocopiers are now disabled. This may be the cause of any lag.") - copier_items_printed_logged = TRUE + if(!GLOB.copier_items_printed_logged) + message_admins("Photocopier cap of [GLOB.copier_max_items] papers reached, all photocopiers are now disabled. This may be the cause of any lag.") + GLOB.copier_items_printed_logged = TRUE break if(emag_cooldown > world.time) @@ -98,7 +98,7 @@ else to_chat(usr, "\The [copyitem] can't be copied by \the [src].") break - copier_items_printed++ + GLOB.copier_items_printed++ use_power(active_power_usage) updateUsrDialog() else if(href_list["remove"]) @@ -184,10 +184,12 @@ /obj/machinery/photocopier/wrench_act(mob/user, obj/item/I) . = TRUE default_unfasten_wrench(user, I) - + /obj/machinery/photocopier/proc/copy(var/obj/item/paper/copy) var/obj/item/paper/c = new /obj/item/paper (loc) + c.header = copy.header c.info = copy.info + c.footer = copy.footer c.name = copy.name // -- Doohl c.fields = copy.fields c.stamps = copy.stamps diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 159b224e384..1134f7a0752 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -179,7 +179,7 @@ qdel(C) -var/list/SpookyGhosts = list("ghost","shade","shade2","ghost-narsie","horror","shadow","ghostian2") +GLOBAL_LIST_INIT(SpookyGhosts, list("ghost","shade","shade2","ghost-narsie","horror","shadow","ghostian2")) /obj/item/camera/spooky name = "camera obscura" @@ -240,7 +240,7 @@ var/list/SpookyGhosts = list("ghost","shade","shade2","ghost-narsie","horror","s if(O.following) continue if(user.mind && !(user.mind.assigned_role == "Chaplain")) - atoms.Add(image('icons/mob/mob.dmi', O.loc, pick(SpookyGhosts), 4, SOUTH)) + atoms.Add(image('icons/mob/mob.dmi', O.loc, pick(GLOB.SpookyGhosts), 4, SOUTH)) else atoms.Add(image('icons/mob/mob.dmi', O.loc, "ghost", 4, SOUTH)) else//its not a ghost @@ -265,7 +265,7 @@ var/list/SpookyGhosts = list("ghost","shade","shade2","ghost-narsie","horror","s var/atom/A = sorted[i] if(A) var/icon/img = getFlatIcon(A)//build_composite_icon(A) - if(istype(A, /obj/item/areaeditor/blueprints)) + if(istype(A, /obj/item/areaeditor/blueprints/ce)) blueprints = 1 // If what we got back is actually a picture, draw it. @@ -324,24 +324,26 @@ var/list/SpookyGhosts = list("ghost","shade","shade2","ghost-narsie","horror","s mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]." return mob_detail -/obj/item/camera/afterattack(atom/target as mob|obj|turf|area, mob/user as mob, flag) - if(!on || !pictures_left || ismob(target.loc)) return +/obj/item/camera/afterattack(atom/target, mob/user, flag) + if(!on || !pictures_left || ismob(target.loc)) + return captureimage(target, user, flag) playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, 1, -3) - + set_light(3, 2, LIGHT_COLOR_TUNGSTEN) + addtimer(CALLBACK(src, /atom./proc/set_light, 0), 2) pictures_left-- desc = "A polaroid camera. It has [pictures_left] photos left." to_chat(user, "[pictures_left] photos left.") icon_state = icon_off - on = 0 + on = FALSE if(istype(src,/obj/item/camera/spooky)) if(user.mind && user.mind.assigned_role == "Chaplain" && see_ghosts) if(prob(24)) handle_haunt(user) spawn(64) icon_state = icon_on - on = 1 + on = TRUE /obj/item/camera/proc/can_capture_turf(turf/T, mob/user) var/viewer = user @@ -544,7 +546,7 @@ var/list/SpookyGhosts = list("ghost","shade","shade2","ghost-narsie","horror","s src.icon_state = icon_on camera = new /obj/machinery/camera(src) camera.network = list("news") - cameranet.removeCamera(camera) + GLOB.cameranet.removeCamera(camera) camera.c_tag = user.name to_chat(user, "You switch the camera [on ? "on" : "off"].") diff --git a/code/modules/pda/PDA.dm b/code/modules/pda/PDA.dm index 4030924a8ac..f17666af19d 100755 --- a/code/modules/pda/PDA.dm +++ b/code/modules/pda/PDA.dm @@ -1,7 +1,7 @@ //The advanced pea-green monochrome lcd of tomorrow. -var/global/list/obj/item/pda/PDAs = list() +GLOBAL_LIST_EMPTY(PDAs) /obj/item/pda @@ -66,8 +66,8 @@ var/global/list/obj/item/pda/PDAs = list() */ /obj/item/pda/Initialize(mapload) . = ..() - PDAs += src - PDAs = sortAtom(PDAs) + GLOB.PDAs += src + GLOB.PDAs = sortAtom(GLOB.PDAs) update_programs() if(default_cartridge) cartridge = new default_cartridge(src) @@ -101,7 +101,7 @@ var/global/list/obj/item/pda/PDAs = list() if((!istype(over_object, /obj/screen)) && can_use()) return attack_self(M) -/obj/item/pda/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = inventory_state) +/obj/item/pda/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.inventory_state) ui_tick++ var/datum/nanoui/old_ui = SSnanoui.get_open_ui(user, src, "main") var/auto_update = 1 @@ -131,7 +131,7 @@ var/global/list/obj/item/pda/PDAs = list() // auto update every Master Controller tick ui.set_auto_update(auto_update) -/obj/item/pda/ui_data(mob/user, ui_key = "main", datum/topic_state/state = inventory_state) +/obj/item/pda/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.inventory_state) var/data[0] data["owner"] = owner // Who is your daddy... @@ -467,7 +467,7 @@ var/global/list/obj/item/pda/PDAs = list() return /obj/item/pda/Destroy() - PDAs -= src + GLOB.PDAs -= src var/T = get_turf(loc) if(id) id.forceMove(T) diff --git a/code/modules/pda/cart_apps.dm b/code/modules/pda/cart_apps.dm index 4ca5b4af427..6c03241a096 100644 --- a/code/modules/pda/cart_apps.dm +++ b/code/modules/pda/cart_apps.dm @@ -103,12 +103,12 @@ "poweravail" = powmonitor.powernet.avail, "powerload" = num2text(powmonitor.powernet.viewload, 10), "powerdemand" = powmonitor.powernet.load, - "apcs" = apc_repository.apc_data(powmonitor.powernet)) + "apcs" = GLOB.apc_repository.apc_data(powmonitor.powernet)) has_back = 1 else data["records"] = list( "powerconnected" = 0, - "powermonitors" = powermonitor_repository.powermonitor_data()) + "powermonitors" = GLOB.powermonitor_repository.powermonitor_data()) has_back = 0 /datum/data/pda/app/power/Topic(href, list/href_list) @@ -127,12 +127,12 @@ /datum/data/pda/app/crew_records/update_ui(mob/user as mob, list/data) var/list/records[0] - if(general_records && (general_records in data_core.general)) + if(general_records && (general_records in GLOB.data_core.general)) data["records"] = records records["general"] = general_records.fields return records else - for(var/A in sortRecord(data_core.general)) + for(var/A in sortRecord(GLOB.data_core.general)) var/datum/data/record/R = A if(R) records += list(list(Name = R.fields["name"], "ref" = "\ref[R]")) @@ -143,7 +143,7 @@ switch(href_list["choice"]) if("Records") var/datum/data/record/R = locate(href_list["target"]) - if(R && (R in data_core.general)) + if(R && (R in GLOB.data_core.general)) load_records(R) if("Back") general_records = null @@ -166,14 +166,14 @@ if(!records) return - if(medical_records && (medical_records in data_core.medical)) + if(medical_records && (medical_records in GLOB.data_core.medical)) records["medical"] = medical_records.fields return records /datum/data/pda/app/crew_records/medical/load_records(datum/data/record/R) ..(R) - for(var/A in data_core.medical) + for(var/A in GLOB.data_core.medical) var/datum/data/record/E = A if(E && (E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) medical_records = E @@ -192,14 +192,14 @@ if(!records) return - if(security_records && (security_records in data_core.security)) + if(security_records && (security_records in GLOB.data_core.security)) records["security"] = security_records.fields return records /datum/data/pda/app/crew_records/security/load_records(datum/data/record/R) ..(R) - for(var/A in data_core.security) + for(var/A in GLOB.data_core.security) var/datum/data/record/E = A if(E && (E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) security_records = E diff --git a/code/modules/pda/core_apps.dm b/code/modules/pda/core_apps.dm index cd86e620970..41f9f994420 100644 --- a/code/modules/pda/core_apps.dm +++ b/code/modules/pda/core_apps.dm @@ -71,8 +71,8 @@ update = PDA_APP_UPDATE_SLOW /datum/data/pda/app/manifest/update_ui(mob/user as mob, list/data) - data_core.get_manifest_json() - data["manifest"] = PDA_Manifest + GLOB.data_core.get_manifest_json() + data["manifest"] = GLOB.PDA_Manifest /datum/data/pda/app/manifest/Topic(href, list/href_list) diff --git a/code/modules/pda/messenger.dm b/code/modules/pda/messenger.dm index ab97c956d85..5ccef4dee41 100644 --- a/code/modules/pda/messenger.dm +++ b/code/modules/pda/messenger.dm @@ -39,7 +39,7 @@ else var/convopdas[0] var/pdas[0] - for(var/A in PDAs) + for(var/A in GLOB.PDAs) var/obj/item/pda/P = A var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) @@ -143,32 +143,41 @@ // check if telecomms I/O route 1459 is stable //var/telecomms_intact = telecomms_process(P.owner, owner, t) var/obj/machinery/message_server/useMS = null - if(message_servers) - for(var/A in message_servers) + if(GLOB.message_servers) + for(var/A in GLOB.message_servers) var/obj/machinery/message_server/MS = A //PDAs are now dependent on the Message Server. if(MS.active) useMS = MS break - var/datum/signal/signal = pda.telecomms_process() + var/turf/sender_pos = get_turf(U) + var/turf/recipient_pos = get_turf(P) - var/useTC = 0 - if(signal) - if(signal.data["done"]) - useTC = 1 - var/turf/pos = get_turf(P) - // TODO: Make the radio system cooperate with the space manager - if(pos.z in signal.data["level"]) - useTC = 2 - //Let's make this barely readable - if(signal.data["compression"] > 0) - t = Gibberish(t, signal.data["compression"] + 50) + // Can the message be sent + var/sendable = FALSE + // Can the message be received? + var/receivable = FALSE + + for(var/obj/machinery/tcomms/core/C in GLOB.tcomms_machines) + if(C.zlevel_reachable(sender_pos.z)) + sendable = TRUE + if(C.zlevel_reachable(recipient_pos.z)) + receivable = TRUE + // Once both are done, exit the loop + if(sendable && receivable) + break + + if(!sendable) // Are we in the range of a reciever? + to_chat(U, "ERROR: No connection to server.") + return + + if(!receivable) // Is our recipient in the range of a reciever? + to_chat(U, "ERROR: No connection to recipient.") + return + + if(useMS && sendable && receivable) // only send the message if its going to work - if(useMS && useTC) // only send the message if it's stable - if(useTC != 2) // Does our recipient have a broadcaster on their level? - to_chat(U, "ERROR: Cannot reach recipient.") - return useMS.send_pda_message("[P.owner]","[pda.owner]","[t]") tnote.Add(list(list("sent" = 1, "owner" = "[P.owner]", "job" = "[P.ownjob]", "message" = "[t]", "target" = "\ref[P]"))) @@ -201,7 +210,7 @@ to_chat(usr, "Turn on your receiver in order to send messages.") return - for(var/A in PDAs) + for(var/A in GLOB.PDAs) var/obj/item/pda/P = A var/datum/data/pda/app/messenger/PM = P.find_program(/datum/data/pda/app/messenger) diff --git a/code/modules/pda/pdas.dm b/code/modules/pda/pdas.dm index 0e5c58f968a..f6f02e3457f 100644 --- a/code/modules/pda/pdas.dm +++ b/code/modules/pda/pdas.dm @@ -38,11 +38,8 @@ desc = "A portable microcomputer by Thinktronic Systems, LTD. The surface is coated with polytetrafluoroethylene and banana drippings." ttone = "honk" - trip_stun = 8 - trip_weaken = 5 - trip_chance = 100 - trip_walksafe = TRUE - trip_verb = TV_SLIP +/obj/item/pda/clown/ComponentInitialize() + AddComponent(/datum/component/slippery, src, 8, 5, 100) /obj/item/pda/mime default_cartridge = /obj/item/cartridge/mime @@ -191,7 +188,7 @@ var/datum/data/pda/app/messenger/M = find_program(/datum/data/pda/app/messenger) if(M) M.m_hidden = 1 - + //Some spare PDAs in a box /obj/item/storage/box/PDAs name = "spare PDAs" diff --git a/code/modules/pda/radio.dm b/code/modules/pda/radio.dm index 3a2f4901caa..f214e705268 100644 --- a/code/modules/pda/radio.dm +++ b/code/modules/pda/radio.dm @@ -197,7 +197,7 @@ var/time = time2text(world.realtime,"hh:mm:ss") var/turf/T = get_turf(src) - lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + GLOB.lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") var/datum/signal/signal = new signal.source = src diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 3757d7e8cd1..234b885284e 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1,8 +1,3 @@ -#define APC_WIRE_IDSCAN 1 -#define APC_WIRE_MAIN_POWER1 2 -#define APC_WIRE_MAIN_POWER2 3 -#define APC_WIRE_AI_CONTROL 4 - //update_state #define UPSTATE_CELL_IN 1 #define UPSTATE_OPENED1 2 @@ -249,7 +244,7 @@ else if(has_electronics && !terminal) . += "Electronics installed but not wired." else /* if(!has_electronics && !terminal) */ - . += "There is no electronics nor connected wires." + . += "There are no electronics nor connected wires." else if(stat & MAINT) . += "The cover is closed. Something wrong with it: it doesn't work." @@ -430,11 +425,11 @@ if(stat & (NOPOWER | BROKEN)) return if(!second_pass) //The first time, we just cut overlays - addtimer(CALLBACK(src, .get_spooked, TRUE), 1) + addtimer(CALLBACK(src, /obj/machinery/power/apc/proc.get_spooked, TRUE), 1) cut_overlays() else flick("apcemag", src) //Second time we cause the APC to update its icon, then add a timer to update icon later - addtimer(CALLBACK(src, .proc/update_icon, TRUE), 10) + addtimer(CALLBACK(src, /obj/machinery/power/apc/proc.update_icon, TRUE), 10) //attack with an item - open/close cover, insert cell, or (un)lock interface /obj/machinery/power/apc/attackby(obj/item/W, mob/living/user, params) @@ -765,11 +760,11 @@ /obj/machinery/power/apc/proc/get_malf_status(mob/living/silicon/ai/malf) if(!istype(malf)) return FALSE - + // Only if they're a traitor OR they have the malf picker from the combat module if(!malf.mind.has_antag_datum(/datum/antagonist/traitor) && !malf.malf_picker) return FALSE - + if(malfai == (malf.parent || malf)) if(occupier == malf) return APC_MALF_SHUNTED_HERE @@ -793,7 +788,7 @@ // Auto update every Master Controller tick ui.set_auto_update(1) -/obj/machinery/power/apc/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/power/apc/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["locked"] = is_locked(user) data["isOperating"] = operating @@ -1079,7 +1074,7 @@ qdel(occupier) if(seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) for(var/obj/item/pinpointer/point in GLOB.pinpointer_list) - for(var/mob/living/silicon/ai/A in ai_list) + for(var/mob/living/silicon/ai/A in GLOB.ai_list) if((A.stat != DEAD) && A.nuking) point.the_disk = A //The pinpointer tracks the AI back into its core. else diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 7260c836d78..0dc2fe0a129 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -79,8 +79,10 @@ By design, d1 is the smallest direction and d2 is the highest return ..() // then go ahead and delete the cable /obj/structure/cable/deconstruct(disassembled = TRUE) + var/turf/T = get_turf(src) + if(usr) + investigate_log("was deconstructed by [key_name(usr, 1)] in [get_area(usr)]([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])","wires") if(!(flags & NODECONSTRUCT)) - var/turf/T = get_turf(src) if(d1) // 0-X cables are 1 unit, X-X cables are 2 units long new/obj/item/stack/cable_coil(T, 2, paramcolor = color) else diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index a5b83d8472c..cf04c8a66f8 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -3,7 +3,7 @@ // Gravity Generator // -var/list/gravity_generators = list() // We will keep track of this by adding new gravity generators to the list, and keying it with the z level. +GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding new gravity generators to the list, and keying it with the z level. #define GRAV_POWER_IDLE 0 #define GRAV_POWER_UP 1 @@ -388,19 +388,19 @@ var/list/gravity_generators = list() // We will keep track of this by adding new var/turf/T = get_turf(src) if(!T) return 0 - if(gravity_generators["[T.z]"]) - return length(gravity_generators["[T.z]"]) + if(GLOB.gravity_generators["[T.z]"]) + return length(GLOB.gravity_generators["[T.z]"]) return 0 /obj/machinery/gravity_generator/main/proc/update_list() var/turf/T = get_turf(src.loc) if(T) - if(!gravity_generators["[T.z]"]) - gravity_generators["[T.z]"] = list() + if(!GLOB.gravity_generators["[T.z]"]) + GLOB.gravity_generators["[T.z]"] = list() if(on) - gravity_generators["[T.z]"] |= src + GLOB.gravity_generators["[T.z]"] |= src else - gravity_generators["[T.z]"] -= src + GLOB.gravity_generators["[T.z]"] -= src // Misc diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 78c2561ae7d..0a31d882488 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -39,81 +39,86 @@ if(3) . += "The casing is closed." -/obj/machinery/light_construct/attackby(obj/item/W as obj, mob/living/user as mob, params) - src.add_fingerprint(user) - if(istype(W, /obj/item/wrench)) - if(src.stage == 1) - playsound(src.loc, W.usesound, 75, 1) - to_chat(usr, "You begin deconstructing [src].") - if(!do_after(usr, 30 * W.toolspeed, target = src)) +/obj/machinery/light_construct/wrench_act(mob/living/user, obj/item/I) + . = TRUE + switch(stage) + if(1) + to_chat(user, "You begin deconstructing [src].") + if(!I.use_tool(src, user, 30, volume = I.tool_volume)) return - new /obj/item/stack/sheet/metal( get_turf(src.loc), sheets_refunded ) - user.visible_message("[user.name] deconstructs [src].", \ - "You deconstruct [src].", "You hear a noise.") - playsound(src.loc, W.usesound, 75, 1) + new /obj/item/stack/sheet/metal(get_turf(loc), sheets_refunded) + user.visible_message("[user] deconstructs [src].", \ + "You deconstruct [src].", "You hear a noise.") qdel(src) - if(src.stage == 2) - to_chat(usr, "You have to remove the wires first.") - return + if(2) + to_chat(user, "You have to remove the wires first.") + if(3) + to_chat(user, "You have to unscrew the case first.") - if(src.stage == 3) - to_chat(usr, "You have to unscrew the case first.") - return - - if(istype(W, /obj/item/wirecutters)) - if(src.stage != 2) return - src.stage = 1 - switch(fixture_type) - if("tube") - src.icon_state = "tube-construct-stage1" - if("bulb") - src.icon_state = "bulb-construct-stage1" - new /obj/item/stack/cable_coil(get_turf(src.loc), 1, paramcolor = COLOR_RED) - user.visible_message("[user.name] removes the wiring from [src].", \ - "You remove the wiring from [src].", "You hear a noise.") - playsound(loc, W.usesound, 100, 1) +/obj/machinery/light_construct/wirecutter_act(mob/living/user, obj/item/I) + if(stage != 2) return + . = TRUE + if(!I.use_tool(src, user, 0)) + return + playsound(loc, I.usesound, 100, 1) + . = TRUE + stage = 1 + switch(fixture_type) + if("tube") + icon_state = "tube-construct-stage1" + if("bulb") + icon_state = "bulb-construct-stage1" + new /obj/item/stack/cable_coil(get_turf(loc), 1, paramcolor = COLOR_RED) + user.visible_message("[user] removes the wiring from [src].", \ + "You remove the wiring from [src].", "You hear a noise.") + +/obj/machinery/light_construct/screwdriver_act(mob/living/user, obj/item/I) + if(stage != 2) + return + . = TRUE + if(!I.use_tool(src, user, 0)) + return + switch(fixture_type) + if("tube") + icon_state = "tube-empty" + if("bulb") + icon_state = "bulb-empty" + stage = 3 + user.visible_message("[user] closes [src]'s casing.", \ + "You close [src]'s casing.", "You hear a noise.") + playsound(loc, I.usesound, 75, 1) + + switch(fixture_type) + if("tube") + newlight = new /obj/machinery/light/built(loc) + if("bulb") + newlight = new /obj/machinery/light/small/built(loc) + + newlight.setDir(dir) + transfer_fingerprints_to(newlight) + qdel(src) + +/obj/machinery/light_construct/attackby(obj/item/W, mob/living/user, params) + add_fingerprint(user) if(istype(W, /obj/item/stack/cable_coil)) - if(src.stage != 1) return + if(stage != 1) + return var/obj/item/stack/cable_coil/coil = W coil.use(1) switch(fixture_type) if("tube") - src.icon_state = "tube-construct-stage2" + icon_state = "tube-construct-stage2" if("bulb") - src.icon_state = "bulb-construct-stage2" - src.stage = 2 + icon_state = "bulb-construct-stage2" + stage = 2 playsound(loc, coil.usesound, 50, 1) - user.visible_message("[user.name] adds wires to [src].", \ - "You add wires to [src].") + user.visible_message("[user.name] adds wires to [src].", \ + "You add wires to [src].") return - if(istype(W, /obj/item/screwdriver)) - if(src.stage == 2) - switch(fixture_type) - if("tube") - src.icon_state = "tube-empty" - if("bulb") - src.icon_state = "bulb-empty" - src.stage = 3 - user.visible_message("[user.name] closes [src]'s casing.", \ - "You close [src]'s casing.", "You hear a noise.") - playsound(src.loc, W.usesound, 75, 1) - - switch(fixture_type) - - if("tube") - newlight = new /obj/machinery/light/built(src.loc) - if("bulb") - newlight = new /obj/machinery/light/small/built(src.loc) - - newlight.dir = src.dir - src.transfer_fingerprints_to(newlight) - qdel(src) - return - else - return ..() + return ..() /obj/machinery/light_construct/blob_act(obj/structure/blob/B) if(B && B.loc == loc) diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 54b81cb9272..b534fbbfda4 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -333,7 +333,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/power/port_gen/pacman/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/power/port_gen/pacman/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["active"] = active diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 7b43291b5a2..c74f9cc0007 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -162,7 +162,7 @@ var/cdir var/turf/T - for(var/card in cardinal) + for(var/card in GLOB.cardinal) T = get_step(loc,card) cdir = get_dir(T,loc) @@ -182,7 +182,7 @@ var/cdir var/turf/T - for(var/card in cardinal) + for(var/card in GLOB.cardinal) T = get_step(loc,card) cdir = get_dir(T,loc) diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm index 870a42a1f7c..e6a933c4458 100644 --- a/code/modules/power/singularity/collector.dm +++ b/code/modules/power/singularity/collector.dm @@ -1,4 +1,4 @@ -var/global/list/rad_collectors = list() +GLOBAL_LIST_EMPTY(rad_collectors) /obj/machinery/power/rad_collector name = "Radiation Collector Array" @@ -19,10 +19,10 @@ var/global/list/rad_collectors = list() /obj/machinery/power/rad_collector/Initialize(mapload) . = ..() - rad_collectors += src + GLOB.rad_collectors += src /obj/machinery/power/rad_collector/Destroy() - rad_collectors -= src + GLOB.rad_collectors -= src return ..() /obj/machinery/power/rad_collector/process() diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 62f2ed36065..b70a79106be 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -113,15 +113,15 @@ field_generator power level display if(!I.tool_use_check(user, 0)) return if(state == FG_SECURED) - WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE - else if(state == FG_WELDED) WELDER_ATTEMPT_FLOOR_WELD_MESSAGE + else if(state == FG_WELDED) + WELDER_ATTEMPT_FLOOR_SLICE_MESSAGE if(I.use_tool(src, user, 20, volume = I.tool_volume)) if(state == FG_SECURED) - WELDER_FLOOR_SLICE_SUCCESS_MESSAGE + WELDER_FLOOR_WELD_SUCCESS_MESSAGE state = FG_WELDED else if(state == FG_WELDED) - WELDER_FLOOR_WELD_SUCCESS_MESSAGE + WELDER_FLOOR_SLICE_SUCCESS_MESSAGE state = FG_SECURED /obj/machinery/field/generator/emp_act() diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index cf3a16432c0..74acdf618d0 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -93,7 +93,7 @@ /obj/singularity/narsie/proc/pickcultist() //Narsie rewards his cultists with being devoured first, then picks a ghost to follow. --NEO var/list/cultists = list() var/list/noncultists = list() - for(var/mob/living/carbon/food in GLOB.living_mob_list) //we don't care about constructs or cult-Ians or whatever. cult-monkeys are fair game i guess + for(var/mob/living/carbon/food in GLOB.alive_mob_list) //we don't care about constructs or cult-Ians or whatever. cult-monkeys are fair game i guess var/turf/pos = get_turf(food) if(pos.z != src.z) continue diff --git a/code/modules/power/singularity/particle_accelerator/particle.dm b/code/modules/power/singularity/particle_accelerator/particle.dm index e409ccc7602..93eb3fa18c6 100644 --- a/code/modules/power/singularity/particle_accelerator/particle.dm +++ b/code/modules/power/singularity/particle_accelerator/particle.dm @@ -5,20 +5,19 @@ icon_state = "particle" anchored = TRUE density = FALSE - var/movement_range = 10 + var/movement_range = 11 var/energy = 10 - var/speed = 1 /obj/effect/accelerated_particle/weak - movement_range = 8 + movement_range = 9 energy = 5 /obj/effect/accelerated_particle/strong - movement_range = 15 + movement_range = 16 energy = 15 /obj/effect/accelerated_particle/powerful - movement_range = 20 + movement_range = 21 energy = 50 diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index fcc37bf943b..61e1d786490 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -113,7 +113,7 @@ if(allowed_size >= STAGE_TWO) // Start moving even before we reach "true" stage two. // If we are stage one and are sufficiently energetic to be allowed to 2, - // it might mean we are stuck in a corner somewere. So move around to try to expand. + // it might mean we are stuck in a corner somewere. So move around to try to expand. move() if(current_size >= STAGE_TWO) pulse() @@ -287,7 +287,7 @@ if(!move_self) return 0 - var/movement_dir = pick(alldirs - last_failed_movement) + var/movement_dir = pick(GLOB.alldirs - last_failed_movement) if(force_move) movement_dir = force_move @@ -431,7 +431,7 @@ /obj/singularity/proc/pulse() - for(var/obj/machinery/power/rad_collector/R in rad_collectors) + for(var/obj/machinery/power/rad_collector/R in GLOB.rad_collectors) if(R.z == z && get_dist(R, src) <= 15) // Better than using orange() every process R.receive_pulse(energy) diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 05451033703..f88128ab974 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -29,11 +29,6 @@ var/output_level_max = 200000 // cap on output_level var/output_used = 0 // amount of power actually outputted. may be less than output_level if the powernet returns excess power - //Holders for powerout event. - var/last_output_attempt = 0 - var/last_input_attempt = 0 - var/last_charge = 0 - var/name_tag = null var/obj/machinery/power/terminal/terminal = null @@ -51,7 +46,7 @@ RefreshParts() dir_loop: - for(var/d in cardinal) + for(var/d in GLOB.cardinal) var/turf/T = get_step(src, d) for(var/obj/machinery/power/terminal/term in T) if(term && term.dir == turn(d, 180)) @@ -371,7 +366,7 @@ // auto update every Master Controller tick ui.set_auto_update(1) -/obj/machinery/power/smes/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/power/smes/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["nameTag"] = name_tag diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index 3a1f13bd10e..d99df1de7bb 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -285,13 +285,15 @@ autostart = 1 // Automatically start /obj/machinery/power/solar_control/Initialize() - ..() - if(!powernet) - return + SSsun.solars |= src + setup() + . = ..() + +/obj/machinery/power/solar_control/proc/setup() connect_to_network() set_panels(cdir) if(autostart) - src.search_for_connected() + search_for_connected() if(connected_tracker && track == 2) connected_tracker.set_angle(SSsun.angle) set_panels(cdir) @@ -379,7 +381,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/power/solar_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/power/solar_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["generated"] = round(lastgen) diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 463121a7bdf..7e1d4f59267 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -183,7 +183,7 @@ if(damage > explosion_point) if(get_turf(src)) var/turf/position = get_turf(src) - for(var/mob/living/mob in GLOB.living_mob_list) + for(var/mob/living/mob in GLOB.alive_mob_list) var/turf/mob_pos = get_turf(mob) if(mob_pos && mob_pos.z == position.z) if(ishuman(mob)) @@ -344,7 +344,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/power/supermatter_shard/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/power/supermatter_shard/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["integrity_percentage"] = round(get_integrity()) @@ -366,7 +366,7 @@ return data /obj/machinery/power/supermatter_shard/proc/transfer_energy() - for(var/obj/machinery/power/rad_collector/R in rad_collectors) + for(var/obj/machinery/power/rad_collector/R in GLOB.rad_collectors) if(get_dist(R, src) <= 15) // Better than using orange() every process R.receive_pulse(power/10) return diff --git a/code/modules/power/tesla/energy_ball.dm b/code/modules/power/tesla/energy_ball.dm index a3a8bb42ec6..60b2a30dc34 100644 --- a/code/modules/power/tesla/energy_ball.dm +++ b/code/modules/power/tesla/energy_ball.dm @@ -67,7 +67,7 @@ //we face the last thing we zapped, so this lets us favor that direction a bit var/first_move = dir for(var/i in 0 to move_amount) - var/move_dir = pick(alldirs + first_move) //give the first move direction a bit of favoring. + var/move_dir = pick(GLOB.alldirs + first_move) //give the first move direction a bit of favoring. if(target && prob(60)) move_dir = get_dir(src,target) var/turf/T = get_step(src, move_dir) diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm index f8b13b47874..8536a0195e3 100644 --- a/code/modules/projectiles/ammunition.dm +++ b/code/modules/projectiles/ammunition.dm @@ -25,7 +25,7 @@ BB = new projectile_type(src) pixel_x = rand(-10.0, 10) pixel_y = rand(-10.0, 10) - dir = pick(alldirs) + dir = pick(GLOB.alldirs) update_icon() /obj/item/ammo_casing/update_icon() diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index d17da9a6d99..d071ad236d1 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -32,8 +32,8 @@ /obj/item/gun/energy/get_cell() return cell -/obj/item/gun/energy/New() - ..() +/obj/item/gun/energy/Initialize(mapload, ...) + . = ..() if(cell_type) cell = new cell_type(src) else diff --git a/code/modules/projectiles/guns/energy/nuclear.dm b/code/modules/projectiles/guns/energy/nuclear.dm index 09b2400c165..2df2d877c53 100644 --- a/code/modules/projectiles/guns/energy/nuclear.dm +++ b/code/modules/projectiles/guns/energy/nuclear.dm @@ -36,9 +36,9 @@ can_flashlight = 0 // Can't attach or detach the flashlight, and override it's icon update actions_types = list(/datum/action/item_action/toggle_gunlight) -/obj/item/gun/energy/gun/mini/New() +/obj/item/gun/energy/gun/mini/Initialize(mapload, ...) gun_light = new /obj/item/flashlight/seclite(src) - ..() + . = ..() cell.maxcharge = 600 cell.charge = 600 diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 7705f3eb66c..e64aced32f9 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -341,8 +341,8 @@ var/emagged = 0 //ups the temperature cap from 500 to 1000, targets hit by beams over 500 Kelvin will burst into flames var/dat = "" -/obj/item/gun/energy/temperature/New() - ..() +/obj/item/gun/energy/temperature/Initialize(mapload, ...) + . = ..() update_icon() START_PROCESSING(SSobj, src) diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm index c2dc67f5773..44273f1e653 100644 --- a/code/modules/projectiles/guns/magic.dm +++ b/code/modules/projectiles/guns/magic.dm @@ -40,7 +40,7 @@ chambered.newshot(params) return -/obj/item/gun/magic/process_fire() +/obj/item/gun/magic/process_fire(atom/target as mob|obj|turf, mob/living/user as mob|obj, message = 1, params, zone_override, bonus_spread = 0) newshot() return ..() diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm index 544ca67a361..7a013f3083c 100644 --- a/code/modules/projectiles/guns/magic/wand.dm +++ b/code/modules/projectiles/guns/magic/wand.dm @@ -41,7 +41,7 @@ to_chat(user, "You know better than to violate the security of The Den, best wait until you leave to use [src].") return else - no_den_usage = 0 + no_den_usage = FALSE zap_self(user) else ..() @@ -51,6 +51,7 @@ user.visible_message("[user] zaps [user.p_them()]self with [src].") playsound(user, fire_sound, 50, 1) user.create_attack_log("[key_name(user)] zapped [user.p_them()]self with a [src]") + add_attack_logs(null, user, "zapped [user.p_them()]self with a [src]", ATKLOG_ALL) ///////////////////////////////////// //WAND OF DEATH @@ -117,7 +118,7 @@ ammo_type = /obj/item/ammo_casing/magic/teleport icon_state = "telewand" max_charges = 10 //10, 5, 5, 4 - no_den_usage = 1 + no_den_usage = TRUE fire_sound = 'sound/magic/wand_teleport.ogg' /obj/item/gun/magic/wand/teleport/zap_self(mob/living/user) @@ -139,6 +140,7 @@ fire_sound = 'sound/magic/staff_door.ogg' icon_state = "doorwand" max_charges = 20 //20, 10, 10, 7 + no_den_usage = TRUE /obj/item/gun/magic/wand/door/zap_self(mob/living/user) to_chat(user, "You feel vaguely more open with your feelings.") diff --git a/code/modules/projectiles/guns/medbeam.dm b/code/modules/projectiles/guns/medbeam.dm index 501a7b63670..056c454663c 100644 --- a/code/modules/projectiles/guns/medbeam.dm +++ b/code/modules/projectiles/guns/medbeam.dm @@ -106,7 +106,7 @@ target.adjustBruteLoss(-4) target.adjustFireLoss(-4) if(ishuman(target)) - var/var/mob/living/carbon/human/H = target + var/mob/living/carbon/human/H = target for(var/obj/item/organ/external/E in H.bodyparts) if(prob(10)) E.mend_fracture() diff --git a/code/modules/projectiles/guns/projectile/sniper.dm b/code/modules/projectiles/guns/projectile/sniper.dm index 09d9ec15aed..761c15a6141 100644 --- a/code/modules/projectiles/guns/projectile/sniper.dm +++ b/code/modules/projectiles/guns/projectile/sniper.dm @@ -43,7 +43,8 @@ /obj/item/gun/projectile/automatic/sniper_rifle/compact //holds very little ammo, lacks zooming, and bullets are primarily damage dealers, but the gun lacks the downsides of the full size rifle name = "compact sniper rifle" - desc = "a compact, unscoped version of the standard issue syndicate sniper rifle. Still capable of sending people crying." + desc = "A compact, unscoped version of the standard issue syndicate sniper rifle. Still capable of sending people crying." + icon_state = "snipercompact" recoil = 0 weapon_weight = WEAPON_LIGHT fire_delay = 0 @@ -52,6 +53,12 @@ can_suppress = FALSE zoomable = FALSE +/obj/item/gun/projectile/automatic/sniper_rifle/compact/update_icon() + if(magazine) + icon_state = "snipercompact-mag" + else + icon_state = "snipercompact" + //Normal Boolets /obj/item/ammo_box/magazine/sniper_rounds name = "sniper rounds (.50)" diff --git a/code/modules/projectiles/guns/rocket.dm b/code/modules/projectiles/guns/rocket.dm index 53de1a16854..96a97c8fe1a 100644 --- a/code/modules/projectiles/guns/rocket.dm +++ b/code/modules/projectiles/guns/rocket.dm @@ -36,7 +36,7 @@ to_chat(user, "You put the rocket in [src].") to_chat(user, "[rockets.len] / [max_rockets] rockets.") else - to_chat(usr, "[src] cannot hold more rockets.") + to_chat(user, "[src] cannot hold more rockets.") else return ..() @@ -55,4 +55,4 @@ rockets -= I qdel(I) else - to_chat(usr, "[src] is empty.") + to_chat(user, "[src] is empty.") diff --git a/code/modules/projectiles/guns/throw/crossbow.dm b/code/modules/projectiles/guns/throw/crossbow.dm index ca626534320..dc03a76fb48 100644 --- a/code/modules/projectiles/guns/throw/crossbow.dm +++ b/code/modules/projectiles/guns/throw/crossbow.dm @@ -94,25 +94,29 @@ user.visible_message("[usr] draws back the string of [src]!","[src] clunks as you draw the string to its maximum tension!!") update_icon() -/obj/item/gun/throw/crossbow/attackby(obj/item/W as obj, mob/user as mob, params) - if(istype(W, /obj/item/stock_parts/cell)) - if(!cell) - user.drop_item() - W.loc = src - cell = W - to_chat(user, "You jam [cell] into [src] and wire it to the firing coil.") - process_chamber() - else - to_chat(user, "[src] already has a cell installed.") - else if(istype(W, /obj/item/screwdriver)) - if(cell) - cell.loc = get_turf(src) - to_chat(user, "You jimmy [cell] out of [src] with [W].") - cell = null - else - to_chat(user, "[src] doesn't have a cell installed.") - else - ..() +/obj/item/gun/throw/crossbow/attackby(obj/item/I, mob/user, params) + if(!istype(I, /obj/item/stock_parts/cell)) + return ..() + + if(cell) + to_chat(user, "[src] already has a cell installed.") + return + + user.drop_item() + I.forceMove(src) + cell = I + to_chat(user, "You jam [cell] into [src] and wire it to the firing coil.") + process_chamber() + +/obj/item/gun/throw/crossbow/screwdriver_act(mob/user, obj/item/I) + . = ..() + if(!cell) + to_chat(user, "[src] doesn't have a cell installed.") + return + + cell.forceMove(get_turf(src)) + to_chat(user, "You jimmy [cell] out of [src] with [I].") + cell = null /obj/item/gun/throw/crossbow/verb/set_tension() set name = "Adjust Tension" diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 01503fb16b7..dc70eda9cec 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -263,12 +263,14 @@ return M.create_attack_log("[key_name(M)] became [new_mob.real_name].") - new_mob.attack_log = M.attack_log + add_attack_logs(null, M, "became [new_mob.real_name]", ATKLOG_ALL) new_mob.a_intent = INTENT_HARM if(M.mind) M.mind.transfer_to(new_mob) else + new_mob.attack_log_old = M.attack_log_old.Copy() + new_mob.logs = M.logs.Copy() new_mob.key = M.key to_chat(new_mob, "Your form morphs into that of a [randomize].") @@ -283,7 +285,7 @@ /obj/item/projectile/magic/animate/Bump(var/atom/change) ..() - if(istype(change, /obj/item) || istype(change, /obj/structure) && !is_type_in_list(change, protected_objects)) + if(istype(change, /obj/item) || istype(change, /obj/structure) && !is_type_in_list(change, GLOB.protected_objects)) if(istype(change, /obj/structure/closet/statue)) for(var/mob/living/carbon/human/H in change.contents) var/mob/living/simple_animal/hostile/statue/S = new /mob/living/simple_animal/hostile/statue(change.loc, firer) diff --git a/code/modules/reagents/chem_splash.dm b/code/modules/reagents/chem_splash.dm index 6ad51779965..9b15b6dca5d 100644 --- a/code/modules/reagents/chem_splash.dm +++ b/code/modules/reagents/chem_splash.dm @@ -41,7 +41,7 @@ for(var/turf/T in (orange(i, epicenter) - orange(i-1, epicenter))) turflist |= T for(var/turf/T in turflist) - if( !(get_dir(T,epicenter) in cardinal) && (abs(T.x - epicenter.x) == abs(T.y - epicenter.y) )) + if( !(get_dir(T,epicenter) in GLOB.cardinal) && (abs(T.x - epicenter.x) == abs(T.y - epicenter.y) )) turflist.Remove(T) turflist.Add(T) // we move the purely diagonal turfs to the end of the list. for(var/turf/T in turflist) @@ -51,7 +51,7 @@ var/turf/NT = thing if(!(NT in accessible)) continue - if(!(get_dir(T,NT) in cardinal)) + if(!(get_dir(T,NT) in GLOB.cardinal)) continue accessible[T] = 1 break diff --git a/code/modules/reagents/chemistry/colors.dm b/code/modules/reagents/chemistry/colors.dm index e9ced2ecfbe..f5f4f252a01 100644 --- a/code/modules/reagents/chemistry/colors.dm +++ b/code/modules/reagents/chemistry/colors.dm @@ -2,7 +2,7 @@ * Returns: * #RRGGBB(AA) on success, null on failure */ -var/list/random_color_list = list("#00aedb","#a200ff","#f47835","#d41243","#d11141","#00b159","#00aedb","#f37735","#ffc425","#008744","#0057e7","#d62d20","#ffa700") +GLOBAL_LIST_INIT(random_color_list, list("#00aedb","#a200ff","#f47835","#d41243","#d11141","#00b159","#00aedb","#f37735","#ffc425","#008744","#0057e7","#d62d20","#ffa700")) /proc/mix_color_from_reagents(const/list/reagent_list) if(!istype(reagent_list)) diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 9774021210c..8811d8f2584 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -8,15 +8,18 @@ var/maximum_volume = 100 var/atom/my_atom = null var/chem_temp = T20C + var/temperature_min = 0 + var/temperature_max = 10000 var/list/datum/reagent/addiction_list = new/list() var/list/addiction_threshold_accumulated = new/list() var/flags - var/list/reagents_generated_per_cycle = new/list() -/datum/reagents/New(maximum = 100) +/datum/reagents/New(maximum = 100, temperature_minimum, temperature_maximum) maximum_volume = maximum - if(!(flags & REAGENT_NOREACT)) - START_PROCESSING(SSobj, src) + if(temperature_minimum) + temperature_min = temperature_minimum + if(temperature_maximum) + temperature_max = temperature_maximum //I dislike having these here but map-objects are initialised before world/New() is called. >_> if(!GLOB.chemical_reagents_list) //Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id @@ -179,7 +182,7 @@ return amount /datum/reagents/proc/set_reagent_temp(new_temp = T0C, react = TRUE) - chem_temp = new_temp + chem_temp = Clamp(new_temp, temperature_min, temperature_max) if(react) temperature_react() handle_reactions() @@ -197,7 +200,7 @@ else if(exposed_temperature < chem_temp) chem_temp -= change - chem_temp = max(min(chem_temp, 10000), 0) //Cap for the moment. + chem_temp = max(min(chem_temp, temperature_max), temperature_min) //Cap for the moment. temperature_react() handle_reactions() @@ -299,10 +302,7 @@ if(R.addiction_stage < 5) if(prob(5)) R.addiction_stage++ - if(M.reagents.has_reagent(R.id)) - R.last_addiction_dose = world.timeofday - R.addiction_stage = 1 - else + if(world.timeofday > R.last_addiction_dose) //time check so addiction act doesn't play over and over. Allows incremental dosages to work. switch(R.addiction_stage) if(1) update_flags |= R.addiction_act_stage1(M) @@ -328,6 +328,7 @@ M.update_canmove() if(update_flags & STATUS_UPDATE_STAMINA) M.update_stamina() + M.update_health_hud() if(update_flags & STATUS_UPDATE_BLIND) M.update_blind_effects() if(update_flags & STATUS_UPDATE_BLURRY) @@ -357,23 +358,10 @@ od_chems.Add(R.id) return od_chems -/datum/reagents/process() - if(flags & REAGENT_NOREACT) - STOP_PROCESSING(SSobj, src) - return - for(var/thing in reagents_generated_per_cycle) - add_reagent(thing, reagents_generated_per_cycle[thing]) - for(var/datum/reagent/R in reagent_list) - R.on_tick() - /datum/reagents/proc/set_reacting(react = TRUE) if(react) - // Order is important, process() can remove from processing if - // the flag is present flags &= ~(REAGENT_NOREACT) - START_PROCESSING(SSobj, src) else - STOP_PROCESSING(SSobj, src) flags |= REAGENT_NOREACT /* @@ -572,7 +560,7 @@ can_process = 1 return can_process -/datum/reagents/proc/reaction(atom/A, method = REAGENT_TOUCH, volume_modifier = 1) +/datum/reagents/proc/reaction(atom/A, method = REAGENT_TOUCH, volume_modifier = 1, show_message = TRUE) var/react_type if(isliving(A)) react_type = "LIVING" @@ -617,7 +605,7 @@ var/check = reaction_check(A, R) if(!check) continue - R.reaction_mob(A, method, R.volume * volume_modifier) + R.reaction_mob(A, method, R.volume * volume_modifier, show_message) if("TURF") R.reaction_turf(A, R.volume * volume_modifier) if("OBJ") @@ -635,7 +623,7 @@ if(total_volume + amount > maximum_volume) amount = (maximum_volume - total_volume) //Doesnt fit in. Make it disappear. Shouldnt happen. Will happen. if(amount <= 0) return 0 - chem_temp = (chem_temp * total_volume + reagtemp * amount) / (total_volume + amount) //equalize with new chems + chem_temp = Clamp((chem_temp * total_volume + reagtemp * amount) / (total_volume + amount), temperature_min, temperature_max) //equalize with new chems for(var/A in reagent_list) @@ -873,8 +861,8 @@ // Convenience proc to create a reagents holder for an atom // Max vol is maximum volume of holder -/atom/proc/create_reagents(max_vol) - reagents = new/datum/reagents(max_vol) +/atom/proc/create_reagents(max_vol, temperature_minimum, temperature_maximum) + reagents = new /datum/reagents(max_vol, temperature_minimum, temperature_maximum) reagents.my_atom = src /proc/get_random_reagent_id() // Returns a random reagent ID minus blacklisted reagents @@ -902,7 +890,6 @@ /datum/reagents/Destroy() . = ..() - STOP_PROCESSING(SSobj, src) QDEL_LIST(reagent_list) reagent_list = null QDEL_LIST(addiction_list) diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index cca429276dd..91d5900610d 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -155,7 +155,7 @@ // open the new ui window ui.open() -/obj/machinery/chem_dispenser/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/chem_dispenser/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["amount"] = amount @@ -275,14 +275,17 @@ if(!panel_open) return if(default_deconstruction_crowbar(user, I)) - if(beaker) - beaker.forceMove(loc) - beaker = null - if(cell) - cell.forceMove(loc) - cell = null return TRUE +/obj/machinery/chem_dispenser/deconstruct(disassembled) + if(beaker) + beaker.forceMove(loc) + beaker = null + if(cell) + cell.forceMove(loc) + cell = null + return ..() + /obj/machinery/chem_dispenser/multitool_act(mob/user, obj/item/I) . = TRUE diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index 169b668250c..79fc47d61a8 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -140,7 +140,7 @@ ui = new(user, src, ui_key, "chem_heater.tmpl", "ChemHeater", 350, 270) ui.open() -/obj/machinery/chem_heater/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/chem_heater/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["targetTemp"] = desired_temp diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 39d491bf192..cf7ff936b6d 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -347,8 +347,8 @@ if(count > 20) count = 20 //Pevent people from creating huge stacks of patches easily. Maybe move the number to defines? var/amount_per_patch = reagents.total_volume/count - if(amount_per_patch > 40) - amount_per_patch = 40 + if(amount_per_patch > 30) + amount_per_patch = 30 var/name = clean_input("Name:", "Name your patch!", "[reagents.get_master_reagent_name()] ([amount_per_patch]u)") if(!name) return @@ -445,7 +445,7 @@ ui = new(user, src, ui_key, "chem_master.tmpl", name, 575, 500) ui.open() -/obj/machinery/chem_master/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/chem_master/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["condi"] = condi diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index ced53381c9f..c748df2a8e4 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -84,8 +84,8 @@ var/vaccine_name = "Unknown" if(!ispath(vaccine_type)) - if(archive_diseases[path]) - var/datum/disease/D = archive_diseases[path] + if(GLOB.archive_diseases[path]) + var/datum/disease/D = GLOB.archive_diseases[path] if(D) vaccine_name = D.name vaccine_type = path @@ -109,11 +109,11 @@ var/datum/disease/D = null if(!ispath(type)) D = GetVirusByIndex(text2num(href_list["create_virus_culture"])) - var/datum/disease/advance/A = archive_diseases[D.GetDiseaseID()] + var/datum/disease/advance/A = GLOB.archive_diseases[D.GetDiseaseID()] if(A) D = new A.type(0, A) else if(type) - if(type in diseases) // Make sure this is a disease + if(type in GLOB.diseases) // Make sure this is a disease D = new type(0, null) if(!D) return @@ -154,15 +154,15 @@ if(..()) return var/id = GetVirusTypeByIndex(text2num(href_list["name_disease"])) - if(archive_diseases[id]) - var/datum/disease/advance/A = archive_diseases[id] + if(GLOB.archive_diseases[id]) + var/datum/disease/advance/A = GLOB.archive_diseases[id] A.AssignName(new_name) for(var/datum/disease/advance/AD in GLOB.active_diseases) AD.Refresh() updateUsrDialog() else if(href_list["print_form"]) var/datum/disease/D = GetVirusByIndex(text2num(href_list["print_form"])) - D = archive_diseases[D.GetDiseaseID()]//We know it's advanced no need to check + D = GLOB.archive_diseases[D.GetDiseaseID()]//We know it's advanced no need to check print_form(D, usr) @@ -180,7 +180,7 @@ //Prints a nice virus release form. Props to Urbanliner for the layout /obj/machinery/computer/pandemic/proc/print_form(var/datum/disease/advance/D, mob/living/user) - D = archive_diseases[D.GetDiseaseID()] + D = GLOB.archive_diseases[D.GetDiseaseID()] if(!(printing) && D) var/reason = input(user,"Enter a reason for the release", "Write", null) as message reason += "" @@ -260,7 +260,7 @@ if(istype(D, /datum/disease/advance)) var/datum/disease/advance/A = D - D = archive_diseases[A.GetDiseaseID()] + D = GLOB.archive_diseases[A.GetDiseaseID()] if(D) if(D.name == "Unknown") dat += "Name Disease
    " @@ -300,7 +300,7 @@ var/disease_name = "Unknown" if(!ispath(type)) - var/datum/disease/advance/A = archive_diseases[type] + var/datum/disease/advance/A = GLOB.archive_diseases[type] if(A) disease_name = A.name else diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index 26dfa2d815f..7f0ed2c91dc 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -43,7 +43,7 @@ /datum/reagent/proc/reaction_temperature(exposed_temperature, exposed_volume) //By default we do nothing. return -/datum/reagent/proc/reaction_mob(mob/living/M, method = REAGENT_TOUCH, volume) //Some reagents transfer on touch, others don't; dependent on if they penetrate the skin or not. +/datum/reagent/proc/reaction_mob(mob/living/M, method = REAGENT_TOUCH, volume, show_message = TRUE) //Some reagents transfer on touch, others don't; dependent on if they penetrate the skin or not. if(holder) //for catching rare runtimes if(method == REAGENT_TOUCH && penetrates_skin) var/block = M.get_permeability_protection() @@ -54,15 +54,9 @@ if(method == REAGENT_INGEST) //Yes, even Xenos can get addicted to drugs. var/can_become_addicted = M.reagents.reaction_check(M, src) - if(can_become_addicted) if(is_type_in_list(src, M.reagents.addiction_list)) - to_chat(M, "You feel slightly better, but for how long?") - for(var/A in M.reagents.addiction_list) - var/datum/reagent/AD = A - if(AD && istype(AD, src)) - AD.last_addiction_dose = world.timeofday - AD.addiction_stage = 1 + to_chat(M, "You feel slightly better, but for how long?") //sate_addiction handles this now, but kept this for the feed back. return TRUE /datum/reagent/proc/reaction_obj(obj/O, volume) @@ -76,6 +70,7 @@ var/total_depletion_rate = metabolization_rate * M.metabolism_efficiency * M.digestion_ratio // Cache it handle_addiction(M, total_depletion_rate) + sate_addiction(M) holder.remove_reagent(id, total_depletion_rate) //By default it slowly disappears. return STATUS_UPDATE_NONE @@ -91,6 +86,14 @@ new_reagent.last_addiction_dose = world.timeofday M.reagents.addiction_list.Add(new_reagent) +/datum/reagent/proc/sate_addiction(mob/living/M) //reagents sate their own withdrawals + if(is_type_in_list(src, M.reagents.addiction_list)) + for(var/A in M.reagents.addiction_list) + var/datum/reagent/AD = A + if(AD && istype(AD, src)) + AD.last_addiction_dose = world.timeofday + AD.addiction_stage = 1 + /datum/reagent/proc/on_mob_death(mob/living/M) //use this to have chems have a "death-triggered" effect return @@ -117,8 +120,10 @@ return // Called every time reagent containers process. -/datum/reagent/proc/on_tick(data) - return +/datum/reagent/process() + if(!holder || holder.flags & REAGENT_NOREACT) + return FALSE + return TRUE // Called when the reagent container is hit by an explosion /datum/reagent/proc/on_ex_act(severity) @@ -200,9 +205,7 @@ return M.emote("deathgasp") M.status_flags |= FAKEDEATH - M.update_stat("fakedeath reagent") - M.med_hud_set_health() - M.med_hud_set_status() + M.updatehealth("fakedeath reagent") /datum/reagent/proc/fakerevive(mob/living/M) if(!(M.status_flags & FAKEDEATH)) @@ -212,10 +215,6 @@ if(M.resting) M.StopResting() M.status_flags &= ~(FAKEDEATH) - M.update_stat("fakedeath reagent end") - M.med_hud_set_status() - M.med_hud_set_health() if(M.healthdoll) M.healthdoll.cached_healthdoll_overlays.Cut() - if(M.dna.species) - M.dna.species.handle_hud_icons(M) + M.updatehealth("fakedeath reagent end") diff --git a/code/modules/reagents/chemistry/reagents/alcohol.dm b/code/modules/reagents/chemistry/reagents/alcohol.dm index 2831d0e3f89..2dde295a70a 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol.dm @@ -6,8 +6,6 @@ reagent_state = LIQUID nutriment_factor = 0 //So alcohol can fill you up! If they want to. color = "#404030" // rgb: 64, 64, 48 - addiction_chance = 1 - addiction_threshold = 10 var/dizzy_adj = 3 var/alcohol_perc = 1 //percentage of ethanol in a beverage 0.0 - 1.0 taste_description = "liquid fire" diff --git a/code/modules/reagents/chemistry/reagents/drinks.dm b/code/modules/reagents/chemistry/reagents/drinks.dm index ae58c806126..4bd061c14b4 100644 --- a/code/modules/reagents/chemistry/reagents/drinks.dm +++ b/code/modules/reagents/chemistry/reagents/drinks.dm @@ -178,7 +178,7 @@ /datum/reagent/consumable/drink/banana/on_mob_life(mob/living/M) var/update_flags = STATUS_UPDATE_NONE - if((ishuman(M) && COMIC in M.mutations) || issmall(M)) + if((ishuman(M) && (COMIC in M.mutations)) || issmall(M)) update_flags |= M.adjustBruteLoss(-1, FALSE) update_flags |= M.adjustFireLoss(-1, FALSE) return ..() | update_flags @@ -409,7 +409,7 @@ /datum/reagent/consumable/drink/bananahonk/on_mob_life(mob/living/M) var/update_flags = STATUS_UPDATE_NONE - if((ishuman(M) && COMIC in M.mutations) || issmall(M)) + if((ishuman(M) && (COMIC in M.mutations)) || issmall(M)) update_flags |= M.adjustBruteLoss(-1, FALSE) update_flags |= M.adjustFireLoss(-1, FALSE) return ..() | update_flags @@ -426,7 +426,7 @@ /datum/reagent/consumable/drink/silencer/on_mob_life(mob/living/M) var/update_flags = STATUS_UPDATE_NONE - if(ishuman(M) && M.job in list("Mime")) + if(ishuman(M) && (M.job in list("Mime"))) update_flags |= M.adjustBruteLoss(-1, FALSE) update_flags |= M.adjustFireLoss(-1, FALSE) return ..() | update_flags diff --git a/code/modules/reagents/chemistry/reagents/drugs.dm b/code/modules/reagents/chemistry/reagents/drugs.dm index a9f5d8a9cb5..a848330e431 100644 --- a/code/modules/reagents/chemistry/reagents/drugs.dm +++ b/code/modules/reagents/chemistry/reagents/drugs.dm @@ -9,7 +9,7 @@ /datum/reagent/lithium/on_mob_life(mob/living/M) if(isturf(M.loc) && !istype(M.loc, /turf/space)) if(M.canmove && !M.restrained()) - step(M, pick(cardinal)) + step(M, pick(GLOB.cardinal)) if(prob(5)) M.emote(pick("twitch","drool","moan")) return ..() @@ -45,7 +45,7 @@ update_flags |= M.Druggy(15, FALSE) if(isturf(M.loc) && !istype(M.loc, /turf/space)) if(M.canmove && !M.restrained()) - step(M, pick(cardinal)) + step(M, pick(GLOB.cardinal)) if(prob(7)) M.emote(pick("twitch","drool","moan","giggle")) return ..() | update_flags @@ -322,13 +322,13 @@ update_flags |= M.AdjustWeakened(-2.5, FALSE) update_flags |= M.adjustStaminaLoss(-2, FALSE) update_flags |= M.SetSleeping(0, FALSE) - M.status_flags |= GOTTAGOFAST_METH + M.status_flags |= GOTTAGOFAST if(prob(50)) update_flags |= M.adjustBrainLoss(1, FALSE) return ..() | update_flags /datum/reagent/methamphetamine/on_mob_delete(mob/living/M) - M.status_flags &= ~GOTTAGOFAST_METH + M.status_flags &= ~GOTTAGOFAST ..() /datum/reagent/methamphetamine/overdose_process(mob/living/M, severity) @@ -684,7 +684,7 @@ update_flags |= M.AdjustStunned(-2, FALSE) update_flags |= M.AdjustWeakened(-2, FALSE) update_flags |= M.adjustStaminaLoss(-2, FALSE) - M.status_flags |= GOTTAGOFAST_METH + M.status_flags |= GOTTAGOFAST M.Jitter(3) update_flags |= M.adjustBrainLoss(0.5, FALSE) if(prob(5)) @@ -692,7 +692,7 @@ return ..() | update_flags /datum/reagent/lube/ultra/on_mob_delete(mob/living/M) - M.status_flags &= ~GOTTAGOFAST_METH + M.status_flags &= ~GOTTAGOFAST ..() /datum/reagent/lube/ultra/overdose_process(mob/living/M, severity) diff --git a/code/modules/reagents/chemistry/reagents/food.dm b/code/modules/reagents/chemistry/reagents/food.dm index 6d1c4d74e72..565a0d483a8 100644 --- a/code/modules/reagents/chemistry/reagents/food.dm +++ b/code/modules/reagents/chemistry/reagents/food.dm @@ -376,7 +376,7 @@ /datum/reagent/consumable/sprinkles/on_mob_life(mob/living/M) var/update_flags = STATUS_UPDATE_NONE - if(ishuman(M) && M.job in list("Security Officer", "Security Pod Pilot", "Detective", "Warden", "Head of Security", "Brig Physician", "Internal Affairs Agent", "Magistrate")) + if(ishuman(M) && (M.job in list("Security Officer", "Security Pod Pilot", "Detective", "Warden", "Head of Security", "Brig Physician", "Internal Affairs Agent", "Magistrate"))) update_flags |= M.adjustBruteLoss(-1, FALSE) update_flags |= M.adjustFireLoss(-1, FALSE) return ..() | update_flags diff --git a/code/modules/reagents/chemistry/reagents/medicine.dm b/code/modules/reagents/chemistry/reagents/medicine.dm index c9e7ac0c1dc..e90789f9d8b 100644 --- a/code/modules/reagents/chemistry/reagents/medicine.dm +++ b/code/modules/reagents/chemistry/reagents/medicine.dm @@ -9,7 +9,7 @@ var/total_depletion_rate = (metabolization_rate / M.metabolism_efficiency) * M.digestion_ratio // Cache it handle_addiction(M, total_depletion_rate) - + sate_addiction(M) holder.remove_reagent(id, total_depletion_rate) //medicine reagents stay longer if you have a better metabolism return STATUS_UPDATE_NONE @@ -173,12 +173,35 @@ metabolization_rate = 0.2 taste_description = "antibiotics" +/datum/reagent/medicine/spaceacillin/on_mob_life(mob/living/M) + var/list/organs_list = list() + if(iscarbon(M)) + var/mob/living/carbon/C = M + organs_list += C.internal_organs + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + organs_list += H.bodyparts + + for(var/X in organs_list) + var/obj/item/organ/O = X + if(O.germ_level < INFECTION_LEVEL_ONE) + O.germ_level = 0 //cure instantly + else if(O.germ_level < INFECTION_LEVEL_TWO) + O.germ_level = max(M.germ_level - 25, 0) //at germ_level == 500, this should cure the infection in 34 seconds + else + O.germ_level = max(M.germ_level - 10, 0) // at germ_level == 1000, this will cure the infection in 1 minutes, 14 seconds + + organs_list.Cut() + M.germ_level = max(M.germ_level - 20, 0) // Reduces the mobs germ level, too + return ..() + /datum/reagent/medicine/silver_sulfadiazine name = "Silver Sulfadiazine" id = "silver_sulfadiazine" description = "This antibacterial compound is used to treat burn victims." reagent_state = LIQUID - color = "#F0C814" + color = "#F0DC00" metabolization_rate = 3 harmless = FALSE //toxic if ingested, and I am NOT going to account for the difference taste_description = "burn cream" @@ -205,7 +228,7 @@ id = "styptic_powder" description = "Styptic (aluminum sulfate) powder helps control bleeding and heal physical wounds." reagent_state = LIQUID - color = "#C8A5DC" + color = "#FF9696" metabolization_rate = 3 harmless = FALSE taste_description = "wound cream" @@ -221,7 +244,7 @@ M.adjustBruteLoss(-volume) if(show_message) to_chat(M, "The styptic powder stings like hell as it closes some of your wounds!") - M.emote("scream") + M.emote("scream") if(method == REAGENT_INGEST) M.adjustToxLoss(0.5*volume) if(show_message) @@ -790,7 +813,7 @@ ..() return M.SetJitter(0) - var/needs_update = M.mutations.len > 0 || M.disabilities > 0 + var/needs_update = M.mutations.len > 0 if(needs_update) for(var/block = 1; block<=DNA_SE_LENGTH; block++) diff --git a/code/modules/reagents/chemistry/reagents/misc.dm b/code/modules/reagents/chemistry/reagents/misc.dm index eb6be801434..f9a6f974dcf 100644 --- a/code/modules/reagents/chemistry/reagents/misc.dm +++ b/code/modules/reagents/chemistry/reagents/misc.dm @@ -310,14 +310,14 @@ /datum/reagent/colorful_reagent/reaction_mob(mob/living/simple_animal/M, method=REAGENT_TOUCH, volume) if(isanimal(M)) - M.color = pick(random_color_list) + M.color = pick(GLOB.random_color_list) ..() /datum/reagent/colorful_reagent/reaction_obj(obj/O, volume) - O.color = pick(random_color_list) + O.color = pick(GLOB.random_color_list) /datum/reagent/colorful_reagent/reaction_turf(turf/T, volume) - T.color = pick(random_color_list) + T.color = pick(GLOB.random_color_list) /datum/reagent/hair_dye name = "Quantum Hair Dye" @@ -450,21 +450,18 @@ var/mob/living/carbon/C = holder.my_atom if(!istype(C)) return - var/mind_type = FALSE if(C.mind) if(C.mind.assigned_role == "Clown" || C.mind.assigned_role == SPECIAL_ROLE_HONKSQUAD) - mind_type = "Clown" to_chat(C, "Whatever that was, it feels great!") else if(C.mind.assigned_role == "Mime") - mind_type = "Mime" to_chat(C, "You feel nauseous.") C.AdjustDizzy(volume) else to_chat(C, "Something doesn't feel right...") C.AdjustDizzy(volume) - C.AddComponent(/datum/component/jestosterone, mind_type) + ADD_TRAIT(C, TRAIT_JESTER, id) C.AddComponent(/datum/component/squeak, null, null, null, null, null, TRUE) - C.AddComponent(/datum/component/waddling) + C.AddElement(/datum/element/waddling) /datum/reagent/jestosterone/on_mob_life(mob/living/carbon/M) if(!istype(M)) @@ -472,8 +469,7 @@ var/update_flags = STATUS_UPDATE_NONE if(prob(10)) M.emote("giggle") - GET_COMPONENT_FROM(jestosterone_component, /datum/component/jestosterone, M) - if(jestosterone_component.mind_type == "Clown") + if(M?.mind.assigned_role == "Clown" || M?.mind.assigned_role == SPECIAL_ROLE_HONKSQUAD) update_flags |= M.adjustBruteLoss(-1.5 * REAGENTS_EFFECT_MULTIPLIER) //Screw those pesky clown beatings! else M.AdjustDizzy(10, 0, 500) @@ -493,18 +489,15 @@ "Your legs feel like jelly.", "You feel like telling a pun.") to_chat(M, "[pick(clown_message)]") - if(jestosterone_component.mind_type == "Mime") + if(M?.mind.assigned_role == "Mime") update_flags |= M.adjustToxLoss(1.5 * REAGENTS_EFFECT_MULTIPLIER) return ..() | update_flags /datum/reagent/jestosterone/on_mob_delete(mob/living/M) ..() - GET_COMPONENT_FROM(remove_fun, /datum/component/jestosterone, M) - GET_COMPONENT_FROM(squeaking, /datum/component/squeak, M) - GET_COMPONENT_FROM(waddling, /datum/component/waddling, M) - remove_fun.Destroy() - squeaking.Destroy() - waddling.Destroy() + REMOVE_TRAIT(M, TRAIT_JESTER, id) + qdel(M.GetComponent(/datum/component/squeak)) + M.RemoveElement(/datum/element/waddling) /datum/reagent/royal_bee_jelly name = "royal bee jelly" diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm index dc79b5f4b3c..9d85459f465 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm @@ -333,19 +333,26 @@ process_flags = ORGANIC | SYNTHETIC taste_description = "bitterness" +/datum/reagent/cryostylane/on_new(data) + ..() + START_PROCESSING(SSprocessing, src) + +/datum/reagent/cryostylane/Destroy() + STOP_PROCESSING(SSprocessing, src) + return ..() + /datum/reagent/cryostylane/on_mob_life(mob/living/M) //TODO: code freezing into an ice cube if(M.reagents.has_reagent("oxygen")) M.reagents.remove_reagent("oxygen", 1) M.bodytemperature -= 30 return ..() -/datum/reagent/cryostylane/on_tick() - if(holder.has_reagent("oxygen")) - holder.remove_reagent("oxygen", 2) - holder.remove_reagent("cryostylane", 2) - holder.temperature_reagents(holder.chem_temp - 200) - holder.temperature_reagents(holder.chem_temp - 200) - ..() +/datum/reagent/cryostylane/process() + if(..()) + if(holder.has_reagent("oxygen")) + holder.remove_reagent("oxygen", 2) + holder.remove_reagent("cryostylane", 2) + holder.temperature_reagents(holder.chem_temp - 200) /datum/reagent/cryostylane/reaction_mob(mob/living/M, method = REAGENT_TOUCH, volume) if(method == REAGENT_TOUCH) @@ -368,19 +375,26 @@ process_flags = ORGANIC | SYNTHETIC taste_description = "bitterness" +/datum/reagent/pyrosium/on_new(data) + ..() + START_PROCESSING(SSprocessing, src) + +/datum/reagent/pyrosium/Destroy() + STOP_PROCESSING(SSprocessing, src) + return ..() + /datum/reagent/pyrosium/on_mob_life(mob/living/M) if(M.reagents.has_reagent("oxygen")) M.reagents.remove_reagent("oxygen", 1) M.bodytemperature += 30 return ..() -/datum/reagent/pyrosium/on_tick() - if(holder.has_reagent("oxygen")) - holder.remove_reagent("oxygen", 2) - holder.remove_reagent("pyrosium", 2) - holder.temperature_reagents(holder.chem_temp + 200) - holder.temperature_reagents(holder.chem_temp + 200) - ..() +/datum/reagent/pyrosium/process() + if(..()) + if(holder.has_reagent("oxygen")) + holder.remove_reagent("oxygen", 2) + holder.remove_reagent("pyrosium", 2) + holder.temperature_reagents(holder.chem_temp + 200) /datum/reagent/firefighting_foam name = "Firefighting foam" diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm index 28ed544cb18..dec256ac455 100644 --- a/code/modules/reagents/chemistry/reagents/toxins.dm +++ b/code/modules/reagents/chemistry/reagents/toxins.dm @@ -192,6 +192,14 @@ color = "#7DFF00" taste_description = "slime" +/datum/reagent/stable_mutagen/on_new(data) + ..() + START_PROCESSING(SSprocessing, src) + +/datum/reagent/stable_mutagen/Destroy() + STOP_PROCESSING(SSprocessing, src) + return ..() + /datum/reagent/stable_mutagen/on_mob_life(mob/living/M) if(!ishuman(M) || !M.dna) return @@ -212,11 +220,11 @@ return ..() -/datum/reagent/stable_mutagen/on_tick() - var/datum/reagent/blood/B = locate() in holder.reagent_list - if(B && islist(B.data) && !data) - data = B.data.Copy() - ..() +/datum/reagent/stable_mutagen/process() + if(..()) + var/datum/reagent/blood/B = locate() in holder.reagent_list + if(B && islist(B.data) && !data) + data = B.data.Copy() /datum/reagent/romerol name = "romerol" diff --git a/code/modules/reagents/chemistry/reagents/water.dm b/code/modules/reagents/chemistry/reagents/water.dm index c6960aac916..f975cac7293 100644 --- a/code/modules/reagents/chemistry/reagents/water.dm +++ b/code/modules/reagents/chemistry/reagents/water.dm @@ -96,21 +96,21 @@ C.l_hand.clean_blood() if(C.wear_mask) if(C.wear_mask.clean_blood()) - C.update_inv_wear_mask(0) + C.update_inv_wear_mask() if(ishuman(M)) var/mob/living/carbon/human/H = C if(H.head) if(H.head.clean_blood()) - H.update_inv_head(0,0) + H.update_inv_head() if(H.wear_suit) if(H.wear_suit.clean_blood()) - H.update_inv_wear_suit(0,0) + H.update_inv_wear_suit() else if(H.w_uniform) if(H.w_uniform.clean_blood()) - H.update_inv_w_uniform(0,0) + H.update_inv_w_uniform() if(H.shoes) if(H.shoes.clean_blood()) - H.update_inv_shoes(0,0) + H.update_inv_shoes() M.clean_blood() ..() diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index db65f761e2e..a091f65a34c 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -11,6 +11,8 @@ var/spawned_disease = null var/disease_amount = 20 var/has_lid = FALSE // Used for containers where we want to put lids on and off + var/temperature_min = 0 // To limit the temperature of a reagent container can atain when exposed to heat/cold + var/temperature_max = 10000 /obj/item/reagent_containers/verb/set_APTFT() //set amount_per_transfer_from_this set name = "Set transfer amount" @@ -30,7 +32,7 @@ ..() if(!possible_transfer_amounts) verbs -= /obj/item/reagent_containers/verb/set_APTFT - create_reagents(volume) + create_reagents(volume, temperature_min, temperature_max) if(spawned_disease) var/datum/disease/F = new spawned_disease(0) var/list/data = list("viruses" = list(F), "blood_color" = "#A10808") diff --git a/code/modules/reagents/reagent_containers/applicator.dm b/code/modules/reagents/reagent_containers/applicator.dm new file mode 100644 index 00000000000..73c3c3759b1 --- /dev/null +++ b/code/modules/reagents/reagent_containers/applicator.dm @@ -0,0 +1,106 @@ +/obj/item/reagent_containers/applicator + name = "auto-mender" + desc = "A small electronic device designed to topically apply healing chemicals." + icon = 'icons/goonstation/objects/objects.dmi' + icon_state = "mender" + item_state = "mender" + volume = 200 + resistance_flags = ACID_PROOF + container_type = REFILLABLE | AMOUNT_VISIBLE + temperature_min = 270 + temperature_max = 350 + var/ignore_flags = FALSE + var/emagged = FALSE + var/applied_amount = 8 // How much it applies + var/applying = FALSE // So it can't be spammed. + var/measured_health = 0 // Used for measuring health; we don't want this to stop applying once the person's health isn't changing. + +/obj/item/reagent_containers/applicator/emag_act(mob/user) + if(!emagged) + emagged = TRUE + ignore_flags = TRUE + to_chat(user, "You short out the safeties on [src].") + +/obj/item/reagent_containers/applicator/on_reagent_change() + if(!emagged) + var/found_forbidden_reagent = FALSE + for(var/datum/reagent/R in reagents.reagent_list) + if(!GLOB.safe_chem_applicator_list.Find(R.id)) + reagents.del_reagent(R.id) + found_forbidden_reagent = TRUE + if(found_forbidden_reagent) + if(ismob(loc)) + to_chat(loc, "[src] identifies and removes a harmful substance.") + else + visible_message("[src] identifies and removes a harmful substance.") + update_icon() + +/obj/item/reagent_containers/applicator/update_icon() + cut_overlays() + + if(reagents.total_volume) + var/mutable_appearance/filling = mutable_appearance('icons/goonstation/objects/objects.dmi', "mender-fluid") + filling.color = mix_color_from_reagents(reagents.reagent_list) + add_overlay(filling) + +/obj/item/reagent_containers/applicator/attack(mob/living/M, mob/user) + if(!reagents.total_volume) + to_chat(user, "[src] is empty!") + return + if(applying) + to_chat(user, "You're already applying [src].") + return + if(!iscarbon(M)) + return + + if(ignore_flags || M.can_inject(user, TRUE)) + if(M == user) + M.visible_message("[user] begins mending [user.p_them()]self with [src].", "You begin mending yourself with [src].") + else + user.visible_message("[user] begins mending [M] with [src].", "You begin mending [M] with [src].") + if(M.reagents) + applying = TRUE + icon_state = "mender-active" + apply_to(M, user, 0.2) // We apply a very weak application up front, then loop. + while(do_after(user, 10, target = M)) + measured_health = M.health + apply_to(M, user, 1, FALSE) + if((measured_health == M.health) || !reagents.total_volume) + to_chat(user, "[M] is finished healing and [src] powers down automatically.") + break + applying = FALSE + icon_state = "mender" + user.changeNext_move(CLICK_CD_MELEE) + + +/obj/item/reagent_containers/applicator/proc/apply_to(mob/living/carbon/M, mob/user, multiplier = 1, show_message = TRUE) + var/total_applied_amount = applied_amount * multiplier + + if(reagents && reagents.total_volume) + var/list/injected = list() + for(var/datum/reagent/R in reagents.reagent_list) + injected += R.name + + var/contained = english_list(injected) + // allow normal logging only if reagents are not harmless and automender is emagged + add_attack_logs(user, M, "Automends with [src] containing ([contained])", (emagged && !(reagents.harmless_helper())) ? null : ATKLOG_ALMOSTALL) + + var/fractional_applied_amount = total_applied_amount / reagents.total_volume + + reagents.reaction(M, REAGENT_TOUCH, fractional_applied_amount, show_message) + reagents.trans_to(M, total_applied_amount * 0.5) + reagents.remove_any(total_applied_amount * 0.5) + + playsound(get_turf(src), pick('sound/goonstation/items/mender.ogg', 'sound/goonstation/items/mender2.ogg'), 50, 1) + +/obj/item/reagent_containers/applicator/brute + name = "brute auto-mender" + list_reagents = list("styptic_powder" = 200) + +/obj/item/reagent_containers/applicator/burn + name = "burn auto-mender" + list_reagents = list("silver_sulfadiazine" = 200) + +/obj/item/reagent_containers/applicator/dual + name = "dual auto-mender" + list_reagents = list("synthflesh" = 200) diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index f80fe2cb62a..1fa4930b0f6 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -1,3 +1,4 @@ +#define BORGHYPO_REFILL_VALUE 5 /obj/item/reagent_containers/borghypo name = "Cyborg Hypospray" @@ -46,18 +47,21 @@ /obj/item/reagent_containers/borghypo/process() //Every [recharge_time] seconds, recharge some reagents for the cyborg charge_tick++ - if(charge_tick < recharge_time) return 0 + if(charge_tick < recharge_time) + return FALSE charge_tick = 0 if(isrobot(loc)) var/mob/living/silicon/robot/R = loc if(R && R.cell) var/datum/reagents/RG = reagent_list[mode] - if(RG.total_volume < RG.maximum_volume) //Don't recharge reagents and drain power if the storage is full. - R.cell.use(charge_cost) //Take power from borg... - RG.add_reagent(reagent_ids[mode], 5) //And fill hypo with reagent. + if(!refill_borghypo(RG, reagent_ids[mode], R)) //If the storage is not full recharge reagents and drain power. + for(var/i in 1 to reagent_list.len) //if active mode is full loop through the list and fill the first one that is not full + RG = reagent_list[i] + if(refill_borghypo(RG, reagent_ids[i], R)) + break //update_icon() - return 1 + return TRUE // Use this to add more chemicals for the borghypo to produce. /obj/item/reagent_containers/borghypo/proc/add_reagent(reagent) @@ -69,7 +73,14 @@ var/datum/reagents/R = reagent_list[reagent_list.len] R.add_reagent(reagent, 30) -/obj/item/reagent_containers/borghypo/attack(mob/living/M, mob/user) +/obj/item/reagent_containers/borghypo/proc/refill_borghypo(datum/reagents/RG, reagent_id, mob/living/silicon/robot/R) + if(RG.total_volume < RG.maximum_volume) + RG.add_reagent(reagent_id, BORGHYPO_REFILL_VALUE) + R.cell.use(charge_cost) + return TRUE + return FALSE + +/obj/item/reagent_containers/borghypo/attack(mob/living/carbon/human/M, mob/user) var/datum/reagents/R = reagent_list[mode] if(!R.total_volume) to_chat(user, "The injector is empty.") @@ -114,3 +125,5 @@ if(empty) . += "It is currently empty. Allow some time for the internal syntheszier to produce more." + +#undef BORGHYPO_REFILL_VALUE diff --git a/code/modules/reagents/reagent_containers/patch.dm b/code/modules/reagents/reagent_containers/patch.dm index b020015e929..582e157004c 100644 --- a/code/modules/reagents/reagent_containers/patch.dm +++ b/code/modules/reagents/reagent_containers/patch.dm @@ -5,10 +5,24 @@ icon_state = "bandaid" item_state = "bandaid" possible_transfer_amounts = null - volume = 40 + volume = 30 apply_type = REAGENT_TOUCH apply_method = "apply" transfer_efficiency = 0.5 //patches aren't as effective at getting chemicals into the bloodstream. + temperature_min = 270 + temperature_max = 350 + var/needs_to_apply_reagents = TRUE + +/obj/item/reagent_containers/food/pill/patch/attack(mob/living/carbon/M, mob/user, def_zone) + if(!istype(M)) + return FALSE + bitesize = 0 + if(M.eat(src, user)) + user.drop_item() + forceMove(M) + M.processing_patches += src + return TRUE + return FALSE /obj/item/reagent_containers/food/pill/patch/afterattack(obj/target, mob/user , proximity) return // thanks inheritance again @@ -18,29 +32,37 @@ desc = "Helps with brute injuries." icon_state = "bandaid_brute" instant_application = 1 - list_reagents = list("styptic_powder" = 40) + list_reagents = list("styptic_powder" = 30) + +/obj/item/reagent_containers/food/pill/patch/styptic/small + name = "healing mini-patch" + list_reagents = list("styptic_powder" = 15) /obj/item/reagent_containers/food/pill/patch/silver_sulf name = "burn patch" desc = "Helps with burn injuries." icon_state = "bandaid_burn" instant_application = 1 - list_reagents = list("silver_sulfadiazine" = 40) + list_reagents = list("silver_sulfadiazine" = 30) + +/obj/item/reagent_containers/food/pill/patch/silver_sulf/small + name = "burn mini-patch" + list_reagents = list("silver_sulfadiazine" = 15) /obj/item/reagent_containers/food/pill/patch/synthflesh name = "synthflesh patch" desc = "Helps with brute and burn injuries." icon_state = "bandaid_med" instant_application = 1 - list_reagents = list("synthflesh" = 20) + list_reagents = list("synthflesh" = 10) /obj/item/reagent_containers/food/pill/patch/nicotine name = "nicotine patch" desc = "Helps temporarily curb the cravings of nicotine dependency." - list_reagents = list("nicotine" = 20) + list_reagents = list("nicotine" = 10) /obj/item/reagent_containers/food/pill/patch/jestosterone name = "jestosterone patch" desc = "Helps with brute injuries if the affected person is a clown, otherwise inflicts various annoying effects." icon_state = "bandaid_clown" - list_reagents = list("jestosterone" = 30) + list_reagents = list("jestosterone" = 20) diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 194675a21d8..48c35415387 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -16,7 +16,7 @@ . = ..() if(. && obj_integrity > 0) if(tank_volume && (damage_flag == "bullet" || damage_flag == "laser")) - boom() + boom(FALSE, TRUE) /obj/structure/reagent_dispensers/attackby(obj/item/I, mob/user, params) if(I.is_refillable()) @@ -43,7 +43,7 @@ /obj/structure/reagent_dispensers/deconstruct(disassembled = TRUE) if(!(flags & NODECONSTRUCT)) if(!disassembled) - boom() + boom(FALSE, TRUE) else qdel(src) @@ -85,15 +85,19 @@ if(!QDELETED(src)) //wasn't deleted by the projectile's effects. if(!P.nodamage && ((P.damage_type == BURN) || (P.damage_type == BRUTE))) message_admins("[key_name_admin(P.firer)] triggered a fueltank explosion with [P.name] at [COORD(loc)] ") + add_attack_logs(P.firer, src, "shot with [P.name]") log_game("[key_name(P.firer)] triggered a fueltank explosion with [P.name] at [COORD(loc)]") investigate_log("[key_name(P.firer)] triggered a fueltank explosion with [P.name] at [COORD(loc)]", INVESTIGATE_BOMB) boom() -/obj/structure/reagent_dispensers/fueltank/boom(rigtrigger = FALSE) // Prevent case where someone who rigged the tank is blamed for the explosion when the rig isn't what triggered the explosion +/obj/structure/reagent_dispensers/fueltank/boom(rigtrigger = FALSE, log_attack = FALSE) // Prevent case where someone who rigged the tank is blamed for the explosion when the rig isn't what triggered the explosion if(rigtrigger) // If the explosion is triggered by an assembly holder message_admins("A fueltank, last rigged by [lastrigger], was triggered at [COORD(loc)]") // Then admin is informed of the last person who rigged the fuel tank log_game("A fueltank, last rigged by [lastrigger], triggered at [COORD(loc)]") + add_attack_logs(lastrigger, src, "rigged fuel tank exploded") investigate_log("A fueltank, last rigged by [lastrigger], triggered at [COORD(loc)]", INVESTIGATE_BOMB) + if(log_attack) + add_attack_logs(usr, src, "blew up", ATKLOG_FEW) if(reagents) reagents.set_reagent_temp(1000) //uh-oh qdel(src) @@ -140,6 +144,7 @@ if(istype(H.a_left, /obj/item/assembly/igniter) || istype(H.a_right, /obj/item/assembly/igniter)) msg_admin_attack("[key_name_admin(user)] rigged [src.name] with [I.name] for explosion (JMP)", ATKLOG_FEW) log_game("[key_name(user)] rigged [src.name] with [I.name] for explosion at [COORD(loc)]") + add_attack_logs(user, src, "rigged fuel tank") investigate_log("[key_name(user)] rigged [src.name] with [I.name] for explosion at [COORD(loc)]", INVESTIGATE_BOMB) lastrigger = "[key_name(user)]" @@ -163,6 +168,7 @@ obj/structure/reagent_dispensers/fueltank/welder_act(mob/user, obj/item/I) user.visible_message("[user] catastrophically fails at refilling [user.p_their()] [I]!", "That was stupid of you.") message_admins("[key_name_admin(user)] triggered a fueltank explosion at [COORD(loc)]") log_game("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]") + add_attack_logs(user, src, "hit with lit welder") investigate_log("[key_name(user)] triggered a fueltank explosion at [COORD(loc)]", INVESTIGATE_BOMB) boom() else diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 906d1136ebc..544deb8d11f 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -269,7 +269,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/disposal/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/disposal/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/pressure = Clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100) @@ -330,7 +330,7 @@ // eject the contents of the disposal unit /obj/machinery/disposal/proc/eject() for(var/atom/movable/AM in src) - AM.loc = src.loc + AM.forceMove(loc) AM.pipe_eject(0) update() @@ -471,7 +471,7 @@ for(var/atom/movable/AM in H) target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5)) - AM.loc = src.loc + AM.forceMove(loc) AM.pipe_eject(0) if(!istype(AM, /mob/living/silicon/robot/drone) && !istype(AM, /mob/living/silicon/robot/syndicate/saboteur)) //Poor drones kept smashing windows and taking system damage being fired out of disposals. ~Z spawn(1) @@ -487,7 +487,7 @@ if(istype(I, /obj/item/projectile)) return if(prob(75)) - I.loc = src + I.forceMove(src) for(var/mob/M in viewers(src)) M.show_message("\the [I] lands in \the [src].", 3) update() @@ -550,7 +550,7 @@ // now everything inside the disposal gets put into the holder // note AM since can contain mobs or objs for(var/atom/movable/AM in D) - AM.loc = src + AM.forceMove(src) SEND_SIGNAL(AM, COMSIG_MOVABLE_DISPOSING, src, D) if(istype(AM, /mob/living/carbon/human)) var/mob/living/carbon/human/H = AM @@ -582,7 +582,7 @@ D.expel(src) // no trunk connected, so expel immediately return - loc = D.trunk + forceMove(D.trunk) active = 1 dir = DOWN spawn(1) @@ -639,11 +639,10 @@ // used when a a holder meets a stuck holder /obj/structure/disposalholder/proc/merge(var/obj/structure/disposalholder/other) for(var/atom/movable/AM in other) - AM.loc = src // move everything in other holder to this one + AM.forceMove(src) // move everything in other holder to this one if(ismob(AM)) var/mob/M = AM - if(M.client) // if a client mob, update eye to follow this holder - M.client.eye = src + M.reset_perspective(src) // if a client mob, update eye to follow this holder if(other.has_fat_guy) has_fat_guy = 1 @@ -712,7 +711,7 @@ // this is unlikely, but just dump out everything into the turf in case for(var/atom/movable/AM in H) - AM.loc = T + AM.forceMove(T) AM.pipe_eject(0) qdel(H) ..() @@ -747,9 +746,9 @@ if(H2 && !H2.active) H.merge(H2) - H.loc = P + H.forceMove(P) else // if wasn't a pipe, then set loc to turf - H.loc = T + H.forceMove(T) return null return P @@ -791,7 +790,7 @@ if(T.density) // dense ouput turf, so stop holder H.active = 0 - H.loc = src + H.forceMove(src) return if(T.intact && istype(T,/turf/simulated/floor)) //intact floor, pop the tile var/turf/simulated/floor/F = T @@ -807,7 +806,7 @@ playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0) if(H) for(var/atom/movable/AM in H) - AM.loc = T + AM.forceMove(T) AM.pipe_eject(direction) spawn(1) if(AM) @@ -822,7 +821,7 @@ for(var/atom/movable/AM in H) target = get_offset_target_turf(T, rand(5)-rand(5), rand(5)-rand(5)) - AM.loc = T + AM.forceMove(T) AM.pipe_eject(0) spawn(1) if(AM) @@ -837,7 +836,7 @@ // remains : set to leave broken pipe pieces in place /obj/structure/disposalpipe/proc/broken(remains = 0) if(remains) - for(var/D in cardinal) + for(var/D in GLOB.cardinal) if(D & dpdir) var/obj/structure/disposalpipe/broken/P = new(src.loc) P.setDir(D) @@ -853,7 +852,7 @@ // this is unlikely, but just dump out everything into the turf in case for(var/atom/movable/AM in H) - AM.loc = T + AM.forceMove(T) AM.pipe_eject(0) qdel(H) return @@ -1070,9 +1069,9 @@ var/obj/structure/disposalholder/H2 = locate() in P if(H2 && !H2.active) H.merge(H2) - H.loc = P + H.forceMove(P) else // if wasn't a pipe, then set loc to turf - H.loc = T + H.forceMove(T) return null return P @@ -1129,9 +1128,9 @@ if(H2 && !H2.active) H.merge(H2) - H.loc = P + H.forceMove(P) else // if wasn't a pipe, then set loc to turf - H.loc = T + H.forceMove(T) return null return P @@ -1361,16 +1360,12 @@ /atom/movable/proc/pipe_eject(var/direction) return -// check if mob has client, if so restore client view on eject -/mob/pipe_eject(var/direction) - reset_perspective(null) - /obj/effect/decal/cleanable/blood/gibs/pipe_eject(var/direction) var/list/dirs if(direction) dirs = list( direction, turn(direction, -45), turn(direction, 45)) else - dirs = alldirs.Copy() + dirs = GLOB.alldirs.Copy() src.streak(dirs) @@ -1379,6 +1374,6 @@ if(direction) dirs = list( direction, turn(direction, -45), turn(direction, 45)) else - dirs = alldirs.Copy() + dirs = GLOB.alldirs.Copy() src.streak(dirs) diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 7d2be6953c6..ecf6b9887fc 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -25,7 +25,7 @@ /obj/structure/bigDelivery/attack_hand(mob/user as mob) playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1) if(wrapped) - wrapped.loc = get_turf(src) + wrapped.forceMove(get_turf(src)) if(istype(wrapped, /obj/structure/closet)) var/obj/structure/closet/O = wrapped O.welded = init_welded @@ -95,6 +95,12 @@ CHECK_TICK ..() +/obj/item/smallDelivery/emp_act(severity) + ..() + for(var/i in contents) + var/atom/A = i + A.emp_act(severity) + /obj/item/smallDelivery/attack_self(mob/user as mob) if(wrapped && wrapped.loc) //sometimes items can disappear. For example, bombs. --rastaf0 wrapped.loc = user.loc @@ -221,6 +227,7 @@ user.visible_message("[user] wraps [target].") user.create_attack_log("Has used [name] on [target]") + add_attack_logs(user, target, "used [name]", ATKLOG_ALL) if(amount <= 0 && !src.loc) //if we used our last wrapping paper, drop a cardboard tube new /obj/item/c_tube( get_turf(user) ) diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index 2e7c668a83f..d907e46247e 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -607,6 +607,14 @@ build_path = /obj/item/reagent_containers/hypospray/safety category = list("initial", "Medical") +/datum/design/automender + name = "Auto-mender" + id = "automender" + build_type = AUTOLATHE + materials = list(MAT_METAL = 1000, MAT_GLASS = 1000) + build_path = /obj/item/reagent_containers/applicator + category = list("initial", "Medical") + /datum/design/prox_sensor name = "Proximity Sensor" id = "prox_sensor" @@ -914,4 +922,3 @@ materials = list(MAT_METAL = 40000) build_path = /obj/item/golem_shell category = list("Imported") - diff --git a/code/modules/research/designs/comp_board_designs.dm b/code/modules/research/designs/comp_board_designs.dm index 821ef606518..67f797ee964 100644 --- a/code/modules/research/designs/comp_board_designs.dm +++ b/code/modules/research/designs/comp_board_designs.dm @@ -302,36 +302,6 @@ build_path = /obj/item/circuitboard/supplycomp category = list("Computer Boards") -/datum/design/comm_monitor - name = "Console Board (Telecommunications Monitoring Console)" - desc = "Allows for the construction of circuit boards used to build a telecommunications monitor." - id = "comm_monitor" - req_tech = list("programming" = 3, "magnets" = 3, "bluespace" = 2) - build_type = IMPRINTER - materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/comm_monitor - category = list("Computer Boards") - -/datum/design/comm_server - name = "Console Board (Telecommunications Server Monitoring Console)" - desc = "Allows for the construction of circuit boards used to build a telecommunication server browser and monitor." - id = "comm_server" - req_tech = list("programming" = 3, "magnets" = 3, "bluespace" = 2) - build_type = IMPRINTER - materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/comm_server - category = list("Computer Boards") - -/datum/design/comm_traffic - name = "Console Board (Telecommunications Traffic Control Console)" - desc = "Allows for the construction of circuit boards used to build a telecommunications traffic control console." - id = "comm_traffic" - req_tech = list("programming" = 3, "magnets" = 3, "bluespace" = 2) - build_type = IMPRINTER - materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/comm_traffic - category = list("Computer Boards") - /datum/design/teleconsole name = "Console Board (Teleporter Console)" desc = "Allows for the construction of circuit boards used to build a teleporter control console." diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 98a181bcdf8..e3bbb2f4aec 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -512,6 +512,17 @@ build_path = /obj/item/organ/internal/eyes/cybernetic category = list("Medical") +/datum/design/cybernetic_ears + name = "Cybernetic Ears" + desc = "A cybernetic pair of ears" + id = "cybernetic_ears" + req_tech = list("biotech" = 4, "materials" = 4) + build_type = PROTOLATHE | MECHFAB + materials = list(MAT_METAL = 500, MAT_GLASS = 500) + construction_time = 60 + build_path = /obj/item/organ/internal/ears/cybernetic + category = list("Medical") + /datum/design/cybernetic_liver name = "Cybernetic Liver" desc = "A cybernetic liver" diff --git a/code/modules/research/designs/telecomms_designs.dm b/code/modules/research/designs/telecomms_designs.dm index 848349dab83..083420d68a4 100644 --- a/code/modules/research/designs/telecomms_designs.dm +++ b/code/modules/research/designs/telecomms_designs.dm @@ -1,143 +1,23 @@ //////////////////////////////////////// //////////Telecomms Equipment/////////// //////////////////////////////////////// -/datum/design/telecomms_bus - name = "Machine Board (Bus Mainframe)" - desc = "Allows for the construction of Telecommunications Bus Mainframes." - id = "s-bus" - req_tech = list("programming" = 2, "engineering" = 2) - build_type = IMPRINTER - materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/telecomms/bus - category = list("Subspace Telecomms") - -/datum/design/telecomms_hub - name = "Machine Board (Hub Mainframe)" - desc = "Allows for the construction of Telecommunications Hub Mainframes." +// Only 2 of these exist, so they should really be in a different place. But oh well. +/datum/design/telecomms_core + name = "Machine Board (Telecommunications Core)" + desc = "Allows for the construction of Telecommunications Cores." id = "s-hub" req_tech = list("programming" = 2, "engineering" = 2) build_type = IMPRINTER materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/telecomms/hub - category = list("Subspace Telecomms") - - -/datum/design/telecomms_processor - name = "Machine Board (Processor Unit)" - desc = "Allows for the construction of Telecommunications Processor equipment." - id = "s-processor" - req_tech = list("programming" = 2, "engineering" = 2) - build_type = IMPRINTER - materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/telecomms/processor + build_path = /obj/item/circuitboard/tcomms/core category = list("Subspace Telecomms") /datum/design/telecomms_relay - name = "Machine Board (Relay Mainframe)" - desc = "Allows for the construction of Telecommunications Relay Mainframes." + name = "Machine Board (Telecommunications Core)" + desc = "Allows for the construction of Telecommunications Relays." id = "s-relay" req_tech = list("programming" = 2, "engineering" = 2, "bluespace" = 2) build_type = IMPRINTER materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/telecomms/relay + build_path = /obj/item/circuitboard/tcomms/relay category = list("Subspace Telecomms") - -/datum/design/telecomms_server - name = "Machine Board (Server Mainframe)" - desc = "Allows for the construction of Telecommunications Servers." - id = "s-server" - req_tech = list("programming" = 2, "engineering" = 2) - build_type = IMPRINTER - materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/telecomms/server - category = list("Subspace Telecomms") - -/datum/design/subspace_broadcaster - name = "Machine Board (Subspace Broadcaster)" - desc = "Allows for the construction of Subspace Broadcasting equipment." - id = "s-broadcaster" - req_tech = list("programming" = 2, "engineering" = 2) - build_type = IMPRINTER - materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/telecomms/broadcaster - category = list("Subspace Telecomms") - -/datum/design/subspace_receiver - name = "Machine Board (Subspace Receiver)" - desc = "Allows for the construction of Subspace Receiver equipment." - id = "s-receiver" - req_tech = list("programming" = 2, "engineering" = 2, "bluespace" = 1) - build_type = IMPRINTER - materials = list(MAT_GLASS = 1000) - build_path = /obj/item/circuitboard/telecomms/receiver - category = list("Subspace Telecomms") - -/datum/design/subspace_crystal - name = "Ansible Crystal" - desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths." - id = "s-crystal" - req_tech = list("magnets" = 2, "materials" = 2, "bluespace" = 3, "plasmatech" = 3) - build_type = PROTOLATHE - materials = list(MAT_GLASS = 800, MAT_SILVER = 100, MAT_GOLD = 100) - build_path = /obj/item/stock_parts/subspace/crystal - category = list("Stock Parts") - -/datum/design/hyperwave_filter - name = "Hyperwave Filter" - desc = "A tiny device capable of filtering and converting super-intense radiowaves." - id = "s-filter" - req_tech = list("programming" = 3, "magnets" = 3) - build_type = PROTOLATHE - materials = list(MAT_METAL = 100, MAT_SILVER = 100) - build_path = /obj/item/stock_parts/subspace/filter - category = list("Stock Parts") - -/datum/design/subspace_amplifier - name = "Subspace Amplifier" - desc = "A compact micro-machine capable of amplifying weak subspace transmissions." - id = "s-amplifier" - req_tech = list("programming" = 3, "magnets" = 4, "materials" = 3, "bluespace" = 2) - build_type = PROTOLATHE - materials = list(MAT_METAL = 100, MAT_GOLD = 100, MAT_URANIUM = 100) - build_path = /obj/item/stock_parts/subspace/amplifier - category = list("Stock Parts") - -/datum/design/subspace_analyzer - name = "Subspace Analyzer" - desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths." - id = "s-analyzer" - req_tech = list("programming" = 3, "magnets" = 4, "materials" = 2, "bluespace" = 3) - build_type = PROTOLATHE - materials = list(MAT_METAL = 100, MAT_GOLD = 100) - build_path = /obj/item/stock_parts/subspace/analyzer - category = list("Stock Parts") - -/datum/design/subspace_ansible - name = "Subspace Ansible" - desc = "A compact module capable of sensing extradimensional activity." - id = "s-ansible" - req_tech = list("programming" = 2, "magnets" = 2, "materials" = 2) - build_type = PROTOLATHE - materials = list(MAT_METAL = 100, MAT_SILVER = 100) - build_path = /obj/item/stock_parts/subspace/ansible - category = list("Stock Parts") - -/datum/design/subspace_transmitter - name = "Subspace Transmitter" - desc = "A large piece of equipment used to open a window into the subspace dimension." - id = "s-transmitter" - req_tech = list("magnets" = 3, "materials" = 4, "bluespace" = 4) - build_type = PROTOLATHE - materials = list(MAT_GLASS = 100, MAT_SILVER = 100, MAT_URANIUM = 100) - build_path = /obj/item/stock_parts/subspace/transmitter - category = list("Stock Parts") - -/datum/design/subspace_treatment - name = "Subspace Treatment Disk" - desc = "A compact micro-machine capable of stretching out hyper-compressed radio waves." - id = "s-treatment" - req_tech = list("programming" = 2, "magnets" = 3, "materials" = 2, "bluespace" = 3) - build_type = PROTOLATHE - materials = list(MAT_METAL = 100, MAT_SILVER = 200) - build_path = /obj/item/stock_parts/subspace/treatment - category = list("Stock Parts") diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index 3951cf23312..caa273594de 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -89,8 +89,8 @@ component_parts += new /obj/item/stock_parts/micro_laser(src) component_parts += new /obj/item/stock_parts/micro_laser(src) spawn(1) - trackedIan = locate(/mob/living/simple_animal/pet/dog/corgi/Ian) in GLOB.mob_list - trackedRuntime = locate(/mob/living/simple_animal/pet/cat/Runtime) in GLOB.mob_list + trackedIan = locate(/mob/living/simple_animal/pet/dog/corgi/Ian) in GLOB.mob_living_list + trackedRuntime = locate(/mob/living/simple_animal/pet/cat/Runtime) in GLOB.mob_living_list SetTypeReactions() RefreshParts() @@ -449,7 +449,7 @@ visible_message("[src]'s crushing mechanism slowly and smoothly descends, flattening the [exp_on]!") new /obj/item/stack/sheet/plasteel(get_turf(pick(oview(1,src)))) if(linked_console.linked_lathe) - GET_COMPONENT_FROM(linked_materials, /datum/component/material_container, linked_console.linked_lathe) + var/datum/component/material_container/linked_materials = linked_console.linked_lathe.GetComponent(/datum/component/material_container) for(var/material in exp_on.materials) linked_materials.insert_amount( min((linked_materials.max_amount - linked_materials.total_amount), (exp_on.materials[material])), material) if(prob(EFFECT_PROB_VERYLOW-badThingCoeff)) diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm index 2a0e201ac54..22b18534dbc 100644 --- a/code/modules/research/message_server.dm +++ b/code/modules/research/message_server.dm @@ -1,4 +1,4 @@ -var/global/list/obj/machinery/message_server/message_servers = list() +GLOBAL_LIST_EMPTY(message_servers) /datum/data_pda_msg var/recipient = "Unspecified" //name of the person @@ -60,14 +60,14 @@ var/global/list/obj/machinery/message_server/message_servers = list() var/decryptkey = "password" /obj/machinery/message_server/New() - message_servers += src + GLOB.message_servers += src decryptkey = GenerateKey() send_pda_message("System Administrator", "system", "This is an automated message. The messaging system is functioning correctly.") ..() return /obj/machinery/message_server/Destroy() - message_servers -= src + GLOB.message_servers -= src return ..() /obj/machinery/message_server/process() @@ -91,7 +91,7 @@ var/global/list/obj/machinery/message_server/message_servers = list() authmsg += "[id_auth]
    " if(stamp) authmsg += "[stamp]
    " - for(var/obj/machinery/requests_console/Console in allConsoles) + for(var/obj/machinery/requests_console/Console in GLOB.allRequestConsoles) if(ckey(Console.department) == ckey(recipient)) if(Console.inoperable()) Console.message_log += "Message lost due to console failure.
    Please contact [station_name()] system adminsitrator or AI for technical assistance.
    " @@ -190,7 +190,7 @@ var/global/list/obj/machinery/message_server/message_servers = list() /datum/feedback_variable/proc/get_parsed() return list(variable,value,details) -var/obj/machinery/blackbox_recorder/blackbox +GLOBAL_DATUM(blackbox, /obj/machinery/blackbox_recorder) //TODO: kill whoever designed this cancer /obj/machinery/blackbox_recorder @@ -222,15 +222,15 @@ var/obj/machinery/blackbox_recorder/blackbox //Only one can exsist in the world! /obj/machinery/blackbox_recorder/New() - if(blackbox) - if(istype(blackbox,/obj/machinery/blackbox_recorder)) + if(GLOB.blackbox) + if(istype(GLOB.blackbox,/obj/machinery/blackbox_recorder)) qdel(src) - blackbox = src + GLOB.blackbox = src /obj/machinery/blackbox_recorder/Destroy() var/turf/T = locate(1,1,2) if(T) - blackbox = null + GLOB.blackbox = null var/obj/machinery/blackbox_recorder/BR = new/obj/machinery/blackbox_recorder(T) BR.msg_common = msg_common BR.msg_science = msg_science @@ -247,8 +247,8 @@ var/obj/machinery/blackbox_recorder/blackbox BR.feedback = feedback BR.messages = messages BR.messages_admin = messages_admin - if(blackbox != BR) - blackbox = BR + if(GLOB.blackbox != BR) + GLOB.blackbox = BR return ..() /obj/machinery/blackbox_recorder/proc/find_feedback_datum(var/variable) @@ -301,10 +301,10 @@ var/obj/machinery/blackbox_recorder/blackbox round_end_data_gathering() //round_end time logging and some other data processing establish_db_connection() - if(!dbcon.IsConnected()) return + if(!GLOB.dbcon.IsConnected()) return var/round_id - var/DBQuery/query = dbcon.NewQuery("SELECT MAX(round_id) AS round_id FROM [format_table_name("feedback")]") + var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT MAX(round_id) AS round_id FROM [format_table_name("feedback")]") query.Execute() while(query.NextRow()) round_id = query.item[1] @@ -315,7 +315,7 @@ var/obj/machinery/blackbox_recorder/blackbox for(var/datum/feedback_variable/FV in feedback) var/sql = "INSERT INTO [format_table_name("feedback")] VALUES (null, Now(), [round_id], \"[FV.get_variable()]\", [FV.get_value()], \"[FV.get_details()]\")" - var/DBQuery/query_insert = dbcon.NewQuery(sql) + var/DBQuery/query_insert = GLOB.dbcon.NewQuery(sql) query_insert.Execute() /obj/machinery/blackbox_recorder/vv_edit_var(var_name, var_value) @@ -323,57 +323,57 @@ var/obj/machinery/blackbox_recorder/blackbox proc/feedback_set(var/variable,var/value) - if(!blackbox) return + if(!GLOB.blackbox) return variable = sanitizeSQL(variable) - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable) if(!FV) return FV.set_value(value) proc/feedback_inc(var/variable,var/value) - if(!blackbox) return + if(!GLOB.blackbox) return variable = sanitizeSQL(variable) - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable) if(!FV) return FV.inc(value) proc/feedback_dec(var/variable,var/value) - if(!blackbox) return + if(!GLOB.blackbox) return variable = sanitizeSQL(variable) - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable) if(!FV) return FV.dec(value) proc/feedback_set_details(var/variable,var/details) - if(!blackbox) return + if(!GLOB.blackbox) return variable = sanitizeSQL(variable) details = sanitizeSQL(details) - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable) if(!FV) return FV.set_details(details) proc/feedback_add_details(var/variable,var/details) - if(!blackbox) return + if(!GLOB.blackbox) return variable = sanitizeSQL(variable) details = sanitizeSQL(details) - var/datum/feedback_variable/FV = blackbox.find_feedback_datum(variable) + var/datum/feedback_variable/FV = GLOB.blackbox.find_feedback_datum(variable) if(!FV) return diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index d4132bf3f4b..d7bf071a8eb 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -645,7 +645,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, ui = new(user, src, ui_key, "r_n_d.tmpl", src.name, 800, 550) ui.open() -/obj/machinery/computer/rdconsole/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/rdconsole/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] files.RefreshResearch() diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm index 7acdc53ce3d..bd4e5528a9b 100644 --- a/code/modules/research/rdmachines.dm +++ b/code/modules/research/rdmachines.dm @@ -20,9 +20,7 @@ var/datum/component/material_container/materials //Store for hyper speed! /obj/machinery/r_n_d/New() - materials = AddComponent(/datum/component/material_container, - list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), 0, - TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) + materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), 0, TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) materials.precise_insertion = TRUE ..() wires["Red"] = 0 diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index 746e0ece0e8..84f15745df6 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -188,7 +188,7 @@ var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control var/obj/machinery/computer/camera_advanced/xenobio/X = target - if(cameranet.checkTurfVis(remote_eye.loc)) + if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) for(var/mob/living/simple_animal/slime/S in X.stored_slimes) S.forceMove(remote_eye.loc) S.visible_message("[S] warps in!") @@ -207,7 +207,7 @@ var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control var/obj/machinery/computer/camera_advanced/xenobio/X = target - if(cameranet.checkTurfVis(remote_eye.loc)) + if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) for(var/mob/living/simple_animal/slime/S in remote_eye.loc) if(X.stored_slimes.len >= X.max_slimes) break @@ -231,7 +231,7 @@ var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control var/obj/machinery/computer/camera_advanced/xenobio/X = target - if(cameranet.checkTurfVis(remote_eye.loc)) + if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) if(LAZYLEN(SSmobs.cubemonkeys) >= config.cubemonkeycap) to_chat(owner, "Bluespace harmonics prevent the spawning of more than [config.cubemonkeycap] monkeys on the station at one time!") return @@ -259,7 +259,7 @@ if(!recycler) to_chat(owner, "There is no connected monkey recycler. Use a multitool to link one.") return - if(cameranet.checkTurfVis(remote_eye.loc)) + if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) for(var/mob/living/carbon/human/M in remote_eye.loc) if(issmall(M) && M.stat) M.visible_message("[M] vanishes as [M.p_theyre()] reclaimed for recycling!") @@ -279,7 +279,7 @@ var/mob/living/C = owner var/mob/camera/aiEye/remote/xenobio/remote_eye = C.remote_control - if(cameranet.checkTurfVis(remote_eye.loc)) + if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) for(var/mob/living/simple_animal/slime/S in remote_eye.loc) slime_scan(S, C) else @@ -301,7 +301,7 @@ to_chat(owner, "No potion loaded.") return - if(cameranet.checkTurfVis(remote_eye.loc)) + if(GLOB.cameranet.checkTurfVis(remote_eye.loc)) for(var/mob/living/simple_animal/slime/S in remote_eye.loc) X.current_potion.attack(S, C) break @@ -357,7 +357,7 @@ // Scans slime /obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickCtrl(mob/living/user, mob/living/simple_animal/slime/S) - if(!cameranet.checkTurfVis(S.loc)) + if(!GLOB.cameranet.checkTurfVis(S.loc)) to_chat(user, "Target is not near a camera. Cannot proceed.") return var/mob/living/C = user @@ -368,7 +368,7 @@ //Feeds a potion to slime /obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickAlt(mob/living/user, mob/living/simple_animal/slime/S) - if(!cameranet.checkTurfVis(S.loc)) + if(!GLOB.cameranet.checkTurfVis(S.loc)) to_chat(user, "Target is not near a camera. Cannot proceed.") return var/mob/living/C = user @@ -383,7 +383,7 @@ //Picks up slime /obj/machinery/computer/camera_advanced/xenobio/proc/XenoSlimeClickShift(mob/living/user, mob/living/simple_animal/slime/S) - if(!cameranet.checkTurfVis(S.loc)) + if(!GLOB.cameranet.checkTurfVis(S.loc)) to_chat(user, "Target is not near a camera. Cannot proceed.") return var/mob/living/C = user @@ -405,7 +405,7 @@ //Place slimes /obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickShift(mob/living/user, turf/T) - if(!cameranet.checkTurfVis(T)) + if(!GLOB.cameranet.checkTurfVis(T)) to_chat(user, "Target is not near a camera. Cannot proceed.") return var/mob/living/C = user @@ -420,7 +420,7 @@ //Place monkey /obj/machinery/computer/camera_advanced/xenobio/proc/XenoTurfClickCtrl(mob/living/user, turf/T) - if(!cameranet.checkTurfVis(T)) + if(!GLOB.cameranet.checkTurfVis(T)) to_chat(user, "Target is not near a camera. Cannot proceed.") return var/mob/living/C = user @@ -438,7 +438,7 @@ //Pick up monkey /obj/machinery/computer/camera_advanced/xenobio/proc/XenoMonkeyClickCtrl(mob/living/user, mob/living/carbon/human/M) - if(!cameranet.checkTurfVis(M.loc)) + if(!GLOB.cameranet.checkTurfVis(M.loc)) to_chat(user, "Target is not near a camera. Cannot proceed.") return var/mob/living/C = user diff --git a/code/modules/response_team/ert.dm b/code/modules/response_team/ert.dm index 9c8d963fdcd..6155c1de6b9 100644 --- a/code/modules/response_team/ert.dm +++ b/code/modules/response_team/ert.dm @@ -7,11 +7,11 @@ /datum/game_mode var/list/datum/mind/ert = list() -var/list/response_team_members = list() -var/responseteam_age = 21 // Minimum account age to play as an ERT member -var/datum/response_team/active_team = null -var/send_emergency_team = FALSE -var/ert_request_answered = FALSE +GLOBAL_LIST_EMPTY(response_team_members) +GLOBAL_VAR_INIT(responseteam_age, 21) // Minimum account age to play as an ERT member +GLOBAL_DATUM(active_team, /datum/response_team) +GLOBAL_VAR_INIT(send_emergency_team, FALSE) +GLOBAL_VAR_INIT(ert_request_answered, FALSE) /client/proc/response_team() set name = "Dispatch CentComm Response Team" @@ -29,7 +29,7 @@ var/ert_request_answered = FALSE to_chat(usr, "The round hasn't started yet!") return - if(send_emergency_team) + if(GLOB.send_emergency_team) to_chat(usr, "Central Command has already dispatched an emergency response team!") return @@ -38,7 +38,7 @@ var/ert_request_answered = FALSE /mob/dead/observer/proc/JoinResponseTeam() - if(!send_emergency_team) + if(!GLOB.send_emergency_team) to_chat(src, "No emergency response team is currently being sent.") return 0 @@ -46,7 +46,7 @@ var/ert_request_answered = FALSE to_chat(src, "You are jobbanned from playing on an emergency response team!") return 0 - var/player_age_check = check_client_age(client, responseteam_age) + var/player_age_check = check_client_age(client, GLOB.responseteam_age) if(player_age_check && config.use_age_restriction_for_antags) to_chat(src, "This role is not yet available to you. You need to wait another [player_age_check] days.") return 0 @@ -58,15 +58,15 @@ var/ert_request_answered = FALSE return 1 /proc/trigger_armed_response_team(datum/response_team/response_team_type, commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots) - response_team_members = list() - active_team = response_team_type - active_team.setSlots(commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots) + GLOB.response_team_members = list() + GLOB.active_team = response_team_type + GLOB.active_team.setSlots(commander_slots, security_slots, medical_slots, engineering_slots, janitor_slots, paranormal_slots, cyborg_slots) - send_emergency_team = TRUE - var/list/ert_candidates = shuffle(pollCandidates("Join the Emergency Response Team?",, responseteam_age, 600, 1, role_playtime_requirements[ROLE_ERT])) + GLOB.send_emergency_team = TRUE + var/list/ert_candidates = shuffle(pollCandidates("Join the Emergency Response Team?",, GLOB.responseteam_age, 600, 1, GLOB.role_playtime_requirements[ROLE_ERT])) if(!ert_candidates.len) - active_team.cannot_send_team() - send_emergency_team = FALSE + GLOB.active_team.cannot_send_team() + GLOB.send_emergency_team = FALSE return // Respawnable players get first dibs @@ -74,37 +74,37 @@ var/ert_request_answered = FALSE if(jobban_isbanned(M, ROLE_TRAITOR) || jobban_isbanned(M, "Security Officer") || jobban_isbanned(M, "Captain") || jobban_isbanned(M, "Cyborg")) continue if((M in GLOB.respawnable_list) && M.JoinResponseTeam()) - response_team_members |= M + GLOB.response_team_members |= M // If there's still open slots, non-respawnable players can fill them for(var/mob/dead/observer/M in (ert_candidates - GLOB.respawnable_list)) if(M.JoinResponseTeam()) - response_team_members |= M + GLOB.response_team_members |= M - if(!response_team_members.len) - active_team.cannot_send_team() - send_emergency_team = FALSE + if(!GLOB.response_team_members.len) + GLOB.active_team.cannot_send_team() + GLOB.send_emergency_team = FALSE return var/list/ert_gender_prefs = list() - for(var/mob/M in response_team_members) + for(var/mob/M in GLOB.response_team_members) ert_gender_prefs.Add(input_async(M, "Please select a gender (10 seconds):", list("Male", "Female"))) - addtimer(CALLBACK(GLOBAL_PROC, .proc/get_ert_role_prefs, response_team_members, ert_gender_prefs), 100) + addtimer(CALLBACK(GLOBAL_PROC, .proc/get_ert_role_prefs, GLOB.response_team_members, ert_gender_prefs), 100) -/proc/get_ert_role_prefs(list/response_team_members, list/ert_gender_prefs) +/proc/get_ert_role_prefs(list/response_team_members, list/ert_gender_prefs) // Why the FUCK is this variable the EXACT SAME as the global one var/list/ert_role_prefs = list() for(var/datum/async_input/A in ert_gender_prefs) A.close() for(var/mob/M in response_team_members) - ert_role_prefs.Add(input_ranked_async(M, "Please order ERT roles from most to least preferred (20 seconds):", active_team.get_slot_list())) + ert_role_prefs.Add(input_ranked_async(M, "Please order ERT roles from most to least preferred (20 seconds):", GLOB.active_team.get_slot_list())) addtimer(CALLBACK(GLOBAL_PROC, .proc/dispatch_response_team, response_team_members, ert_gender_prefs, ert_role_prefs), 200) -/proc/dispatch_response_team(list/response_team_members, list/ert_gender_prefs, list/ert_role_prefs) +/proc/dispatch_response_team(list/response_team_members, list/datum/async_input/ert_gender_prefs, list/datum/async_input/ert_role_prefs) var/spawn_index = 1 for(var/i = 1, i <= response_team_members.len, i++) - if(spawn_index > emergencyresponseteamspawn.len) + if(spawn_index > GLOB.emergencyresponseteamspawn.len) break - if(!active_team.get_slot_list().len) + if(!GLOB.active_team.get_slot_list().len) break var/gender_pref = ert_gender_prefs[i].result var/role_pref = ert_role_prefs[i].close() @@ -115,9 +115,9 @@ var/ert_request_answered = FALSE // Player was afk and did not select continue for(var/role in role_pref) - if(active_team.check_slot_available(role)) - var/mob/living/new_commando = M.client.create_response_team(gender_pref, role, emergencyresponseteamspawn[spawn_index]) - active_team.reduceSlots(role) + if(GLOB.active_team.check_slot_available(role)) + var/mob/living/new_commando = M.client.create_response_team(gender_pref, role, GLOB.emergencyresponseteamspawn[spawn_index]) + GLOB.active_team.reduceSlots(role) spawn_index++ if(!M || !new_commando) break @@ -125,17 +125,17 @@ var/ert_request_answered = FALSE new_commando.key = M.key new_commando.update_icons() break - send_emergency_team = FALSE + GLOB.send_emergency_team = FALSE - if(active_team.count) - active_team.announce_team() + if(GLOB.active_team.count) + GLOB.active_team.announce_team() return // Everyone who said yes was afk - active_team.cannot_send_team() + GLOB.active_team.cannot_send_team() /client/proc/create_response_team(new_gender, role, turf/spawn_location) if(role == "Cyborg") - var/cyborg_unlock = active_team.getCyborgUnlock() + var/cyborg_unlock = GLOB.active_team.getCyborgUnlock() var/mob/living/silicon/robot/ert/R = new /mob/living/silicon/robot/ert(spawn_location, cyborg_unlock) return R @@ -185,7 +185,7 @@ var/ert_request_answered = FALSE SSjobs.CreateMoneyAccount(M, role, null) - active_team.equip_officer(role, M) + GLOB.active_team.equip_officer(role, M) return M @@ -227,6 +227,7 @@ var/ert_request_answered = FALSE return cyborg_unlock /datum/response_team/proc/get_slot_list() + RETURN_TYPE(/list) var/list/slots_available = list() for(var/role in slots) if(slots[role]) @@ -257,10 +258,10 @@ var/ert_request_answered = FALSE M.equipOutfit(command_outfit) /datum/response_team/proc/cannot_send_team() - event_announcement.Announce("[station_name()], we are unfortunately unable to send you an Emergency Response Team at this time.", "ERT Unavailable") + GLOB.event_announcement.Announce("[station_name()], we are unfortunately unable to send you an Emergency Response Team at this time.", "ERT Unavailable") /datum/response_team/proc/announce_team() - event_announcement.Announce("Attention, [station_name()]. We are sending a team of highly trained assistants to aid(?) you. Standby.", "ERT En-Route") + GLOB.event_announcement.Announce("Attention, [station_name()]. We are sending a team of highly trained assistants to aid(?) you. Standby.", "ERT En-Route") // -- AMBER TEAM -- @@ -273,7 +274,7 @@ var/ert_request_answered = FALSE paranormal_outfit = /datum/outfit/job/centcom/response_team/paranormal/amber /datum/response_team/amber/announce_team() - event_announcement.Announce("Attention, [station_name()]. We are sending a code AMBER light Emergency Response Team. Standby.", "ERT En-Route") + GLOB.event_announcement.Announce("Attention, [station_name()]. We are sending a code AMBER light Emergency Response Team. Standby.", "ERT En-Route") // -- RED TEAM -- @@ -286,7 +287,7 @@ var/ert_request_answered = FALSE paranormal_outfit = /datum/outfit/job/centcom/response_team/paranormal/red /datum/response_team/red/announce_team() - event_announcement.Announce("Attention, [station_name()]. We are sending a code RED Emergency Response Team. Standby.", "ERT En-Route") + GLOB.event_announcement.Announce("Attention, [station_name()]. We are sending a code RED Emergency Response Team. Standby.", "ERT En-Route") // -- GAMMA TEAM -- @@ -300,7 +301,7 @@ var/ert_request_answered = FALSE cyborg_unlock = 1 /datum/response_team/gamma/announce_team() - event_announcement.Announce("Attention, [station_name()]. We are sending a code GAMMA elite Emergency Response Team. Standby.", "ERT En-Route") + GLOB.event_announcement.Announce("Attention, [station_name()]. We are sending a code GAMMA elite Emergency Response Team. Standby.", "ERT En-Route") /datum/outfit/job/centcom/response_team name = "Response team" diff --git a/code/modules/ruins/lavalandruin_code/ash_walker_den.dm b/code/modules/ruins/lavalandruin_code/ash_walker_den.dm index c0b8e0f5555..62b2343f10a 100644 --- a/code/modules/ruins/lavalandruin_code/ash_walker_den.dm +++ b/code/modules/ruins/lavalandruin_code/ash_walker_den.dm @@ -25,7 +25,7 @@ STOP_PROCESSING(SSprocessing, src) /obj/structure/lavaland/ash_walker/deconstruct(disassembled) - new /obj/item/assembly/signaler/anomaly(get_step(loc, pick(alldirs))) + new /obj/item/assembly/signaler/anomaly(get_step(loc, pick(GLOB.alldirs))) new /obj/effect/collapse(loc) return ..() @@ -50,7 +50,7 @@ /obj/structure/lavaland/ash_walker/proc/spawn_mob() if(meat_counter >= ASH_WALKER_SPAWN_THRESHOLD) - new /obj/effect/mob_spawn/human/ash_walker(get_step(loc, pick(alldirs))) + new /obj/effect/mob_spawn/human/ash_walker(get_step(loc, pick(GLOB.alldirs))) visible_message("One of the eggs swells to an unnatural size and tumbles free. It's ready to hatch!") meat_counter -= ASH_WALKER_SPAWN_THRESHOLD diff --git a/code/modules/ruins/lavalandruin_code/sin_ruins.dm b/code/modules/ruins/lavalandruin_code/sin_ruins.dm index 82fbd410ea1..8e3876f7d2f 100644 --- a/code/modules/ruins/lavalandruin_code/sin_ruins.dm +++ b/code/modules/ruins/lavalandruin_code/sin_ruins.dm @@ -111,7 +111,7 @@ "Perfect. Much better! Now nobody will be able to resist yo-") var/turf/T = get_turf(user) - var/list/levels = space_manager.z_list.Copy() + var/list/levels = GLOB.space_manager.z_list.Copy() for(var/level in levels) if(!is_teleport_allowed(level)) levels -= level diff --git a/code/modules/ruins/lavalandruin_code/syndicate_base.dm b/code/modules/ruins/lavalandruin_code/syndicate_base.dm index 33e4fb527ae..d053e139f61 100644 --- a/code/modules/ruins/lavalandruin_code/syndicate_base.dm +++ b/code/modules/ruins/lavalandruin_code/syndicate_base.dm @@ -17,7 +17,7 @@ /obj/item/grenade/chem_grenade/cryo = 5, /obj/item/grenade/chem_grenade/adv_release = 5, /obj/item/reagent_containers/food/drinks/bottle/holywater = 1) - product_slogans = "It's not pyromania if you're getting paid!;You smell that? Plasma, son. Nothing else in the world smells like that.;I love the smell of Plasma in the morning." + slogan_list = list("It's not pyromania if you're getting paid!","You smell that? Plasma, son. Nothing else in the world smells like that.","I love the smell of Plasma in the morning.") resistance_flags = FIRE_PROOF // Spawners @@ -32,6 +32,7 @@
    You are free to attack anyone not aligned with the Syndicate in the vicinity of your base. DO NOT work against Syndicate personnel (such as traitors or nuclear operatives). You may work with or against non-Syndicate antagonists on a case-by-case basis. DO NOT leave your base without admin permission." outfit = /datum/outfit/lavaland_syndicate assignedrole = "Lavaland Syndicate" + del_types = list() // Necessary to prevent del_types from removing radio! allow_species_pick = TRUE /obj/effect/mob_spawn/human/lavaland_syndicate/Destroy() @@ -46,7 +47,7 @@ suit = /obj/item/clothing/suit/storage/labcoat shoes = /obj/item/clothing/shoes/combat gloves = /obj/item/clothing/gloves/combat - r_ear = /obj/item/radio/headset/syndicate/alt + r_ear = /obj/item/radio/headset/syndicate/alt/lavaland // See del_types above back = /obj/item/storage/backpack r_pocket = /obj/item/gun/projectile/automatic/pistol id = /obj/item/card/id/syndicate/anyone @@ -74,9 +75,13 @@ /datum/outfit/lavaland_syndicate/comms name = "Lavaland Syndicate Comms Agent" + r_ear = /obj/item/radio/headset/syndicate/alt // See del_types above r_hand = /obj/item/melee/energy/sword/saber mask = /obj/item/clothing/mask/chameleon/gps suit = /obj/item/clothing/suit/armor/vest + backpack_contents = list( + /obj/item/paper/monitorkey = 1 // message console on lavaland does NOT spawn with this + ) /obj/item/clothing/mask/chameleon/gps/New() . = ..() diff --git a/code/modules/ruins/ruin_areas.dm b/code/modules/ruins/ruin_areas.dm index 2d8ce5a33ac..754f8d44f29 100644 --- a/code/modules/ruins/ruin_areas.dm +++ b/code/modules/ruins/ruin_areas.dm @@ -44,3 +44,8 @@ /area/ruin/onehalf/bridge name = "Bridge" icon_state = "bridge" + +// Old tcommsat +/area/ruin/tcommsat + name = "Telecommunications Satellite" + icon_state = "tcomsatcham" diff --git a/code/modules/security_levels/keycard authentication.dm b/code/modules/security_levels/keycard authentication.dm index 99a04205117..06ebfaa3374 100644 --- a/code/modules/security_levels/keycard authentication.dm +++ b/code/modules/security_levels/keycard authentication.dm @@ -78,7 +78,7 @@ ui = new(user, src, ui_key, "keycard_auth.tmpl", "Keycard Authentication Device UI", 540, 320) ui.open() -/obj/machinery/keycard_auth/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/keycard_auth/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["screen"] = screen data["event"] = event @@ -168,7 +168,7 @@ atom_say("All Emergency Response Teams are dispatched and can not be called at this time.") return atom_say("ERT request transmitted!") - command_announcer.autosay("ERT request transmitted. Reason: [ert_reason]", name) + GLOB.command_announcer.autosay("ERT request transmitted. Reason: [ert_reason]", name) print_centcom_report(ert_reason, station_time_timestamp() + " ERT Request") var/fullmin_count = 0 @@ -176,12 +176,12 @@ if(check_rights(R_EVENT, 0, C.mob)) fullmin_count++ if(fullmin_count) - ert_request_answered = TRUE + GLOB.ert_request_answered = TRUE ERT_Announce(ert_reason , event_triggered_by, 0) ert_reason = "Reason for ERT" feedback_inc("alert_keycard_auth_ert",1) spawn(3000) - if(!ert_request_answered) + if(!GLOB.ert_request_answered) ERT_Announce(ert_reason , event_triggered_by, 1) else trigger_armed_response_team(new /datum/response_team/amber) // No admins? No problem. Automatically send a code amber ERT. @@ -189,37 +189,37 @@ /obj/machinery/keycard_auth/proc/is_ert_blocked() return SSticker.mode && SSticker.mode.ert_disabled -var/global/maint_all_access = 0 -var/global/station_all_access = 0 +GLOBAL_VAR_INIT(maint_all_access, 0) +GLOBAL_VAR_INIT(station_all_access, 0) /proc/make_maint_all_access() for(var/area/maintenance/A in world) for(var/obj/machinery/door/airlock/D in A) D.emergency = 1 D.update_icon(0) - minor_announcement.Announce("Access restrictions on maintenance and external airlocks have been removed.") - maint_all_access = 1 + GLOB.minor_announcement.Announce("Access restrictions on maintenance and external airlocks have been removed.") + GLOB.maint_all_access = 1 /proc/revoke_maint_all_access() for(var/area/maintenance/A in world) for(var/obj/machinery/door/airlock/D in A) D.emergency = 0 D.update_icon(0) - minor_announcement.Announce("Access restrictions on maintenance and external airlocks have been re-added.") - maint_all_access = 0 + GLOB.minor_announcement.Announce("Access restrictions on maintenance and external airlocks have been re-added.") + GLOB.maint_all_access = 0 /proc/make_station_all_access() for(var/obj/machinery/door/airlock/D in GLOB.airlocks) if(is_station_level(D.z)) D.emergency = 1 D.update_icon(0) - minor_announcement.Announce("Access restrictions on all station airlocks have been removed due to an ongoing crisis. Trespassing laws still apply unless ordered otherwise by Command staff.") - station_all_access = 1 + GLOB.minor_announcement.Announce("Access restrictions on all station airlocks have been removed due to an ongoing crisis. Trespassing laws still apply unless ordered otherwise by Command staff.") + GLOB.station_all_access = 1 /proc/revoke_station_all_access() for(var/obj/machinery/door/airlock/D in GLOB.airlocks) if(is_station_level(D.z)) D.emergency = 0 D.update_icon(0) - minor_announcement.Announce("Access restrictions on all station airlocks have been re-added. Seek station AI or a colleague's assistance if you are stuck.") - station_all_access = 0 + GLOB.minor_announcement.Announce("Access restrictions on all station airlocks have been re-added. Seek station AI or a colleague's assistance if you are stuck.") + GLOB.station_all_access = 0 diff --git a/code/modules/security_levels/security levels.dm b/code/modules/security_levels/security levels.dm index effaae3f0ad..0f07107a00b 100644 --- a/code/modules/security_levels/security levels.dm +++ b/code/modules/security_levels/security levels.dm @@ -1,4 +1,4 @@ -/var/security_level = 0 +GLOBAL_VAR_INIT(security_level, 0) //0 = code green //1 = code blue //2 = code red @@ -7,8 +7,8 @@ //5 = code delta //config.alert_desc_blue_downto -/var/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 0, new_sound = sound('sound/misc/notice1.ogg')) -/var/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 0) +GLOBAL_DATUM_INIT(security_announcement_up, /datum/announcement/priority/security, new(do_log = 0, do_newscast = 0, new_sound = sound('sound/misc/notice1.ogg'))) +GLOBAL_DATUM_INIT(security_announcement_down, /datum/announcement/priority/security, new(do_log = 0, do_newscast = 0)) /proc/set_security_level(var/level) switch(level) @@ -26,8 +26,8 @@ level = SEC_LEVEL_DELTA //Will not be announced if you try to set to the same level as it already is - if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level) - if(level >= SEC_LEVEL_RED && security_level < SEC_LEVEL_RED) + if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != GLOB.security_level) + if(level >= SEC_LEVEL_RED && GLOB.security_level < SEC_LEVEL_RED) // Mark down this time to prevent shuttle cheese SSshuttle.emergency_sec_level_time = world.time @@ -42,8 +42,8 @@ switch(level) if(SEC_LEVEL_GREEN) - security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.") - security_level = SEC_LEVEL_GREEN + GLOB.security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.") + GLOB.security_level = SEC_LEVEL_GREEN post_status("alert", "outline") @@ -53,11 +53,11 @@ FA.overlays += image('icons/obj/monitors.dmi', "overlay_green") if(SEC_LEVEL_BLUE) - if(security_level < SEC_LEVEL_BLUE) - security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.") + if(GLOB.security_level < SEC_LEVEL_BLUE) + GLOB.security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.") else - security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.") - security_level = SEC_LEVEL_BLUE + GLOB.security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.") + GLOB.security_level = SEC_LEVEL_BLUE post_status("alert", "outline") @@ -67,11 +67,11 @@ FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue") if(SEC_LEVEL_RED) - if(security_level < SEC_LEVEL_RED) - security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") + if(GLOB.security_level < SEC_LEVEL_RED) + GLOB.security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") else - security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") - security_level = SEC_LEVEL_RED + GLOB.security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!") + GLOB.security_level = SEC_LEVEL_RED var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in GLOB.airlocks if(R && is_station_level(R.z)) @@ -86,12 +86,12 @@ FA.overlays += image('icons/obj/monitors.dmi', "overlay_red") if(SEC_LEVEL_GAMMA) - security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!", new_sound = sound('sound/effects/new_siren.ogg')) - security_level = SEC_LEVEL_GAMMA + GLOB.security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!", new_sound = sound('sound/effects/new_siren.ogg')) + GLOB.security_level = SEC_LEVEL_GAMMA move_gamma_ship() - if(security_level < SEC_LEVEL_RED) + if(GLOB.security_level < SEC_LEVEL_RED) for(var/obj/machinery/door/airlock/highsecurity/red/R in GLOB.airlocks) if(is_station_level(R.z)) R.locked = 0 @@ -111,8 +111,8 @@ FA.update_icon() if(SEC_LEVEL_EPSILON) - security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!", new_sound = sound('sound/effects/purge_siren.ogg')) - security_level = SEC_LEVEL_EPSILON + GLOB.security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!", new_sound = sound('sound/effects/purge_siren.ogg')) + GLOB.security_level = SEC_LEVEL_EPSILON post_status("alert", "epsilonalert") @@ -122,8 +122,8 @@ FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon") if(SEC_LEVEL_DELTA) - security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!", new_sound = sound('sound/effects/deltaalarm.ogg')) - security_level = SEC_LEVEL_DELTA + GLOB.security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!", new_sound = sound('sound/effects/deltaalarm.ogg')) + GLOB.security_level = SEC_LEVEL_DELTA post_status("alert", "deltaalert") @@ -133,16 +133,16 @@ FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta") if(level >= SEC_LEVEL_RED) - atc.reroute_traffic(yes = TRUE) // Tell them fuck off we're busy. + GLOB.atc.reroute_traffic(yes = TRUE) // Tell them fuck off we're busy. else - atc.reroute_traffic(yes = FALSE) + GLOB.atc.reroute_traffic(yes = FALSE) SSnightshift.check_nightshift(TRUE) else return /proc/get_security_level() - switch(security_level) + switch(GLOB.security_level) if(SEC_LEVEL_GREEN) return "green" if(SEC_LEVEL_BLUE) diff --git a/code/modules/shuttle/assault_pod.dm b/code/modules/shuttle/assault_pod.dm index 0d2953017c8..9505ac475e2 100644 --- a/code/modules/shuttle/assault_pod.dm +++ b/code/modules/shuttle/assault_pod.dm @@ -33,8 +33,8 @@ /obj/item/assault_pod/attack_self(mob/living/user) var/target_area - target_area = input("Area to land", "Select a Landing Zone", target_area) in teleportlocs - var/area/picked_area = teleportlocs[target_area] + target_area = input("Area to land", "Select a Landing Zone", target_area) in GLOB.teleportlocs + var/area/picked_area = GLOB.teleportlocs[target_area] if(!src || QDELETED(src)) return diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 7f9eddc0df4..f82598b1e14 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -49,20 +49,20 @@ if(auth_need - authorized.len > 0) message_admins("[key_name_admin(user)] has authorized early shuttle launch.") log_game("[key_name(user)] has authorized early shuttle launch in ([x], [y], [z]).") - minor_announcement.Announce("[auth_need - authorized.len] more authorization(s) needed until shuttle is launched early") + GLOB.minor_announcement.Announce("[auth_need - authorized.len] more authorization(s) needed until shuttle is launched early") else message_admins("[key_name_admin(user)] has launched the emergency shuttle [seconds] seconds before launch.") log_game("[key_name(user)] has launched the emergency shuttle in ([x], [y], [z]) [seconds] seconds before launch.") - minor_announcement.Announce("The emergency shuttle will launch in 10 seconds") + GLOB.minor_announcement.Announce("The emergency shuttle will launch in 10 seconds") SSshuttle.emergency.setTimer(100) if("Repeal") if(authorized.Remove(W:registered_name)) - minor_announcement.Announce("[auth_need - authorized.len] authorizations needed until shuttle is launched early") + GLOB.minor_announcement.Announce("[auth_need - authorized.len] authorizations needed until shuttle is launched early") if("Abort") if(authorized.len) - minor_announcement.Announce("All authorizations to launch the shuttle early have been revoked.") + GLOB.minor_announcement.Announce("All authorizations to launch the shuttle early have been revoked.") authorized.Cut() /obj/machinery/computer/emergency_shuttle/emag_act(mob/user) @@ -70,7 +70,7 @@ var/time = SSshuttle.emergency.timeLeft() message_admins("[key_name_admin(user)] has emagged the emergency shuttle: [time] seconds before launch.") log_game("[key_name(user)] has emagged the emergency shuttle in ([x], [y], [z]): [time] seconds before launch.") - minor_announcement.Announce("The emergency shuttle will launch in 10 seconds", "SYSTEM ERROR:") + GLOB.minor_announcement.Announce("The emergency shuttle will launch in 10 seconds", "SYSTEM ERROR:") SSshuttle.emergency.setTimer(100) emagged = 1 @@ -151,9 +151,9 @@ emergency_shuttle_called.Announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ]") if(reason == "Automatic Crew Transfer" && signalOrigin == null) // Best way we have to check that it's actually a crew transfer and not just a player using the same message- any other calls to this proc should have a signalOrigin. - atc.shift_ending() + GLOB.atc.shift_ending() else // Emergency shuttle call (probably) - atc.reroute_traffic(yes = TRUE) + GLOB.atc.reroute_traffic(yes = TRUE) /obj/docking_port/mobile/emergency/cancel(area/signalOrigin) @@ -252,7 +252,7 @@ if(SHUTTLE_DOCKED) if(time_left <= 0 && SSshuttle.emergencyNoEscape) - priority_announcement.Announce("Hostile environment detected. Departure has been postponed indefinitely pending conflict resolution.") + GLOB.priority_announcement.Announce("Hostile environment detected. Departure has been postponed indefinitely pending conflict resolution.") sound_played = 0 mode = SHUTTLE_STRANDED @@ -272,9 +272,9 @@ enterTransit() mode = SHUTTLE_ESCAPE timer = world.time - priority_announcement.Announce("The Emergency Shuttle has left the station. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.") + GLOB.priority_announcement.Announce("The Emergency Shuttle has left the station. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.") for(var/mob/M in GLOB.player_list) - if(!isnewplayer(M) && !M.client.karma_spent && !(M.client.ckey in karma_spenders) && !M.get_preference(DISABLE_KARMA_REMINDER)) + if(!isnewplayer(M) && !M.client.karma_spent && !(M.client.ckey in GLOB.karma_spenders) && !M.get_preference(DISABLE_KARMA_REMINDER)) to_chat(M, "You have not yet spent your karma for the round; was there a player worthy of receiving your reward? Look under Special Verbs tab, Award Karma.") if(SHUTTLE_ESCAPE) @@ -291,7 +291,7 @@ var/destination_dock = "emergency_away" if(is_hijacked()) destination_dock = "emergency_syndicate" - priority_announcement.Announce("Corruption detected in shuttle navigation protocols. Please contact your supervisor.") + GLOB.priority_announcement.Announce("Corruption detected in shuttle navigation protocols. Please contact your supervisor.") dock_id(destination_dock) diff --git a/code/modules/shuttle/ert.dm b/code/modules/shuttle/ert.dm index 1f664a69c8f..356ca9687dc 100644 --- a/code/modules/shuttle/ert.dm +++ b/code/modules/shuttle/ert.dm @@ -6,6 +6,14 @@ resistance_flags = INDESTRUCTIBLE flags = NODECONSTRUCT +/obj/machinery/computer/shuttle/ert/Topic(href, href_list) + if(href_list["move"]) + var/authorized_roles = list(SPECIAL_ROLE_ERT, SPECIAL_ROLE_DEATHSQUAD) + if(!((usr.mind.assigned_role in authorized_roles) || is_admin(usr))) + message_admins("Potential ERT shuttle hijack, ERT shuttle moved by unauthorized user: [key_name_admin(usr)]") + ..() + + /obj/machinery/computer/camera_advanced/shuttle_docker/ert name = "specops navigation computer" desc = "Used to designate a precise transit location for the specops shuttle." diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index dbec1c611f7..f0394349f4d 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -1,5 +1,5 @@ // Shuttle on-movement // -/atom/movable/proc/onShuttleMove(turf/oldT, turf/T1, rotation) +/atom/movable/proc/onShuttleMove(turf/oldT, turf/T1, rotation, mob/caller) var/turf/newT = get_turf(src) if(newT.z != oldT.z) onTransitZ(oldT.z, newT.z) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index 36ad93eb28e..fd4bb0b6ad5 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -218,6 +218,8 @@ var/travelDir = 0 //direction the shuttle would travel in var/rebuildable = 0 //can build new shuttle consoles for this one + var/mob/last_caller // Who called the shuttle the last time + var/obj/docking_port/stationary/destination var/obj/docking_port/stationary/previous @@ -496,7 +498,7 @@ areaInstance.moving = TRUE //move mobile to new location for(var/atom/movable/AM in T0) - AM.onShuttleMove(T0, T1, rotation) + AM.onShuttleMove(T0, T1, rotation, last_caller) if(rotation) T1.shuttleRotate(rotation) @@ -774,7 +776,7 @@ ui = new(user, src, ui_key, "shuttle_console.tmpl", M ? M.name : "shuttle", 300, 200) ui.open() -/obj/machinery/computer/shuttle/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/shuttle/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId) data["status"] = M ? M.getStatusText() : null @@ -807,11 +809,13 @@ if(href_list["move"]) if(!options.Find(href_list["move"])) //I see you're trying Href exploits, I see you're failing, I SEE ADMIN WARNING. // Seriously, though, NEVER trust a Topic with something like this. Ever. - message_admins("move HREF ([src] attempted to move to: [href_list["move"]]) exploit attempted by [key_name_admin(usr)] on [src] (JMP)") + // Sidenote for whoever did this last. Why did you set it to echo whatever the user entered to admin chat? You solved one exploit and created another. + message_admins("EXPLOIT: [ADMIN_LOOKUPFLW(usr)] attempted to move [src] to an invalid location! [ADMIN_COORDJMP(src)]") return - switch(SSshuttle.moveShuttle(shuttleId, href_list["move"], 1)) + switch(SSshuttle.moveShuttle(shuttleId, href_list["move"], 1, usr)) if(0) atom_say("Shuttle departing! Please stand away from the doors.") + usr.create_log(MISC_LOG, "used [src] to call the [shuttleId] shuttle") if(1) to_chat(usr, "Invalid shuttle requested.") else diff --git a/code/modules/shuttle/shuttle_manipulator.dm b/code/modules/shuttle/shuttle_manipulator.dm index 0e67b74de67..c9184b2a484 100644 --- a/code/modules/shuttle/shuttle_manipulator.dm +++ b/code/modules/shuttle/shuttle_manipulator.dm @@ -64,7 +64,7 @@ if(!ui) // the ui does not exist, so we'll create a new() one // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm - ui = new(user, src, ui_key, "shuttle_manipulator.tmpl", "Shuttle Manipulator", 660, 700, null, null, admin_state) + ui = new(user, src, ui_key, "shuttle_manipulator.tmpl", "Shuttle Manipulator", 660, 700, null, null, GLOB.admin_state) // when the ui is first opened this is the data it will use // open the new ui window ui.open() @@ -80,8 +80,8 @@ data["templates_tabs"] = list() data["selected"] = null - for(var/shuttle_id in shuttle_templates) - var/datum/map_template/shuttle/S = shuttle_templates[shuttle_id] + for(var/shuttle_id in GLOB.shuttle_templates) + var/datum/map_template/shuttle/S = GLOB.shuttle_templates[shuttle_id] if(!templates[S.port_id]) data["templates_tabs"] += S.port_id @@ -138,7 +138,7 @@ // Preload some common parameters var/shuttle_id = href_list["shuttle_id"] - var/datum/map_template/shuttle/S = shuttle_templates[shuttle_id] + var/datum/map_template/shuttle/S = GLOB.shuttle_templates[shuttle_id] if(href_list["selectMenuKey"]) diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 80094c876df..50cf7ff7d28 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -102,7 +102,10 @@ var/pointsEarned for(var/atom/movable/MA in areaInstance) - if(MA.anchored) continue + if(MA.anchored) + continue + if(istype(MA, /mob/dead)) + continue SSshuttle.sold_atoms += " [MA.name]" // Must be in a crate (or a critter crate)! @@ -413,19 +416,19 @@ ui = new(user, src, ui_key, "order_console.tmpl", name, ORDER_SCREEN_WIDTH, ORDER_SCREEN_HEIGHT) ui.open() -/obj/machinery/computer/ordercomp/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/ordercomp/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["last_viewed_group"] = last_viewed_group var/category_list[0] - for(var/category in all_supply_groups) + for(var/category in GLOB.all_supply_groups) category_list.Add(list(list("name" = get_supply_group_name(category), "category" = category))) data["categories"] = category_list var/cat = text2num(last_viewed_group) var/packs_list[0] for(var/set_name in SSshuttle.supply_packs) var/datum/supply_packs/pack = SSshuttle.supply_packs[set_name] - if(!pack.contraband && !pack.hidden && !pack.special && pack.group == cat) + if((!pack.contraband && !pack.hidden && !pack.special && pack.group == cat) || (!pack.contraband && !pack.hidden && (pack.special && pack.special_enabled) && pack.group == cat)) // 0/1 after the pack name (set_name) is a boolean for ordering multiple crates packs_list.Add(list(list("name" = pack.name, "amount" = pack.amount, "cost" = pack.cost, "command1" = list("doorder" = "[set_name]0"), "command2" = list("doorder" = "[set_name]1"), "command3" = list("contents" = set_name)))) @@ -559,12 +562,12 @@ ui = new(user, src, ui_key, "supply_console.tmpl", name, SUPPLY_SCREEN_WIDTH, SUPPLY_SCREEN_HEIGHT) ui.open() -/obj/machinery/computer/supplycomp/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/supplycomp/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/data[0] data["last_viewed_group"] = last_viewed_group var/category_list[0] - for(var/category in all_supply_groups) + for(var/category in GLOB.all_supply_groups) category_list.Add(list(list("name" = get_supply_group_name(category), "category" = category))) data["categories"] = category_list diff --git a/code/modules/space_management/level_check.dm b/code/modules/space_management/level_check.dm index a9abdaa5472..c49843cd7ea 100644 --- a/code/modules/space_management/level_check.dm +++ b/code/modules/space_management/level_check.dm @@ -1,5 +1,5 @@ /proc/is_on_level_name(atom/A,name) - var/datum/space_level/S = space_manager.get_zlev_by_name(name) + var/datum/space_level/S = GLOB.space_manager.get_zlev_by_name(name) return A.z == S.zpos // For expansion later diff --git a/code/modules/space_management/level_traits.dm b/code/modules/space_management/level_traits.dm index 6fcd267105f..1d88f70454f 100644 --- a/code/modules/space_management/level_traits.dm +++ b/code/modules/space_management/level_traits.dm @@ -36,28 +36,28 @@ secure = (z == level_name_to_num(CENTCOMM)) return secure -var/list/default_map_traits = MAP_TRANSITION_CONFIG +GLOBAL_LIST_INIT(default_map_traits, MAP_TRANSITION_CONFIG) /proc/check_level_trait(z, trait) if(!z) return 0 // If you're nowhere, you have no traits var/list/trait_list - if(space_manager.initialized) - var/datum/space_level/S = space_manager.get_zlev(z) + if(GLOB.space_manager.initialized) + var/datum/space_level/S = GLOB.space_manager.get_zlev(z) trait_list = S.flags else - trait_list = default_map_traits[z] + trait_list = GLOB.default_map_traits[z] trait_list = trait_list["attributes"] return (trait in trait_list) /proc/levels_by_trait(trait) var/list/result = list() - for(var/A in space_manager.z_list) - var/datum/space_level/S = space_manager.z_list[A] + for(var/A in GLOB.space_manager.z_list) + var/datum/space_level/S = GLOB.space_manager.z_list[A] if(trait in S.flags) result |= S.zpos return result /proc/level_name_to_num(name) - var/datum/space_level/S = space_manager.get_zlev_by_name(name) + var/datum/space_level/S = GLOB.space_manager.get_zlev_by_name(name) return S.zpos diff --git a/code/modules/space_management/space_level.dm b/code/modules/space_management/space_level.dm index 8443951d1d3..44c692363af 100644 --- a/code/modules/space_management/space_level.dm +++ b/code/modules/space_management/space_level.dm @@ -31,11 +31,11 @@ /datum/space_level/Destroy() if(linkage == CROSSLINKED) - if(space_manager.linkage_map) - remove_from_space_network(space_manager.linkage_map) + if(GLOB.space_manager.linkage_map) + remove_from_space_network(GLOB.space_manager.linkage_map) - space_manager.unbuilt_space_transitions -= src - space_manager.z_list -= "[zpos]" + GLOB.space_manager.unbuilt_space_transitions -= src + GLOB.space_manager.z_list -= "[zpos]" return ..() /datum/space_level/proc/build_space_destination_arrays() @@ -95,7 +95,7 @@ transit_east -= S /datum/space_level/proc/apply_transition(turf/space/S) - if(src in space_manager.unbuilt_space_transitions) + if(src in GLOB.space_manager.unbuilt_space_transitions) return // Let the space manager handle this one switch(linkage) if(UNAFFECTED) @@ -124,10 +124,10 @@ return // Remove ourselves from the linkage map if we were cross-linked if(linkage == CROSSLINKED) - if(space_manager.linkage_map) - remove_from_space_network(space_manager.linkage_map) + if(GLOB.space_manager.linkage_map) + remove_from_space_network(GLOB.space_manager.linkage_map) - space_manager.unbuilt_space_transitions |= src + GLOB.space_manager.unbuilt_space_transitions |= src linkage = transition_type switch(transition_type) if(UNAFFECTED) @@ -143,9 +143,9 @@ D.register() D.forceMove(locate(200, 200, zpos)) -var/list/atmos_machine_typecache = typecacheof(/obj/machinery/atmospherics) -var/list/cable_typecache = typecacheof(/obj/structure/cable) -var/list/maploader_typecache = typecacheof(/obj/effect/landmark/map_loader) +GLOBAL_LIST_INIT(atmos_machine_typecache, typecacheof(/obj/machinery/atmospherics)) +GLOBAL_LIST_INIT(cable_typecache, typecacheof(/obj/structure/cable)) +GLOBAL_LIST_INIT(maploader_typecache, typecacheof(/obj/effect/landmark/map_loader)) /datum/space_level/proc/resume_init() if(dirt_count > 0) @@ -156,9 +156,9 @@ var/list/maploader_typecache = typecacheof(/obj/effect/landmark/map_loader) init_list = list() var/watch = start_watch() listclearnulls(our_atoms) - var/list/late_maps = typecache_filter_list(our_atoms, maploader_typecache) - var/list/pipes = typecache_filter_list(our_atoms, atmos_machine_typecache) - var/list/cables = typecache_filter_list(our_atoms, cable_typecache) + var/list/late_maps = typecache_filter_list(our_atoms, GLOB.maploader_typecache) + var/list/pipes = typecache_filter_list(our_atoms, GLOB.atmos_machine_typecache) + var/list/cables = typecache_filter_list(our_atoms, GLOB.cable_typecache) // If we don't carefully add dirt around the map templates, bad stuff happens // so we separate them out here our_atoms -= late_maps @@ -193,9 +193,9 @@ var/list/maploader_typecache = typecacheof(/obj/effect/landmark/map_loader) /datum/space_level/proc/do_late_maps(list/late_maps) var/watch = start_watch() log_debug("Loading map templates on z-level '[zpos]'!") - space_manager.add_dirt(zpos) // Let's not repeatedly resume init for each template + GLOB.space_manager.add_dirt(zpos) // Let's not repeatedly resume init for each template for(var/atom/movable/AM in late_maps) AM.Initialize() late_maps.Cut() - space_manager.remove_dirt(zpos) + GLOB.space_manager.remove_dirt(zpos) log_debug("Took [stop_watch(watch)]s") diff --git a/code/modules/space_management/space_transition.dm b/code/modules/space_management/space_transition.dm index f432d9733a5..5312938d588 100644 --- a/code/modules/space_management/space_transition.dm +++ b/code/modules/space_management/space_transition.dm @@ -63,8 +63,8 @@ var/oppose = get_opposite_direction(direction) neighbors[direction] = S S.neighbors[oppose] = src - space_manager.unbuilt_space_transitions |= src - space_manager.unbuilt_space_transitions |= S + GLOB.space_manager.unbuilt_space_transitions |= src + GLOB.space_manager.unbuilt_space_transitions |= S /datum/space_level/proc/get_connection(direction) @@ -169,7 +169,7 @@ var/datum/space_level/S = spl.neighbors[direction] var/oppose = get_opposite_direction(direction) S.neighbors.Remove(oppose) - space_manager.unbuilt_space_transitions |= S + GLOB.space_manager.unbuilt_space_transitions |= S spl.reset_connections() spl = initial(spl) diff --git a/code/modules/space_management/zlevel_manager.dm b/code/modules/space_management/zlevel_manager.dm index e45aff76078..5582288a813 100644 --- a/code/modules/space_management/zlevel_manager.dm +++ b/code/modules/space_management/zlevel_manager.dm @@ -1,4 +1,4 @@ -var/global/datum/zlev_manager/space_manager = new +GLOBAL_DATUM_INIT(space_manager, /datum/zlev_manager, new()) /datum/zlev_manager // A list of z-levels @@ -17,11 +17,11 @@ var/global/datum/zlev_manager/space_manager = new // Populate our space level list // and prepare space transitions /datum/zlev_manager/proc/initialize() - var/num_official_z_levels = map_transition_config.len + var/num_official_z_levels = GLOB.map_transition_config.len var/k = 1 // First take care of "Official" z levels, without visiting levels outside of the list - for(var/list/features in map_transition_config) + for(var/list/features in GLOB.map_transition_config) if(k > world.maxz) CRASH("More map attributes pre-defined than existent z levels - [num_official_z_levels]") var/name = features["name"] @@ -107,6 +107,7 @@ var/global/datum/zlev_manager/space_manager = new // Increments the max z-level by one // For convenience's sake returns the z-level added /datum/zlev_manager/proc/add_new_zlevel(name, linkage = SELFLOOPING, traits = list(BLOCK_TELEPORT)) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_Z, args) if(name in levels_by_name) throw EXCEPTION("Name already in use: [name]") world.maxz++ diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index 5b0be539578..2e3c89017ef 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -24,7 +24,7 @@ layer = 3.9 infra_luminosity = 15 - var/list/mob/pilot //There is only ever one pilot and he gets all the privledge + var/mob/pilot //There is only ever one pilot and he gets all the privledge var/list/mob/passengers = list() //passengers can't do anything and are variable in number var/max_passengers = 0 var/obj/item/storage/internal/cargo_hold @@ -37,8 +37,6 @@ var/datum/gas_mixture/cabin_air var/obj/machinery/portable_atmospherics/canister/internal_tank var/use_internal_tank = 0 - var/datum/global_iterator/pr_int_temp_processor //normalizes internal air mixture temperature - var/datum/global_iterator/pr_give_air //moves air from tank to cabin var/datum/effect_system/trail_follow/ion/space_trail/ion_trail @@ -117,8 +115,6 @@ src.ion_trail.set_up(src) src.ion_trail.start() src.use_internal_tank = 1 - pr_int_temp_processor = new /datum/global_iterator/pod_preserve_temp(list(src)) - pr_give_air = new /datum/global_iterator/pod_tank_give_air(list(src)) equipment_system = new(src) equipment_system.installed_modules += battery GLOB.spacepods_list += src @@ -127,6 +123,7 @@ cargo_hold.storage_slots = 0 //You need to install cargo modules to use it. cargo_hold.max_w_class = 5 //fit almost anything cargo_hold.max_combined_w_class = 0 //you can optimize your stash with larger items + START_PROCESSING(SSobj, src) /obj/spacepod/Destroy() if(equipment_system.cargo_system) @@ -136,8 +133,6 @@ QDEL_NULL(battery) QDEL_NULL(cabin_air) QDEL_NULL(internal_tank) - QDEL_NULL(pr_int_temp_processor) - QDEL_NULL(pr_give_air) QDEL_NULL(ion_trail) occupant_sanity_check() if(pilot) @@ -148,13 +143,14 @@ M.forceMove(get_turf(src)) passengers -= M GLOB.spacepods_list -= src + STOP_PROCESSING(SSobj, src) return ..() /obj/spacepod/process() + give_air() + regulate_temp() if(src.empcounter > 0) src.empcounter-- - else - STOP_PROCESSING(SSobj, src) /obj/spacepod/proc/update_icons() if(!pod_overlays) @@ -216,6 +212,7 @@ deal_damage(damage) visible_message("[user] [user.attacktext] [src]!") user.create_attack_log("attacked [src.name]") + add_attack_logs(user, src, "attacked") return TRUE /obj/spacepod/attack_alien(mob/user) @@ -287,7 +284,6 @@ deal_damage(80 / severity) if(empcounter < (40 / severity)) empcounter = 40 / severity - START_PROCESSING(SSobj, src) switch(severity) if(1) @@ -697,7 +693,7 @@ return 1 /obj/spacepod/MouseDrop_T(atom/A, mob/user) - if(user == pilot || user in passengers) + if(user == pilot || (user in passengers)) return if(istype(A,/mob)) @@ -997,22 +993,17 @@ return 1 -/datum/global_iterator/pod_preserve_temp //normalizing cabin air temperature to 20 degrees celsium - delay = 20 - - process(var/obj/spacepod/spacepod) - if(spacepod.cabin_air && spacepod.cabin_air.return_volume() > 0) - var/delta = spacepod.cabin_air.temperature - T20C - spacepod.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1))) - -/datum/global_iterator/pod_tank_give_air - delay = 15 - -/datum/global_iterator/pod_tank_give_air/process(var/obj/spacepod/spacepod) - if(spacepod && spacepod.internal_tank) - var/datum/gas_mixture/tank_air = spacepod.internal_tank.return_air() - var/datum/gas_mixture/cabin_air = spacepod.cabin_air +// Fun fact, these procs are just copypastes from mech code +// And have been for the past 4 years +// Please send help +/obj/spacepod/proc/regulate_temp() + if(cabin_air && cabin_air.return_volume() > 0) + var/delta = cabin_air.temperature - T20C + cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1))) +/obj/spacepod/proc/give_air() + if(internal_tank) + var/datum/gas_mixture/tank_air = internal_tank.return_air() var/release_pressure = ONE_ATMOSPHERE var/cabin_pressure = cabin_air.return_pressure() var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2) @@ -1023,7 +1014,7 @@ var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) cabin_air.merge(removed) else if(pressure_delta < 0) //cabin pressure higher than release pressure - var/datum/gas_mixture/t_air = spacepod.get_turf_air() + var/datum/gas_mixture/t_air = get_turf_air() pressure_delta = cabin_pressure - release_pressure if(t_air) pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) @@ -1034,8 +1025,6 @@ t_air.merge(removed) else //just delete the cabin gas, we're in space or some shit qdel(removed) - else - return stop() /obj/spacepod/relaymove(mob/user, direction) if(user != src.pilot) diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm index bc0576c9d52..426af9a97ac 100644 --- a/code/modules/station_goals/bsa.dm +++ b/code/modules/station_goals/bsa.dm @@ -215,6 +215,7 @@ playsound(src, 'sound/machines/bsa_fire.ogg', 100, 1) message_admins("[key_name_admin(user)] has launched an artillery strike.") + log_admin("[key_name(user)] has launched an artillery strike.") // Line below handles logging the explosion to disk explosion(bullseye,ex_power,ex_power*2,ex_power*4) reload() @@ -313,7 +314,7 @@ ui.open() ui.set_auto_update(1) -/obj/machinery/computer/bsa_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/bsa_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/list/data = list() data["connected"] = cannon data["notice"] = notice @@ -352,12 +353,12 @@ /obj/machinery/computer/bsa_control/proc/calibrate(mob/user) var/list/gps_locators = list() - for(var/obj/item/gps/G in GPS_list) //nulls on the list somehow + for(var/obj/item/gps/G in GLOB.GPS_list) //nulls on the list somehow gps_locators[G.gpstag] = G var/list/options = gps_locators if(area_aim) - options += target_all_areas ? ghostteleportlocs : teleportlocs + options += target_all_areas ? GLOB.ghostteleportlocs : GLOB.teleportlocs var/V = input(user,"Select target", "Select target",null) in options|null target = options[V] diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm index 5b07d27361e..db801fa5d0f 100644 --- a/code/modules/station_goals/dna_vault.dm +++ b/code/modules/station_goals/dna_vault.dm @@ -74,7 +74,7 @@ plants = list() dna = list() -var/list/non_simple_animals = typecacheof(list(/mob/living/carbon/human/monkey,/mob/living/carbon/alien)) +GLOBAL_LIST_INIT(non_simple_animals, typecacheof(list(/mob/living/carbon/human/monkey,/mob/living/carbon/alien))) /obj/item/dna_probe/afterattack(atom/target, mob/user, proximity) ..() @@ -95,7 +95,7 @@ var/list/non_simple_animals = typecacheof(list(/mob/living/carbon/human/monkey,/ to_chat(user, "Plant data added to local storage.") //animals - if(isanimal(target) || is_type_in_typecache(target, non_simple_animals)) + if(isanimal(target) || is_type_in_typecache(target, GLOB.non_simple_animals)) if(isanimal(target)) var/mob/living/simple_animal/A = target if(!A.healable)//simple approximation of being animal not a robot or similar @@ -220,7 +220,7 @@ var/list/non_simple_animals = typecacheof(list(/mob/living/carbon/human/monkey,/ L += pick_n_take(possible_powers) power_lottery[user] = L -/obj/machinery/dna_vault/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) //TODO Make it % bars maybe +/obj/machinery/dna_vault/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) //TODO Make it % bars maybe var/list/data = list() data["plants"] = plants.len data["plants_max"] = plants_max diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm index 9995528c9b5..42bd3b2a10a 100644 --- a/code/modules/station_goals/shield.dm +++ b/code/modules/station_goals/shield.dm @@ -71,7 +71,7 @@ if(S.id == id && atoms_share_level(src, S)) S.toggle() -/obj/machinery/computer/sat_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = default_state) +/obj/machinery/computer/sat_control/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.default_state) var/list/data = list() data["satellites"] = list() diff --git a/code/modules/station_goals/station_goal.dm b/code/modules/station_goals/station_goal.dm index d6be4540a01..47f65ea2553 100644 --- a/code/modules/station_goals/station_goal.dm +++ b/code/modules/station_goals/station_goal.dm @@ -12,7 +12,7 @@ var/report_message = "Complete this goal." /datum/station_goal/proc/send_report() - priority_announcement.Announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", 'sound/AI/commandreport.ogg') + GLOB.priority_announcement.Announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", 'sound/AI/commandreport.ogg') print_command_report(get_report(), "Nanotrasen Directive [pick(GLOB.phonetic_alphabet)] \Roman[rand(1,50)]") on_report() diff --git a/code/modules/store/store.dm b/code/modules/store/store.dm index 84c85fea29e..2557008def0 100644 --- a/code/modules/store/store.dm +++ b/code/modules/store/store.dm @@ -16,7 +16,7 @@ job objectives = good stock market, shitty job objective completion = shitty eco Goal for now is to get the store itself working, however. */ -var/global/datum/store/centcomm_store=new +GLOBAL_DATUM_INIT(centcomm_store, /datum/store, new()) /datum/store var/list/datum/storeitem/items=list() @@ -40,7 +40,7 @@ var/global/datum/store/centcomm_store=new T.target_name = "[command_name()] Merchandising" T.purpose = "Purchase of [item.name]" T.amount = -amount - T.date = current_date_string + T.date = GLOB.current_date_string T.time = station_time_timestamp() T.source_terminal = "\[CLASSIFIED\] Terminal #[rand(111,333)]" mind.initial_account.transaction_log.Add(T) diff --git a/code/modules/surgery/limb_reattach.dm b/code/modules/surgery/limb_reattach.dm index 11ceaaeb0fb..db1ad04aef3 100644 --- a/code/modules/surgery/limb_reattach.dm +++ b/code/modules/surgery/limb_reattach.dm @@ -160,7 +160,7 @@ ..() if(E.limb_name == "head") var/obj/item/organ/external/head/H = target.get_organ("head") - var/datum/robolimb/robohead = all_robolimbs[H.model] + var/datum/robolimb/robohead = GLOB.all_robolimbs[H.model] if(robohead.is_monitor) //Ensures that if an IPC gets a head that's got a human hair wig attached to their body, the hair won't wipe. H.h_style = "Bald" H.f_style = "Shaved" diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index 6215bbe88bc..08553c47188 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -305,10 +305,14 @@ icon = 'icons/obj/power.dmi' icon_state = "wire1" flags = NOBLUDGEON + var/drawing_power = FALSE /obj/item/apc_powercord/afterattack(atom/target, mob/user, proximity_flag, click_parameters) if(!istype(target, /obj/machinery/power/apc) || !ishuman(user) || !proximity_flag) return ..() + if(drawing_power) + to_chat(user, "You're already charging.") + return user.changeNext_move(CLICK_CD_MELEE) var/obj/machinery/power/apc/A = target var/mob/living/carbon/human/H = user @@ -329,6 +333,7 @@ /obj/item/apc_powercord/proc/powerdraw_loop(obj/machinery/power/apc/A, mob/living/carbon/human/H) H.visible_message("[H] inserts a power connector into \the [A].", "You begin to draw power from \the [A].") + drawing_power = TRUE while(do_after(H, 10, target = A)) if(loc != H) to_chat(H, "You must keep your connector out while charging!") @@ -350,6 +355,7 @@ to_chat(H, "You are now fully charged.") break H.visible_message("[H] unplugs from \the [A].", "You unplug from \the [A].") + drawing_power = FALSE /obj/item/organ/internal/cyberimp/arm/telebaton name = "telebaton implant" diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/augments_eyes.dm index 80dceea5048..53907e86d79 100644 --- a/code/modules/surgery/organs/augments_eyes.dm +++ b/code/modules/surgery/organs/augments_eyes.dm @@ -11,7 +11,7 @@ var/see_in_dark = 0 var/see_invisible = 0 var/lighting_alpha - + var/eye_colour = "#000000" // Should never be null var/old_eye_colour = "#000000" var/flash_protect = 0 @@ -88,14 +88,14 @@ /obj/item/organ/internal/cyberimp/eyes/hud/insert(var/mob/living/carbon/M, var/special = 0) ..() if(HUD_type) - var/datum/atom_hud/H = huds[HUD_type] + var/datum/atom_hud/H = GLOB.huds[HUD_type] H.add_hud_to(M) M.permanent_huds |= H /obj/item/organ/internal/cyberimp/eyes/hud/remove(var/mob/living/carbon/M, var/special = 0) . = ..() if(HUD_type) - var/datum/atom_hud/H = huds[HUD_type] + var/datum/atom_hud/H = GLOB.huds[HUD_type] M.permanent_huds ^= H H.remove_hud_from(M) diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm index fab2d0fd8a4..19ff7fa37d8 100644 --- a/code/modules/surgery/organs/augments_internal.dm +++ b/code/modules/surgery/organs/augments_internal.dm @@ -111,9 +111,9 @@ /obj/item/organ/internal/cyberimp/brain/anti_drop/proc/release_items() active = FALSE - if(!l_hand_ignore && l_hand_obj in owner.contents) + if(!l_hand_ignore && (l_hand_obj in owner.contents)) l_hand_obj.flags ^= NODROP - if(!r_hand_ignore && r_hand_obj in owner.contents) + if(!r_hand_ignore && (r_hand_obj in owner.contents)) r_hand_obj.flags ^= NODROP /obj/item/organ/internal/cyberimp/brain/anti_drop/remove(var/mob/living/carbon/M, special = 0) @@ -141,9 +141,11 @@ /obj/item/organ/internal/cyberimp/brain/anti_stun/emp_act(severity) if(crit_fail || emp_proof) return - crit_fail = 1 - spawn(90 / severity) - crit_fail = 0 + crit_fail = TRUE + addtimer(CALLBACK(src, .proc/reboot), 90 / severity) + +/obj/item/organ/internal/cyberimp/brain/anti_stun/proc/reboot() + crit_fail = FALSE /obj/item/organ/internal/cyberimp/brain/clown_voice name = "Comical implant" @@ -230,11 +232,13 @@ if(owner.stat == DEAD) return if(owner.nutrition <= hunger_threshold) - synthesizing = 1 + synthesizing = TRUE to_chat(owner, "You feel less hungry...") owner.adjust_nutrition(50) - spawn(50) - synthesizing = 0 + addtimer(CALLBACK(src, .proc/synth_cool), 50) + +/obj/item/organ/internal/cyberimp/chest/nutriment/proc/synth_cool() + synthesizing = FALSE /obj/item/organ/internal/cyberimp/chest/nutriment/emp_act(severity) if(!owner || emp_proof) @@ -309,10 +313,15 @@ var/mob/living/carbon/human/H = owner if(H.stat != DEAD && prob(50 / severity)) H.set_heartattack(TRUE) - spawn(600 / severity) - H.set_heartattack(FALSE) - if(H.stat == CONSCIOUS) - to_chat(H, "You feel your heart beating again!") + addtimer(CALLBACK(src, .proc/undo_heart_attack), 600 / severity) + +/obj/item/organ/internal/cyberimp/chest/reviver/proc/undo_heart_attack() + var/mob/living/carbon/human/H = owner + if(!istype(H)) + return + H.set_heartattack(FALSE) + if(H.stat == CONSCIOUS) + to_chat(H, "You feel your heart beating again!") //BOX O' IMPLANTS diff --git a/code/modules/surgery/organs/ears.dm b/code/modules/surgery/organs/ears.dm index 4f23bf18243..bc57338dbbe 100644 --- a/code/modules/surgery/organs/ears.dm +++ b/code/modules/surgery/organs/ears.dm @@ -19,7 +19,7 @@ return var/mob/living/carbon/C = owner // genetic deafness prevents the body from using the ears, even if healthy - if(C.disabilities & DEAF) + if(DEAF in C.mutations) deaf = max(deaf, 1) else if(ishuman(C)) @@ -35,9 +35,9 @@ /obj/item/organ/internal/ears/proc/RestoreEars() deaf = 0 ear_damage = 0 - + var/mob/living/carbon/C = owner - if(istype(C) && C.disabilities & DEAF) + if(istype(C) && (DEAF in C.mutations)) deaf = 1 /obj/item/organ/internal/ears/proc/AdjustEarDamage(ddmg, ddeaf) @@ -66,3 +66,15 @@ if(ears) ears.MinimumDeafTicks(value) +/obj/item/organ/internal/ears/cybernetic + name = "cybernetic ears" + icon_state = "ears-c" + desc = "a basic cybernetic designed to mimic the operation of ears." + origin_tech = "biotech=4" + status = ORGAN_ROBOT + +/obj/item/organ/internal/ears/cybernetic/emp_act(severity) + if(emp_proof) + return + ..() + AdjustEarDamage(30, 120) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 60f4c22743d..1b205f957ce 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -9,7 +9,7 @@ var/list/colourmatrix = null var/list/colourblind_matrix = MATRIX_GREYSCALE //Special colourblindness parameters. By default, it's black-and-white. var/list/replace_colours = LIST_GREYSCALE_REPLACE - var/dependent_disabilities = null //Gets set by eye-dependent disabilities such as colourblindness so the eyes can transfer the disability during transplantation. + var/dependent_disabilities = list() //Gets set by eye-dependent disabilities such as colourblindness so the eyes can transfer the disability during transplantation. var/weld_proof = null //If set, the eyes will not take damage during welding. eg. IPC optical sensors do not take damage when they weld things while all other eyes will. var/vision_flags = 0 @@ -30,7 +30,7 @@ return eyes_icon /obj/item/organ/internal/eyes/proc/get_colourmatrix() //Returns a special colour matrix if the eyes are organic and the mob is colourblind, otherwise it uses the current one. - if(!is_robotic() && owner.disabilities & COLOURBLIND) + if(!is_robotic() && (COLOURBLIND in owner.mutations)) return colourblind_matrix else return colourmatrix @@ -44,19 +44,19 @@ if(istype(M) && eye_colour) M.update_body() //Apply our eye colour to the target. - if(!(M.disabilities & COLOURBLIND) && (dependent_disabilities & COLOURBLIND)) //If the eyes are colourblind and we're not, carry over the gene. - dependent_disabilities &= ~COLOURBLIND - M.dna.SetSEState(COLOURBLINDBLOCK,1) - genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + if(!(COLOURBLIND in M.mutations) && (COLOURBLIND in dependent_disabilities)) //If the eyes are colourblind and we're not, carry over the gene. + dependent_disabilities -= COLOURBLIND + M.dna.SetSEState(GLOB.colourblindblock,1) + genemutcheck(M,GLOB.colourblindblock,null,MUTCHK_FORCED) else M.update_client_colour() //If we're here, that means the mob acquired the colourblindness gene while they didn't have eyes. Better handle it. /obj/item/organ/internal/eyes/remove(mob/living/carbon/human/M, special = 0) - if(!special && (M.disabilities & COLOURBLIND)) //If special is set, that means these eyes are getting deleted (i.e. during set_species()) - if(!(dependent_disabilities & COLOURBLIND)) //We only want to change COLOURBLINDBLOCK and such it the eyes are being surgically removed. + if(!special && (COLOURBLIND in M.mutations)) //If special is set, that means these eyes are getting deleted (i.e. during set_species()) + if(!(COLOURBLIND in dependent_disabilities)) //We only want to change COLOURBLINDBLOCK and such it the eyes are being surgically removed. dependent_disabilities |= COLOURBLIND - M.dna.SetSEState(COLOURBLINDBLOCK,0) - genemutcheck(M,COLOURBLINDBLOCK,null,MUTCHK_FORCED) + M.dna.SetSEState(GLOB.colourblindblock,0) + genemutcheck(M,GLOB.colourblindblock,null,MUTCHK_FORCED) . = ..() /obj/item/organ/internal/eyes/surgeryize() @@ -67,7 +67,7 @@ owner.SetEyeBlurry(0) owner.SetEyeBlind(0) -/obj/item/organ/internal/eyes/robotize() +/obj/item/organ/internal/eyes/robotize(make_tough) colourmatrix = null ..() //Make sure the organ's got the robotic status indicators before updating the client colour. if(owner) @@ -75,7 +75,7 @@ /obj/item/organ/internal/eyes/cybernetic name = "cybernetic eyes" - icon_state = "eyes-prosthetic" + icon_state = "eyes-c" desc = "An electronic device designed to mimic the functions of a pair of human eyes. It has no benefits over organic eyes, but is easy to produce." origin_tech = "biotech=4" status = ORGAN_ROBOT diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index 9269b2340af..8308a793ca9 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -23,9 +23,8 @@ Stop() return - spawn(120) - if(!owner) - Stop() + if(!special) + addtimer(CALLBACK(src, .proc/stop_if_unowned), 120) /obj/item/organ/internal/heart/emp_act(intensity) if(!is_robotic() || emp_proof) @@ -43,14 +42,16 @@ return if(!beating) Restart() - spawn(80) - if(!owner) - Stop() + addtimer(CALLBACK(src, .proc/stop_if_unowned), 80) /obj/item/organ/internal/heart/safe_replace(mob/living/carbon/human/target) Restart() ..() +/obj/item/organ/internal/heart/proc/stop_if_unowned() + if(!owner) + Stop() + /obj/item/organ/internal/heart/proc/Stop() beating = FALSE update_icon() @@ -238,6 +239,8 @@ /obj/item/organ/internal/heart/cybernetic/upgraded/shock_organ(intensity) if(!ishuman(owner)) return + if(emp_proof) + return intensity = min(intensity, 100) var/numHigh = round(intensity / 5) var/numMid = round(intensity / 10) diff --git a/code/modules/surgery/organs/organ.dm b/code/modules/surgery/organs/organ.dm index baf974ad944..3dab4065f7d 100644 --- a/code/modules/surgery/organs/organ.dm +++ b/code/modules/surgery/organs/organ.dm @@ -116,18 +116,19 @@ necrotize() else if(owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs - //** Handle antibiotics and curing infections - handle_antibiotics() - handle_germ_effects() + // Handle antibiotics and curing infections + if(germ_level) + handle_germs() + return TRUE /obj/item/organ/proc/is_preserved() if(istype(loc,/obj/item/mmi)) germ_level = max(0, germ_level - 1) // So a brain can slowly recover from being left out of an MMI - return 1 + return TRUE if(is_found_within(/obj/structure/closet/crate/freezer)) - return 1 + return TRUE if(is_found_within(/obj/machinery/clonepod)) - return 1 + return TRUE if(isturf(loc)) if(world.time - last_freezer_update_time > freezer_update_period) // I don't want to loop through everything in the tile constantly, especially since it'll be a pile of organs @@ -142,7 +143,7 @@ return is_in_freezer // I'd like static varibles, please // You can do your cool location temperature organ preserving effects here! - return 0 + return FALSE /obj/item/organ/examine(mob/user) . = ..() @@ -152,33 +153,30 @@ else . += "It looks in need of repairs." -/obj/item/organ/proc/handle_germ_effects() - //** Handle the effects of infections - var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin") - - if(germ_level > 0 && germ_level < INFECTION_LEVEL_ONE/2 && prob(30)) +/obj/item/organ/proc/handle_germs() + if(germ_level > 0 && germ_level < INFECTION_LEVEL_ONE / 2 && prob(30)) germ_level-- - if(germ_level >= INFECTION_LEVEL_ONE/2) + if(germ_level >= INFECTION_LEVEL_ONE / 2) //aiming for germ level to go from ambient to INFECTION_LEVEL_TWO in an average of 15 minutes - if(antibiotics < 5 && prob(round(germ_level/6))) + if(prob(round(germ_level / 6))) germ_level++ if(germ_level >= INFECTION_LEVEL_ONE) - var/fever_temperature = (owner.dna.species.heat_level_1 - owner.dna.species.body_temperature - 5)* min(germ_level/INFECTION_LEVEL_TWO, 1) + owner.dna.species.body_temperature - owner.bodytemperature += between(0, (fever_temperature - T20C)/BODYTEMP_COLD_DIVISOR + 1, fever_temperature - owner.bodytemperature) + var/fever_temperature = (owner.dna.species.heat_level_1 - owner.dna.species.body_temperature - 5) * min(germ_level / INFECTION_LEVEL_TWO, 1) + owner.dna.species.body_temperature + owner.bodytemperature += between(0, (fever_temperature - T20C) / BODYTEMP_COLD_DIVISOR + 1, fever_temperature - owner.bodytemperature) if(germ_level >= INFECTION_LEVEL_TWO) var/obj/item/organ/external/parent = owner.get_organ(parent_organ) //spread germs - if(antibiotics < 5 && parent.germ_level < germ_level && ( parent.germ_level < INFECTION_LEVEL_ONE*2 || prob(30) )) + if(parent.germ_level < germ_level && ( parent.germ_level < INFECTION_LEVEL_ONE * 2 || prob(30))) parent.germ_level++ -/obj/item/organ/internal/handle_germ_effects() +/obj/item/organ/internal/handle_germs() ..() if(germ_level >= INFECTION_LEVEL_TWO) if(prob(3)) //about once every 30 seconds - receive_damage(1,silent=prob(30)) + receive_damage(1, silent = prob(30)) /obj/item/organ/proc/rejuvenate() damage = 0 @@ -200,21 +198,6 @@ /obj/item/organ/proc/is_broken() return (damage >= min_broken_damage || ((status & ORGAN_BROKEN) && !(status & ORGAN_SPLINTED))) -//Germs -/obj/item/organ/proc/handle_antibiotics() - var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin") - - if(!germ_level || antibiotics <= 0.4) - return - - if(germ_level < INFECTION_LEVEL_ONE) - germ_level = 0 //cure instantly - else if(germ_level < INFECTION_LEVEL_TWO) - germ_level -= 24 //at germ_level == 500, this should cure the infection in 15 seconds - else - germ_level -= 8 // at germ_level == 1000, this will cure the infection in 1 minute, 15 seconds - // Let's not drag this on, medbay has only so much antibiotics - //Adds autopsy data for used_weapon. /obj/item/organ/proc/add_autopsy_data(var/used_weapon = "Unknown", var/damage) var/datum/autopsy_data/W = autopsy_data[used_weapon] @@ -248,7 +231,7 @@ return damage = max(damage - amount, 0) -/obj/item/organ/proc/robotize() //Being used to make robutt hearts, etc +/obj/item/organ/proc/robotize(make_tough) //Being used to make robutt hearts, etc status &= ~ORGAN_BROKEN status &= ~ORGAN_SPLINTED status |= ORGAN_ROBOT diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm index 305c08ff17e..143bf1d1ed6 100644 --- a/code/modules/surgery/organs/organ_external.dm +++ b/code/modules/surgery/organs/organ_external.dm @@ -68,7 +68,7 @@ icon_state = dead_icon if(owner) to_chat(owner, "You can't feel your [name] anymore...") - owner.update_body(update_sprite) + owner.update_body() if(vital) owner.death() @@ -305,10 +305,10 @@ This function completely restores a damaged organ to perfect condition. if(!(status & ORGAN_BROKEN)) perma_injury = 0 - //Infections - update_germs() - else - ..() + if(..()) + if(owner.germ_level > germ_level && infection_check()) + //Open wounds can become infected + germ_level++ //Updating germ levels. Handles organ germ levels and necrosis. /* @@ -325,40 +325,16 @@ the actual time is dependent on RNG. INFECTION_LEVEL_ONE below this germ level nothing happens, and the infection doesn't grow INFECTION_LEVEL_TWO above this germ level the infection will start to spread to internal and adjacent organs INFECTION_LEVEL_THREE above this germ level the player will take additional toxin damage per second, and will die in minutes without - antitox. also, above this germ level you will need to overdose on spaceacillin to reduce the germ_level. + antitox.. Note that amputating the affected organ does in fact remove the infection from the player's body. */ -/obj/item/organ/external/proc/update_germs() - if(is_robotic() || (NO_GERMS in owner.dna.species.species_traits)) //Robotic limbs shouldn't be infected, nor should nonexistant limbs. - germ_level = 0 - return - - if(owner.bodytemperature >= 170) //cryo stops germs from moving and doing their bad stuffs - //** Syncing germ levels with external wounds - handle_germ_sync() - - //** Handle antibiotics and curing infections - handle_antibiotics() - - //** Handle the effects of infections - handle_germ_effects() - -/obj/item/organ/external/proc/handle_germ_sync() - var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin") - if(antibiotics < 5) - //Open wounds can become infected - if(owner.germ_level > germ_level && infection_check()) - germ_level++ - -/obj/item/organ/external/handle_germ_effects() +/obj/item/organ/external/handle_germs() if(germ_level < INFECTION_LEVEL_TWO) return ..() - var/antibiotics = owner.reagents.get_reagent_amount("spaceacillin") - if(germ_level >= INFECTION_LEVEL_TWO) //spread the infection to internal organs var/obj/item/organ/internal/target_organ = null //make internal organs become infected one at a time instead of all at once @@ -383,17 +359,16 @@ Note that amputating the affected organ does in fact remove the infection from t if(children) for(var/obj/item/organ/external/child in children) if(child.germ_level < germ_level && !child.is_robotic()) - if(child.germ_level < INFECTION_LEVEL_ONE*2 || prob(30)) + if(child.germ_level < INFECTION_LEVEL_ONE * 2 || prob(30)) child.germ_level++ if(parent) if(parent.germ_level < germ_level && !parent.is_robotic()) - if(parent.germ_level < INFECTION_LEVEL_ONE*2 || prob(30)) + if(parent.germ_level < INFECTION_LEVEL_ONE * 2 || prob(30)) parent.germ_level++ - if(germ_level >= INFECTION_LEVEL_THREE && antibiotics < 30) //overdosing is necessary to stop severe infections + if(germ_level >= INFECTION_LEVEL_THREE) necrotize() - germ_level++ owner.adjustToxLoss(1) @@ -404,7 +379,7 @@ Note that amputating the affected organ does in fact remove the infection from t fracture() /obj/item/organ/external/proc/check_for_internal_bleeding(damage) - if(owner && NO_BLOOD in owner.dna.species.species_traits) + if(owner && (NO_BLOOD in owner.dna.species.species_traits)) return var/local_damage = brute_dam + damage if(damage > 15 && local_damage > 30 && prob(damage) && !is_robotic()) @@ -515,7 +490,7 @@ Note that amputating the affected organ does in fact remove the infection from t if(!clean) // Throw limb around. if(src && istype(loc,/turf)) - dropped_part.throw_at(get_edge_target_turf(src,pick(alldirs)),rand(1,3),30) + dropped_part.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),30) dir = 2 brute_dam = 0 burn_dam = 0 //Reset the damage on the limb; the damage should have transferred to the parent; we don't want extra damage being re-applied when then limb is re-attached @@ -589,12 +564,12 @@ Note that amputating the affected organ does in fact remove the infection from t holder = owner if(!holder) return - if(holder.handcuffed && body_part in list(ARM_LEFT, ARM_RIGHT, HAND_LEFT, HAND_RIGHT)) + if(holder.handcuffed && (body_part in list(ARM_LEFT, ARM_RIGHT, HAND_LEFT, HAND_RIGHT))) holder.visible_message(\ "\The [holder.handcuffed.name] falls off of [holder.name].",\ "\The [holder.handcuffed.name] falls off you.") holder.unEquip(holder.handcuffed) - if(holder.legcuffed && body_part in list(FOOT_LEFT, FOOT_RIGHT, LEG_LEFT, LEG_RIGHT)) + if(holder.legcuffed && (body_part in list(FOOT_LEFT, FOOT_RIGHT, LEG_LEFT, LEG_RIGHT))) holder.visible_message(\ "\The [holder.legcuffed.name] falls off of [holder.name].",\ "\The [holder.legcuffed.name] falls off you.") @@ -663,7 +638,7 @@ Note that amputating the affected organ does in fact remove the infection from t /obj/item/organ/external/proc/set_company(var/company) model = company - var/datum/robolimb/R = all_robolimbs[company] + var/datum/robolimb/R = GLOB.all_robolimbs[company] if(R) force_icon = R.icon name = "[R.company] [initial(name)]" @@ -672,12 +647,12 @@ Note that amputating the affected organ does in fact remove the infection from t /obj/item/organ/external/proc/mutate() src.status |= ORGAN_MUTATED if(owner) - owner.update_body(1, 1) //Forces all bodyparts to update in order to correctly render the deformed sprite. + owner.update_body(TRUE) //Forces all bodyparts to update in order to correctly render the deformed sprite. /obj/item/organ/external/proc/unmutate() src.status &= ~ORGAN_MUTATED if(owner) - owner.update_body(1, 1) //Forces all bodyparts to update in order to correctly return them to normal. + owner.update_body(TRUE) //Forces all bodyparts to update in order to correctly return them to normal. /obj/item/organ/external/proc/get_damage() //returns total damage return max(brute_dam + burn_dam - perma_injury, perma_injury) //could use health? diff --git a/code/modules/surgery/organs/organ_icon.dm b/code/modules/surgery/organs/organ_icon.dm index ef2f729811c..c2df537e771 100644 --- a/code/modules/surgery/organs/organ_icon.dm +++ b/code/modules/surgery/organs/organ_icon.dm @@ -1,4 +1,4 @@ -var/global/list/limb_icon_cache = list() +GLOBAL_LIST_EMPTY(limb_icon_cache) /obj/item/organ/external/proc/compile_icon() // I do this so the head's overlays don't get obliterated @@ -62,7 +62,7 @@ var/global/list/limb_icon_cache = list() get_icon() . = ..() -/obj/item/organ/external/proc/get_icon(skeletal, fat) +/obj/item/organ/external/proc/get_icon(skeletal) // Kasparrov, you monster if(force_icon) mob_icon = new /icon(force_icon, "[icon_name]") @@ -181,13 +181,6 @@ var/global/list/limb_icon_cache = list() icon_file = icobase return list(icon_file, new_icon_state) -/obj/item/organ/external/chest/get_icon_state(skeletal) - var/result = ..() - if(fat && !skeletal && !is_robotic() && (CAN_BE_FAT in dna.species.species_traits)) - result[2] += "_fat" - return result - - // new damage icon system // adjusted to set damage_state to brute/burn code only (without r_name0 as before) /obj/item/organ/external/update_icon() diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 25f87d71104..53283ada95e 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -141,7 +141,7 @@ // Brain is defined in brain_item.dm. -/obj/item/organ/internal/robotize() +/obj/item/organ/internal/robotize(make_tough) if(!is_robotic()) var/list/states = icon_states('icons/obj/surgery.dmi') //Insensitive to specially-defined icon files for species like the Drask or whomever else. Everyone gets the same robotic heart. if(slot == "heart" && ("[slot]-c-on" in states) && ("[slot]-c-off" in states)) //Give the robotic heart its robotic heart icons if they exist. @@ -225,31 +225,30 @@ slot = "brain_tumor" var/organhonked = 0 var/suffering_delay = 900 - var/datum/component/waddle var/datum/component/squeak /obj/item/organ/internal/honktumor/insert(mob/living/carbon/M, special = 0) ..() M.mutations.Add(CLUMSY) - M.mutations.Add(COMICBLOCK) - M.dna.SetSEState(CLUMSYBLOCK,1,1) - M.dna.SetSEState(COMICBLOCK,1,1) - genemutcheck(M,CLUMSYBLOCK,null,MUTCHK_FORCED) - genemutcheck(M,COMICBLOCK,null,MUTCHK_FORCED) + M.mutations.Add(GLOB.comicblock) + M.dna.SetSEState(GLOB.clumsyblock,1,1) + M.dna.SetSEState(GLOB.comicblock,1,1) + genemutcheck(M,GLOB.clumsyblock,null,MUTCHK_FORCED) + genemutcheck(M,GLOB.comicblock,null,MUTCHK_FORCED) organhonked = world.time - waddle = M.AddComponent(/datum/component/waddling) + M.AddElement(/datum/element/waddling) squeak = M.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg' = 1), 50) /obj/item/organ/internal/honktumor/remove(mob/living/carbon/M, special = 0) . = ..() M.mutations.Remove(CLUMSY) - M.mutations.Remove(COMICBLOCK) - M.dna.SetSEState(CLUMSYBLOCK,0) - M.dna.SetSEState(COMICBLOCK,0) - genemutcheck(M,CLUMSYBLOCK,null,MUTCHK_FORCED) - genemutcheck(M,COMICBLOCK,null,MUTCHK_FORCED) - QDEL_NULL(waddle) + M.mutations.Remove(GLOB.comicblock) + M.dna.SetSEState(GLOB.clumsyblock,0) + M.dna.SetSEState(GLOB.comicblock,0) + genemutcheck(M,GLOB.clumsyblock,null,MUTCHK_FORCED) + genemutcheck(M,GLOB.comicblock,null,MUTCHK_FORCED) + M.RemoveElement(/datum/element/waddling) QDEL_NULL(squeak) qdel(src) diff --git a/code/modules/surgery/organs/parasites.dm b/code/modules/surgery/organs/parasites.dm index 48cc4a408d5..b61a7c429bc 100644 --- a/code/modules/surgery/organs/parasites.dm +++ b/code/modules/surgery/organs/parasites.dm @@ -74,7 +74,8 @@ if(is_away_level(owner.z)) awaymission_infection = TRUE if(awaymission_infection) - if(!is_away_level(owner.z)) + var/turf/T = get_turf(owner) + if(istype(T) && !is_away_level(T.z)) owner.gib() qdel(src) return diff --git a/code/modules/surgery/organs/robolimbs.dm b/code/modules/surgery/organs/robolimbs.dm index 2e25a1c1998..eb40fa40994 100644 --- a/code/modules/surgery/organs/robolimbs.dm +++ b/code/modules/surgery/organs/robolimbs.dm @@ -1,19 +1,19 @@ -var/global/list/all_robolimbs = list() -var/global/list/chargen_robolimbs = list() -var/global/list/selectable_robolimbs = list() -var/global/datum/robolimb/basic_robolimb +GLOBAL_LIST_EMPTY(all_robolimbs) +GLOBAL_LIST_EMPTY(chargen_robolimbs) +GLOBAL_LIST_EMPTY(selectable_robolimbs) +GLOBAL_DATUM(basic_robolimb, /datum/robolimb) /proc/populate_robolimb_list() - basic_robolimb = new() + GLOB.basic_robolimb = new() for(var/limb_type in typesof(/datum/robolimb)) var/datum/robolimb/R = new limb_type() - all_robolimbs[R.company] = R + GLOB.all_robolimbs[R.company] = R if(!R.unavailable_at_chargen) if(R != "head" && R != "chest" && R != "groin" ) //Part of the method that ensures only IPCs can access head, chest and groin prosthetics. if(R.has_subtypes) //Ensures solos get added to the list as well be incorporating has_subtypes == 1 and has_subtypes == 2. - chargen_robolimbs[R.company] = R //List only main brands and solo parts. + GLOB.chargen_robolimbs[R.company] = R //List only main brands and solo parts. if(R.selectable) - selectable_robolimbs[R.company] = R + GLOB.selectable_robolimbs[R.company] = R /datum/robolimb var/company = "Unbranded" // Shown when selecting the limb. diff --git a/code/modules/surgery/organs/subtypes/standard.dm b/code/modules/surgery/organs/subtypes/standard.dm index 4c122ffe04b..c736930f084 100644 --- a/code/modules/surgery/organs/subtypes/standard.dm +++ b/code/modules/surgery/organs/subtypes/standard.dm @@ -15,27 +15,8 @@ gendered_icon = 1 parent_organ = null encased = "ribcage" - var/fat = FALSE convertable_children = list(/obj/item/organ/external/groin) -/obj/item/organ/external/chest/proc/makeFat(update_body_icon = 1) - fat = TRUE - if(owner) - owner.update_body(update_body_icon) - else - // get_icon updates the sprite icon, update_icon updates the injuries overlay. - // Madness. - get_icon() - -/obj/item/organ/external/chest/proc/makeSlim(update_body_icon = 1) - fat = FALSE - if(owner) - owner.update_body(update_body_icon) - else - // get_icon updates the sprite icon, update_icon updates the injuries overlay. - // Madness. - get_icon() - /obj/item/organ/external/groin name = "lower body" limb_name = "groin" diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 9d91682f057..c9b26f61228 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -1,39 +1,39 @@ -var/static/regex/stun_words = regex("stop|wait|stand still|hold on|halt") -var/static/regex/weaken_words = regex("drop|fall|trip") -var/static/regex/sleep_words = regex("sleep|slumber") -var/static/regex/vomit_words = regex("vomit|throw up") -var/static/regex/silence_words = regex("shut up|silence|ssh|quiet|hush") -var/static/regex/hallucinate_words = regex("see the truth|hallucinate") -var/static/regex/wakeup_words = regex("wake up|awaken") -var/static/regex/heal_words = regex("live|heal|survive|mend|heroes never die") -var/static/regex/hurt_words = regex("die|suffer") -var/static/regex/bleed_words = regex("bleed") -var/static/regex/burn_words = regex("burn|ignite") -var/static/regex/repulse_words = regex("shoo|go away|leave me alone|begone|flee|fus ro dah") -var/static/regex/whoareyou_words = regex("who are you|say your name|state your name|identify") -var/static/regex/saymyname_words = regex("say my name") -var/static/regex/knockknock_words = regex("knock knock") -var/static/regex/statelaws_words = regex("state laws|state your laws") -var/static/regex/move_words = regex("move") -var/static/regex/walk_words = regex("walk|slow down") -var/static/regex/run_words = regex("run") -var/static/regex/helpintent_words = regex("help") -var/static/regex/disarmintent_words = regex("disarm") -var/static/regex/grabintent_words = regex("grab") -var/static/regex/harmintent_words = regex("harm|fight") -var/static/regex/throwmode_words = regex("throw|catch") -var/static/regex/flip_words = regex("flip|rotate|revolve|roll|somersault") -var/static/regex/rest_words = regex("rest") -var/static/regex/getup_words = regex("get up") -var/static/regex/sit_words = regex("sit") -var/static/regex/stand_words = regex("stand") -var/static/regex/dance_words = regex("dance") -var/static/regex/jump_words = regex("jump") -var/static/regex/salute_words = regex("salute") -var/static/regex/deathgasp_words = regex("play dead") -var/static/regex/clap_words = regex("clap|applaud") -var/static/regex/honk_words = regex("ho+nk") //hooooooonk -var/static/regex/multispin_words = regex("like a record baby") +GLOBAL_DATUM_INIT(stun_words, /regex, regex("stop|wait|stand still|hold on|halt")) +GLOBAL_DATUM_INIT(weaken_words, /regex, regex("drop|fall|trip")) +GLOBAL_DATUM_INIT(sleep_words, /regex, regex("sleep|slumber")) +GLOBAL_DATUM_INIT(vomit_words, /regex, regex("vomit|throw up")) +GLOBAL_DATUM_INIT(silence_words, /regex, regex("shut up|silence|ssh|quiet|hush")) +GLOBAL_DATUM_INIT(hallucinate_words, /regex, regex("see the truth|hallucinate")) +GLOBAL_DATUM_INIT(wakeup_words, /regex, regex("wake up|awaken")) +GLOBAL_DATUM_INIT(heal_words, /regex, regex("live|heal|survive|mend|heroes never die")) +GLOBAL_DATUM_INIT(hurt_words, /regex, regex("die|suffer")) +GLOBAL_DATUM_INIT(bleed_words, /regex, regex("bleed")) +GLOBAL_DATUM_INIT(burn_words, /regex, regex("burn|ignite")) +GLOBAL_DATUM_INIT(repulse_words, /regex, regex("shoo|go away|leave me alone|begone|flee|fus ro dah")) +GLOBAL_DATUM_INIT(whoareyou_words, /regex, regex("who are you|say your name|state your name|identify")) +GLOBAL_DATUM_INIT(saymyname_words, /regex, regex("say my name")) +GLOBAL_DATUM_INIT(knockknock_words, /regex, regex("knock knock")) +GLOBAL_DATUM_INIT(statelaws_words, /regex, regex("state laws|state your laws")) +GLOBAL_DATUM_INIT(move_words, /regex, regex("move")) +GLOBAL_DATUM_INIT(walk_words, /regex, regex("walk|slow down")) +GLOBAL_DATUM_INIT(run_words, /regex, regex("run")) +GLOBAL_DATUM_INIT(helpintent_words, /regex, regex("help")) +GLOBAL_DATUM_INIT(disarmintent_words, /regex, regex("disarm")) +GLOBAL_DATUM_INIT(grabintent_words, /regex, regex("grab")) +GLOBAL_DATUM_INIT(harmintent_words, /regex, regex("harm|fight")) +GLOBAL_DATUM_INIT(throwmode_words, /regex, regex("throw|catch")) +GLOBAL_DATUM_INIT(flip_words, /regex, regex("flip|rotate|revolve|roll|somersault")) +GLOBAL_DATUM_INIT(rest_words, /regex, regex("rest")) +GLOBAL_DATUM_INIT(getup_words, /regex, regex("get up")) +GLOBAL_DATUM_INIT(sit_words, /regex, regex("sit")) +GLOBAL_DATUM_INIT(stand_words, /regex, regex("stand")) +GLOBAL_DATUM_INIT(dance_words, /regex, regex("dance")) +GLOBAL_DATUM_INIT(jump_words, /regex, regex("jump")) +GLOBAL_DATUM_INIT(salute_words, /regex, regex("salute")) +GLOBAL_DATUM_INIT(deathgasp_words, /regex, regex("play dead")) +GLOBAL_DATUM_INIT(clap_words, /regex, regex("clap|applaud")) +GLOBAL_DATUM_INIT(honk_words, /regex, regex("ho+nk")) //hooooooonk +GLOBAL_DATUM_INIT(multispin_words, /regex, regex("like a record baby")) /obj/item/organ/internal/vocal_cords //organs that are activated through speech with the :x channel name = "vocal cords" @@ -127,7 +127,7 @@ var/static/regex/multispin_words = regex("like a record baby") /obj/item/organ/internal/vocal_cords/colossus/prepare_eat() return - + /obj/item/organ/internal/vocal_cords/colossus/can_speak_with() if(world.time < next_command) to_chat(owner, "You must wait [(next_command - world.time)/10] seconds before Speaking again.") @@ -152,7 +152,7 @@ var/static/regex/multispin_words = regex("like a record baby") message = lowertext(message) playsound(get_turf(owner), 'sound/magic/invoke_general.ogg', 300, 1, 5) - var/mob/living/list/listeners = list() + var/list/mob/living/listeners = list() for(var/mob/living/L in get_mobs_in_view(8, owner, TRUE)) if(L.can_hear() && !L.null_rod_check() && L != owner && L.stat != DEAD) if(ishuman(L)) @@ -172,7 +172,7 @@ var/static/regex/multispin_words = regex("like a record baby") if(owner.mind.isholy) power_multiplier *= 2 //Command staff has authority - if(owner.mind.assigned_role in command_positions) + if(owner.mind.assigned_role in GLOB.command_positions) power_multiplier *= 1.4 //Why are you speaking if(owner.mind.assigned_role == "Mime") @@ -210,34 +210,34 @@ var/static/regex/multispin_words = regex("like a record baby") message = copytext(message, 0, 1)+copytext(message, 1 + length(found_string), length(message) + 1) //STUN - if(findtext(message, stun_words)) + if(findtext(message, GLOB.stun_words)) for(var/V in listeners) var/mob/living/L = V L.Stun(3 * power_multiplier) next_command = world.time + cooldown_stun //WEAKEN - else if(findtext(message, weaken_words)) + else if(findtext(message, GLOB.weaken_words)) for(var/V in listeners) var/mob/living/L = V L.Weaken(3 * power_multiplier) next_command = world.time + cooldown_stun //SLEEP - else if((findtext(message, sleep_words))) + else if((findtext(message, GLOB.sleep_words))) for(var/V in listeners) var/mob/living/L = V L.Sleeping(2 * power_multiplier) next_command = world.time + cooldown_stun //VOMIT - else if((findtext(message, vomit_words))) + else if((findtext(message, GLOB.vomit_words))) for(var/mob/living/carbon/C in listeners) C.vomit(10 * power_multiplier) next_command = world.time + cooldown_stun //SILENCE - else if((findtext(message, silence_words))) + else if((findtext(message, GLOB.silence_words))) for(var/mob/living/carbon/C in listeners) if(owner.mind && (owner.mind.assigned_role == "Librarian" || owner.mind.assigned_role == "Mime")) power_multiplier *= 3 @@ -245,41 +245,41 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_stun //HALLUCINATE - else if((findtext(message, hallucinate_words))) + else if((findtext(message, GLOB.hallucinate_words))) for(var/V in listeners) var/mob/living/L = V new /obj/effect/hallucination/delusion(get_turf(L),L,duration=150 * power_multiplier,skip_nearby=0) next_command = world.time + cooldown_meme //WAKE UP - else if((findtext(message, wakeup_words))) + else if((findtext(message, GLOB.wakeup_words))) for(var/V in listeners) var/mob/living/L = V L.SetSleeping(0) next_command = world.time + cooldown_damage //HEAL - else if((findtext(message, heal_words))) + else if((findtext(message, GLOB.heal_words))) for(var/V in listeners) var/mob/living/L = V L.heal_overall_damage(10 * power_multiplier, 10 * power_multiplier, TRUE, 0, 0) next_command = world.time + cooldown_damage //BRUTE DAMAGE - else if((findtext(message, hurt_words))) + else if((findtext(message, GLOB.hurt_words))) for(var/V in listeners) var/mob/living/L = V L.apply_damage(15 * power_multiplier, def_zone = "chest") next_command = world.time + cooldown_damage //BLEED - else if((findtext(message, bleed_words))) + else if((findtext(message, GLOB.bleed_words))) for(var/mob/living/carbon/human/H in listeners) H.bleed_rate += (5 * power_multiplier) next_command = world.time + cooldown_damage //FIRE - else if((findtext(message, burn_words))) + else if((findtext(message, GLOB.burn_words))) for(var/V in listeners) var/mob/living/L = V L.adjust_fire_stacks(1 * power_multiplier) @@ -287,7 +287,7 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_damage //REPULSE - else if((findtext(message, repulse_words))) + else if((findtext(message, GLOB.repulse_words))) for(var/V in listeners) var/mob/living/L = V var/throwtarget = get_edge_target_turf(owner, get_dir(owner, get_step_away(L, owner))) @@ -295,7 +295,7 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_damage //WHO ARE YOU? - else if((findtext(message, whoareyou_words))) + else if((findtext(message, GLOB.whoareyou_words))) for(var/V in listeners) var/mob/living/L = V /*if(L.mind && L.mind.devilinfo) @@ -305,34 +305,34 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_meme //SAY MY NAME - else if((findtext(message, saymyname_words))) + else if((findtext(message, GLOB.saymyname_words))) for(var/V in listeners) var/mob/living/L = V L.say("[owner.name]!") //"Unknown!" next_command = world.time + cooldown_meme //KNOCK KNOCK - else if((findtext(message, knockknock_words))) + else if((findtext(message, GLOB.knockknock_words))) for(var/V in listeners) var/mob/living/L = V L.say("Who's there?") next_command = world.time + cooldown_meme //STATE LAWS - else if((findtext(message, statelaws_words))) + else if((findtext(message, GLOB.statelaws_words))) for(var/mob/living/silicon/S in listeners) S.statelaws(S.laws) next_command = world.time + cooldown_stun //MOVE - else if((findtext(message, move_words))) + else if((findtext(message, GLOB.move_words))) for(var/V in listeners) var/mob/living/L = V - step(L, pick(cardinal)) + step(L, pick(GLOB.cardinal)) next_command = world.time + cooldown_meme //WALK - else if((findtext(message, walk_words))) + else if((findtext(message, GLOB.walk_words))) for(var/V in listeners) var/mob/living/L = V if(L.m_intent != MOVE_INTENT_WALK) @@ -342,7 +342,7 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_meme //RUN - else if((findtext(message, run_words))) + else if((findtext(message, GLOB.run_words))) for(var/V in listeners) var/mob/living/L = V if(L.m_intent != MOVE_INTENT_RUN) @@ -352,44 +352,44 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_meme //HELP INTENT - else if((findtext(message, helpintent_words))) + else if((findtext(message, GLOB.helpintent_words))) for(var/mob/living/carbon/human/H in listeners) H.a_intent_change(INTENT_HELP) next_command = world.time + cooldown_meme //DISARM INTENT - else if((findtext(message, disarmintent_words))) + else if((findtext(message, GLOB.disarmintent_words))) for(var/mob/living/carbon/human/H in listeners) H.a_intent_change(INTENT_DISARM) next_command = world.time + cooldown_meme //GRAB INTENT - else if((findtext(message, grabintent_words))) + else if((findtext(message, GLOB.grabintent_words))) for(var/mob/living/carbon/human/H in listeners) H.a_intent_change(INTENT_GRAB) next_command = world.time + cooldown_meme //HARM INTENT - else if((findtext(message, harmintent_words))) + else if((findtext(message, GLOB.harmintent_words))) for(var/mob/living/carbon/human/H in listeners) H.a_intent_change(INTENT_HARM) next_command = world.time + cooldown_meme //THROW/CATCH - else if((findtext(message, throwmode_words))) + else if((findtext(message, GLOB.throwmode_words))) for(var/mob/living/carbon/C in listeners) C.throw_mode_on() next_command = world.time + cooldown_meme //FLIP - else if((findtext(message, flip_words))) + else if((findtext(message, GLOB.flip_words))) for(var/V in listeners) var/mob/living/L = V L.emote("flip") next_command = world.time + cooldown_meme //REST - else if((findtext(message, rest_words))) + else if((findtext(message, GLOB.rest_words))) for(var/V in listeners) var/mob/living/L = V if(!L.resting) @@ -397,7 +397,7 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_meme //GET UP - else if((findtext(message, getup_words))) + else if((findtext(message, GLOB.getup_words))) for(var/V in listeners) var/mob/living/L = V if(L.resting) @@ -408,7 +408,7 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_damage //SIT - else if((findtext(message, sit_words))) + else if((findtext(message, GLOB.sit_words))) for(var/V in listeners) var/mob/living/L = V for(var/obj/structure/chair/chair in get_turf(L)) @@ -417,7 +417,7 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_meme //STAND UP - else if((findtext(message, stand_words))) + else if((findtext(message, GLOB.stand_words))) for(var/V in listeners) var/mob/living/L = V if(L.buckled && istype(L.buckled, /obj/structure/chair)) @@ -425,14 +425,14 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_meme //DANCE - else if((findtext(message, dance_words))) + else if((findtext(message, GLOB.dance_words))) for(var/V in listeners) var/mob/living/L = V L.emote("dance") next_command = world.time + cooldown_meme //JUMP - else if((findtext(message, jump_words))) + else if((findtext(message, GLOB.jump_words))) for(var/V in listeners) var/mob/living/L = V L.say("HOW HIGH?!!") @@ -440,28 +440,28 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_meme //SALUTE - else if((findtext(message, salute_words))) + else if((findtext(message, GLOB.salute_words))) for(var/V in listeners) var/mob/living/L = V L.emote("salute") next_command = world.time + cooldown_meme //PLAY DEAD - else if((findtext(message, deathgasp_words))) + else if((findtext(message, GLOB.deathgasp_words))) for(var/V in listeners) var/mob/living/L = V L.emote("deathgasp") next_command = world.time + cooldown_meme //PLEASE CLAP - else if((findtext(message, clap_words))) + else if((findtext(message, GLOB.clap_words))) for(var/V in listeners) var/mob/living/L = V L.emote("clap") next_command = world.time + cooldown_meme //HONK - else if((findtext(message, honk_words))) + else if((findtext(message, GLOB.honk_words))) spawn(25) playsound(get_turf(owner), 'sound/items/bikehorn.ogg', 300, 1) if(owner.mind && owner.mind.assigned_role == "Clown") @@ -472,7 +472,7 @@ var/static/regex/multispin_words = regex("like a record baby") next_command = world.time + cooldown_meme //RIGHT ROUND - else if((findtext(message, multispin_words))) + else if((findtext(message, GLOB.multispin_words))) for(var/V in listeners) var/mob/living/L = V L.SpinAnimation(speed = 10, loops = 5) diff --git a/code/modules/surgery/robotics.dm b/code/modules/surgery/robotics.dm index 31164aaf54e..62efb298006 100644 --- a/code/modules/surgery/robotics.dm +++ b/code/modules/surgery/robotics.dm @@ -575,7 +575,7 @@ ..() /datum/surgery_step/robotics/external/customize_appearance/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery) - var/chosen_appearance = input(user, "Select the company appearance for this limb.", "Limb Company Selection") as null|anything in selectable_robolimbs + var/chosen_appearance = input(user, "Select the company appearance for this limb.", "Limb Company Selection") as null|anything in GLOB.selectable_robolimbs if(!chosen_appearance) return FALSE var/obj/item/organ/external/affected = target.get_organ(target_zone) diff --git a/code/modules/telesci/bscrystal.dm b/code/modules/telesci/bscrystal.dm index b0b2941b3d2..d5df0bf9402 100644 --- a/code/modules/telesci/bscrystal.dm +++ b/code/modules/telesci/bscrystal.dm @@ -13,7 +13,7 @@ toolspeed = 1 usesound = 'sound/items/deconstruct.ogg' -/obj/item/stack/ore/bluespace_crystal/New() +/obj/item/stack/ore/bluespace_crystal/New(loc, new_amount, merge = TRUE) ..() pixel_x = rand(-5, 5) pixel_y = rand(-5, 5) @@ -54,7 +54,7 @@ // Polycrystals, aka stacks -var/global/list/datum/stack_recipe/bluespace_crystal_recipes = list(new/datum/stack_recipe("Breakdown into bluespace crystal", /obj/item/stack/ore/bluespace_crystal/refined, 1)) +GLOBAL_LIST_INIT(bluespace_crystal_recipes, list(new/datum/stack_recipe("Breakdown into bluespace crystal", /obj/item/stack/ore/bluespace_crystal/refined, 1))) /obj/item/stack/sheet/bluespace_crystal name = "bluespace polycrystal" @@ -70,6 +70,6 @@ var/global/list/datum/stack_recipe/bluespace_crystal_recipes = list(new/datum/st /obj/item/stack/sheet/bluespace_crystal/New() ..() - recipes = bluespace_crystal_recipes + recipes = GLOB.bluespace_crystal_recipes pixel_x = rand(0,4)-4 pixel_y = rand(0,4)-4 diff --git a/code/modules/telesci/gps.dm b/code/modules/telesci/gps.dm index 00999b47f7a..9b7ba72209b 100644 --- a/code/modules/telesci/gps.dm +++ b/code/modules/telesci/gps.dm @@ -1,6 +1,6 @@ -var/list/GPS_list = list() +GLOBAL_LIST_EMPTY(GPS_list) /obj/item/gps - name = "global positioning system" + name = "default gps" desc = "Helping lost spacemen find their way through the planets since 2016." icon = 'icons/obj/telescience.dmi' icon_state = "gps-c" @@ -15,12 +15,13 @@ var/list/GPS_list = list() /obj/item/gps/New() ..() - GPS_list.Add(src) - name = "global positioning system ([gpstag])" + GLOB.GPS_list.Add(src) + if(name == "default gps") //use default naming scheme + name = "global positioning system ([gpstag])" overlays += "working" /obj/item/gps/Destroy() - GPS_list.Remove(src) + GLOB.GPS_list.Remove(src) return ..() /obj/item/gps/emp_act(severity) @@ -35,7 +36,7 @@ var/list/GPS_list = list() overlays += "working" /obj/item/gps/AltClick(mob/user) - if(CanUseTopic(user, inventory_state) != STATUS_INTERACTIVE) + if(CanUseTopic(user, GLOB.inventory_state) != STATUS_INTERACTIVE) return 1 //user not valid to use gps if(emped) to_chat(user, "It's busted!") @@ -54,7 +55,7 @@ var/list/GPS_list = list() return var/obj/item/gps/t = "" - var/gps_window_height = 110 + GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show + var/gps_window_height = 110 + GLOB.GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show if(emped) t += "ERROR" else @@ -66,7 +67,7 @@ var/list/GPS_list = list() var/turf/own_pos = get_turf(src) var/own_z = own_pos.z - for(var/obj/item/gps/G in GPS_list) + for(var/obj/item/gps/G in GLOB.GPS_list) var/turf/pos = get_turf(G) var/area/gps_area = get_area(G) var/tracked_gpstag = G.gpstag diff --git a/code/modules/tram/tram.dm b/code/modules/tram/tram.dm index 6ef45b8cc44..ea43f3fd659 100644 --- a/code/modules/tram/tram.dm +++ b/code/modules/tram/tram.dm @@ -84,7 +84,7 @@ last_played_rail = RT return stored_rail = RT - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) for(var/obj/tram/rail/R in get_step(src,cdir)) if(!istype(R)) continue if(R != last_played_rail) @@ -99,7 +99,7 @@ if(!T) return var/obj/tram/floor/TTF = locate(/obj/tram/floor) in T if(istype(TTF)) add_floor(TTF) //Find and link floor on controller turf - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) var/turf/T2 = get_step(T,cdir) var/obj/tram/floor/TF = locate(/obj/tram/floor) in T2 if(istype(TF)) @@ -115,7 +115,7 @@ var/obj/tram/floor/TTW = locate(/obj/tram/wall) in T //Find and link wall on controller turf if(istype(TTW)) add_wall(TTW) for(var/obj/tram/floor/TF in tram_floors) - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) var/obj/tram/wall/TW = locate(/obj/tram/wall) in get_step(TF,cdir) if(istype(TW)) if(TW in tram_walls) continue @@ -201,7 +201,7 @@ collide_list.Cut() var/list/collisions = list() for(var/obj/tram/wall/W in tram_walls) - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) var/turf/T = get_step(W, cdir) if(istype(T)) if(T.density) @@ -212,7 +212,7 @@ if(tram.Find(A)) continue collisions += cdir for(var/obj/tram/floor/F in tram_floors) - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) var/turf/T = get_step(F, cdir) if(istype(T)) if(T.density) @@ -243,6 +243,7 @@ qdel(src) src.visible_message("[M] has [M.attacktext] [src]!") M.create_attack_log("attacked [src.name]") + add_attack_logs(M, src, "attacked") /obj/tram/bullet_act(var/obj/item/projectile/proj) if(prob(proj.damage)) diff --git a/code/modules/tram/tram_floor.dm b/code/modules/tram/tram_floor.dm index a5c3ec2a3a0..ede3013567b 100644 --- a/code/modules/tram/tram_floor.dm +++ b/code/modules/tram/tram_floor.dm @@ -11,7 +11,7 @@ var/turf/T = get_turf(src) if(!T) return if(!controller) return - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) var/turf/T2 = get_step(T,cdir) var/obj/tram/floor/TF = locate(/obj/tram/floor) in T2 if(istype(TF)) diff --git a/code/modules/tram/tram_wall.dm b/code/modules/tram/tram_wall.dm index 73c278f0ca0..b39417f5f85 100644 --- a/code/modules/tram/tram_wall.dm +++ b/code/modules/tram/tram_wall.dm @@ -12,7 +12,7 @@ var/turf/T = get_turf(src) if(!T) return if(!controller) return - for(var/cdir in cardinal) + for(var/cdir in GLOB.cardinal) var/turf/T2 = get_step(T,cdir) var/obj/tram/wall/TW = locate(/obj/tram/wall) in T2 if(istype(TW)) diff --git a/code/modules/vehicle/ambulance.dm b/code/modules/vehicle/ambulance.dm index 450a6c88372..37c9d97e5c6 100644 --- a/code/modules/vehicle/ambulance.dm +++ b/code/modules/vehicle/ambulance.dm @@ -92,7 +92,7 @@ bed = null . = ..() if(bed && get_dist(oldloc, loc) <= 2) - bed.Move(oldloc) + bed.Move(oldloc, get_dir(bed, oldloc), (last_move_diagonal? 2 : 1) * (vehicle_move_delay + config.human_delay)) bed.dir = Dir if(bed.has_buckled_mobs()) for(var/m in bed.buckled_mobs) diff --git a/code/modules/vehicle/janicart.dm b/code/modules/vehicle/janicart.dm index 12ed9f727eb..d7ba87b818c 100644 --- a/code/modules/vehicle/janicart.dm +++ b/code/modules/vehicle/janicart.dm @@ -44,7 +44,7 @@ origin_tech = "materials=3;engineering=4" /obj/vehicle/janicart/Move(atom/OldLoc, Dir) - ..() + . = ..() if(floorbuffer) var/turf/tile = loc if(isturf(tile)) diff --git a/code/modules/vehicle/vehicle.dm b/code/modules/vehicle/vehicle.dm index 79021affa25..cdbb8580da6 100644 --- a/code/modules/vehicle/vehicle.dm +++ b/code/modules/vehicle/vehicle.dm @@ -153,7 +153,8 @@ unbuckle_mob(user) return - if(world.time < last_vehicle_move + ((last_move_diagonal? 2 : 1) * (vehicle_move_delay + config.human_delay))) + var/delay = (last_move_diagonal? 2 : 1) * (vehicle_move_delay + config.human_delay) + if(world.time < last_vehicle_move + delay) return last_vehicle_move = world.time @@ -161,7 +162,7 @@ var/turf/next = get_step(src, direction) if(!Process_Spacemove(direction) || !isturf(loc)) return - step(src, direction) + Move(get_step(src, direction), direction, delay) if((direction & (direction - 1)) && (loc == next)) //moved diagonally last_move_diagonal = TRUE @@ -185,7 +186,7 @@ to_chat(user, "You'll need the keys in one of your hands to drive [src].") -/obj/vehicle/Move(NewLoc, Dir = 0, step_x = 0, step_y = 0) +/obj/vehicle/Move(NewLoc, Dir = 0, movetime) . = ..() handle_vehicle_layer() handle_vehicle_offsets() diff --git a/config/example/admin_ranks.txt b/config/example/admin_ranks.txt index c7d1cccef98..6f37f5bf234 100644 --- a/config/example/admin_ranks.txt +++ b/config/example/admin_ranks.txt @@ -23,7 +23,8 @@ # +SOUND (or +SOUNDS) = allows you to upload and play sounds # +SPAWN (or +CREATE) = mob transformations, spawning of most atoms including mobs (high-risk atoms, e.g. blackholes, will require the +FUN flag too) # +EVERYTHING (or +HOST or +ALL) = Simply gives you everything without having to type every flag - +# +VIEWRUNTIMES = Allows a player to view the runtimes of the server, but not use other debug verbs + # Admin Ranks Admin Observer Mentor +MENTOR diff --git a/config/example/dbconfig.txt b/config/example/dbconfig.txt index b1113fb625d..2ab248072cf 100644 --- a/config/example/dbconfig.txt +++ b/config/example/dbconfig.txt @@ -9,7 +9,7 @@ ## This value must be set to the version of the paradise schema in use. ## If this value does not match, the SQL database will not be loaded and an error will be generated. ## Roundstart will be delayed. -DB_VERSION 11 +DB_VERSION 12 ## Server the MySQL database can be found at. # Examples: localhost, 200.135.5.43, www.mysqldb.com, etc. diff --git a/dreamchecker.exe b/dreamchecker.exe new file mode 100644 index 00000000000..068a9f58a0c Binary files /dev/null and b/dreamchecker.exe differ diff --git a/goon/browserassets/html/browserOutput.html b/goon/browserassets/html/browserOutput.html index a7dfb16abee..ed2c77a306c 100644 --- a/goon/browserassets/html/browserOutput.html +++ b/goon/browserassets/html/browserOutput.html @@ -15,7 +15,7 @@ - + diff --git a/goon/browserassets/json/unicode_9_annotations.json b/goon/browserassets/js/unicode_9_annotations.js similarity index 99% rename from goon/browserassets/json/unicode_9_annotations.json rename to goon/browserassets/js/unicode_9_annotations.js index 50b00d32116..483e08d47ff 100644 --- a/goon/browserassets/json/unicode_9_annotations.json +++ b/goon/browserassets/js/unicode_9_annotations.js @@ -1487,4 +1487,4 @@ var UNICODE_9_EMOJI = { "zimbabwe": "🇿🇼", "zipper_mouth_face": "ðŸ¤", "zzz": "💤" -}; \ No newline at end of file +}; diff --git a/goon/code/datums/browserOutput.dm b/goon/code/datums/browserOutput.dm index f32b1d53610..74c9d844728 100644 --- a/goon/code/datums/browserOutput.dm +++ b/goon/code/datums/browserOutput.dm @@ -4,6 +4,7 @@ var/list/chatResources = list( "goon/browserassets/js/json2.min.js", "goon/browserassets/js/twemoji.min.js", "goon/browserassets/js/browserOutput.js", + "goon/browserassets/js/unicode_9_annotations.js", "goon/browserassets/css/fonts/fontawesome-webfont.eot", "goon/browserassets/css/fonts/fontawesome-webfont.svg", "goon/browserassets/css/fonts/fontawesome-webfont.ttf", @@ -12,7 +13,6 @@ var/list/chatResources = list( "goon/browserassets/css/font-awesome.css", "goon/browserassets/css/browserOutput.css", "goon/browserassets/css/browserOutput-dark.css", - "goon/browserassets/json/unicode_9_annotations.json", "goon/browserassets/html/saveInstructions.html" ) @@ -304,8 +304,15 @@ var/to_chat_src target << output(output_message, "browseroutput:output") -/proc/__to_chat(target, message, flag) - if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized) +/proc/to_chat(target, message, flag) + /* + If any of the following conditions are met, do NOT use SSchat. These conditions include: + - Is the MC still initializing? + - Has SSchat initialized? + - Has SSchat been offlined due to MC crashes? + If any of these are met, use the old chat system, otherwise people wont see messages + */ + if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized || SSchat?.flags & SS_NO_FIRE) to_chat_immediate(target, message, flag) return SSchat.queue(target, message, flag) diff --git a/html/88x31.png b/html/archived_changelog/88x31.png similarity index 100% rename from html/88x31.png rename to html/archived_changelog/88x31.png diff --git a/html/archived_changelog/_README.txt b/html/archived_changelog/_README.txt new file mode 100644 index 00000000000..38842c99a01 --- /dev/null +++ b/html/archived_changelog/_README.txt @@ -0,0 +1 @@ +This directory has the old changelog system, no longer used \ No newline at end of file diff --git a/html/bug-minus.png b/html/archived_changelog/bug-minus.png similarity index 100% rename from html/bug-minus.png rename to html/archived_changelog/bug-minus.png diff --git a/html/burn-exclamation.png b/html/archived_changelog/burn-exclamation.png similarity index 100% rename from html/burn-exclamation.png rename to html/archived_changelog/burn-exclamation.png diff --git a/html/changelog.css b/html/archived_changelog/changelog.css similarity index 100% rename from html/changelog.css rename to html/archived_changelog/changelog.css diff --git a/html/changelog.html b/html/archived_changelog/changelog.html similarity index 98% rename from html/changelog.html rename to html/archived_changelog/changelog.html index 3ffad2b6c96..a3b160b4115 100644 --- a/html/changelog.html +++ b/html/archived_changelog/changelog.html @@ -1,14382 +1,14439 @@ - - - - Paradise Station Changelog - - - - - - - -
    NameFrom DepartmentTo DepartmentSent AtSent ByView
    [F.name][F.from_department]
    - - - - -
    -
    Paradise Station
    - -

    -
    - - - - - -
    - Current Project Maintainers: -Click Here-
    - Currently Active GitHub contributor list: -Click Here-
    - Coders: ZomgPonies, DaveTheHeadcrab, tigercat2000, FalseIncarnate, AuroraBlade, Tastyfish, Crazylemon64, KasparoVy
    - Spriters: FullOfSkittles
    - Sounds:
    - Main Testers: Anyone who has submitted a bug to the issue tracker
    - Thanks to: Baystation 12, /tg/station, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original SpaceStation developers and Radithor for the title image.
    Also a thanks to anybody who has contributed who is not listed here :( Ask to be added here on irc.
    -
    Have a bug to report?
    Visit our Issue Tracker.
    - Please ensure that the bug has not already been reported and be as descriptive as possible about the circumstances under which the bug occurred. -
    - - -
    - -

    27 October 2019

    -

    AdamElTablawy updated:

    -
      -
    • Xenobiology can no longer produce hellhounds with gold slime cores.
    • -
    -

    AzuleUtama updated:

    -
      -
    • Vampire's shape shift ability and DNA scrambler item now clear flavour text on use.
    • -
    -

    Darkmight9 updated:

    -
      -
    • Adds a wide variety of craftable decorations! You can find them in the new 'Decorations' tab in the crafting menu.
    • -
    • tweaked the duct tape component so that you can now add it to items to make them naturally stick to walls.
    • -
    • added decorative sprites.
    • -
    -

    Fox McCloud updated:

    -
      -
    • windows are easier to break
    • -
    • Adds in the Rod of Asclepius, a healing item that carries an immense burden
    • -
    • Fixes Bubblegum spawning being ridiculously rare
    • -
    • Fixes planetary atmos not correctly happening
    • -
    • Fixes atmos pipe unwrenching
    • -
    • Survival pod medical vendors only have 2 pairs of splints instead of a wide array of medicines
    • -
    • Hivelord core, when used on someone, no longer fully revives them; instead it heals 25 burn, 25 brute, resets body temperature, removes all CC, cures all internal bleeding, and mends all fractures (slowdown bonus still stays
    • -
    • updates the close icon for storage to not be a trashy codersprite
    • -
    • Fixes excessive mob and tendril clumping on Lavaland
    • -
    • Fixes being able to exploit the destructive analyzer for unlimited materials
    • -
    • Fixes Hierophant arena atmos
    • -
    -

    Ionward updated:

    -
      -
    • fixed Battlemage armor having an unintended helmet light
    • -
    • added Vox versions of Battlemage, Paranormal, Inquisitor, Berserker, and Syndicate Elite Hardsuits.
    • -
    -

    SteelSlayer updated:

    -
      -
    • Fixes the RPED and bluespace RPED not displaying a list of parts in players chat when used on a machine
    • -
    -

    TDSSS updated:

    -
      -
    • yellow documents are no longer indestructible.
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • single quotes showing up weird in names and announcement titles
    • -
    -

    Terilia updated:

    -
      -
    • Headcrab Nests
    • -
    • Headcrabs can now eat dead simple_animal corpses to regain 10 hp.
    • -
    • Poison Headcrabs will not inject LSD anymore.
    • -
    • Headcrabs have more HP and some do more damage.
    • -
    • Headcrabs will not stop attacking people after they are unconscious.
    • -
    • Headcrab Nest DMI
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Admin attack log level of heirophant club updated
    • -
    -

    actioninja updated:

    -
      -
    • Nanoui interfaces in fancy mode now open more cleanly
    • -
    -

    craftxbox updated:

    -
      -
    • Vanilla JS Regex for chat highlighting
    • -
    • Removed jquery mark
    • -
    • quickfix to stop people using the scanner inside it
    • -
    -

    farie82 updated:

    -
      -
    • Cult whispering now uses your real name
    • -
    • Fixed the invisible blob zombies
    • -
    • A runtime in blob/factory/run_action
    • -
    - -

    13 October 2019

    -

    Darkmight9 updated:

    -
      -
    • Re-added the handheld defib sprites
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes wrench attacking telepads
    • -
    • performance improvements for xenobio stuff
    • -
    • LINDA is much more aggressive at distributing gas between turfs in an excited group
    • -
    -

    Kyep updated:

    -
      -
    • Removed admin-only "show duplicate discord links" verb.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Captains can access their display case again
    • -
    • Reverted autoban using legacy system causing issues
    • -
    -

    streather updated:

    -
      -
    • fixed a typo in the autolathe
    • -
    - -

    09 October 2019

    -

    Darkmight9 updated:

    -
      -
    • Gives the handheld defib a new sprite
    • -
    -

    Fox McCloud updated:

    -
      -
    • DNA vault requires 5 pico manipulators and 5 super capacitors instead of quadratic capacitors
    • -
    • Powers of the DNA vault adjusted
    • -
    • DNA vault no longer allows you to have unlimited genetics powers.
    • -
    • All previous powers removed with the exception of no breathing
    • -
    • New powers: breathable plasma immunity+virus immunity, heat immunity+burn reduction, speed increase, species armoring+pierce immunity, stun reduction, and action speed increase
    • -
    • Removes consoles screens; use plane old glass in place of them. Holy sheet, they were a pane.
    • -
    • Adds being able to make leather with the bio-generator
    • -
    • removed a lot of leather-related recipes from the bio-generator; these have been moved to leather crafting
    • -
    • can make hide mantles with leather
    • -
    • wearing pants while wearing an undershirt means your arms and chest are covered
    • -
    • Fixes AI swarmers not doing anything
    • -
    • swarmers can eat circuitboards and their own shells now
    • -
    • Fixed being able to eat soil
    • -
    • de-activated swarmer shells give 10,000 metal and 4,000 glass instead of 100 metal and 400 glass.
    • -
    • Fixes lavaland swarmers not being able to teleport people away
    • -
    • Swarmers can place lattice over lava
    • -
    • Floors no longer get dirty by walking on them
    • -
    • Zone selection tweaked; shouldn't notice anything different
    • -
    • melting research lockboxes no longer dumps the contents
    • -
    • Fixes reflective blobs using horrifying code that didn't reflect things *properly*
    • -
    • Fixes APCs not being hackable
    • -
    • Fixes explosions not properly interacting with storage items
    • -
    -

    Ionward updated:

    -
      -
    • Fixed a single pixel offset on Grey's Bags of Holding sprite.
    • -
    -

    JKnutson101 updated:

    -
      -
    • Shades can be stored in any Soul Stone.
    • -
    • Shades can once again be stored in Soul Stones.
    • -
    • Non-cultists and Non-wizards can no longer use most Soul Stones.
    • -
    • Cult Specters properly log as antags.
    • -
    • Cult Specters are properly removed from the cult on death.
    • -
    -

    KasparoVy updated:

    -
      -
    • Fixes an issue with the Tajaran striped tail's wagging animation by removing an extra frame.
    • -
    -

    PidgeyThePirate updated:

    -
      -
    • The abductor's silencer now actually silences radios for 10-20 seconds.
    • -
    -

    SteelSlayer and McRamon updated:

    -
      -
    • Added a new subtype of shade used exclusively by cultists to prevent chaplains metagaming with their shade sprites
    • -
    • Renamed path names for the altar and archives to be less confusing, and replaced all instances of the path names to reflect the change
    • -
    • Replaced nearly every sprite for reaper cult, including constructs, structures, airlocks and the reaper himself.
    • -
    • Removed the old reaper cult construct sprites
    • -
    -

    craftxbox updated:

    -
      -
    • cult teleport rune teleporting ai eye
    • -
    - -

    07 October 2019

    -

    AffectedArc07 updated:

    -
      -
    • SQL now properly disconnects at end round
    • -
    -

    Couls updated:

    -
      -
    • reviver implant now heals even when you're conscious
    • -
    -

    Darkmight9 updated:

    -
      -
    • Hair styles, body markings, clothes, and other character customization options are now alphabetized.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Most things are universally damageable
    • -
    • Acid melts things a bit differently now
    • -
    • Lava actually sets most things on fire.
    • -
    • Captain no longer has access to his display case by default
    • -
    • Xenos can break open vents
    • -
    • Fix syringe in-hand icon not updating
    • -
    • Fixes syringes not having materials
    • -
    • Lethal injection syringes should be a bit more...lethal
    • -
    • PDA health scans should be more in line with regular health analyzer scans
    • -
    • some blood type fixes, nothing noteworthy
    • -
    -

    Ionward updated:

    -
      -
    • fixed invisible Drask surgical masks
    • -
    • added Drask surgery cap icons
    • -
    -

    JKnutson101 updated:

    -
      -
    • Pylons heal robotic limbs.
    • -
    • Soul Shards fail when used on mobs that have never had a ckey.
    • -
    • Soul Stone Shards properly poll dead chat to be filled.
    • -
    • Incorrect icon path for reaper tome
    • -
    -

    Kyep updated:

    -
      -
    • Fixed the medkit spawning in the syndie depot being empty.
    • -
    -

    PidgeyThePirate updated:

    -
      -
    • Revived simple animals keep their ability to pull things and their density if they originally had it.
    • -
    • replaced the Lavaland winter dome ATV with a snowmobile.
    • -
    • The snowmobile key in the winterdome now accompanies an actual snowmobile instead of an incompatible vehicle.
    • -
    -

    SteelSlayer updated:

    -
      -
    • Added GPS coordinates under that status tab for cyborgs which have a GPS
    • -
    • You can no longer fire mining cyborg's KA with no cooldown
    • -
    • Bought items from the wizard spell book are first placed into any empty hands. If all hands are full, it places the item on the ground.
    • -
    • Cultists no longer get more than one summon objective
    • -
    • Mindslaves now show up in their own "Mindslaves" section in the check antagonists panel
    • -
    • Mindslaves will now get their objectives added to their notes and announced in their chat properly
    • -
    • Mindslaves will now have the red (A) in admin attack logs, which shows that the attacker is an antag
    • -
    -

    TDSSS updated:

    -
      -
    • fixed visual issues in beach gateway
    • -
    -

    farie82 updated:

    -
      -
    • Tickets can now be unassigned by staff members.
    • -
    • Toxic compensation now deals the right amount of toxic damage. Instead of just the last healed damage
    • -
    - -

    30 September 2019

    -

    Couls updated:

    -
      -
    • Renames slime organs to be more player friendly
    • -
    -

    PidgeyThePirate updated:

    -
      -
    • The Ripley now collects all the ore it unearths after drilling.
    • -
    -

    SteelSlayer updated:

    -
      -
    • Cultists will no longer get multiple summoning objectives
    • -
    -

    TheSardele updated:

    -
      -
    • MULEbots no longer cause any damage when running over SSDs.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • "Factual" changed to Actual in the explosion doppler array detector system
    • -
    - -

    29 September 2019

    -

    AzuleUtama updated:

    -
      -
    • The camera bug now lists all cameras in alphabetical order.
    • -
    -

    Couls updated:

    -
      -
    • species without bones no longer have ribs or a skull either
    • -
    • slime heart and fleshy masses no longer go invisible after being removed through surgery or being eaten or necrotizing
    • -
    -

    Evankhell561 updated:

    -
      -
    • replace high power cells with high power cell+
    • -
    -

    Fox McCloud updated:

    -
      -
    • can insert keys into vehicles instead of having to hold them in your hand (alt-click while riding a vehicle to remove the key); lava boat still requires holding the key in your hand
    • -
    • Fixes moving diagonally with vehicles making you super fast
    • -
    • Vehicles now factor in the configured human movement delay; this means all vehicles are slower than they previously were
    • -
    • fixes a bug with mobs on vehicles causing incorrect space transitions
    • -
    • ATV sprites updated
    • -
    • Slime speed potions can now apply to vehicles, which makes them faster
    • -
    -

    JKnutson101 updated:

    -
      -
    • Allows for robotic hands, feet, and groin to undergo customization surgery.
    • -
    -

    PidgeyThePirate updated:

    -
      -
    • Abductor surgery will now remove heart subtypes.
    • -
    • Capitalized abductor surgery names for consistency with the surgery UI.
    • -
    • changelings no longer go bald after reviving.
    • -
    - -

    27 September 2019

    -

    PidgeyThePirate updated:

    -
      -
    • Rebooting a drone no longer requires both engineering and robotics access.
    • -
    • fixed a rare glitch in which a guardian that is killed instantly (i.e by a wand of death) may draw its charge into null space.
    • -
    • bluespace anomalies no longer teleport ghosts when their event fires.
    • -
    -

    SteelSlayer updated:

    -
      -
    • Fixes round-start autotraitors not getting their objectives and uplink codes
    • -
    - -

    26 September 2019

    -

    AzuleUtama updated:

    -
      -
    • Improvised shotguns are now in the correct tab when trying to craft them.
    • -
    -

    Couls updated:

    -
      -
    • Slime lungs and heart
    • -
    • Slimes no longer take toxins damage from blood loss
    • -
    • Slimes no longer take brute damage in crit
    • -
    • Slimes now breathe
    • -
    • slimes now use new crit
    • -
    -

    Kyep updated:

    -
      -
    • Fixed NPC redsuited syndicates from being unable to move in space.
    • -
    • Fixed NPC bots thinking that they can path through airlocks which are welded shut. refactor: Refactors some safety checks so that its impossible for depot mobs to generate runtimes in rare cases (e.g: admins spawning them outside the depot for testing)
    • -
    -

    MrMagolor updated:

    -
      -
    • Cult pylons no longer delete unsimulated walls and turn them into floors.
    • -
    • Cult pylons now turn simulated walls into cult walls.
    • -
    -

    TDSSS updated:

    -
      -
    • added missing tools to one abductor ship
    • -
    -

    farie82 updated:

    -
      -
    • Morphs examine text now stays true to the humanoid target they choose.
    • -
    • Cult constructs now show their examine text when you're next to it. Instead of on top of it.
    • -
    - -

    24 September 2019

    -

    AzuleUtama updated:

    -
      -
    • Fixed misleading uplink description for chef's traitor knife.
    • -
    • Reorganises products in seed vendor.
    • -
    • Fixes Durathread mutating into more Durathread
    • -
    -

    Dave-TH updated:

    -
      -
    • Mob spawners will no longer sometimes send players to the void.
    • -
    • The ghosts inside possessed blades are now invincible and will not die to weird edge cases.
    • -
    -

    Evankhell561 updated:

    -
      -
    • mechs now start with a high-capacity power cell+
    • -
    -

    Fox McCloud updated:

    -
      -
    • Buckling has its own icon
    • -
    • Fixes Xenobio monkey shortcuts not working
    • -
    • Bodyscanners are similar to sleepers; interact with them by clicking on the scanner; there is no console anymore
    • -
    • Summon guns/magic is no longer free, but costs 2 spells points
    • -
    • Summon guns/magic makes 10% of the crew antags with the objective to collect guns/magical items and kill anyone who gets in their way
    • -
    • If a wizard (or admin) summons guns/magic, latejoiners to the round will also acquire summoned items
    • -
    • Wizard's hardsuit is now battlemage armor
    • -
    • Battlemage armor protects you from pressure of space (but not the cold), has no slowdown, and a moderate amount of armor, however, it has 16 shields to block incoming attacks
    • -
    • Can purchase additional charges for your battlemage armor for 1 spell point
    • -
    • Shielded hardsuits now show the shield on the mob
    • -
    • Abductors, Skeletons, Shadowlings, and Plasmamen never get hungry
    • -
    • Abductors, Skeleton, and Plasmamen can't taste anything
    • -
    • Wood Golems now have a diet and taste sensitivity much like Diona
    • -
    • Unathi are more sensitive to tastes
    • -
    • Adjusted the sensitivity of "sharp" and "dull" tastes a bit
    • -
    • Slimes are a simple mob subtype
    • -
    • using a bloodlust slime potion on a docile slime removes the docility
    • -
    • using a docility potion on a rabid slime calms them down
    • -
    • slime core removal surgery steps are now just scalpel->hemostat
    • -
    • Slimes have action buttons to feed on, evolve, or reproduce
    • -
    • Fixes beepsky arresting slimes (maybe it should be a feature....)
    • -
    • Fixes Seed Vault gene modder having limitations
    • -
    • Fixes not being able to extinguish some items
    • -
    -

    Ionward updated:

    -
      -
    • Fixed Tajaran fat sprites, they are no longer duplicates of their slim torso.
    • -
    • Fixed fat aqua jumpsuit only using one direction.
    • -
    • Fixed missing Lasagna icon.
    • -
    -

    Kyep updated:

    -
      -
    • The Hierophant club and warp cubes (lavaland loot) no longer allow you to teleport into or out of areas that are set to forbid teleports.
    • -
    • Fixed a small bug that caused coins named "syndicate coin" or "antag token" to both incorrectly appear as "valid coin".
    • -
    -

    Markolie updated:

    -
      -
    • Fixed naked equipment selection and reincarnation not working.
    • -
    -

    TDSSS updated:

    -
      -
    • all huds are the first option when ghosts cycle through huds
    • -
    • fixed brig door timers from announcing admin names when stopped via admin powers.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • You can now silence the current midi with a verb in the preferences tab, without affecting your prefrence to hear midis in the future.
    • -
    -

    datlo updated:

    -
      -
    • Fixed clown changelings not losing comic sans on transformation
    • -
    • Clowns can now lose the clumsy and comic genes through DNA manipulation (but not mutadone)
    • -
    - -

    22 September 2019

    -

    Evankhell561 updated:

    -
      -
    • Mech ID upload panels now come with [add all] and [delete all] options
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes corpses/lying down mobs blocking projectiles
    • -
    -

    MarsM0nd updated:

    -
      -
    • can safely pick up nettles again
    • -
    -

    SteelSlayer updated:

    -
      -
    • Traitor and mindslave status is handled in a datum instead of the mind
    • -
    • You can no longer use a mindslave implant on a person with no mind
    • -
    • Adds the ability for admins to de-mindslave somone through the traitor panel
    • -
    • De-traitoring malf AIs via the traitor panel removes all instances of their Law 0
    • -
    • De-traitoring malf AIs via the traitor panel removes their ability to still state laws over the syndicate channel
    • -
    • De-traitoring malf AIs via the traitor panel removes their ability to shunt to hacked APCs
    • -
    • Unemagging borgs via the traitor panel properly removes their syndicate laws and gives them the crewsimov lawset
    • -
    • Unemagging borgs via the traitor panel who did not have a module selected does not cause a runtime anymore
    • -
    -

    TDSSS updated:

    -
      -
    • Just slight gloves refactor, shouldn't impact anything in game.
    • -
    - -

    21 September 2019

    -

    AzuleUtama updated:

    -
      -
    • The Captain's rapier can now be assigned as a theft objective.
    • -
    • Slime extracts and plasma tanks have been removed as theft objectives.
    • -
    • Document trading no longer counts towards a traitor's total number of assigned objectives.
    • -
    • Fixes a grammar error with the ambulance and slightly misleading description with the combat gloves.
    • -
    • Headpat gloves now inherit their click speed from the North Star gloves and are no longer as fast as before.
    • -
    • Sarin gas grenades no longer purchasable for nuke ops. balance: Grenadier belt now contains a sarin gas grenade. balance: Tactical medkit's hypospray tweaked to contain chems better for dealing with newcrit. balance: C20 bundle increased in price to 18TC, contains an additional clip of ammo. balance: Medical bundle increased in price to 20TC, Donk LMG removed, replaced with medbeam gun and magboots.
    • -
    • Fixed some minor spelling/grammar errors with synthflesh patches and sarin gas grenades.
    • -
    • R&D Console no longer has a default design called 'Name' show up in the mining category.
    • -
    • Syndie and Binary keys now use their own sprites rather than the default ones.
    • -
    -

    Couls updated:

    -
      -
    • Romerol virus that requires two traitors to team up to purchase
    • -
    • zombies that have a slow but steady health regeneration and cannot be killed permanently outside of decapitations and removal of the tumor in the brain
    • -
    • blood no longer stacks on itself endlessly
    • -
    • fixes footprints stacking
    • -
    • removes zombie from the secondary language list
    • -
    • hotkey menu option in the dropdown works correctly now
    • -
    • configurable limit to amount of monkeys that can be spawned by monkey cubes
    • -
    • handle_death is passed the gibbed variable
    • -
    • spec_death replaced with handle_death in romerol
    • -
    • you no longer hit yourself with things you throw
    • -
    • missing arguments in some procs
    • -
    • some macros that were defined twice
    • -
    • recycled monkeys were not being subtracted from the monkey cap
    • -
    -

    Dave-TH updated:

    -
      -
    • Fixes some vending machines (namely miner nanomeds) from adding all of their product twice.
    • -
    • Magical weapons can now be properly dual-wielded.
    • -
    • Fixes the description of energy shields, which said they block things that they do not.
    • -
    • Crayon drawings can stack again.
    • -
    • Crayons can no longer draw on multiple tiles at the same time, sorry octo-artist!
    • -
    • Fixes the lack of cooldown on attacking light fixtures.
    • -
    • Examining an air analyzer now informs you about its lesser-known function!
    • -
    -

    Emanthealmighty updated:

    -
      -
    • Updated the netherworld creatures' sprites.
    • -
    -

    Fox McCloud updated:

    -
      -
    • refactored gloves of the North Star to be more adminbusy
    • -
    • Adds Gloves of Headpats to the pet vendor as a premium item
    • -
    • Refactors the very core and soul of SS13 and enhances the code that powers it
    • -
    • Bible fartgibbing is now a form of suicide
    • -
    • Fixes mice coming back to life
    • -
    • Fixes nurse spiders not wrapping things
    • -
    • Fixes spiders not spazzing out
    • -
    • Simple mobs will now attack everything in the vicinity instead of just specific object types
    • -
    • Gutlunches now eat internal organs
    • -
    • ranged guardians don't rapid fire anymore, but have a lower cooldown on attacks
    • -
    • Fixes some turf underlays not working
    • -
    • adds in a wooden hatechet and rake to the ashwalker base; replaces the regular bucket with a wooden one
    • -
    • Fixes some blank tastes
    • -
    • Fixes not being able to brew fruit wine
    • -
    • Fixes poor TG copy pasta code that caused hundreds of runtimes
    • -
    • Reduces round-start lag
    • -
    • Fixes certain PDA cartridges causing insane performance loss
    • -
    • Carp Migration event no longer deletes the carp when it ends; they will continue to stick around the station
    • -
    • Personal crafting now has subcategories
    • -
    • Finishing crafting an item puts it in your hands instead of on the floor
    • -
    • comments out romerol (much like zombies, it will rise again, don't worry!)
    • -
    • zombies are high and lower pressure immune in addition to immune to heat and tox damage
    • -
    • Ian now has persistence; if he's killed, he'll start over life as a puppy--if he lives to a very long old age, he'll get a unique sprite
    • -
    • Pugs will now yipe on death and can bark
    • -
    • Adds new dog mob; a generic black dog
    • -
    • Foxes are now a dog subtype
    • -
    • Can manually yelp as a dog
    • -
    • All dog subtypes can now chase their tail and be given pats and pets. They all can additionally eat (and taste!) food
    • -
    • Nar-Sie will absolutely not tolerate sacrificing doggos
    • -
    • Ripleys are slightly faster on station, but dramatically faster on Lavaland
    • -
    • Mech mining drings can no longer drill through floors; they also don't just drill once. After a short delay, they'll attempt to drill the target, repeatedly.
    • -
    • Mech mining drills no longer instantly knock out mobs; if the mob is dead and has over 200 brute, the drill will attempt to harvest or gib the mob; can also disembowel
    • -
    • Mech plasma gun has a lower cooldown
    • -
    • Mining scanners apply a much brighter and visible overlay; mining a turf will now instantly clear the overlay
    • -
    • Mining mech (the one that's a lavaland find) has a partially depleted cell; it'll also no longer have multiple mining tools on it
    • -
    • Fixes null animal type with regards to pugs
    • -
    • Legion body loot adjusted; may find rare alternative mining belt or primitive one; bone bracers also show up on Ashwalkers; mini pickaxe spawn also possible
    • -
    • Large legions can damage objects
    • -
    • Small legion skulls no longer block mob movement
    • -
    • Basilisks are now gold core spawnable
    • -
    • Gutlunches no longer produce adult version of themselves, but have babies that grow into gutlunches
    • -
    • Mining belts can now hold pillbottles and shovels
    • -
    • Goliath cloaks hold different items now; more inclined to what Ashwalkers would use and not miners
    • -
    • Swarmer megafauna now has its proper GPS
    • -
    • Can't kill mining fauna by overheating them
    • -
    • new sprite for the Hierophant
    • -
    • Refactored tendrils; they won't show up on health HUDs anymore
    • -
    • Fixes Tendrils not emitting light
    • -
    • Fixes tendrils not changing the terrain around them
    • -
    • Fixes being able to exploit vending machines by deconstructing then reconstructing them to get additional items. Get an additional restocking units from cargo you filthy dirty exploiters
    • -
    • All vending machines require only a single restocking unit to build
    • -
    • Clothing, NanoMed, Wallmed, Vendomat, EngiVend, NutriMax, Megaseed Servitor, Sustenance Vendor, Dinnerware Vendor, Cart Tech, Robco Toolmaker, soviet BODA, security tech, and modular PC vendors are all now makeable/restockable
    • -
    • Most vendors can be damaged by brute force (Nanomed, wallmed, and youtool are notable exceptions)
    • -
    • Most restocking units can be ordered from cargo
    • -
    • Removed snowflakey laptop vendor
    • -
    • Adds in new laptop+tablet vendor; don't expect it to have as much (ask science for upgrade parts!)
    • -
    • Sustenance vendor has a new set of contraband if prisoners can actually hack the thing
    • -
    • breaks up the clothing restocking unit cargo pack from a single pack into 4 separate packs, 15 points each
    • -
    • Fixes Megafauna spawning near the base
    • -
    • Fixes lava rivers not forming
    • -
    • Upped the labor mineral spawn rate
    • -
    • Removed the ability to find random code-locked crates when mining
    • -
    • Watcher Icewing blasts will briefly freeze you
    • -
    • Fixes too much detecting corgis
    • -
    • Tweaks a few reagents tastes
    • -
    • fixes being able to taste metaphorical salt
    • -
    • nutriment no longer restores blood
    • -
    • Nuke ops can no longer advanced syndie magboots
    • -
    • Fixes an inconsistency with chameleon kit pricing--it was only 2 TC, making the no slip syndicate shoes worthless; price is now 4 TC
    • -
    • operatives pay 2 TC more for the no slip syndicate shoes and the chameleon kit
    • -
    • Wizard hardsuits no longer come with magboots
    • -
    • Syndie magboots are nuke ops only
    • -
    • Can purchase no slip shoes from the uplink instead of a full chameleon kit
    • -
    • Operatives can purchase no slip syndicate shoes
    • -
    • No slip shoes can protect against atmos pushing
    • -
    • removed most round-start magboots with the exception of EVA, atmostechs, CE, and engineering hardsuit dispensers
    • -
    • Fixes carp not being a threat to the station due to killing themselves
    • -
    • Fixes being able to exploit simple mob AI so it kills itself in an atmos death blender
    • -
    • vent and scrubbers work far more efficiently and quickly now
    • -
    • Fixes wideband on scrubbers constantly resetting itself
    • -
    • Portable scrubbers far more effective
    • -
    • Flamethrowers far more effective
    • -
    • Nanofrost twice as expensive
    • -
    • regular syndicate borgs don't have magpulse by default
    • -
    • Atmos pushing completely refactored; it'll still push you frequently and push items around frequently, but it won't throw you. Depending on how many dense objects or turfs are around you to "grab onto" will determine how effective atmos is at pushing you around. Does not alter the speed at which LINDA runs.
    • -
    • Plasma glass shards do less damage when attacking, but slightly more when stepping on them
    • -
    • Spears made out of plasma glass do slightly more damage
    • -
    • Light replacer can now be used in-hand to attempt to reload empty lighting fixtures around you in addition to showing how many lights it has
    • -
    • Light replacer needs less shards to increment bulbs
    • -
    • Updates moonflower, sunflower, novaflower, and pineapple sprites
    • -
    • Adds in Garlic
    • -
    • Fixes a few issues with incorrect values from the wine PR
    • -
    • Can now grow and extract the reagents/traits of Lavaland flora
    • -
    • Slightly tweaks soybean oil production on soybeans
    • -
    • Adds amusing garlic suicide
    • -
    • Ash Drake reworked; it's much more powerful now and has a diverse set of attacks--its fire breath is more random, it moves faster, it can turn the ground into lava, and once it's lower on health, will seal you into an arena and make you play the "only one turf is safe; stand on it or suffer" mini-game
    • -
    • Bubblegum is now much more difficult; instead of just spraying blood at you and attempting to endlessly charge you (walking backwards essentially counters it), it's now faster, engages in zig-zag attacks, uses a hallucination multi-attack, and can rapidly melee attack you in range
    • -
    • Fixes megafauana endlessly attacking dead mobs
    • -
    • Blood drunk Colossus, and Ash Drake made to be more player friendly if they control the fauna
    • -
    • Adds in Space dragon; a very weak version of the Ash drake which can't swoop, but can still breathe fire--has a spell that whips you back with its tail, too (not currently used anywhere)
    • -
    • The real Roman shield and real Roman helmets in the Autodrobe have been replaced by fake, armorless, varieties
    • -
    • Hierophant has been updated--it'll be a bit tougher and will attempt to trap you if you run for it.
    • -
    • Heirophant is no longer a weird bird thing, but a massive, indecipherable piece of machinery that will make you dance to ITS tune
    • -
    • Hierophant club is weaker up front, but becomes stronger the lower health you are
    • -
    • Fixes tendrils spawning inside ruins
    • -
    • Fixes light replacers breaking/hitting lights
    • -
    • Fixes blood drunk buff not making you slow immune
    • -
    • Regenerative core will give you 1 minute of slow immunity on application
    • -
    • carp sprites now support a wider range of colors
    • -
    • Megacarp names randomized in addition to their stats
    • -
    • Adds new friendly life reaction (strange reagent + synthflesh + sugar + heat)
    • -
    • Life reaction amount of critters spawned varies with created volume
    • -
    • Can now spawn the xeno maid, lightgeists, and bees with slimes cores/life
    • -
    • can no longer spawn the Shamebrero penguin with slimes cores/life
    • -
    • Adds new EVIL crab; is a "hostile" slime core/life mob
    • -
    • simple Xenos are a bit more powerful
    • -
    • Butchering simple Xenos now leaves a Xeno hide; use it to make a Xeno costume
    • -
    • Fixes spriteless dog
    • -
    • Fixes being able to spawn Proc with slimes cores/life
    • -
    • Fixes Blooddrunk being a flying mob
    • -
    • can move dense objects around corners
    • -
    • Removes unused, highly buggy VR code
    • -
    • Completely transitions to Lavaland for all maps. The mining asteroid and it's related bits are removed
    • -
    • Vox reworked
    • -
    • Vox are no longer spaceproof
    • -
    • EMP's no longer wreck cortical stacks
    • -
    • Vox cortical stacks are their brains; there's no longer two separate organs for Vox brain+cortical stack
    • -
    • Vox are immune to decay and will not skeletonize
    • -
    • Vox internal organs will never accumulate germs or decay, even when they're outside a Vox's body
    • -
    • Vox external organs do not accumulate germs when attached to their body
    • -
    • Vox have silent footsteps
    • -
    • Vox can process BOTH organic and synthetic reagents
    • -
    • Diona no longer decay into skeletons
    • -
    • Can now pick the species you want to play as for lavaland ghost roles
    • -
    • Golems have been buffed.
    • -
    • Golems are faster, better protected against damage, and have limbs that cannot break or be dismembered.
    • -
    • Golems are no longer virus immune
    • -
    • Golems can now wear labcoats and boxing gloves
    • -
    • Fixes golems being able to be healed/injected on parts other than the chest
    • -
    • Having a robotic chest allow you to wear an ID, PDA, and belt without a jumpsuit. Having a robotic right leg allows you to use your right pocket without a jumpsuit; same for your left
    • -
    • stepping on glass tubes now shatters them; can trip you up if you aren't wearing shoes
    • -
    • Stepping on a D4 will deal between 1 and 4 damage to you if you aren't wearing shoes and trip you up
    • -
    • skeletons have built in pierce immunity
    • -
    -

    Ionward updated:

    -
      -
    • Greys, Unathi, Tajaran, and Vulpkanin now have sprites for Lavaland reward hardsuits (Wizard, Elite Syndicate, and Paranormals), Biosuits, Voidsuits, and Syndicate Soft suits.
    • -
    • Plasmamen Librarians now have visible helmets.
    • -
    • Atmos Hardsuits now have inhand sprites again.
    • -
    • Added new uniform and hat to the AutoDrobe, the Rhumba outfit.
    • -
    -

    KasparoVy updated:

    -
      -
    • Tajaran characters can now have the tiny & short tails (plus marking).
    • -
    • Adds a striped tail marking for Tajara derived from the sriped/wingler body accessory to allow more flexible colouration.
    • -
    • Renames Vulpkanin alt. tails for brevity and easier keyboard navigation.
    • -
    -

    Kyep updated:

    -
      -
    • Fixed bug that made the syndicate depot impossibly difficult.
    • -
    • Various improvements to syndi depot, such as use of plastitanium walls, and nerfs to some cheese strategies.
    • -
    • Ported TG's simple_human.dmi, a sprite file of humanoid sprites (including syndicates).
    • -
    • Added a few extra syndi sprites from FoS.
    • -
    • fixed an issue with keyboard input
    • -
    • Brig timers now display the job of brigged people. E.g. "Joe Schmoe (Chemist) was incarcerated" as opposed to just "Joe Schmoe was incarcerated".
    • -
    • Brig timers now notify a person's boss via PDA when they are incarcerated. E.g. if a chemist is temporarily brigged, the CMO is notified of the brigging via PDA.
    • -
    -

    Markolie updated:

    -
      -
    • Guardian communciation now longer shows up to players in the lobby.
    • -
    -

    Mocha-Not-Latte updated:

    -
      -
    • Fixes #12354
    • -
    -

    Shadow-Quill updated:

    -
      -
    • Fixed ATM withdrawals doubling.
    • -
    • Fixed Fore Port Solars' APC not charging.
    • -
    • Fixed a typo in admin gloves of rapidness.
    • -
    • Plasma cutters will no longer eat plasma if you try recharging a full gun.
    • -
    • Blobs now get a audio notification roundstart (like traitors do.)
    • -
    -

    SomeSortaSquid updated:

    -
      -
    • Karma purchases no longer loop infinitely, leading to repeated purchase prompts or "You do not have enough karma!" message after successful purchase.
    • -
    -

    SteelSlayer updated:

    -
      -
    • The AI and magistrate get bold text when the "louder command members" telecomms setting is on
    • -
    • Command members will get the first letter of their radio message auto capitalized when the "louder command members" telecomms setting is on
    • -
    • Malf AI's overload machine & override machine action button behavior is changed to a point and click style ability.
    • -
    • Added some new mouse pointer icons for the machine overload and machine override abilities
    • -
    • The "Show Player Panel" verb is now right click only
    • -
    • The "C.M.A. - Admin" verb is now right click only
    • -
    • The "C.M.A. - Self" verb is now right click only
    • -
    • The "Check Contents" verb is now right click only
    • -
    • The "Freeze" verb is now right click only
    • -
    • The "Freeze Mech" verb is now right click only
    • -
    • The "Jump to Turf" verb is now right click only
    • -
    • The "Update Mob Sprite" verb is now right click only
    • -
    • The "List SSDs" and "List AFKs" verbs have been combined into one verb named "List SSDs and AFKs"
    • -
    • The "Resolve All Open Mentor Tickets" verb has been moved inside the mentor ticket interface window
    • -
    • The "Resolve All Open Admin Tickets" verb has been moved inside the admin ticket interface window
    • -
    • Increases the width of the new "List SSDs and AFKs" window a bit
    • -
    • The gravitational catapult no longer pushes ghosts when used
    • -
    • Fixes a runtime preventing walls from being repaired properly
    • -
    • Adds the ability to repair and remove bullet holes from reinforced walls that have no structural damage
    • -
    -

    TDSSS updated:

    -
      -
    • local gps signals, visible only on the same z level
    • -
    • lavaland mob signals were made local, reducing gps clutter
    • -
    • Objective to abductors to not disrupt crew too much.
    • -
    • healing fountain lavaland ruin now correctly heals
    • -
    • lowered attack log level of self-harm
    • -
    • certain harmless chems and food have reduced attack log logging levels
    • -
    • the most grave of wrong tips
    • -
    • The uplink dart gun now comes with some syringes to use with it.
    • -
    -

    Terilia updated:

    -
      -
    • stat_attack from unconscious to dead
    • -
    • added new headcrabs (poison and fast)
    • -
    • added new headcrab sounds for the poison headcrab and the fast zombie
    • -
    -

    TheMadTrickster updated:

    -
      -
    • fixed wonky/bugged sprites for custom guitar and hair gel
    • -
    • new improved clean sprites for custom items
    • -
    • old messy sprites for custom items
    • -
    -

    TheSardele updated:

    -
      -
    • Changes the attack log setting required to have the blood-drunk miner buff actively log to all attack logs.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Headpat gloves added to arcade machine prizes
    • -
    • Minor ban evasion update
    • -
    • Autonote for manual bans removed
    • -
    • SSD players no longer drown in shallow water
    • -
    • Admins can now autoreply with common answers to common questions / issues.
    • -
    • Opening an adminhelp/mentorhelp ticket will play a sound
    • -
    • Adminhelp ticket information color changed from neon green to a more toned down green
    • -
    • Global admin midis will now silence lobby music for those who have midis enabled.
    • -
    • Adds "Man Up" to autoreply
    • -
    • Autoreponses now show up as the last admin response in tickets
    • -
    • Fixes an issue where autoresolve was appearing in mentorhelps to mentors
    • -
    • Resolve button on adminhelps and mentorhelps work again
    • -
    • Fixes reversed logic in autorespond confirmation alert
    • -
    • Removed custom admin event info that only admins could view due to confusion with the regular non-admin verb.
    • -
    -

    datlo updated:

    -
      -
    • Added the Banana Touch and Mime Malaise spells to the Wizard spellbook.
    • -
    • Station goal crates now come in engineering crates.
    • -
    • Replaced the red emergency toolbox in hermit ruin by a regular blue toolbox.
    • -
    -

    farie82 updated:

    -
      -
    • Hoodies now work like they do in TG. Less abuse of NO DROP, more better
    • -
    • Welding a tile away now gives a more useful message when doing so.
    • -
    • Admins now don't get spammed by hugs.
    • -
    -

    kazboo updated:

    -
      -
    • added a nice metalic alarm sound for when the nuclear self-destruct is activated on the station.
    • -
    • candle boxes on the station are now properly filled
    • -
    -

    variableundefined updated:

    -
      -
    • Multiple food now have their own tastes
    • -
    • Corgi and mice can now taste food
    • -
    • Hallucination causes you to taste strange things
    • -
    • Nutriments now carry over the tastes of food
    • -
    • A quick resolve button to adminhelp and mentorhelp message!
    • -
    • Config option to let gamemode ignore the number of required players.
    • -
    • Hit_reaction proc has been refactored.
    • -
    • Flamethrower and grenade detonation by shot is now logged.
    • -
    • Refactored wooden chair so placing them won't make you see normal metallic chair anymore.
    • -
    • Contribution guideline has been updated. No in game changes.
    • -
    • Github pull request template has been changed
    • -
    • Officer starter pack to cargo. For 30 cargo points you can equip an officer just like an officer closet! Backpack not included due to budget cut.
    • -
    -

    xProlithium updated:

    -
      -
    • Replaced link to CA (check antags) in adminhelps, tickets, and adminmoreinfo with a link to TP (traitor panel)
    • -
    • Altered CA to TP for prayers and adminpms.
    • -
    - -

    30 August 2019

    -

    AffectedArc07 updated:

    -
      -
    • Fixes the changelog
    • -
    -

    Arkatos updated:

    -
      -
    • Added new icon for Charge spell
    • -
    • Added new icon for No Clothes spell
    • -
    • Added new icon for Wizard spellbook
    • -
    • Added new animations to 10 single-use spellbooks
    • -
    • Added new sprite for Bottle of Tickles
    • -
    • Added refunding functionality to the Bottle of Ooze akin to the other summoning bottles. Click with the bottle in hand on a wizard spellbook to refund its cost and limit slot.
    • -
    • Fixed an issue where Bottle of Tickles did not properly refund
    • -
    • Fixed an issue with alpha layering on Bottle of Ooze sprite
    • -
    • Very slightly adjusted brightness of the Boo! ghost spell icon
    • -
    • Wizard spellbook was completely reorganized, and new appropriate categories were added, each category is sorted by price, and if price of the two or more spells is the same, they are sorted alphabetically
    • -
    • Polymorph can now turn a mob into Syndicate medical or saboteur modules
    • -
    • Mobs made via polymorph into borgs are now unbounded free borgs
    • -
    • Repulse spell cost decreased from 2 to 1
    • -
    • Lighting bolt spell cost decreased from 2 to 1
    • -
    • Slaughter/Laughter demons and Magical Morphs now always have their second fluff objective considered as complete no matter the circumstances
    • -
    • Laughter Demons very slightly buffed, they are still a bit weaker than Slaughter Demons
    • -
    • Improved descriptions and wording regarding Wizard spellbook and Wizard spells
    • -
    • Traitor AI now uses action buttons for its malfunction abilities
    • -
    -

    AzuleUtama updated:

    -
      -
    • Adds false-bottomed briefcase from VG.
    • -
    -

    Couls updated:

    -
      -
    • Rechargers can now be crafted from science using one capacitor and a recharger board tweak:Smaller machines like microwaves and cell chargers can now be placed on tables(Fax machines included) tweak:can screwdriver open rechargers and then apply a crowbar to deconstruct them
    • -
    • Blood spread now depends on volume of the blood, requires more drips of blood to create a pool
    • -
    • DUAL WIELDING
    • -
    • new chatsubsystem from TG!
    • -
    • Update issue templates to latest version and clean up the current template
    • -
    • mining shuttle warning message and delay before launching
    • -
    • cardboard boxes are no longer sonic speed
    • -
    • shuttle timers now get set properly
    • -
    -

    EmanTheAlmighty updated:

    -
      -
    • Blobbernauts can now be controlled by players through a prompt which appears when they are spawned by blobs.
    • -
    • Blobbernauts and blobs can now communicate with each other.
    • -
    • Blobbernauts now regenerate health overtime when standing on blob structures.
    • -
    • Blobbernauts will slowly lose health if they are not standing on blob structures while not at full health. balance: Blobbernauts have been nerfed, they now have less health, deal less damage and cannot break walls anymore. balance: Blob's "Produce Blobbernaut" ability has been made more expensive to use, now costing 60 resources instead of 20.
    • -
    -

    Emanthealmighty updated:

    -
      -
    • The poll to play as a blobbernaut now lasts 10 seconds from 15.
    • -
    • Blobbernauts no longer chase after people while players are being polled to play as one.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Plasmamen dramatically overhauled.
    • -
    • Plasmamen can be cloned without burning to death in the clonepod
    • -
    • Plasmamen no longer start with spacesuits
    • -
    • Plasmamen start off with jumpsuits that seal to protect against oxygen. This allows for you to customize their appearance more
    • -
    • Plasmamen helmets now allow you to see a Plasmaman's actual face; should be able to see their eye color and mouth color now
    • -
    • Plasmamen take 50% extra brute and burn
    • -
    • Plasmamen are immune to radiation
    • -
    • Plasmamen start out with a small tank that can fit on a belt or in a pocket; it should be enough to last an entire shift
    • -
    • Plasmaman helmets now have built in welding goggles
    • -
    • Plasmaman karma cost lowered from 100 to 45
    • -
    • Reworks Diona
    • -
    • Diona bleed (call it chlorophy; it's green)
    • -
    • Diona Breathe (plants do need to exchange gas after all)
    • -
    • Rad Immunity Removed
    • -
    • Diona regenerate 1 OXY, 1 BURN, 1 BRUTE, and 1 TOX if they are in a bright area; this effect does not kick in if they're in crit
    • -
    • Diona no longer have unbreakable bones (wood can crack ya know!)
    • -
    • Diona are no longer space proof
    • -
    • Diona are more vulnerable to fire and heat damage
    • -
    • Diona weakness to weedkiller dramatically nerfed
    • -
    • Diona now use Newcrit
    • -
    • Diona are no longer slow
    • -
    • Diona can wear spacesuits
    • -
    • Fixes stun absorbing not working
    • -
    • Fixes parallax insane setting not doing anything
    • -
    • Ores can be destroyed by devastating explosions
    • -
    • silver, gold, and diamond pickaxes do a bit more damage and mine faster than before
    • -
    • drills slightly slower, but diamond drills slightly faster
    • -
    • Spade is the same speed as a shovel
    • -
    • Hivelord stabilizer will now make a hivelord core/legion soul stabilize and be preserved, even if it was previously inert
    • -
    • can use a hivelord core in your active hand to apply it to yourself
    • -
    • soulstone in the abandoned locked crates can now be used by anyone
    • -
    • Adds firelemon seeds to the abandoned locked crates as potential loot
    • -
    • Hardsuits have an integrated helmet; you no longer have to attach helmets
    • -
    • Toggling up/down helmets is now done with an action button
    • -
    • can no longer attach magboots to a hardsuit
    • -
    • Hardsuit base melee armor increased from 10 to 30
    • -
    • Security and HoS hardsuit melee armor increased by 5
    • -
    • HoS hardsuit helmet armor matches his hardsuit
    • -
    • CE's hardsuit helmet armor for rads increased by 10 (should be fully rad proof now)
    • -
    • Elite syndicate suits can't be acided
    • -
    • Fixes stuns and weakens related to reagents
    • -
    • Fixes the displayed cost of Plasmamen
    • -
    • Adds jetpack hardsuit upgrades: get yours at mining for 2000 points
    • -
    • Removes mining carbon dioxide jetpack
    • -
    • Can no longer use jetpacks in your suit storage slot
    • -
    • Chief Engineer's hardsuit, Syndicate Hardsuit (normal and elite), and Shielded Syndicate Hardsuit all have built in jetpacks
    • -
    • Fixes random singularity releases from the grid check event
    • -
    • loadout costs for most things cut from 2 to 1
    • -
    • Adds fingerless gloves, eyepatch, prescription glasses, black shoes, brown shoes, white shoes, and ian's shirt to the loadout
    • -
    • moved hipster glasses from donator to general glasses
    • -
    • Adds in sandbags. Use them to deploy destructable barriers; miners start off with a few
    • -
    • Removes access based security barriers
    • -
    • Adds in security barrier grenade. When it goes off, it will deploy up to 3 barriers that will lock into place; should find 4 of these in the armory
    • -
    • can tear up bedsheet and gauze to get cloth--requires a sharp object
    • -
    • Fixes plasmamen atmos techs not getting their proper suit
    • -
    • Adds in a loom, craft one out of 10 wood
    • -
    • Adds in cotton and durathread cotton to botany to grow
    • -
    • Adds in a number of expanded items to create out of cloth, such as improvised gauze, beanies, and softcaps
    • -
    • Adds the ability to use personal crafting to make durathread jumpsuits, bandanas, armor, helmets, beanies and berets. Aside from the bandana, these all have minor armor on them
    • -
    • Adds a number of new items to personally craft, related to clothing: ability to make health, sec, diagnotic, and reagent sunglasses.
    • -
    • Can additionally craft cowboy boots, lizardskin cowboy boots, fannypacks, and a spooky ghost disguise
    • -
    • adds a whole range of beanies, find them in the clothing vendor or make them yourself
    • -
    • Updates the cowboy boots sprites
    • -
    • Unironically fixes about several thousand runtimes
    • -
    • Fixes jackets not keeping you warm
    • -
    • Chefs are now trained in the art of Close Quarters Cooking
    • -
    • Adds the Book of Babel as tendril loot
    • -
    • Adds Jacbo's Ladder as tendril loot
    • -
    • Fixes fungus, blood, and graffiti not showing up on a wall
    • -
    • Fixes the lavaland inquisitor and berserker hardsuits having incorrect armor and slowdown values
    • -
    • Fixes baseball bats throwing anchored things
    • -
    • Fixes blood drunk buff
    • -
    • Fixes using a crusher on a trophy to equip it causing you to drop the crusher
    • -
    • refactors lazarus capsules; no real behavioral change
    • -
    • Fixes being able to revive megafauna with strange reagent
    • -
    -

    Fox McCloud and FullOfSkittles updated:

    -
      -
    • Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites
    • -
    • Fixes telebacon not properly acting as...well, a bacon beacon
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Added an Engine Picker, which uses new engine beacons.
    • -
    • Replaced the current two engine generators with one engine beacon.
    • -
    -

    Ionward updated:

    -
      -
    • Drask crewmembers now have properly fitting shoes.
    • -
    • Fixed some minor issues in Drasks uniforms
    • -
    • non-humans now have proper sprites for durathread goods
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds sprites for all Vox & Armalis earwear.
    • -
    • Adds sprites for Armalis default backpack, nitrogen tank (old-style back & new-style belt) & all breath mask variations.
    • -
    • You can now species-fit in-hand icons: Use a single .dmi file and suffix the icon states with _l or _r.
    • -
    • Fixes an issue preventing Vox Armalis from being rendered with the proper in-hand icons for their massive noise cannons.
    • -
    • Fixes an issue preventing the species-fitting of earwear.
    • -
    • Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask.
    • -
    • Picking up uniforms no longer renders a default grey jumpsuit on Vox.
    • -
    • Resolves an issue causing shining eyes to be rendered darker than intended.
    • -
    • Resolves an issue preventing appearance features (hair, eyes, etc.) from rendering on disembodied heads.
    • -
    • Resolves an issue preventing Admin-revived decapitated bodies from having appearance features or ears.
    • -
    • Non-shining eyes render the proper colour again.
    • -
    -

    Kurgis updated:

    -
      -
    • Beepsky now bumps around on its wheels when patrolling for crime.
    • -
    -

    Markolie updated:

    -
      -
    • A new outfit manager has been added for admins (under debug). It lets them save and load custom outfits on their computer and use these to equip players.
    • -
    • Upon transforming players into humans or reincarnating them through the player panel, admins will now directly be able to select their equipment.
    • -
    • The select equipment verb now works on observers: it'll create a human with the given equipment under the ghost.
    • -
    • A "Copy Outfit" button has been added to the View Variables dropdown, which lets admins instantly copy an outfit.
    • -
    • Outfits now support accessories and internal boxes.
    • -
    • The separate option to equip ERT members has been removed. It's been integrated into their regular outfits.
    • -
    • Water coming from sinks and certain water effects is now 10C instead of body temperature.
    • -
    -

    Shadow-Quill updated:

    -
      -
    • [Meta] Added buckshot and slugs to armoury.
    • -
    • [Meta] Added surgical tools, robotic first aid kits, and a photocopier to Robotics.
    • -
    • [Meta] R&D doors now has proper access requirements.
    • -
    • [Meta] Added RCS and telepad to cargo.
    • -
    • [Meta] Disposals sheet stacker and conveyor belts now works properly.
    • -
    • [Meta] One-way airlocks added in Medbay/Brig.
    • -
    • [Meta] Disposals sheet stacker disposals chute leads directly to the mailroom.
    • -
    • AIs not being able to restore their own power if in an area with an APC.
    • -
    • Fixed being able to talk in OOC under certain circumstances if it's disabled.
    • -
    • Lockers can no longer move around anchored mobs.
    • -
    -

    SteelSlayer updated:

    -
      -
    • You can no longer spam dismantle a SMES terminal and get 10 cable for every progress bar
    • -
    • The game will properly remove 10 cable from your stack after building a SMES terminal, instead of removing 0
    • -
    • A cable adding sound gets played when you add wires to create a terminal for a SMES
    • -
    • Rapid pipe dispensers can now place disposal sorting pipes
    • -
    • When changing the sort location of a disposal sorting pipe, the name of the pipe now also changes to the desired destination
    • -
    • Added a destination tagger to the atmosheric technician locker
    • -
    • Added atmospherics access to Engi-Vend's and Engineering checkpoint airlocks
    • -
    • Removed some random grey pixels from disposal sorting junction pipe sprites, and certain normal disposal junction pipe sprites
    • -
    • IV bags are able to transfer their contents to other containers by clicking on them with the bag
    • -
    • Adds a handheld defibrillator to the paramedic EVA closet
    • -
    • You can insert magazines into L6 SAWs again
    • -
    • Removed one of the high capacity tanks in hydroponics
    • -
    • Added a disk compartmentalizer to hydroponics
    • -
    • Delaying round start actually delays round start again
    • -
    -

    Terilia updated:

    -
      -
    • added headcrabs
    • -
    • adjusted the path's for headslugs. They are not called headcrab anymore
    • -
    -

    TheSardele updated:

    -
      -
    • Removes the ability of obese people and those with matter eater to swallow others.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Fixed a bug where hotwiring solar panels would allow for the station to remain powered in the Grid Check power failure event.
    • -
    -

    datlo updated:

    -
      -
    • Added ashstorm immunity to titanium and plastitanium golems.
    • -
    • Added lava immunity to plastitanium golems.
    • -
    • Bananium golems now slowly waddle around.
    • -
    • Uranium golems now properly irradiate nearby mobs that arent rad immune.
    • -
    • Tranquillite golems now properly get their miming powers.
    • -
    • Added the Clown and Winter biodomes as possible lavaland ruins.
    • -
    • Update a changeling error message to be clearer.
    • -
    -

    farie82 updated:

    -
      -
    • Items with NODROP that are dropped now lose the flag if they didn't get created with it
    • -
    • Adds tip text to the examine text of the ambulance trolley about how to attach it
    • -
    • Adds tip text to the nuke when trying to use the NAD before deploying it
    • -
    • Adds tip text to the fire axe cabinet about how to lock/unlock it
    • -
    • Adds tip text to airlocks if they have a note on them about how to remove the note
    • -
    • Can't put the NAD in the nuke now when it has the NODROP flag
    • -
    • Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep
    • -
    • Can't put a nodrop fire axe in fire axe cabinets now. Duping them
    • -
    • Implants like the IPC charging work again. They won't get deleted after first use
    • -
    -

    variableundefined updated:

    -
      -
    • A proc's name got changed. That's it
    • -
    - -

    23 August 2019

    -

    AffectedArc07, Keekenox, Floyd/Qustinnus updated:

    -
      -
    • P A R A L L A X (That fancy space thing)
    • -
    • Adds a new Parallax layer that resembles Lavaland (Lava Planet), it spawns on a random location near the station. You need your parallax on high to see it.
    • -
    -

    Arkatos updated:

    -
      -
    • Added colored pillbottles
    • -
    • Added an option to change color of the pillbottles to ChemMaster3000
    • -
    • Added new description to patch packs
    • -
    • Jump to Node ability now shows a location of each Blob node
    • -
    • Added SlimeHUD when playing as a slime. This means slimes will have their own unique health doll and pull icon.
    • -
    • Action buttons can now be dragged onto each other to swap places
    • -
    • Fixed a case where dragging locked action buttons could result in white tooltip over the screen
    • -
    -

    AzuleUtama updated:

    -
      -
    • The Traitor thermal glasses and chameleon security HUD now use the updated chameleon code. balance: Traitor thermal glasses will no longer cause eye damage when hit with EMP.
    • -
    -

    Citinited updated:

    -
      -
    • Removes the big pipe dispensers from atmospherics, you can still find them elsewhere.
    • -
    -

    Couls updated:

    -
      -
    • After many complaints about being stuck in medbay. NT has modified all the airlocks on the station to allow leaving certain departments without requiring an respective ID. This new modification is indicated by a white light near the airlocks in the direction of unrestricted access.
    • -
    • New unrestricted access can be built by NT engineers through modification of the airlock electronics.
    • -
    • hit effects!
    • -
    • hit effect sprites for lasers, bullet hole and dent decals for walls
    • -
    • mice now have a very low chance of chewing through wires, this kills them if the wire is powered
    • -
    • You can now homerun things thrown at you with a baseball bat!
    • -
    • new baseball hit noise, new baseball sprite
    • -
    • there are much less one-way airlocks on station
    • -
    -

    DoctorDrugs updated:

    -
      -
    • removed the ability to eat the divine vocal cords
    • -
    -

    EmanTheAlmighty updated:

    -
      -
    • The AI can now change its intent by clicking on the new on-screen button or pressing 4 to switch to help or harm.
    • -
    • The AI can now toggle airlock safeties instead of toggling door bolt lights by pressing middle mouse.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Majorly updates lavaland
    • -
    • Miner starting equipment altered. They now start with a kinetic accelerator
    • -
    • Miners start off with a mini pickaxe
    • -
    • Adds in the boxed implant kit, regular shelter capsule, and mining drone passthrough upgrade to the mining equipment vendor
    • -
    • re-ordered the equipment vendor, so things are grouped together more logically
    • -
    • Added a number of new kinetic accelerator upgrades acquirable through tendril chests
    • -
    • Mining bot now uses an actual kinetic accelerator as opposed to a "Look alike"; you can upgrade its internal gun with various kinetic accelerator modkits.
    • -
    • Sentient mining bot nerfed; you can no longer apply the armor or melee buff to them; offset by the fact you can upgrade their kinetic gun.
    • -
    • Indoor pressure mod removed from R&D and made into a miner traitor item
    • -
    • Resonators have an increased amount of fields and do more damage in low pressure. Additionally, if you place a field on a tile that already has a field, it'll cause it to detonate early
    • -
    • Plasmacutter no longer does increased damage in low pressure, Advanced plasma cutter does slightly more base damage but has a bit less range. Price has been cut at R&D
    • -
    • removed the AoE Mob+Turf upgrade for mining pods
    • -
    • Fixes ripleys being slow on lavaland
    • -
    • Fixes walking on lavaland sounding like walking on metal plating
    • -
    • Adds in kinetic crusher trophies
    • -
    • Kinetic crusher can be wielded/unwielded (but you can't attack with it unwielded)
    • -
    • Adds the HECK suit as Bubblegum loot
    • -
    • Adds the kinetic accelerator bounty mod as Tendril loot
    • -
    • Add fulton extract packs to the mining vendor; rescue precious valuable or dead miners!
    • -
    • Adds mini-fans to the mining, engineering, and security shuttles
    • -
    • Adds a number of primal recipes: rake (cultivator), wooden bucket, firebrand (long burning match), and bone bracers (armored arm protection that goes on your glove slot)
    • -
    • Can attach bayonets to C20rs, bolt action rifles, security auto-rifles, and kinetic accelerator; harm intent to stab with them
    • -
    • can craft ore boxes out of wood
    • -
    • Skull helmets are now proper helmets
    • -
    • Survival autoinjectors tweaked
    • -
    • Survival autoinjectors have 15 units of teporone in them
    • -
    • Survival autoinjectors have double the epinpehrine and weak omnizine instead of saline glucose.
    • -
    • lavaland extract altered; it no longer heals tox or oxy, and heals slightly less brute and burn, but has nearly halved the metabolization rate and has a less harsh overdose
    • -
    • Fixes airlocks spamming their open and close when you stand in them
    • -
    • Fixes overriden door timers not working
    • -
    -

    Fox McCloud and FullofSkittles updated:

    -
      -
    • Changes the Venus Human Flytrap sprite
    • -
    -

    Ionward updated:

    -
      -
    • Adjusted Greys uniforms and backpack sprites.
    • -
    • Added a bunch of Drask masks and glasses.
    • -
    • Added God Eye sprites for Greys, Drask, and Vox.
    • -
    -

    JKnutson101 updated:

    -
      -
    • Issue where Emergency NanoMed Vendors required Medical ID to Access.
    • -
    • Added the ability for cyborgs with zero battery to use the 'succumb' verb.
    • -
    -

    Markolie updated:

    -
      -
    • Players now have thirty seconds instead of just five seconds to select if they want to be somebody's butler through a die of fate roll.
    • -
    • The Netherworld portal is now properly destroyed upon being killed. In addition, its max health is now equal to its starting health.
    • -
    • The iron ore sprite that shows up when using the miner scanner no longer has a background, making it blend in better with the actual rock.
    • -
    • Tightening the bolts of a falsewall now works properly.
    • -
    • Deconstructing plating now requires it to be unfastened using a screwdriver first, in order to prevent it from being accidentally deconstructed with a welder.
    • -
    -

    Quantum-M updated:

    -
      -
    • Minor grammar edits to the text that tells you that your thirst is dealt with but no blood power is given. balance: Vampires are no longer able to drink get power from ckeyless humanoid monkeys, they will now need to hunt down actual characters with ckey to get power.
    • -
    -

    Shadow-Quill updated:

    -
      -
    • Mass drivers now need two rods/cable coil instead of three to construct.
    • -
    • The RD's office door can now be opened by the RD, instead of by just the Captain.
    • -
    • Science lockdown can now only be (de)activated by the RD, instead of any scientist.
    • -
    • Using a health analyzer in-hand will switch the verbosity.
    • -
    • You no longer have to unscrew a plating to repair it.
    • -
    • The shivering symptom in virology now properly chills people.
    • -
    -

    SteelSlayer updated:

    -
      -
    • Wizard rounds now end if all wizards and apprentices are either dead, inside cyborgs, or in MMIs
    • -
    • Re-enabled the wizard's hud. Wizards can now see their own antag icon along with seeing other wizard's and apprentice's icons
    • -
    • When a cult sacrifice target leaves the round via cryo, the game will reassign a new target for them
    • -
    • Added an alarm sound that plays for cultists when their sacrifice target leave the round via cryo
    • -
    • When a cult sacrifice target leaves the round via cryo, the game will update every cultist's notes to reflect the change
    • -
    • Adds a new verb named "Toggle Health Scan" to the ghost tab. While toggled on, ghosts can perform health scans on humanoids and cyborgs by left clicking on them
    • -
    -

    TDSSS updated:

    -
      -
    • syndicate fax machine to lavaland syndie base.
    • -
    • syndicate lavaland base self destruct now requires syndie access.
    • -
    • moved headsets in lavaland syndie base.
    • -
    • Gave the HoP fax long-ranged faxing capabilities.
    • -
    • midround event spawned xeno larva now need less time to grow up and evolve.
    • -
    • cult talisman got unique icons to tell them apart
    • -
    • mining hardsuits come with helmets now again
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Whether you join the ERT is no longer determined by how fast you click "yes" on the prompt.
    • -
    • Drag and drop support and 20 seconds to pick ERT role instead of 15
    • -
    • Fix extra newline after field and disable Github Flavored Markdown in papers (normal markdown still works)
    • -
    • autogenerated papers no longer appear as HTML code
    • -
    • message window links added to PM send receipt
    • -
    • Many shuttle flight directions fixed
    • -
    -

    TheSardele updated:

    -
      -
    • All-In-one Grinders can now be constructed and upgraded
    • -
    • All-In-one Grinders now produce more reagents when upgraded.
    • -
    • Icon for cybernetic eyes
    • -
    • Sleeping while drunk no longer makes you more drunk.
    • -
    -

    dovydas12345 updated:

    -
      -
    • Fixes being able to pick up chairs and stools when you have items in both hand or when you don't have hands.
    • -
    • Adds a ERT shuttle console which is accessible to ERT members
    • -
    -

    farie82 updated:

    -
      -
    • Rigging a crate now doesn't delete your coil stack anymore but instead uses 15 of it. Borgs can use it safely again
    • -
    -

    kazboo updated:

    -
      -
    • adjusts the hierophant blast layer to make for it to always be below the effect. this should be the case already due to mouse_opacity, though for some unknown reason, it just doesn't work sometimes, so this should fix it.
    • -
    - -

    12 August 2019

    -

    AffectedArc07 updated:

    -
      -
    • Panic Bunker
    • -
    -

    Allfd updated:

    -
      -
    • Panthers can now see in the dark.
    • -
    -

    Arkatos updated:

    -
      -
    • You can ctrl-click any action button to lock/unlock its position
    • -
    • All actions buttons now start with their position locked
    • -
    -

    Citinited updated:

    -
      -
    • Mappers have a new tool that creates a fully functional cycling airlock.
    • -
    -

    CornMyCob updated:

    -
      -
    • The cursed heart you get from necropolis chests is now the one that heals you.
    • -
    -

    Couls updated:

    -
      -
    • Diagonal movement
    • -
    • Input subsystem(numpad targetting, press numpad 8 multiple times to target eyes and mouth, numpad 6 or 4 to target arms and press them again to target hands and numpad 1 or 3 to target legs and press them again to target feet) taken from https://github.com/tgstation/tgstation/pull/32751
    • -
    • change confused status to have you move diagonally randomly in the direction you're headed if not too confused(now you can drunkenly walk down the hall)
    • -
    • clients are now children of datums like everything else in BYOND taken from https://github.com/tgstation/tgstation/pull/20394
    • -
    • AZERTY and numpad targetting preferences
    • -
    • Reworks the biohazard event to have a chance of giving a randomized advanced disease with 6 varying symptoms instead of a preset disease.
    • -
    • change how bone breakage is calculated
    • -
    • can now butcher koi for salmon meat
    • -
    • adds a line to alert people as to why they're not getting blood from the monkeys
    • -
    • The vampires are finally off their monkey diet, theycan now suck blood from players and humanized monkeys
    • -
    • Symptoms are now correctly generated for level 7 biohazards
    • -
    • Borgs can now cycle modules with X again
    • -
    • Ahelp message is less confusing
    • -
    • F2 (say) F3(ooc) F4(me) buttons have been restored tweak:when numpad targetting is off you can use numpad 1-4 to change intents tweak:pressing shift before any of the intent buttons doesn't change intents(for people with shift+1-4 macros) tweak:backspace now sets the focus to the chat bar
    • -
    • fixes the runtime caused by running keyloop for clients
    • -
    • Preferences not saving properly
    • -
    • issue with preload_rsc
    • -
    • Restore hotkey mode
    • -
    • Q no longer drops items as a cyborg on AZERTY mode
    • -
    • Automatically offload ore you're carrying to an orebox you're dragging
    • -
    • typing indicators show up again
    • -
    • TG waddle component, clowns can now optionally waddle, penguins always waddle. Ctrl Click clown shoes in hand to toggle waddling
    • -
    • Added invismin macro back to F9
    • -
    • stealthmin macro removed from F9
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Fixes a bug that would cause ghosts to teleport their bodies sometimes
    • -
    -

    Dave-TH updated:

    -
      -
    • The syndicate uplink is now complete with a new spooky background. Very neat!
    • -
    -

    DoctorDrugs updated:

    -
      -
    • Adds additional roundstart miner slots and the additional gear required for them to do their jobs
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes being able to sharpen toy double-bladed energy swords
    • -
    -

    IAmBigCoat updated:

    -
      -
    • Added explosion warnings to medbeams, because medbeams can cause explosions. DON'T CROSS THE BEAMS!
    • -
    -

    Ionward updated:

    -
      -
    • Fixed vox jester uniform not appearing correctly.
    • -
    • species specific fit underwear for greys
    • -
    -

    KasparoVy updated:

    -
      -
    • Re-adds the ability to see in the dark. Adds overlays for each level of darksight (>=8,7,6,5,4,3,<=2).
    • -
    -

    Kyep updated:

    -
      -
    • Round time (h:mm) and station security level (green/red/blue/etc) are now visible on our server hub entry.
    • -
    • Round time is now visible to all player-controlled mobs in their status panel (including simple animals).
    • -
    • Admins using the 'MOST' attack log setting no longer see player-v-NPC combat, or any attack logs generated in the admin room, admin testing area, thunderdome arena, or lavaland syndicate base. Prevents admins being spammed with attack logs.
    • -
    • Heads of department may now issue department-specific medals to members of their department.
    • -
    -

    Markolie updated:

    -
      -
    • Humans and mice that are secretly blobs now have an antagHUD icon.
    • -
    • All hivemind languages now display follow links to ghosts.
    • -
    • Announcements, whispers (with ghost ears) and cultist messages are no longer displayed in the lobby.
    • -
    • The sentience event no longer triggers a huge number of ghost polling messages.
    • -
    • When xenomorphs are damaged, their health HUD now updates properly.
    • -
    • Custom title for ghost notifications now work properly.
    • -
    • Fixed double admin commands in the grenade priming message.
    • -
    • Ghosts will now always see whispers/zero pressure speaking if they're on the screen with the mob speaking.
    • -
    • Ghosts with ghost sight enabled will no longer see emotes from clientless mobs.
    • -
    • The prison labor point system has been refactored so it works properly.
    • -
    • Plating can now be removed (exposing the baseturf) using a welder.
    • -
    • All remaining Lavaland ruins have been ported over from /tg/.
    • -
    • All chairs on shuttles have been replaced with brand new shuttle chairs.
    • -
    • Tribal splints have been added to the game, which can be crafted with two bones and one piece of sinew.
    • -
    • The Lavaland Syndicate base now has a defibrillator and mounted defibrillator. The animal hospital now has a mounted defibrillator.
    • -
    • The Ash Walker storage area now comes with an advanced medkit instead of a regular one and one set of medical splints. It also comes with aloe vera, comfrey and wheat seeds.
    • -
    • The water tank in the Ash Walker nest has been replaced with a puddle.
    • -
    • The items in vending machines on the beach ruin and animal hospital are now free.
    • -
    • Fixed an issue where slimes wouldn't take damage from water in space.
    • -
    • It is no longer possible to unanchor the surivval pod storage units.
    • -
    • Drinking from a beaker now only applies the effect of five units of the ingested chemical, instead of the entire volume of the beaker.
    • -
    • Resolved an issue where beaker attack logs were reversed.
    • -
    • Moving through portals very quickly no longer breaks movement.
    • -
    -

    Quantum-M updated:

    -
      -
    • New sprites for vampires being "hungry".
    • -
    • New sprite for vampire usable blood count.
    • -
    • New sprites for the safety muzzle.
    • -
    • Safety muzzle (aka the anti-bitting one) can no longer be resisted out of.
    • -
    • Vampires can now suck blood from monkey mobs (e.g. monkeys, stoks, etc.) for sustenance but do not get blood power points.
    • -
    • RnD is no longer able to print out any telescience boards.
    • -
    -

    SteelSlayer updated:

    -
      -
    • Gives vampire thralls an objective, which can be viewed in their notes
    • -
    • Increases the size of the enthralling message seen by newly created vampire thralls
    • -
    • Vampire thralls are now stunned briefly (about 3 seconds) upon being enthralled
    • -
    • The AI's robot control window now allows you to see and interact with available bots again
    • -
    -

    TDSSS updated:

    -
      -
    • cult teleport runes and similar powers now work on z levels 9-12
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Inputs sanitized
    • -
    • autocomplete input mishandling single quotes (you can teleport to Wizard's den now)
    • -
    • newlines not working in CC announcements
    • -
    • players not being able to send single quotes in ahelps or PMs
    • -
    • robots not being able to pick their name
    • -
    -

    TheSardele updated:

    -
      -
    • Lowers throwforce of drinking cartons from 15 to 0
    • -
    • Bees no longer inject venom when nuzzling
    • -
    • Sec pod pilots can now spawn with the loadout security armbands
    • -
    • It is no longer possible to raise zero to -infinity fingers using the *signal emote
    • -
    • Earmuffs now properly protect you from vampire screeches no matter what you are wearing on your other ear
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Reworded permanent bans to non-expiring bans.
    • -
    • Door remotes now add to admin-only hidden fingerprint list
    • -
    • Gave plastic surgery to line 364 of atoms.dm
    • -
    -

    and DominikPanic updated:

    -
      -
    • Limits IC notes
    • -
    -

    datlo updated:

    -
      -
    • Free Golems are now a lavaland ruin spawn instead of a space ruin spawn.
    • -
    • Free Golems must now purchase their shuttle board for 2000 mining points before being able to fly their shuttle.
    • -
    • Added a shuttle recall console at the golem lavaland spawn point so that golems can always recall the shuttle back to lavaland
    • -
    • The Free Golem Ship can now move to the Construction Site, the Derelict, or back to their Lavaland spawn.
    • -
    • The Free Golem Ship has been redesigned with an open floor plan, removing most of its interior walls for extra space.
    • -
    • Free Golems no longer get a free kinetic accelerator on their ship.
    • -
    • New crit species with below -100 health will be considered dead for hijack purposes, and will not interrupt a shuttle hijack attempt.
    • -
    • Fix some cases of traitors getting conflicting objectives, such as assassinating and protecting the same target.
    • -
    -

    farie82 updated:

    -
      -
    • Beepsky will now respect your disguise again. No more looking right through that gasmask
    • -
    • Medical and security HUDs now use the correct way to identify somebody. They will see the same as you do on your screen.
    • -
    • You will now get a job icon in the sec HUD when you use your PDA as ID. It'll use the PDA's assigned job.
    • -
    • Ticket takes now ask for confirmation if you want to take an already assigned ticket.
    • -
    • Blindfolds are now craftable from 3 cloth. For those vampire prisoners you want to keep in check
    • -
    • Empty beaker button from the PANDEMIC is now replaced with Empty and eject beaker
    • -
    • List AFK players is now a verb for admins to use
    • -
    • Adds the AFK auto cryo system. By default it won't affect players unless they activate it themselves by setting the preference in their game preferences tab.
    • -
    • The syndicate can't use meta warfare no more. Advanced pinpointers no longer crash the server
    • -
    -

    iantine updated:

    -
      -
    • Mouse suicide
    • -
    -

    improvedname updated:

    -
      -
    • adds lasagna
    • -
    -

    kazboo updated:

    -
      -
    • changed the display name shown to a player upon being frozen in a manner that only the admins ckey is displayed, not the character name along with it
    • -
    - -

    08 July 2019

    -

    Arkatos updated:

    -
      -
    • Clicking on a health doll icon will now check you for injuries
    • -
    • Rechargers now show their contents and charge status on close examine
    • -
    • Smartfridge will now try to put an item in your hands after vending, if able
    • -
    -

    AzuleUtama updated:

    -
      -
    • The cybernetic implant bundle can no longer be bought by traitors.
    • -
    -

    Citinited updated:

    -
      -
    • Alt-clicking the RPD now brings up a radial menu with rotate, flip, and delete modes accessible. The main interface remains unchanged.
    • -
    • Writing in blood can't be done while dead or incapacitated any more
    • -
    • You can't write stuff in blood at a distance any more
    • -
    -

    Couls updated:

    -
      -
    • lantern sprites
    • -
    • typo in msg
    • -
    -

    Improvedname updated:

    -
      -
    • Explorer suits now properly hide tails
    • -
    -

    JKnutson101 updated:

    -
      -
    • Fixed Construction Permits deleting themselves prematurely.
    • -
    -

    Kyep updated:

    -
      -
    • fixed a bug with biogenerator.
    • -
    -

    Markolie updated:

    -
      -
    • Ghosts can now see all PDA messages when enabled through a preference setting.
    • -
    • The Mask of Nar'Sie transformation buttons have been removed, as the mask was removed a long time ago.
    • -
    -

    Shadeykins updated:

    -
      -
    • Changed Quarantine, NT Default, Aggressive, and Corporate AI lawsets. balance: Reduced the ability for NT Default AI's to murder people just because.
    • -
    • Removed several redundancies in Aggressive lawset.
    • -
    • Fixed a few subject-verb disagreements (is -> are).
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • paper supports markdown as well as pencode
    • -
    • Autocomplete for ghost buttons
    • -
    • PMs window scrollable
    • -
    • Fix a bug where a player who reconnects is still shown as disconnected
    • -
    -

    datlo updated:

    -
      -
    • Fix an antag rolling exploit.
    • -
    - -

    30 June 2019

    -

    Crazylemon64 updated:

    -
      -
    • SDQL2 no longer allows a macro argument
    • -
    - -

    28 June 2019

    -

    AffectedArc07 updated:

    -
      -
    • SSticker
    • -
    • You can no longer force-start a round unless its fully initialised.
    • -
    • Tweaks some preference orders
    • -
    • Moved a global define
    • -
    -

    Akatos updated:

    -
      -
    • Smartfridges now visually show approximate number of items inside
    • -
    -

    Arkatos updated:

    -
      -
    • Ragin' Mages gamemode should now be playable without any major issue
    • -
    • Slaughter and Laughter Demons no longer have duplicit objective shown at the Round End
    • -
    • Laughter Demon is now properly called Laughter Demon instead of Slaughter Demon in the role polls
    • -
    • Improved wording and fixed mistakes in Wizard and Ragin' Mages gamemodes
    • -
    • Wizards are now properly polled in the Ragin' Mages gamemode
    • -
    • You can no longer buy Summon Ghosts spell in the Ragin' Mages gamemode
    • -
    • You can no longer buy Bind Soul spell in the Ragin' Mages gamemode
    • -
    • Deck of tarot cards renamed to Guardian Deck in the Wizard spellbook
    • -
    • Rituals and Challenges categories merged into one in the Wizard spellbook
    • -
    • Laughter Demon is now slightly weaker compared to the Slaughter Demon
    • -
    • Bottle of Ooze now creates a magical morph instead of a normal one. Magical morph is capable of casting smoke and forcewall spells.
    • -
    • Visible ghosts will now get a special description about their visibility
    • -
    • Removed Cursed Heart from the Wizard spellbook
    • -
    • Changeling verbs replaced with action buttons
    • -
    • Changeling ability descriptions updated
    • -
    • Added custom icons for changeling action buttons
    • -
    • Added movement animation for mice, chickens and killer tomatoes
    • -
    • Added inhand sprite for eggbox
    • -
    • Added inhand sprites for all types of soaps
    • -
    • Added inhand sprite for small parcel
    • -
    • Added inhand sprite for sechailer
    • -
    • Added inhand sprite for bag of holding
    • -
    • Added new system for outputting contents of smartfridges
    • -
    • Blob split consciousness ability now requires you to directly target a node you want to turn into another sentient overmind instead of selecting a nearest one
    • -
    • Fixed and improved some descriptions regarding Blob offspring
    • -
    • Fixed a case where ghosts had an extra ghost icon visible on them
    • -
    • Fixed a case where some ghosts were too bright
    • -
    • You are now unable to swap forms with another changeling
    • -
    • You can no longer hiss while muzzled
    • -
    • Upon purchasing Augmented Eyesight changeling ability, changeling immediately receives passive version of the ability
    • -
    • Changelings in the lesser form can now toggle Augmented Eyesight ability
    • -
    • Changelings are now removed properly via Traitor Panel
    • -
    • Changelings do not get their action buttons bugged when using Swap Forms ability now
    • -
    • Action buttons should update their cooldown statuses more reliably
    • -
    • Changelings should now correctly receive their action buttons
    • -
    • Changelings now do not steal action buttons from other changelings
    • -
    • Added new Boo! spell icon
    • -
    -

    Christasmurf updated:

    -
      -
    • Fixes a random pixel on the leather shoes
    • -
    -

    Citinited updated:

    -
      -
    • Boo affects APCs again
    • -
    • Boo no longer fully charges when you enter your corpse
    • -
    • The button to close radial menus is much more obvious and easily-clickable now
    • -
    • Destroying a disposals trunk should no longer occasionally delete things held inside it.
    • -
    • Fixes conveyor belts not moving items spawned via an autolathe. (And other possible behaviours when machines switch between speed and normal processes)
    • -
    • Ports liquid dispenser sprites from tgstation.
    • -
    -

    Couls updated:

    -
      -
    • Only names from the manifest will be used for syndicate code phrases
    • -
    • randomly generated people names from syndicate code phrases
    • -
    • Medical category to exosuit fabricator with implants and cybernetics
    • -
    • t-t-t-typo!
    • -
    • codephrase names no longer appear blank
    • -
    -

    EmanTheAlmighty updated:

    -
      -
    • Admin made cultists can now properly summon their Gods if the gamemode wasn't initially Cult.
    • -
    -

    Evankhell561 updated:

    -
      -
    • Portable Seed Extractor designon the protolathe.
    • -
    -

    Fethas updated:

    -
      -
    • Fixes an oversight from the lavaland port invovling Laz injectors and sentience typing that didn't carry over from tg.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Future proofs the coming Ticker subsystem
    • -
    • Removes the Process Scheduler
    • -
    -

    Improvedname updated:

    -
      -
    • Cargo miner starter kit crate will no longer include a ID
    • -
    -

    Kyep updated:

    -
      -
    • Ported XKeyScore from TG.
    • -
    • New system to securely link ingame/forum accounts
    • -
    • Removed old insecure 'link discord account' system
    • -
    • unanchored vending machines will no longer generate a runtime error when throwing products at people.
    • -
    • Disarming/grabbing a door with IDSCAN disabled no longer results in a can_admin_interact runtime error.
    • -
    • Terror Spiders no longer trigger their special attack when nuzzling someone on help intent.
    • -
    -

    Markolie updated:

    -
      -
    • Chameleon items now use the appropriate species icon.
    • -
    • Lighting now respects color blindness again.
    • -
    • pAI flashlights now work properly.
    • -
    • Rotatium can now be created properly.
    • -
    • Ghosts can now transition through space again. This is now done by clicking on the edge of space.
    • -
    • Added custom explorer gas mask sprites for Grey/Drask.
    • -
    • Added a lantern to the Hermit cave.
    • -
    • Added a bone setter, bone gel, FixOVein, sterile masks and sterile gloves to the Lavaland Syndicate base.
    • -
    • The pickaxes on the Lavaland labor camp have been replaced with safety variants. The flashlights have been replaced with lanterns.
    • -
    • Fixed many species missing sprites for explorer gas masks and jumpsuits. They now use the humans icons until we have custom sprites.
    • -
    • Resolved an issue with piping not working on the Lavaland mining bases.
    • -
    • Fixed all items being free in the mining vendor.
    • -
    • Fixed improper wiring to the turbine in the Lavaland Syndicate base.
    • -
    • Fixed the Lavaland Syndicate base oxygen sensor not working.
    • -
    • Moved the pipe dispenser in the Lavaland Syndicate base so it doesn't clip with tables.
    • -
    • Fixed the Lavaland Syndicate base incinerator doors not working.
    • -
    • Ash Walkers now once more have fine manipulation. Their lack of fine manipulation caused unintended side effects (such as them being unable to mine).
    • -
    • Ash Walkers (and other ghost spawner roles) can no longer be antagonist targets or become antagonists through the antagonist creation.
    • -
    • Fixed the Lavaland Syndicate base incinerator buttons not working.
    • -
    • Fixed the Syndicate communication agent spawning with a broken voice changer mask.
    • -
    • Fixed the Disk Compartmentalizer not having a sprite.
    • -
    • The Ancient Goliath now has a small chance of spawning instead of regular goliaths.
    • -
    • Survival capsules now have a NanoMed.
    • -
    • Water bottles now behave as glass containers.
    • -
    • The behaviour of glass reagent containers has changed. When used on non-mobs, contents will now only be spilled on harm intent. When used on mobs, on any intent aside from harm the contents will be fed to the mob like regular drinks. On harm intent it will still be spilled.
    • -
    • Hairless hide can now be made wet using most sources of water (minimum volume of 10), instead of just washing machines.
    • -
    • Added some additional offstation role checks to ensure ghost spawner roles don't become antagonists, are kidnap targets or are counted towards station goals.
    • -
    • Fixed some piping in the Lavaland Syndicate base incinerator and made sure the vault door starts locked.
    • -
    • Fixed the Lavaland swarmers getting stuck on propulsion.
    • -
    • Fix goliath tentacles sometimes being left behind.
    • -
    • The walls around the Lavaland Syndicate base turbine have been coated, to prevent them from starting a plasma fire in the base.
    • -
    • Syndicate agents can now access the air alarms on the Lavaland Syndicate base.
    • -
    • Air alarm control computers can no longer access the air alarms on the Lavaland Syndicate base.
    • -
    • Fixed the disk compartmentalizer/drying rack missing a sprite under certain circumstances.
    • -
    • Fixed the Lavaland Syndicate base triggering atmospherics alerts.
    • -
    • You can now properly place tiles on basalt.
    • -
    • An exploit with the sheet multiplier has been fixed.
    • -
    • Portals can now be activated by clicking on them with or without an object. Ghosts can now also click on them to be taken to their destination.
    • -
    • Portals now warn admins when they are used to teleport megafauna.
    • -
    • The singularity can now eat basalt and chasms on Lavaland. They get turned into lava.
    • -
    • AI swarmers will no longer get stuck on effects (such as blood).
    • -
    • Fixed the spectral blade turning all ghosts visible.
    • -
    • Fixed a runtime with assigning outfits to mindless mobs.
    • -
    • Fixed certain alarms triggering despite being outside of station contact and the Syndicate base still triggering fire alarms.
    • -
    • Fixed being unable to put the wormhole jaunter in the belt slot.
    • -
    • Fixed the disk compartmentalizer not accepting disks.
    • -
    • Gutlunches and Gubbucks will now reproduce properly.
    • -
    • The necropolis chest cult clothing drop no longer spawns with a cult hood as well, as that's part of the suit itself.
    • -
    • Goliath steaks can now be eaten properly.
    • -
    • Fixed a stray light on the beach ruin.
    • -
    • Lavaland ruins should no longer spawn on the Labor Camp.
    • -
    • Ancient goliaths will now properly randomly spawn tentacles.
    • -
    • The labor camp will now spawn properly with a processing console.
    • -
    • Water turfs in the beach ruin (and other water turfs that previously didn't do so) will now properly apply water to you.
    • -
    • Ash flora is now anchored.
    • -
    • Gutlunches will now eat properly.
    • -
    • The tesla can no longer travel through wormholes.
    • -
    • Fixed an issue with honkbot construction.
    • -
    -

    Markolie and Ionward updated:

    -
      -
    • Added Tajaran, Vulpkanin, Unathi and Vox sprites for the explorer gas mask (thanks to Ionward!)
    • -
    • Added custom species sprites for the explorer suits and hoods (thanks to Ionward!)
    • -
    • Added missing surgical tools and a pet vendor to the animal hospital.
    • -
    • Added a custom cigarette vendor to the beach biodome ruin.
    • -
    • Added an autolathe and RPD to the Lavaland Syndicate base. Also added a custom cigarette vendor and made the vendors not charge money.
    • -
    • Added tiny fans to the mining base and labor camp exist.
    • -
    • A separate jobban for ghost roles has been added.
    • -
    • The alternative sink now has directional sprites. This resolves an issue with shelters having sinks facing the wrong way.
    • -
    • Fixed the Syndicate sleepers on the Lavaland Syndicate base pointing the wrong way when a ghost role spawns in.
    • -
    • Fixed Lava being removed by the staff of lava not working. Also added a missing warning effect when the staff is turning regular turf into lava.
    • -
    • Fixed random bookcases not spawning books (hopefully).
    • -
    • Fixed surgical drapes not having a sprite.
    • -
    • Fixed being unable to modify the GPS tag of shelters.
    • -
    • Fixed the Lavaland swarmers not eating anything.
    • -
    • The ash drake swoop attack is no longer incredibly loud.
    • -
    • The Syndicate base self-destruct is now much more powerful and capable of destroying the entire base.
    • -
    • The flavor text of Ash Walkers and Syndicate operatives now clarifies what they can('t) do.
    • -
    • Ash walkers can no longer use machinery.
    • -
    -

    Ported by Markolie and CornMyCob. Developed by many /tg/ coders updated:

    -
      -
    • The mining asteroid has been replaced with Lavaland.
    • -
    -

    Shadeykins updated:

    -
      -
    • Fixes a paper exploit.
    • -
    • Fixes rogue pixels on breath masks/gas masks for Plasmamen.
    • -
    -

    TDSSS updated:

    -
      -
    • Vampire rejuv wakes you up if you're asleep now
    • -
    • Cling epinephrine wakes you up if you're asleep now
    • -
    • Sling glare popup no longer lists invalid targets for glaring
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Messages window (My PMs in OOC tab)
    • -
    • You no longer have to wait on others for ERT spawning
    • -
    • Admin jobs no longer announced
    • -
    -

    Terilia updated:

    -
      -
    • Added the Donksoft sniper into the Trader spawnpool.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Changed admin take ticket color from neon green to Asay pink
    • -
    • Manual bans now auto-note
    • -
    • Stops projectiles using the legacy system such as emitters from hurting shield blobs due to an exploit where it would always hit or go through.
    • -
    -

    craftxbox updated:

    -
      -
    • Highlight string uses regex
    • -
    • Removed jquery mark
    • -
    -

    datlo updated:

    -
      -
    • The Syndicate will no longer hire golems as agents.
    • -
    • Banana juice and Banana honk will now heal everyone with the Comic Sans mutation instead of checking for the clown job
    • -
    • Nothing will now check if the player has an active vow of silence instead of checking for the mime job
    • -
    • Ghosts will no longer get the wrong role offered when a nukie spawns a borg and will properly be informed whether they will spawn as a nuke ops or a syndi cyborg.
    • -
    -

    dovydas12345 updated:

    -
      -
    • Fixes cryopod removing ambulance, secway keys
    • -
    • Fixes cryopod recovering the invisible headpocket item
    • -
    -

    farie82 updated:

    -
      -
    • Can't use cuffs now while you have antidrop
    • -
    • can_equip now checks if you have the limbs required to equip something
    • -
    • Reverts the string highlighting done by regex
    • -
    -

    iantine updated:

    -
      -
    • Skrell *warble emote
    • -
    -

    uc_guy updated:

    -
      -
    • Theft objective locations hints now ignore the Centcomm Z level.
    • -
    • Adv. Pinpointer no longer targets items in Centcom Z level.
    • -
    • Fixed "Venus Human Traps" being invisible.
    • -
    - -

    10 May 2019

    -

    AffectedArc07 updated:

    -
      -
    • Removes an infinite loop in the code
    • -
    • Removes unused code
    • -
    • Captains display case now actually has captains thumbprint lock on it
    • -
    • Morgue updates happen slightly better now
    • -
    • Fixes a minor NTTC issue
    • -
    -

    Arkatos updated:

    -
      -
    • Patch Pack is now craftable with a cardboard, costs 2 cardboard sheets.
    • -
    • Examine tooltip delay increased slightly
    • -
    • Examine tooltips now work properly on items in storage
    • -
    • Full toolbelts now spawn with randomly a colored cable coil
    • -
    • Added inhand sprites for belts
    • -
    • Species name now shows in a species theme color on examine
    • -
    • Added 4 new plushies
    • -
    -

    Couls updated:

    -
      -
    • necromantic stone now forces the ghost back into the body as a skeleton
    • -
    • allow skeletons to give up their bodies and offer control to ghosts
    • -
    -

    Crazylemon and Fox McCloud updated:

    -
      -
    • Fixes toggles not properly saving
    • -
    -

    EvadableMoxie updated:

    -
      -
    • Added the Nanotrasen Hospital Vessel Asclepius, able to be deployed by admins.
    • -
    • Admin shuttle now requires ERT clearance instead of admin clearance.
    • -
    • Admin shuttle now has a navigation computer and tiny fans at the airlock.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes a few instances generating log spam relating to z-level tracking
    • -
    • Fixes weird behavior with ghosts being able to trigger a few things by crossing over them
    • -
    • Fixes drifting ghosts
    • -
    -

    Ionward updated:

    -
      -
    • Updated the cautery sprite!
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds a verb to eyewear you can use to adjust them so they appear above or below masks. Discover interesting combinations and enjoy a cool look.
    • -
    -

    Kyep updated:

    -
      -
    • Trying to latejoin a round with no open job slots now results in an informative error message, rather than broken-looking blank window.
    • -
    • Added new bonus loadout items for higher-tier patrons. Also gave admins access to patron items, and ensured that during custom events, you see the custom event announcement when you connect.
    • -
    • You can now identify when someone is using internals from a tank in their pocket, without having to remove the tank.
    • -
    • punching a windoor no longer generates a runtime error.
    • -
    • cryogenic_liquid/envenomed_filaments blobs no longer generate runtimes when their blob special attack hits mobs that do not process reagents
    • -
    • fixed $5+ donors not getting extra loadout points.
    • -
    -

    Markolie updated:

    -
      -
    • Ambient occlusion had been added to the game. This represents a shadowy effect on most objects. It can be turned off through the game preferences menu.
    • -
    • Our lighting system has been updated to /tg/'s latest version. Hopefully this means we'll have less lag later in the round.
    • -
    • Night vision has been modified. There are now three levels of night vision. Certain creatures that were previously able to toggle night vision can now switch between all levels. Thermals now give some night vision.
    • -
    • Mesons now no longer fully light up non-visible turfs. It uses slight darkness instead.
    • -
    • Syndicate operatives may now purchase a chameleon bundles (2TC), which allows them to disguise not just their jumpsuit, but all of their equipment. They can change individual clothing as well as the outfit as a whole.
    • -
    • When using a voice changer, NTTC will no longer default to an "Unknown" job: it'll still use the assignment on your card to prevent meta-gaming. Always combine a voice changer and a Syndicate ID.
    • -
    • Admins with advanced admin interaction toggled on can now interact with the small airlock buttons.
    • -
    • The steel_rain runtime fix has been re-applied.
    • -
    • The propulsion on the admin shuttles has been fixed. The shutters on the south side of the hospital shuttle now point the right way.
    • -
    • Nuclear Operative reinforcements now spawn with a properly counted agent designation.
    • -
    • Fixed an issue where a mob's sight wouldn't update properly in certain cases, such as being revived.
    • -
    • Resolved an issue where the lobby would be bright white when being sent back.
    • -
    • Resolved an issue where the ambient occlusion preference wouldn't update properly in the lobby.
    • -
    • Resolved an issue where clicking on a windoor would no longer prevent it from auto-closing.
    • -
    • When a nuclear operative chooses to play as the borg instead of operative using the cyborg teleporter, ghosts will now be informed of this in their acceptance message.
    • -
    • Resolved an issue where cameras couldn't take pictures of non-dynamic lighting areas, such as the holodeck or space.
    • -
    • Resolved an issue where mobs would appear above water.
    • -
    • Resolved an issue where radiation storms would make lighting invisible in space.
    • -
    • Simple mobs no longer retain their X-Ray upon being revived.
    • -
    • Applying brute/fire damage through the View Variables menu for non-humans has been fixed.
    • -
    • NTTC regex has been disabled due to an urgent security issue.
    • -
    -

    Mitchs98 updated:

    -
      -
    • You can now order a Pig Crate from Cargo for 25 points.
    • -
    -

    TDSSS updated:

    -
      -
    • typo on sst shuttle console
    • -
    • opening turret covers now stay on top of their turret.
    • -
    -

    Twinmold93 updated:

    -
      -
    • Adds Server Time to the Status Tab for Admins.
    • -
    -

    farie82 updated:

    -
      -
    • Transforming into another species will now retain the items correctly. Example clings will keep their armblades and they won't get stuck with a non existing armblade they can't put back
    • -
    • Devour and regurgitate use forcemove now. So no being buckled inside an alien
    • -
    -

    fludd12 updated:

    -
      -
    • Project Mind now has a corollary ability, Scan Mind. Now communication can be two-way!
    • -
    -

    variableundefined updated:

    -
      -
    • Simple animals actually use the new subsystem now
    • -
    • What was NPCAI is now renamed to NPCPool - Its the functional equivalent of what it is in tg
    • -
    • Simple animals actually run on subsystem instead of a process now.
    • -
    • idleNPCpool has been added reducing performance impact of hostile simple animals
    • -
    • NPCAI Process (That run both SNPC and SimpleAnimals) that was somehow left out by me
    • -
    • SNPC & assocaited NPCAI Subsystem
    • -
    • Some of space hotel's functions.
    • -
    • Bodysnatch gland.
    • -
    • process_ai has been deprecated
    • -
    - -

    02 May 2019

    -

    AffectedArc07 updated:

    -
      -
    • ssMapping
    • -
    • Gateway and space ruins are now loaded with ssMapping
    • -
    • Master Controller
    • -
    • Darkmode chat department colors match NTTC theming now
    • -
    • SSvotes
    • -
    • SSradio
    • -
    • SSevents
    • -
    • SSholiday
    • -
    • We no longer check if its Christmas every tick. Dont ask.
    • -
    • SSalarms
    • -
    -

    Arkatos updated:

    -
      -
    • Shadowlings now have a slightly bigger colored text when speaking in the Shadowling Hivemind
    • -
    • Replaced title2.ogg music with a higher quality version
    • -
    • Shield Blobs automatically spawned around Blob Cores now give no refund upon removing. No freebies.
    • -
    • Added new Wizard Spell - Summon Ghosts! This nefarious spell will make all ghosts visible to the living. Be careful though, as while they cannot harm you in any way, they might prove a bit.. annoying. Costs 0 points in the Wizard's spellbook.
    • -
    • Ghosts now orbit around their followed targets
    • -
    • Added new Shadowling Ability - Null Charge! This new ability allows Shadowling to completely drain an APC of it's power after a moderate delay. Shadowling must not be interrupted, or the whole process will fail.
    • -
    • Added custom icon for the Null Charge ability
    • -
    • Shadowling Drain Life ability removed
    • -
    • Added Observer HUD buttons for Jump to Mob, Orbit, Re-enter corpse, and Teleport
    • -
    • Added custom icons for Observer HUD buttons
    • -
    • Added Floorbot color variants. Different toolboxes will result in a differently colored Floorbots. One even might be a little stronger than others..
    • -
    • Added sprites of Floorbot color variants
    • -
    • Fixed incorrect amount of required floortiles for the Floorbot in the crafting tab
    • -
    • Added cancel button to Wizard teleportation scrolls
    • -
    • Added an option to grant Martial Arts via administrative Var menu
    • -
    • Toggling hardhat light on/off now correctly updates wearer's sprite
    • -
    • Added deathsound for Silicons
    • -
    • Dice will now roll when thrown
    • -
    • Added sound when adding or removing IDs from ID modification computers
    • -
    • Added cancel button to transfer amount from stack menu
    • -
    • Alt-click is a new shortcut to take a custom amount from stack
    • -
    • Added shortcuts for handling pumps, volume pumps, filters, and mixers. Ctrl-click these devices to turn them on/off and Alt-click them to set their output to maximum.
    • -
    • Added ability to rename pumps, volume pumps, filters and mixers with a pen.
    • -
    • Added sound for throwing bolas
    • -
    • Added hitsound for all types of bolas
    • -
    • Added AntagHUD to everyone at the round end
    • -
    • Circuit Boards now show their required components on examine
    • -
    • Revenants now have randomly generated flavor names
    • -
    • You can shift-click any action button to reset it's position. Alt-click on Hide Buttons will reset all action buttons to their default positions.
    • -
    • Pill Bottles are now printable in the Autolathe. You can find them in the Medical section, and each costs 80 metal and 20 glass to print.
    • -
    • Puts beakers in your hand upon eject from chemistry machines
    • -
    • Cardboard can now be made in the Biogenerator
    • -
    • You can now hotswap tanks in a canister or gas pump by clicking it with a new tank!
    • -
    • You can now also close a canister's valve and remove the tank inside it by alt-clicking it.
    • -
    • Added examine toolptips. Hover over any equipped or hold item for a little while and it will display the item description as a tooltip.
    • -
    • Ghost teleport verb will no locker flicker when used
    • -
    • Alt-click now opens and closes fire extinguisher cabinet
    • -
    • Fire extinguisher cabinet now properly updates it's sprite correctly when putting fire extinquisher inside the cabinet
    • -
    • Fire extinguisher no longer sprays when put into fire extinguisher cabinet with a safety off
    • -
    • Added sound for opening and closing fire extinguisher cabinet
    • -
    • Added new torch sprites
    • -
    • Torch light color is now orange instead of red
    • -
    • Torch sprite now correctly shows all inhand sprites
    • -
    • Blob Rally Spores power is now free to use
    • -
    • Blob mobs can no longer speak while being dead via Blob Broadcast
    • -
    • Blob structures now properly show working animation
    • -
    • Added new sprites for variants of Blob resource, factory and storage structures
    • -
    • Added inhand sprites for winter coats
    • -
    • Carps now spawn with a random color! There might even be some really rare ones..
    • -
    • Added carp color variants sprites
    • -
    -

    Arkatos and Paradise community: updated:

    -
      -
    • Added Tip of the round to a pre-game lobby
    • -
    • Added Show Custom Tip admin verb
    • -
    • Added Give Random Tip OOC verb
    • -
    -

    Citinited updated:

    -
      -
    • You can no longer turn transit turfs into foamed metal flooring.
    • -
    • Foamed metal floors have a sprite now.
    • -
    • Pipe dispensers (the big ones) now work again.
    • -
    • Cooldown on pipe dispensers reduced to 0.4 seconds, down from 1.5 seconds
    • -
    -

    CornMyCob updated:

    -
      -
    • The plasma cutter now cuts through multiple rock tiles.
    • -
    -

    CthulhuOnIce updated:

    -
      -
    • you can smell dead bodies, even if someone else shouldn't
    • -
    -

    Fethas updated:

    -
      -
    • Cluwne suits should no longer fall off cluwnes from being fat.
    • -
    -

    Fox McCloud updated:

    -
      -
    • CQC has been updated; a few combos are more powerful
    • -
    • cost increased to 13 TC
    • -
    • CQC is now nuke ops only
    • -
    • gloves of the north star restriction on CQC removed
    • -
    • CQC disarms will now take the item from your opponent
    • -
    • CQC blocks melee weapons and a couple of stun weapons and not everything now
    • -
    • Reagents will now adjust to the body temperature over time as opposed to all at once
    • -
    • Strange Reagent will work 25% of the time with TOUCH based reactions
    • -
    • Strange reagent will revive whether there's a ghost or not (can use SR on clientless mobs now, like monkies)
    • -
    • SR puts the occupant back in their body automatically
    • -
    • Cloners that eject their messes will now eject the unattached organs
    • -
    • the message for brain death will now properly and only occur when they have truly died from brain damage
    • -
    • Fixes being able to attain brain damage over 120
    • -
    • Updates nations. Updates nations so hard right into the void
    • -
    • Plasma fires should burn a bit faster now
    • -
    • Bleeding will now stop at the temperature at which cryoxadone heals
    • -
    • Fixes a few potential exploits with forcing chem, dust, and explosive implants activating with the deathgasp emote, prior to death
    • -
    • Tesla can't zap cameras and other disposal structures anymore
    • -
    • Simple mobs can now be shocked
    • -
    • Electrocution damage scales a bit more linearly up to its maximum potential instead of being heavily random
    • -
    • Fixes being able to shock yourself with TK, at range, on electrical equipment
    • -
    • simple mobs can now be shocked by the tesla and other sources
    • -
    • Fixes goats not attacking people
    • -
    • Goats will eat glowshrooms
    • -
    • Goats will eat full grown diona
    • -
    • Remapped toxins to be more compatible with the modern age
    • -
    • updates plasma and N2O sprites
    • -
    • Fixes not being able to look at a turf if it had plasma/N2O on it
    • -
    • cold turfs no longer become icy
    • -
    • Cryostylane makes turfs icy
    • -
    • Icy turfs are slippery; wear magboots to counteract the effect. Watch your head!
    • -
    • Fixes grammar of slipping on turfs; no more "you slipped on floor" or "you slipped on wet floor"
    • -
    • removes ponies
    • -
    • object and fast processing are now proper subsystems
    • -
    • Fixes multi-spawn blobs
    • -
    • Powersinks drain rate increased, but they also explode a bit sooner
    • -
    • Multitools display total power, load, and free power
    • -
    • Fix emitter sparks sparking at the location of emitters where biult as opposed to emitter current location
    • -
    -

    Ionward updated:

    -
      -
    • Added new mantles! Check the ClothesMate, or in department head's lockers.
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds striped normal-height socks.
    • -
    • Vox can now wear whatever undergarment they want.
    • -
    • Removes flesh from shredded Vox uniform sprites.
    • -
    • Armalis can no longer wear undergarments. They didn't fit, anyhow.
    • -
    • Underwear no can no longer lock up the character creator.
    • -
    -

    Kyep updated:

    -
      -
    • bans issued by admins via the Player Panel no longer incorrectly omit IP/etc information
    • -
    • admins issuing permanent bans are no longer presented with an "ip ban?" prompt, as all bans include IP/CID information now. This prompt was a legacy thing from back when the filesystem was used to store bans, and hasn't ever affected how DB-based bans were stored.
    • -
    • Added a config file option which allows SSD crew members to be moved to cryo after a defined amount of minutes.
    • -
    • Added a config file option which causes most people trying to attack/loot/interact with a SSD character to need to confirm they've read the rules before being able to do so.
    • -
    • Fixed an error message being inappropriately generated for admins when someone signs up as a pAI.
    • -
    • The ID computer now color-codes potential job transfer options, highlighting good choices for a job transfer in green, and bad ones in gray.
    • -
    • Taking a job transfer now gives you playtime based on your new job, instead of incorrectly still giving you playtime based on your old job.
    • -
    • Job transfers to karma jobs are now possible - if you have the job unlocked.
    • -
    • Attempting to bypass a job ban via a job transfer now generates a warning to all online admins.
    • -
    • Refactored and improved our entry on the server hub.
    • -
    • Fixed a runtime in job_exp.dm
    • -
    -

    Markolie updated:

    -
      -
    • Safes can now consist of more than two tumblers.
    • -
    • All safes now have three tumblers by default, instead of two.
    • -
    • The safe opening mechanism has changed slightly. This is described on the safe cracking UI.
    • -
    • The hardsuit equipment lockers on the Syndicate Nuclear Operative shuttle have been replaced with suit storage units. Suit storage units now have a separate slot for magboots.
    • -
    • Nuclear Operatives can now purchase reinforcements. These reinforcements cost 25 telecrystals each.
    • -
    • A number of new ammunition and weapon bundles have been added for Nuclear Operatives.
    • -
    • For every ten players on the server, the Nuclear Operatives now receive 2 extra telecrystals.
    • -
    • The Syndicate borg spawners have been separated into three separate spawners, one for each type of Syndicate cyborg. Their prices have been modified.
    • -
    • Saboteur borgs now spawn with thermals.
    • -
    • The Syndicate borg and exosuits have been moved to a new category, "Support and Mechanized Exosuits".
    • -
    • Existing bundles and telecrystal purchases have been moved to a new category, "Bundles and Telecrystals".
    • -
    • There are now more spawn points for nuclear operatives on their base. The number of operatives spawning has not been changed.
    • -
    • Spawning nuclear operatives through the traitor panel now causes their ID to be properly updated.
    • -
    • Shuttles no longer leave behind their propulsion.
    • -
    • AZERTY hotkey mode users can now switch between regular mode and hotkey mode properly using TAB again.
    • -
    • Jumpsuits are now removed by clicking instead of clicking and dragging.
    • -
    • Removed a useless message that would be sent to admins whenever a drone joins the round.
    • -
    • Fixed an issue where admins would receive a message whenever someone joined up as a pAI.
    • -
    -

    McDonald072 updated:

    -
      -
    • You can no longer examine or teleport things using clipboards
    • -
    -

    Quantum-M updated:

    -
      -
    • Two multicolor pens to the Internal Affairs Office
    • -
    -

    TDSSS updated:

    -
      -
    • nukies can buy plasma grenades again
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Moves AI admin log to the all preference
    • -
    -

    dovydas12345 updated:

    -
      -
    • Fixes normal cameras spooking non-chaplains even when they don't capture any ghosts
    • -
    -

    farie82 updated:

    -
      -
    • Makes puke less lag inducing
    • -
    • Puke can now appear on all kinds of turfs except spess
    • -
    • Ticket messages now have their corresponding span classes. Making them easier to notice
    • -
    • PM's now shouldn't go to the wrong client anymore when the target left.
    • -
    • Cure text for Shock and Cardiac failure are more clear now
    • -
    • Ducttape gags can now be removed properly without spawning an invisible one in your hands
    • -
    • Windoors now give the airlock assembly electronics once deconstructed
    • -
    • Can't place runes in space anymore
    • -
    • Admins can now use all mhelp related things again
    • -
    • Fixed the toggle mentor ticket messages text
    • -
    • Vampiric glaring is logged now
    • -
    • Doctor delight and orange juice now heal again
    • -
    • Fixes admin PM's. Bwoinks are back on the menu!
    • -
    • Organs will now prompt a update_stat. Meaning that IRCs and the like now get revived when possible when you put their battery and brain in
    • -
    • The typing limiter option should now work for all edge cases. Such as dying while talking and such
    • -
    • Borgs health status now updates properly when removing and adding parts
    • -
    • You won't try to fix destroyed components in borgs anymore. Which resulted to lost materials and no healing
    • -
    • Borg analysers will now properly show missing components and won't show their damage if missing
    • -
    • Self diagnostics for borgs now also shows missing parts and destroyed ones
    • -
    -

    iantine updated:

    -
      -
    • Adds Lumi's vox suit fluff
    • -
    -

    uc_guy updated:

    -
      -
    • Players in the lobby no longer see cult speak.
    • -
    - -

    08 April 2019

    -

    TDSSS updated:

    -
      -
    • Added missing vent in toxins mixing
    • -
    - -

    07 April 2019

    -

    Arkatos updated:

    -
      -
    • Guardians can no longer change action intents on their own
    • -
    • Fixes #10900 - Guardians can no longer attack their host while inside them
    • -
    • Explosive and Support Guardians now get precise cooldown shown (instead of just static estimate) before their bomb and beacon abitilites are ready to be used again, respectively
    • -
    • HARM action intent icon for Guardians updated
    • -
    • Dehydrated Space Carp TC cost changed from 3 to 2
    • -
    • Shadowling Glare ability reworked - The further Shadowling is from their glared target, the shorter stun their target gets. Stuns also have a delay before they kick in, based on the distance, however targets will be slowed and muted before stun takes effect. Targets on the tile just next to them are still stunned and muted for 10 seconds without any delay.
    • -
    • Added victory message to the End Round messages in the Shadowlings Rounds
    • -
    • Shadowling Destroy Engines ability reworked. You now need to sacrifice non-ally target to delay the emergency shuttle arrival by 10 minutes, and shuttle will be unable to be recalled. This ability can be used only once across ALL Shadowlings.
    • -
    • Descriptions now show with a mouse hover over action buttons
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes Russian revolvers triggering no matter where you clicked
    • -
    • Power gloves electric shocks can target anything now (still only damages mobs)
    • -
    • Power gloves electric arcs will bounce around (if it happens to target a mob though, it'll ground out and not bounce any more)
    • -
    • Power gloves cooldown lowered from 12 to 4
    • -
    • Power gloves heat up the turf they target
    • -
    • Using power gloves on disarm intent will weaken your target instead of dealing damage
    • -
    • CLF3, Phlogiston, and Fluorosulfuric acid all require greater volumes to achieve their upper damage limits
    • -
    • CLF3 and Phlogiston have lower minimum damage
    • -
    • Grey's treat water more closely to sulfuric acid (including passive damage while it's in them)
    • -
    • Grey's don't instantly purge all sulfuric acid from their system; it depletes at the normal rate, but doens't cause damage
    • -
    • Foam altered to be a bit more viable compared to smoke
    • -
    • Fixes being unable to view pill bottle inventory in some circumstances
    • -
    • Vending items from vending machines will try to put the item in your hands after vending
    • -
    • Vending machines with refill-canisters can be beaten apart and broken
    • -
    -

    Kyep updated:

    -
      -
    • Ghosting while alive, conscious, and a member of the crew will now result in your body being moved to cryo after 5 minutes, assuming your body isn't killed or restrained in any way in the meantime.
    • -
    • An AI that ghosts while alive gets a dismissable hint that they might consider using OOC -> Wipe Core instead.
    • -
    • Ghosting out of your body while you are alive, and an antag, will result in admins being informed, so that they may replace you as an antag if needed.
    • -
    • Empress of terror (admin-only mob) is no longer incorrectly prevented from laying brown spider eggs.
    • -
    • Admins are now able to spawn a queen of terror in a room without a vent. Previously, queens would not allow this. Now, this just results in an alert to admins (since its probably a mistake) and deactivates the mob AI (but leaves it available for player control).
    • -
    • If there are player controlled terror spiders, admins using check antags panel will now be able to see eggs/spiderlings currently growing on the station. These counters only count eggs/spiderlings on station, and ignore fake spiderlings.
    • -
    • Empress of terror's 'erase brood' ability no longer incorrectly causes mothers of terror to spawn spiderlings on death. sprite: Empress of terror now has its own sprite.
    • -
    • White spider infections have been nerfed a bit. They no longer provide passive healing or increase infection progress while their host/victim is in crit. Also, the first spiderling to emerge from an infection can no longer be a green. Finally, the eggs now self-delete after the third spiderling emerges, so even in the event they aren't treated with surgery, the host isn't left with confused movement forever.
    • -
    -

    Markolie updated:

    -
      -
    • Changing your hotkey mode now happens instantaneously and no longer lags.
    • -
    • An issue where the Hotkey Toggle button wasn't working has been fixed.
    • -
    -

    TDSSS updated:

    -
      -
    • upload consoles now tell you if you forgot to select an ai/borg before using an upload module.
    • -
    • trick revolver comes in a box, so you can tell what it is when getting it in a surplus crate.
    • -
    -

    farie82 updated:

    -
      -
    • Gives you the option to disable text popup spam. Aka if enabled you won't get popups after you pressed T and had a lagspike and you typed a sentence containing a lot of T's. Default is off
    • -
    • Now checks if OOC and LOOC are enabled before showing the popup
    • -
    • Adds a Mhelp ticket system
    • -
    • Take in the m/a-helps now actually takes the question
    • -
    • a/m-help followup responses using a-mhelp verb now get added to the last ticket like it should
    • -
    • Normal players can now see their open tickets using the My Admin/Mentor tickets verb
    • -
    - -

    06 April 2019

    -

    Fox McCloud updated:

    -
      -
    • Fixes people popping out of cloning taking tons of damage
    • -
    • Fixes Teslium recipe
    • -
    • Fixes some reagents not causing status updates
    • -
    -

    Twinmold updated:

    -
      -
    • No longer costs toner to send a fax to Central Command
    • -
    -

    dovydas12345 updated:

    -
      -
    • Fixed diamond statue names and description.
    • -
    -

    farie82 updated:

    -
      -
    • Sec huds work again. No longer does the perp need glasses to be set to arrest. Cool does not equal arrest now
    • -
    - -

    04 April 2019

    -

    Kyep updated:

    -
      -
    • Improved the interface for Syndicate Uplinks. They now clearly mark which items are hijack-only and which are not. If you attempt to purchase a hijack-only item without hijack, they will explain why you can't.
    • -
    • Atmos Gas Grenades (the uplink grenade kit) are now split into Knockout grenades (2 N2O grenades, 8 TC, available to all agents), and Plasma Fire grenades (2 plasma fire grenades, 12 TC, only available if you have hijack). This both makes knockout grenades more useful for normal traitors, and also prevents non-hijackers using a plasma fire grenade to cause massive casualties/damage.
    • -
    • Plasma Grenades and the Syndicate Bomb can no longer show up in surplus crates, or be discounted. This means while you can buy one if you intend to, you're not randomly encouraged to bomb your target.
    • -
    - -

    03 April 2019

    -

    Fox McCloud updated:

    -
      -
    • Dramatically improves human life performance (sorry, doesn't fix your actual crappy real life)
    • -
    • Blobspores will additionally zomify all players who have 200 damage or more
    • -
    • Holoparasites will additionally die once their host has 200 damage or more
    • -
    • Fixes blob zombies who infect players who have no head being invisible
    • -
    -

    farie82 updated:

    -
      -
    • Death nettle can be picked up again
    • -
    • Auto cloning now doesn't clone a person more than once.
    • -
    • A person in the cloning scanner won't be scanned if he's already being cloned
    • -
    - -

    02 April 2019

    -

    Alonefromhell & AffectedArc07 updated:

    -
      -
    • Fixed an edgecase compile error for spacehotel.dmm
    • -
    -

    Arkatos updated:

    -
      -
    • Added Medical Beamgun to a Syndicate Medical Cyborg
    • -
    • Appropriate antagonist sound theme now plays when an antagonist is selected via Traitor Panel
    • -
    • Cult sound theme now plays for a new cult converts
    • -
    • Traitor/Malfunction sound theme now plays for newly autotraitored crew/AI
    • -
    -

    AzuleUtama updated:

    -
      -
    • Cleaned up some outdated code left in uplinks.dm
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes some mobs not being able to hear sounds
    • -
    • Fixes the Master Controller not actually shutting down on round end
    • -
    • Adds space ants to the game; leave your food on tables or inside a container to avoid infestation!
    • -
    • Fixes bees not properly generating if they have a reagent in them
    • -
    • Can break bee boxes
    • -
    • Fixes bees breaking things they shouldn't
    • -
    • Fixes bees not properly injecting toxin if they lacked a reagent
    • -
    • purchased bee boxes are no longer wrenched down by default
    • -
    • Adds trick revolver to the syndicate uplink for the clown. Teach those pesky validhunters a lesson!
    • -
    • Adds the ability for admins to start a revolver only summon gun version; there's also a suicidal version that makes half the guns summoned real and the other half trick revolvers
    • -
    • stabilizing agent gets used up in reactions that utilize it
    • -
    • flashbangs spark when they initially go off
    • -
    • Fixes mech users being stunned by their own flashbangs
    • -
    • Fixes necromantic stone not working properly and other edge cases where you had O2 damage and could become O2 damage immune
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds Vox-fitted Tajaran veil sprites.
    • -
    • Removed stray pixel from Vox-fitted gasmask sprites.
    • -
    • Adjusts the Vox-fitted blindfold sprite.
    • -
    -

    Kyep updated:

    -
      -
    • Blob mobs can definitely no longer be spawned in xenobio.
    • -
    • Changed playtime requirements for command jobs. HoS/RD/CE/CMO/AI now require 5h played in their department to be playable. HoP/Captain now require 5h played as a member of the command staff.
    • -
    -

    Markolie updated:

    -
      -
    • Fixed some issues the compiler doesn't spot and some start up issues.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Start now confirmation is now a config option
    • -
    • Grid check event sound effect
    • -
    -

    farie82 updated:

    -
      -
    • Antidrop give edge case fixed
    • -
    • Can't give items to resting people now
    • -
    • put_in_hands now checks if you actually have hands
    • -
    • Wrapping lockers and crates now takes 1.5 seconds to do
    • -
    • Welding lockers now takes 1.5 seconds to do
    • -
    - -

    01 April 2019

    -

    Arkatos updated:

    -
      -
    • New Blob UI buttons for Storage Blob and Split consciousness abilities
    • -
    • New custom icons for Storage Blob and Split consciousness abilities
    • -
    • Added Node Requirement verb to the Blob. This verb, which is activated by default, enforces that resource and factory blob structures are built in a close proximity of the core/node in order to properly function. Players can disable it anytime in the Blob tab.
    • -
    • Remove Blob verb now has a new feature - partial refund for special Blob structures. When Blob Overmind removes special blob structure (such as a factory or node), it will receive 30% of the structure cost back as a refund.
    • -
    • Blob Overminds now show in Check Antagonists admin verb
    • -
    • Blob Mobs now use complementary colors of the Blob Overmind reagent as their own color
    • -
    • Removed Dark Matter from a list of possible Blob reagents
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes syndicate medborgs and regular medborgs not having handheld defibs
    • -
    • Fixes multi-tile airlocks breaking and not leaving behind an assembly
    • -
    • Updates the Timer SS
    • -
    • Roundstart ChemMasters are now constructable/deconstructable
    • -
    • Can upgrade ChemMasters. Larger beakers mean a larger reservoir
    • -
    • Mobs that are gibbed with strange reagent and GBS have a bit more of a dramatic flare to them with violent convulsions before exploding into tiny bits
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Modified alert sounds for Code Gamma and Code Epsilon.
    • -
    -

    dovydas12345 updated:

    -
      -
    • Fixes AI's toggle floor bolts ability
    • -
    -

    farie82 updated:

    -
      -
    • Bluespace golems no longer can crash the server
    • -
    • Spontaneous combustion now has a minimum stacksize of 1. No more getting wet from the fire virus
    • -
    - -

    30 March 2019

    -

    Fox McCloud updated:

    -
      -
    • Fixes a runtime involving decapitation
    • -
    • playing sounds performs better
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Removes SSD sleep bubbles from ghosts
    • -
    - -

    29 March 2019

    -

    Arkatos updated:

    -
      -
    • Fixes #11087 - Swarmers are now locked to their default action intent
    • -
    • Swarmers are now able to open airlocks and windoors (access restrictions still apply)
    • -
    • Added new Wizard item - Bottle of Ooze! This powerful item awakens all-consuming Morph, ready to eat everyone and everything on the station! Be careful though, as Morph diet also includes Wizards.. Costs 1 point in the spellbook.
    • -
    • Added custom icon for Bottle of Ooze
    • -
    • Morph introduction is now properly formatted
    • -
    • Added new Blob UI and icons, ported from /tg/station13
    • -
    • Added new *Blob Help* verb, designated to help out new players playing as Blob
    • -
    • Added descriptions for each Blob reagent
    • -
    • Added complementary colors for each Blob reagent
    • -
    • Blob marker now uses complementary color of Blob reagent as it's own color
    • -
    • Blob shortcuts updated. Blob shortcuts are now: Click = Expand Blob | CTRL Click = Create Shield Blob | Middle Mouse Click = Rally Spores | Alt Click = Remove Blob
    • -
    -

    Fox McCloud updated:

    -
      -
    • Crit has been dramatically overhauled. Treating patients now requires a broader range of medicine. Recommend checking out a guide for how to treat using the new system!
    • -
    • Medical vendors now have styptic and silver sulfadiazine, saline, atropine, mannitol, mutadone, calomel, diphenhydramine, oculine, insulin, morphine, and potassium iodide for helping treat new patients. Amount of Gauze, Advanced Trauma, and Burn packs has also been increased.
    • -
    • Adds new handheld defibs. Utilize these for treating patients with cardiac arrest. Note: these do not revive people from the dead!
    • -
    • Doctors lockers now have a handheld defib in addition to a regular defib.
    • -
    • Medical borgs now have a handheld defib
    • -
    • CPR dramatically buffed. Heavily lowers O2 damage and resets losebreath to 0
    • -
    • Cryoxadone tuned down a little
    • -
    • Health analyzer UI altered ever so slightly for cardiac arerest, so it's easier to find
    • -
    • Added bacon grease reagent to traitor poison bottles; induces immediate cardiac failure
    • -
    • Upgraded Robotic Hearts now attempt to correct both cardiac failure and cardiac arrest tweak; Upgraded Robotic Hearts now do not punish you quite as severely for receiving a shock while having one (EMPs will still destroy you though)
    • -
    • Corazone recipe removed
    • -
    • hotspot sprites updated; fire will also now appear over top of things, rather than underneath it
    • -
    • Roundstart chem dispensers are now construcable/deconstrucable and can be moved
    • -
    • Energy ratio for chem dispensers increased by x10 (how many reagents you can dispense before running out and how quickly it recharges is all the same, however)
    • -
    • Adds the ability to add a single unit of reagent in the chem dispenser
    • -
    • Adds the ability to isolate reagents in the chem dispenser
    • -
    • Portable chem dispenser removed (the circuit board for them now makes full dispensers)
    • -
    • Fixes some suicides dealing damage and gibbing you at the same time
    • -
    • Allows you to suicide with more object types. Currently the only new object type you can suicide with is the gibber
    • -
    -

    Kyep updated:

    -
      -
    • Blob mobs can no longer be spawned in xenobio.
    • -
    • Blob mobs spawned by blob cores can no longer have sentience potions used on them, which would allow whoever controls them to kill the blob with no countermeasure.
    • -
    -

    Mitchs98 updated:

    -
      -
    • Adds in Shrimp & Fish Skewers as well as Cheeseburgers. Shrimp Skewer(Grill): 4 Shrimp(uncooked) + 1 Metal Rod, Fish Skewer(Grill): 2 Salmon Meat + Metal Rod + 10u Flour, Cheese Burger(Microwave): Burger + Cheese Wedge.
    • -
    -

    farie82 updated:

    -
      -
    • Borgs can now only cuff people with two hands. Just like humanoids
    • -
    • You can cuff people with at least one hand now
    • -
    -

    ingles98 updated:

    -
      -
    • Plasma Golems will now report their suicide acts to the Admins.
    • -
    - -

    25 March 2019

    -

    Fox McCloud updated:

    -
      -
    • Fixes some reagent performance edges cases
    • -
    • Fixes chem smoke lagging under some circumstances
    • -
    • Fixes smoke not wanting to garbage collect
    • -
    • Fixes flares not returning a qdel hint
    • -
    • Fixes hotspots being slow to ignite turfs around them
    • -
    • Fixes LINDA not conducting temperature through things.
    • -
    -

    Mitchs98 updated:

    -
      -
    • Chitinous Mass is no longer weaponized lag if examined.
    • -
    -

    farie82 updated:

    -
      -
    • Diona nymphs are grabbable and punchable again
    • -
    - -

    24 March 2019

    -

    AffectedArc07 updated:

    -
      -
    • Preferences are now in alphabetical order
    • -
    -

    AzuleUtama updated:

    -
      -
    • Added Syndicate MMI for Roboticist Traitors, priced at 2TC. balance: Removed Syndicate MMI from the traitor surgery duffelbag. Price reduced to 2TC.
    • -
    -

    EmanTheAlmighty updated:

    -
      -
    • Can no longer offer Gateway Terror Spiders sentience potions. ( They literally exploded if you did, and that could have been used to effortlessly clear out hordes of them. )
    • -
    • Using the Shadowling ability "Hatch" as a monkey will change your HUD to be the human one.
    • -
    • It is now possible to put a collar on any animal that has gained sentience.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Pills maximum size increased from 50 to 100
    • -
    • Chem Master bottle size increased from 30 to 50
    • -
    • Pill bottles can now hold 50 pills instead of 14
    • -
    • Pill bottles can no longer hold patches
    • -
    • Adds Patch Boxes, which can hold patches, but not pills
    • -
    • Can now use a pill bottle or patch box on someone to apply a pill/patch from the bottle/box to a mob. Usual delays will still apply
    • -
    • Can down an entire pill bottle at once!
    • -
    • Cryostylane and pyrosium reactions now consume 2 of themselves when exposed to oxygen
    • -
    • fires, temperature, and hotspots can heat anything that contains reagents
    • -
    • Having hot/cold chemicals dumped on you or ingesting them will hurt you. Wear a mask or hat to protect from having someone dump the hot/cold things on you.
    • -
    • Chem Heater temperature adjustment tweaked; can no longer set temperature on empty containers.
    • -
    • Chem Heater generally heats faster, but cannot be upgraded
    • -
    • Chem Heater automatically stops around target temperature
    • -
    • Adjusts fire stacks and how they're applied with a few chems. Naplam, Phlogiston, fuel, thermite, and a few others have all received changes. Most direct fire damage removed.
    • -
    • Adds phlogiston dust; a safer, cooler burning Phlogiston.
    • -
    • Water and Firefighting foam will no longer automagically put out mob based fires; they'll reduce fire stacks (when fire stacks hit 0 they put the mob out)
    • -
    • cryostylane puts out mobs instantly
    • -
    • Heating fuel can set it off. Be careful when heating it now
    • -
    • Increased welding fuel tank size from 1000 to 4000 (wall mounted are still 1000)
    • -
    • Sorium and Dark matter now actually throw things
    • -
    • Thermite now gets applied to turfs. You'll have to heat the turf up to ignite it. Anything that can heat can now ignite thermite on walls
    • -
    • Adds fake hotspots. They don't do anything except set you on fire when you cross into them. Chemistry's pyrotechnics use these, for the most part; anything that causes a fireball that's chemistry related uses these
    • -
    • Sorium and Liquid dark matter now have visual effects
    • -
    • Fixes chem smoke being on the wrong layer.
    • -
    • Adds in unidentified tank filled with an unknown experimental gas in deep space. Find it and experiment!
    • -
    -

    Tails2091 updated:

    -
      -
    • New emotes to Cats and Corgis.
    • -
    • Change directories for some creature sounds to be in the creature sound folder.
    • -
    • Two bark sounds, a yelp, and a meow.
    • -
    -

    farie82 updated:

    -
      -
    • Holo firedoors now update atmos correctly after being destroyed
    • -
    • Inflatable walls/doors now update atmos correctly after being destroyed
    • -
    • Alien resin walls now update atmos correctly after being destroyed
    • -
    • Foamed metal walls now update atmos correctly after being destroyed
    • -
    • Pod doors (shouldn't ever happen) now update atmos correctly after being destroyed
    • -
    • Mining flaps now update atmos correctly after being destroyed
    • -
    - -

    23 March 2019

    -

    Arkatos updated:

    -
      -
    • Players who enable AntagHUD are now unable to join the round as swarmers
    • -
    • Adds a message explaining why Antag-banned players cannot join the round as cortical borer
    • -
    -

    Calecute updated:

    -
      -
    • South Prison camera now belongs to Prison camera network, thus showind in Prison camera monitor
    • -
    -

    Kyep updated:

    -
      -
    • Admins offering control of a mob with no real_name to ghosts will no longer cause a "Do you want to play as ?" popup. Instead, the ? will be replaced with a descriptive string, such as "the blobbernaut".
    • -
    -

    Tails2091 updated:

    -
      -
    • Lockboxes actually close when locked now.
    • -
    -

    farie82 updated:

    -
      -
    • When disarming a bomb from a guardian you now don't pickup an empty object.
    • -
    • no more organ: spam sorry admins
    • -
    - -

    22 March 2019

    -

    Arkatos updated:

    -
      -
    • Updated Tarot Deck description in Wizard's spellbook, credits to /tg/station13
    • -
    -

    Fox McCloud updated:

    -
      -
    • Smoke now has much better sprites and has a new area of denial behavior
    • -
    -

    Mitchs98 updated:

    -
      -
    • Fixed Dionae names so "Embrace of Starsong (as Embrace Of Starsong)" will no longer happen when renaming ID's at a ID Console.
    • -
    -

    Quantum-M updated:

    -
      -
    • Vox Cargo Crate - Contains two vox tanks and two vox masks. Costs 50 cargo points.
    • -
    • Plasmaman Cargo Crate - Contains a Orange plasmaman space suit and helmet, along with a breathing mask and a emergency plasmaman tank. Costs 75 cargo points and requires EVA access.
    • -
    - -

    20 March 2019

    -

    Dave-TH updated:

    -
      -
    • Krav Maga gloves can no longer steal the unstealable.
    • -
    -

    farie82 updated:

    -
      -
    • Fixed the middle mousebutton locking exploit
    • -
    - -

    17 March 2019

    -

    AffectedArc07 and Alonefromhell updated:

    -
      -
    • Cell management consoles: See the status of all brig cells without having to leave your office
    • -
    • New screen sprite for cell management console
    • -
    -

    Jazz23 updated:

    -
      -
    • Xenobio hotkeys, slime potion thing, remote slime scanner, monkey recycler linking.
    • -
    -

    Kyep updated:

    -
      -
    • It is no longer possible to crawl into a vent while you are simultaneously buckled to a chair or other solid object.
    • -
    -

    farie82 updated:

    -
      -
    • Adds a confirmation to the start now verb. Make it ansari proof
    • -
    • The invisible bumping into something should be fixed now
    • -
    • Fixes the atmos bug
    • -
    - -

    16 March 2019

    -

    Ty-Omaha and Ionward updated:

    -
      -
    • Carbon humans (people, not animals) who go SSD will now get ZZZ bubbles to indicate they are SSD
    • -
    - -

    15 March 2019

    -

    Arkatos updated:

    -
      -
    • Fixes #10987 - Guardians can now see the action intent they are on
    • -
    • Added custom action intent icons for Guardians
    • -
    -

    Couls updated:

    -
      -
    • Added a new line to the defib examine text
    • -
    - -

    14 March 2019

    -

    Couls updated:

    -
      -
    • tweaked shesi's fluff sprite
    • -
    -

    Quantum-M updated:

    -
      -
    • Changes the stamp sprites.
    • -
    • Add new sprites for the infernal and employment contracts.
    • -
    • Different organ sprites for each species
    • -
    • Different MMI sprites based on different species brains.
    • -
    - -

    13 March 2019

    -

    Couls updated:

    -
      -
    • universal translate no longer makes emotes over comms impossible
    • -
    • fixed a few typos with simple mobs
    • -
    - -

    12 March 2019

    -

    Arkatos updated:

    -
      -
    • Fixes #10261 - Pure Vampires in Traitor+Vampire gamemode will now properly show in AntagHUD
    • -
    • Fixes #9494 - Pure Changelings in Traitor+Changeling gamemode will now properly show in AntagHUD
    • -
    - -

    11 March 2019

    -

    Couls updated:

    -
      -
    • Display if karma gains are enabled or not on round start(instead of just disabled)
    • -
    • Fix wrong message when toggling karma
    • -
    -

    rb303 updated:

    -
      -
    • Fluff scarf for Rb303
    • -
    - -

    10 March 2019

    -

    AffectedArc07 updated:

    -
      -
    • You will now automatically be given admin rights if you connect to your local server
    • -
    • Mapmerge has been replaced with mapmerge2
    • -
    • Maps are now the TGM format. This means nothing for people who do not make map edits
    • -
    • Discord-related verbs are now under "Special Verbs" instead of "OOC"
    • -
    -

    Couls updated:

    -
      -
    • Toggle karma button in special verbs
    • -
    -

    Kyep updated:

    -
      -
    • Admins can now flag characters as having an event role, which makes them show up when admins look at the antag list, in admin attack logs, on antaghuds, and on the end-round score screen.
    • -
    -

    Tails2091 updated:

    -
      -
    • Added missing simple_animal emote help text.
    • -
    -

    TheMadTrickster updated:

    -
      -
    • added new fixed nice sprites
    • -
    • trashed old ugly buggy sprites
    • -
    - -

    08 March 2019

    -

    AzuleUtama updated:

    -
      -
    • Fixed nuke ops cybernetic bundles giving 6 implants rather than 5.
    • -
    • Fixed nuke ops cybernetic bundles being delivered in a box that was then delivered inside another box. balance: Nuke ops shotgun ammo bags and cybernetic bundles can no longer be discounted.
    • -
    -

    Dave-TH updated:

    -
      -
    • Medical smartfridges now accept IV bags.
    • -
    -

    Jazz23 updated:

    -
      -
    • Golems loose their shell when they switch species
    • -
    • Mousedrop applies slime speed/chill potions.
    • -
    - -

    07 March 2019

    -

    AzuleUtama updated:

    -
      -
    • Uplink items now use tooltips for their descriptions.
    • -
    • Uplink reformatted slightly.
    • -
    -

    Fox McCloud updated:

    -
      -
    • His Grace now allows you to toggle on/off binding to your hand
    • -
    • Activating his grace is now down by attempting to open it while it's in your hands
    • -
    • His Grace now removes slowed status, confusion, and resets shock stage if you're healthy
    • -
    • His Grace can now consume all mobs. Mobs consumed are permanently killed
    • -
    • His Grace will now neatly package up the inventory of people he consumes
    • -
    -

    Triiodine updated:

    -
      -
    • changes Neo-Russkiya Lang key to ?
    • -
    - -

    04 March 2019

    -

    AffectedArc07 updated:

    -
      -
    • Fluff item
    • -
    -

    Arkatos updated:

    -
      -
    • Fixes #10815 - Cloned cultists now retain their Commune ability
    • -
    -

    Fox McCloud updated:

    -
      -
    • Hopefully fixes weird stack issues. Maybe. Who knows. The World can burn.
    • -
    -

    Kyep updated:

    -
      -
    • Hardsuits that can already carry RCDs in their suit storage slot can now also carry RPDs in that slot.
    • -
    -

    Nicaragua1 updated:

    -
      -
    • Genewul Giftskee is less annoying
    • -
    • Fixed Griefsky acces and drop
    • -
    -

    Triiodine updated:

    -
      -
    • Neo-Russkiya Language
    • -
    -

    craftxbox updated:

    -
      -
    • open button is separated more from previous href
    • -
    -

    datlo updated:

    -
      -
    • Shuttle hijacking is no longer interrupted by people cuffed, straight jacketed, or locked inside a welded/locked locker or wall locker.
    • -
    • Updated hijack's objective description to reflect the change.
    • -
    - -

    03 March 2019

    -

    Fox McCloud updated:

    -
      -
    • Fixes genetic powers always activating when injected
    • -
    • Fixes Diona being able to be speedy and irradiate themselves with genetic powers
    • -
    - -

    02 March 2019

    -

    Dave-TH updated:

    -
      -
    • Wall-mounted defib frames. Swipe an appropriate card to lock the defib in place and use it to save lives!
    • -
    • IV bags have been refactored and may now accept any chemical. Play around with them a bit!
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes invisible stacks in hands
    • -
    • Fixes invisible bluespace crystals
    • -
    -

    Kyep updated:

    -
      -
    • Fixed cases of some genetics block SE injectors that are spawned at round start (such as the ones that can appear on the Sol Trade ship) not initializing properly, which would cause them to fail to work, and generate a runtime error. refactor: Did some minor refactoring to dna_injector.dm, fixing bad spacing.
    • -
    -

    Nicaragua1 updated:

    -
      -
    • Bots now drop their proper robotic arm
    • -
    • Honkbot drop is consistent with other bots
    • -
    -

    datlo updated:

    -
      -
    • Added navigation computers to the nuclear, SIT, SST, ERT, and vox shuttles. This computer lets you set a custom destination to jump to.
    • -
    • Most off-station shuttle consoles are now indestructible and impossible to deconstruct.
    • -
    • Added atmos blocking tiny fans and a security camera console to the ERT shuttle.
    • -
    -

    farie82 updated:

    -
      -
    • Can't use telepathy now when unconcious or dead
    • -
    - -

    26 February 2019

    -

    Fox McCloud updated:

    -
      -
    • Adds in stable mutagen; a DNA altering compound
    • -
    • Having the max allowable number of advanced viruses will no longer confer total and complete disease immunity to *all* future viruses infections
    • -
    • Maximum number of advanced viruses you can have in your system at once reduced from 3 to 1
    • -
    • Removed stimulant symptom
    • -
    • Removed weight gain and weight even symptoms
    • -
    • Removed Sensory Destruction symptom
    • -
    • Sensory Restoration renamed to Mind Restoration.
    • -
    • Mind restoration functions largely the same as Sensory restoration, with a few minor number changes that adjust it downward ever so slighty. It no longer heals toxin or eye damage
    • -
    • Vision Restoration renamed to a more appropriate "Sensory Restoration"
    • -
    • Capulettium is no longer a perma-stun as long as it's in your system; keeps your paralyzed for the same time as it did previously.
    • -
    • Fixes edge case mutagen behavior
    • -
    • Adds upgraded cybernetic heart to R&D
    • -
    • can now repair robotic organs, outside of the body, with nanopaste
    • -
    -

    Kyep updated:

    -
      -
    • Pink terror spiders are now called Queens after they evolve.
    • -
    • The terror spider major event now has a princess variant, and no longer has a mother variant.
    • -
    • White terror spider infestations are now less predictable, more spread out over time, and affected by nutrition and some chems, but also have worse consequences if left completely untreated for a long time.
    • -
    -

    PidgeyThePirate updated:

    -
      -
    • changed a whole bunch of strings to add a bit more flavor to most reagents in the game (most of these can be found in the spreadsheet).
    • -
    • resurrected the old "flavor_strength" value which appears fully functional in testing but has been entirely unused.
    • -
    -

    Ralta updated:

    -
      -
    • Ian can now wear a CentComm Officer Beret to become Blueshield Ian
    • -
    • Sprite added for Blueshield armor to corgi_back.dmi
    • -
    • beret_centcom_officer and beret_centcom_officer_navy copied to corgi_head.dmi spritesheet
    • -
    -

    UmeFuu updated:

    -
      -
    • New recipe for cookies and sugar cookies, new ingredients such as pastry dough, flat pastry dough, unbaked cookies and a new tool called circular cutter (Added to the dinnerware vendor). New chem mix to create a specific type of dough for cookies and pastries.
    • -
    • Removed old cookie/sugarcookie recipe
    • -
    • added reagents of the cookies (They now actually taste like sugar and chocolate): - sugar = 3 - hot_coco = 5 -Also adjusted the sugar cookies nutriment from 3 to 1, just like chocolate cookies (They're made of the same dough after all) Chocolate bar can now be cutted into pieces/chocolate pile
    • -
    • added cookie(pastry) dough, flat cookie(pastry) dough, unbaked cookies/choco and circular cutter sprites. (Disclaimer: The cookie dough and flat cookie dough are edits of the normal doughs, pretty obvious but credits to who sprited them. Same with the tray with the unbaked cookies)
    • -
    -

    datlo updated:

    -
      -
    • Added a "voice" option to the magic mirror, letting you toggle comic sans/wingdings/swedish/chav
    • -
    • Free Golem Ship's interior walls and floors are now fully simulated titanium walls/floors, so they can be deconstructed, built upon, etc. balance: Increased the cost of RND boards for free golems to 2000 mining points (from 1500)
    • -
    • Golems can no longer activate robotic brains or have their brain put into an MMI.
    • -
    • Replaced one welding fuel tank in the golem ship by a chem master 3000.
    • -
    -

    farie82 updated:

    -
      -
    • Beepsky now can't insta cuff you when you run away and get back close to him.
    • -
    - -

    24 February 2019

    -

    Fox McCloud updated:

    -
      -
    • Adds the compact syndicate sniper rifle to the uplink. A weaker, low capacity variant of the operative syndicate rifle
    • -
    • Fixes blindness mutation not making you blind
    • -
    -

    datlo updated:

    -
      -
    • Golems can no longer use telescience consoles.
    • -
    • Nuclear operatives can now choose to take over a cyborg when spawning one, with a ghost playing the nuclear operative.
    • -
    - -

    23 February 2019

    -

    datlo updated:

    -
      -
    • Golems can no longer be objective targets
    • -
    • Offstation antag/special roles such as the ERT, abductors, etc, can no longer be objectives targets
    • -
    • Nukies no longer retain flavor text from saved character
    • -
    • Antag clowns can now toggle their clumsiness off and on.
    • -
    - -

    19 February 2019

    -

    Citinited updated:

    -
      -
    • Using a multitool on a conveyor switch now switches between one and two directions without needing you to set it on a menu.
    • -
    - -

    17 February 2019

    -

    Arkatos updated:

    -
      -
    • Changed Aurora Caelus event ending title to actually reflect that event is ending
    • -
    -

    Nicaragua1 updated:

    -
      -
    • Name of secbots
    • -
    • Honkbot wasnt dropping oil when exploded
    • -
    - -

    16 February 2019

    -

    Alonefromhell & AffectedArc07 updated:

    -
      -
    • Tweaked the discord link alert text slightly.
    • -
    -

    Mitchs98 updated:

    -
      -
    • Bar Starter Kit to Cargo. 20 points for both Beer/Soda Boards and a package of glasses.
    • -
    • Beer and Soda Machines can now be wrenched to move them.
    • -
    • Beer and Soda Machines can now be constructed as well as upgraded to include a slightly wider range of drinks.
    • -
    • Properly named the Banana Honk to Banana Honk from Banana Mama.
    • -
    -

    Nicaragua1 updated:

    -
      -
    • Adds General Griefsky bot and a toy version!
    • -
    • Spin-sabre sound
    • -
    • Adds Griefsky sprites
    • -
    -

    Terilia updated:

    -
      -
    • Added the donksoft sniper rifle
    • -
    • special donksoft sniper foam darts & special foamforce sniper foam darts
    • -
    • Sniper Foam Boxes && Riot Sniper Foam Boxes.
    • -
    • creates an admin log, if a player is being hit by a Foam Dart which has been tinkered with.
    • -
    • fixes a small misalignment in the magazine sprite if a dart is loaded.
    • -
    -

    aleksix updated:

    -
      -
    • AI's "Wipe Core" now properly ghosts the player
    • -
    -

    farie82 updated:

    -
      -
    • Removes some of the chaplain special religion names
    • -
    - -

    15 February 2019

    -

    aleksix updated:

    -
      -
    • posibrains and robobrains don't vanish upon the controlling player's suicide
    • -
    - -

    14 February 2019

    -

    AzuleUtama updated:

    -
      -
    • Added Super Surplus Crates from TG. They contain 125TC worth of gear, but cost 40TC meaning you'll need to team up if you want one.
    • -
    • The Surplus chance value for various uplink items will now work when ordering a crate.
    • -
    -

    Citinited updated:

    -
      -
    • Adds jestosterone to the list of standard reagents, not sure if this has any in-game effect.
    • -
    -

    EmanTheAlmighty updated:

    -
      -
    • Sentience event now adds some damage to the affected mob.
    • -
    • Sentience event now adds health to the affected mob, rather than replacing the old value with another value.
    • -
    -

    Mitchs98 updated:

    -
      -
    • IV Drip crate can now be opened by general medical personnel, instead of only the CMO.
    • -
    -

    TDSSS updated:

    -
      -
    • NT rep and Magistrate lose access to the HOP office
    • -
    -

    aleksix updated:

    -
      -
    • made the lighter size consistent before and after first lighting.
    • -
    -

    datlo updated:

    -
      -
    • The Nuclear Authentification Disk can no longer be taken from the station by the ERT, Abductors, or Sol Traders.
    • -
    - -

    12 February 2019

    -

    Citinited updated:

    -
      -
    • Fixes some spelling mistakes in the NT soul ownership contract
    • -
    -

    Kyep updated:

    -
      -
    • Added pink (princess) T3 terror spider, better terror spiderling AI.
    • -
    • Tweaked green and mother terror spiders. All terror spider types now have their own variants of the standard spider web.
    • -
    -

    datlo updated:

    -
      -
    • Added Greey's fluff duffelbag
    • -
    • Staff and wand of door can now also open lockers.
    • -
    - -

    11 February 2019

    -

    AffectedArc07 updated:

    -
      -
    • Admins that linked their discord account that round no longer show up as "the adminkey" in adminwho.
    • -
    • Changelog button loads properly on darkmode now
    • -
    • Added an admin verb that allows admins to forcefully unlink discord accounts
    • -
    -

    Fox McCloud updated:

    -
      -
    • Cryotubes no longer passively heal patients without chems. Effectiveness at stabilizing critical patients increased
    • -
    • Sleepers no longer gain additional chemicals when upgraded. Selection of chemicals altered
    • -
    -

    Shadeykins updated:

    -
      -
    • Added Chav to roundstart character preferences.
    • -
    • Removed Epilepsy, Tourette's, and Can't speak properly from roundstart character preferences.
    • -
    -

    datlo updated:

    -
      -
    • Reworked golems to use the ghost spawner system. Craft a golem shell with adamantine then apply 10 sheets of minerals to finish it.
    • -
    • Added golem subtypes. Each material has pros and sometimes cons. Type depends on the material used during construction.
    • -
    • Golems are now more resistant to damage and are no longer slowed by the cold of space.
    • -
    • Golems now get golem-y names.
    • -
    • Fixed golem's stone face hiding their identity, showing them as unknown.
    • -
    • Added the Free Golems mob spawners and ship. Go do whatever.
    • -
    • Added a small asteroid on the telecomms zlevel.
    • -
    • Added Shesi's fluff winter coat
    • -
    • You can no longer use mob spawners (old station/golems) if you've forfeited your right to respawn.
    • -
    - -

    10 February 2019

    -

    Fox McCloud updated:

    -
      -
    • Allows you to switch strap sides on leather satchel
    • -
    -

    TDSSS updated:

    -
      -
    • New space ruin, the crashed wizard shuttle. Rumored to contain fabulous magical treasures.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Reviver implant does not heal when you sleep, only when you fall unconscious involuntarily
    • -
    - -

    09 February 2019

    -

    AffectedArc07 updated:

    -
      -
    • You can now link your discord account and BYOND account together
    • -
    • With the accounts linked, you can get roundstart notifications within discord!
    • -
    • Fixed roundstart message in discord so that people are notified instead of characters being replaced
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds Fox's fluff coat
    • -
    • Health HUDs now have a defib indicator showing if they can be revived with a defib or not
    • -
    • Defib "safe" time reduced from 5 minutes to 2 minutes
    • -
    • fixes a bug where sometimes revived individuals still appeared to be dead or severely damaged on health HUDs after being revived with a defib
    • -
    -

    MINIMAN10000 updated:

    -
      -
    • Configuration option for disabling subsystems
    • -
    -

    Quantum-M updated:

    -
      -
    • Headslug sprite looks more deader.
    • -
    -

    TDSSS updated:

    -
      -
    • Singularities can no longer be pushed
    • -
    -

    Triiodine updated:

    -
      -
    • ozewse fluff item
    • -
    - -

    08 February 2019

    -

    Alonefromhell updated:

    -
      -
    • Drones should die properly now.
    • -
    -

    Kyep updated:

    -
      -
    • Characters are no longer massively more/less likely to be chosen for head jobs, especially the Captain job, based on their character's age.
    • -
    -

    Shadeykins updated:

    -
      -
    • Food descriptions/casing.
    • -
    - -

    07 February 2019

    -

    Alonefromhell updated:

    -
      -
    • Pineapple Salad's fluff coat
    • -
    -

    Dovydas12345 updated:

    -
      -
    • Fixes cult shackles appearing on the ground when removed
    • -
    - -

    06 February 2019

    -

    DrunkDwarf updated:

    -
      -
    • Reduced the size of the Ward-Takahashi Alt IPC head to prevent pixels clipping when wearing human clothing.
    • -
    - -

    05 February 2019

    -

    Alonefromhell updated:

    -
      -
    • LDM and Sorium should no longer push/pull ghosts
    • -
    -

    Kyep updated:

    -
      -
    • fixed a "_logging.dm,85: Cannot execute null.simple info line()" runtime when xenobio slimes emoted.
    • -
    - -

    03 February 2019

    -

    Fox McCloud updated:

    -
      -
    • Fixes a few edge cases of being able to create immunity to a few diseases
    • -
    • Adds suspiciously Voxy outfit to the game
    • -
    • Lack of breathing will render you unable to speak
    • -
    -

    MINIMAN10000 updated:

    -
      -
    • Boom function now properly checks for fuel
    • -
    -

    Tayyyyyyy, TaukaUsanake updated:

    -
      -
    • pAI units now have access to a flashlight module, which can be obtained with 5 RAM points.
    • -
    - -

    02 February 2019

    -

    AzuleUtama updated:

    -
      -
    • Added Pack of C-4 for Traitors and Nuke ops. Comes with 5 C-4 charges for 4TC.
    • -
    -

    Kyep updated:

    -
      -
    • Made playtime numbers displayed to admins (in the playtime report) and players (in the 'check my playtime' verb) clearer in meaning.
    • -
    -

    MINIMAN10000 updated:

    -
      -
    • Mobs in help intent do not push mobs pulling a structure or the structure they are pulling
    • -
    • mobs standing on the same tile when being walked into on help intent.
    • -
    • structures pulled beyond 1 distance call stop_pulling
    • -
    • stop_pulling() now sets pulledby to null
    • -
    -

    Shadeykins updated:

    -
      -
    • Thunderdome volume.
    • -
    • Newscaster placement
    • -
    • Power alarm subtype (noalarm), vomit/blood
    • -
    -

    TDSSS updated:

    -
      -
    • Mob spawner menu buttons now work. This time it really works, I swear.
    • -
    -

    uc_guy updated:

    -
      -
    • Non-breathing mobs no longer cause an increase in germ level by not wearing a mask.
    • -
    - -

    01 February 2019

    -

    AffectedArc07 updated:

    -
      -
    • Disabled darkmode is now normal grey, not full white
    • -
    • Changelog button now respects darkmode and will update when clicked
    • -
    -

    Citinited updated:

    -
      -
    • Sexy clown suits now have the squeak component
    • -
    • You can now change the way your sexy clown mask looks
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Admin save feature in build mode will ignore mobs
    • -
    -

    datlo updated:

    -
      -
    • Wingdings now garbles sentences.
    • -
    • Clown and mime now have their ID properly updated to their new name after they rename roundstart
    • -
    • Added some ID photo outfits to some jobs missing it.
    • -
    • Agent ID photo editing refactored. The photo now looks the same as a real ID, with an outfit based on the job you've forged on the ID.
    • -
    • Agent ID should now be impossible to distinguish from a real ID by non-antagonists once properly forged.
    • -
    • You can now reset access or delete the agent ID's information without having to do both.
    • -
    - -

    31 January 2019

    -

    Darkmight9 updated:

    -
      -
    • Adds the Camera Flash. A flash disguised as a camera for use as a cheap stun against non-sec, blinding crowds for a get away, and stunning borgs for emaging. Has a charge based system to prevent burning out.
    • -
    • Did some changes to flash code allowing different flashes to not be overcharged if one wants to or play a different sound when used.
    • -
    -

    Kyep updated:

    -
      -
    • Fixed various door control buttons that did not work correctly (brig prison lockdown, admin room lockdown, terror spider away mission containment doors, etc). refactor: refactored door_control buttons to check the GLOB.airlocks list, rather than doing a range(huge_number) check.
    • -
    • Terror Spider movement speed settings are no longer ignored when under player control. Instead, movement speed has been unified for both AI and player controlled spiders. Under player control, reds will now be slower, and purples will be faster. Under AI control, all spiders will be slower, except reds, which will be faster.
    • -
    -

    alffd updated:

    -
      -
    • revert to SS13 bot standard.
    • -
    -

    datlo updated:

    -
      -
    • Fixed surgery bugging and sometimes not starting properly when you try to surgery on a table or roller bed.
    • -
    • Surgery can now be done on any type of bed, with penalties.
    • -
    • Help intent is now required to start surgery. Was already needed to do surgery steps.
    • -
    • Surgery early cautery has been refactored. It is still done by holding a cautery in your inactive hand, but can now be done using ghetto tools, which can fail.
    • -
    • Medical cyborgs now have a laser scalpel instead of scalpel and cautery. lt is slightly faster and more versatile than standard tools.
    • -
    • Medical cyborgs now have a medical gripper. You can help patients up with it.
    • -
    • Medical cyborg can now cauterize incisions early by using the laser scalpel.
    • -
    • Added two black suit jackets to the arrivals locker room vendor
    • -
    • Added the armored suit jacket to the Bond, Payday, and Professional syndicate bundles.
    • -
    • Replaced the X4 in the Payday bundles by a C4.
    • -
    • The professional syndicate bundle now gets thermal fake sunglasses instead of thermal fake mesons.
    • -
    • Replaced the toolbox in the professional syndicate bundle by a pair of combat gloves.
    • -
    • Wingdings mutation works again.
    • -
    - -

    30 January 2019

    -

    AffectedArc07 & Teri updated:

    -
      -
    • There is now a toggle-darkmode verb to switch darkmode on and off
    • -
    • Chat settings also has a dark mode
    • -
    • The icon for the server is now the paradise palm tree
    • -
    -

    Shadeykins updated:

    -
      -
    • New Russian statue
    • -
    • Moved some cables, swapped a vendor.
    • -
    • Fixed missing door button, some dupes, and unintended object behavior.
    • -
    -

    Terilia updated:

    -
      -
    • Added a notification about the chat reconnecting on toggling of the dark chat mode.
    • -
    - -

    29 January 2019

    -

    Alonefromhell and Mitchs98 and farie82 updated:

    -
      -
    • Cake cat is now makeable.
    • -
    -

    Kyep updated:

    -
      -
    • Player-controlled hellhounds will no longer activate their smoke attack when they touch people on help intent.
    • -
    • Greater hellhounds (a far more dangerous version of the hellhound) now have descriptions that make it clear they are not the same as the regular hellhounds people are used to seeing.
    • -
    -

    farie82 updated:

    -
      -
    • fixes the viruses symptom creation being bugged. No more bluespace symptom creation
    • -
    -

    v0idp updated:

    -
      -
    • Discord Bot Functionality
    • -
    - -

    28 January 2019

    -

    AzuleUtama updated:

    -
      -
    • Fixed Binary Key's description to give the correct code to use when communicating with the AI or borgs.
    • -
    -

    Ionward updated:

    -
      -
    • Ionward's fluff coat
    • -
    -

    Shadeykins updated:

    -
      -
    • New derelict station. New floortiles (brownfull, cautionfull, darkredgreen, darkredblue, darkredyellow) New trash subtype (spent ammo casings) New titanium walls subtype (nodecon) Minor/oblique lore references (USSP, TSF, Cult/Bluespace) Context/modified objects (custom descriptions, slogans, etc.)
    • -
    • Old derelict station, two suspicious toolboxes
    • -
    • Remap teleporter, DJ station
    • -
    • Clown shuttle missing adjacent wall tiles
    • -
    -

    datlo updated:

    -
      -
    • Abductors no longer start with your preset character's flavor text.
    • -
    • Abductor scientists now have their SE properly cleaned on spawn.
    • -
    - -

    27 January 2019

    -

    Citinited updated:

    -
      -
    • Fixes tape being unapplicable to headsets and the autopsy scanner
    • -
    • You can't tape intercoms any more
    • -
    • The chemist can now create a new clown-based reagent using banana juice, lube, blood, space drugs, and salt.
    • -
    • Jestosterone heals brute damage for clowns, triggers annoying side-effects in other crewmembers, and is toxic to mimes.
    • -
    -

    Kyep updated:

    -
      -
    • fixed a runtime in hear_say.dm
    • -
    • Fixed item_attack / attack_obj runtime.
    • -
    • Fixed runtime when double-clicking a stool in-hand.
    • -
    • Antag objectives (kill, debrain, etc) can no longer target people on unreachable zlevels, like the admin-only/centcom zlevel.
    • -
    • fixed incorrect definitions of some spells related to shapeshifting.
    • -
    • Admin JMP links now work even if you're already following someone/something.
    • -
    -

    Kyep and alonefromhell and Ty Omaha updated:

    -
      -
    • Whispers are now fully readable in admin log.
    • -
    -

    TDSSS updated:

    -
      -
    • ether in syndie medical borg's hypospray replaced with hydrocodone
    • -
    • syndicate medical borg's hypospray no longer incorrectly lists its content
    • -
    -

    datlo updated:

    -
      -
    • Syndicate medical cyborgs now get a portable full body analyzer, making them much more effective field surgeons.
    • -
    • Bat swarm can no longer be spawned by gold slime extracts or reality tears. Regular bats can still be spawned.
    • -
    - -

    26 January 2019

    -

    AzuleUtama updated:

    -
      -
    • C4 and X4 are now much better at destroying objects they are directly placed on.
    • -
    -

    Citinited updated:

    -
      -
    • Renames the "Bar" on the Centcomm level to "Bar Lounge".
    • -
    -

    Shadow-Quill updated:

    -
      -
    • The engineering outpost now has atmospheric blocking tinyfans in the mass drivers.
    • -
    • Changed the wall in the Kitchen/Botany vendor to a plating.
    • -
    -

    datlo updated:

    -
      -
    • Fixed bluespace bunny ears fluff item description
    • -
    • Chameleon flag reworked : Now cost 1 TC from 7, but starts without an explosive. It can be boobytrapped using any grenade or a syndicate minibomb.
    • -
    • Chameleon flag moved from "Explosives" to "Stealthy Tools" in the uplink.
    • -
    • Fixed description of syndicate flags on the suspicious supply depot.
    • -
    • Books now deal light damage on hit if you're not on help intent. Space law book deals extra damage.
    • -
    - -

    25 January 2019

    -

    Agameofscones updated:

    -
      -
    • Cheeky Crenando's Soviet Greatcoat Fluff item.
    • -
    -

    Aurorablade updated:

    -
      -
    • Pineapplesalad fluff item
    • -
    -

    AzuleUtama updated:

    -
      -
    • Damp rags no longer have a lid, and must remain inferior to other containers.
    • -
    -

    Jazz23 updated:

    -
      -
    • Surgical Arm Menu
    • -
    -

    Kyep updated:

    -
      -
    • Fixed a mapping error in the brig remap PR.
    • -
    -

    blinkdog updated:

    -
      -
    • Normalized some paths in the code tree
    • -
    -

    datlo updated:

    -
      -
    • Reduced the cost of plasteel bomb frame crafting to 3 plasteel sheets (from 10)
    • -
    • Added emergency oxygen grenades to atmospherics lockers and the cargo emergency equipment crate.
    • -
    -

    warior4356 updated:

    -
      -
    • Drills now properly stop when turned off.
    • -
    - -

    23 January 2019

    -

    AzuleUtama updated:

    -
      -
    • Various text and formatting changes to traitor items.
    • -
    -

    Dovydas12345 updated:

    -
      -
    • Fixes simple animals (mice, corgis, etc.) and silicons (borgs, drones) being able to grab decks of cards, paperbins, chairs, stools.
    • -
    • Fixes simple animals (mice, corgis, etc.) and silicons (borgs, drones) being able to split stacks of sheets.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes null crafting recipes
    • -
    -

    Ionward updated:

    -
      -
    • Updated some drink sprites!
    • -
    -

    datlo updated:

    -
      -
    • Added sprites for the SST hardsuit (Mostly black with dark red), sprited by Ionward
    • -
    • Mapped SST and SIT shuttles on deltastation map.
    • -
    -

    iantine updated:

    -
      -
    • Lumi's fluff mouse
    • -
    • Mice now use their rest sprite when resting
    • -
    - -

    22 January 2019

    -

    TDSSS updated:

    -
      -
    • Suit Storage Units to most places that held hardsuits.
    • -
    • Ugly hardsuits on racks
    • -
    • reworked engineering slightly, removed the pointless hardsuit holding room.
    • -
    -

    Terilia updated:

    -
      -
    • Added Cake Cat - allowing the chef to create a living small pet in his kitchen.
    • -
    • Fixed frosted donuts, as they were filled with "spinkles" and not "sprinkles"
    • -
    - -

    21 January 2019

    -

    AzuleUtama updated:

    -
      -
    • Backpacks will now give a rough indication as to how much space they have left when examining them.
    • -
    -

    Nicaragua1 updated:

    -
      -
    • added mining drone sprites
    • -
    • sound alert for vampire gamemode
    • -
    • clown bot
    • -
    • clown box (Its made stamping a piece of cardboard with a clown stamp)
    • -
    • "honkbot evil laugh"
    • -
    • clown bot and box sprites
    • -
    • honkbot sprites
    • -
    -

    Spartan6 updated:

    -
      -
    • Gives Sol Traders a baton and a cargo cap.
    • -
    -

    datlo updated:

    -
      -
    • RD, CMO, and CE greys will now properly get a translator implant if they need one.
    • -
    • Updated the Syndicate Strike team's gear and ready room. Syndicate commandos will now be wearing reinforced black elite syndicate hardsuits and pack more ammo and supplies.
    • -
    • Syndicate commandos no longer start with all access.
    • -
    • Fixed some issues and improved the usability of the SIT and SST shuttle blast doors. They can now be reliably used to lockdown your shuttle from NT would-be intruders, and can be opened from inside and outside.
    • -
    • Fix accidental revert of the Syndicate Forward Base area name
    • -
    - -

    20 January 2019

    -

    AzuleUtama updated:

    -
      -
    • Fixed bee briefcase going into a negative number of remaining bees when used with less than 5 left.
    • -
    -

    Shadow-Quill updated:

    -
      -
    • You will no longer smack body scanner consoles when you rotate them.
    • -
    -

    datlo updated:

    -
      -
    • Fixed deathgasp emote not being called on death
    • -
    • Fixed nukies no longer exploding on death
    • -
    - -

    19 January 2019

    -

    Alonefromhell updated:

    -
      -
    • Mulecloset killing machine has been fixed. Mulebots are no longer able to be put into closets.
    • -
    -

    Shadow-Quill updated:

    -
      -
    • Removed a description that gets overwritten, moved the current one to it's old location.
    • -
    - -

    18 January 2019

    -

    Alonefromhell updated:

    -
      -
    • Revenant and Statue vision mode fixed.
    • -
    -

    AzuleUtama updated:

    -
      -
    • Added Professional Syndicate Bundle
    • -
    • Added Soporific Sniper Rifle. balance: Syndicate Bundles rebalanced to be worth more TC on average.
    • -
    -

    Nicaragua1 updated:

    -
      -
    • clown and mime locker now have correct acces
    • -
    • Golgrubs now run away from mechas being piloted
    • -
    -

    Quantum-M updated:

    -
      -
    • Medical Head Mirror, two spawn in the white medical clothes closet.
    • -
    -

    datlo updated:

    -
      -
    • Syndicate will no longer force you to play with the shiny new saboteur borg and instead send you the assault borg you actually ordered
    • -
    - -

    17 January 2019

    -

    Eschess updated:

    -
      -
    • Jetpacks work properly when placed on suit slot
    • -
    - -

    16 January 2019

    -

    Shadow-Quill updated:

    -
      -
    • Fixed a typo for when spiderlings enter vents.
    • -
    -

    uc_guy updated:

    -
      -
    • The burial suit (needed for the devil game mode) now shows up properly.
    • -
    - -

    15 January 2019

    -

    Jazz23 updated:

    -
      -
    • Bluespace Closet
    • -
    • Bluespace closet animations/sprites
    • -
    -

    uc_guy updated:

    -
      -
    • Actually activates devil friends contract.
    • -
    • Adds employment cabinet and codex gigas.
    • -
    - -

    14 January 2019

    -

    Kyep updated:

    -
      -
    • Doubled playtime requirements for command/sec jobs.
    • -
    • Starts tracking playtime on a per-department basis as well. E.g: "X hours in the Sec department".
    • -
    • Fixes bug which can cause more than 2 traders to spawn during the Sol Trader event.
    • -
    • Further improved sol trader event in general.
    • -
    • Enabled sol trader event to happen late-round as a randomly chosen event. Can only happen if the alert level is below red.
    • -
    -

    Quantum-M updated:

    -
      -
    • Magistrate Locker to the code.
    • -
    • Magistrate version of the Nanotrasen Navy Suit.
    • -
    • Gives the Magistrate a new wig, called Justice wig.
    • -
    • Magistrate specific stamp.
    • -
    • Adds the NT Rep version of the Nanotrasen Navy Suit (which already existed) to the NT Rep locker.
    • -
    -

    datlo updated:

    -
      -
    • ED bots no longer arrests you just because you have no ID by default
    • -
    • Nuke ops now spawn with their pinpointer.
    • -
    - -

    13 January 2019

    -

    Aurorablade updated:

    -
      -
    • Fluff item for Asmerath. rscadd:Accordions now have inhands
    • -
    -

    Shadow-Quill updated:

    -
      -
    • Stopped emergency shield generators from magically unbolting themselves when they get turned off.
    • -
    -

    Superhats updated:

    -
      -
    • Vox, Drask, Diona and Grey can now choose the Neutral gender option.
    • -
    -

    datlo updated:

    -
      -
    • Nuclear operatives can now select the Saboteur module when picking a cyborg, a modified engineering module designed around stealth and sabotage.
    • -
    • Fixed an exploit allowing you to get free syndicate cyborgs.
    • -
    -

    lordPidey updated:

    -
      -
    • Infernal devils have been seen onboard our spacestations, offering great boons in exchange for your soul.
    • -
    • Employees are reminded that their soul already belongs to Nanotrasen. If you have sold your soul in error, a lawyer or head of personnel can help return your soul to Nanotrasen by hitting you with your employment contract.
    • -
    • Nanotrasen headquarters will be bluespacing employment contracts into the IA's office filing cabinet when a new arrival reaches the station. It is recommended that the lawyer create copies of some of these for safe keeping.
    • -
    • Due to the recent infernal incursions, the station library has been equipped with a Codex Gigas to help research infernal weaknesses. Please note that reading this book may have unintended side effects. Also note, you must spell the devil's name exactly, as there are countless demons with similar names.
    • -
    • When a devil dies, if the proper banishment ritual is not performed on it's remains, the devil will revive itself at the cost of some of it's power. The banishment ritual is described in the Codex Gigas.
    • -
    • When a demon gains enough souls, It's form will mutate to a more demonic looking form. The Arch-demon form is known to be on par with an ascended shadowling in power.
    • -
    • Added Devil agent gamemode, where multiple devils are each trying to buy more souls than the next in line.
    • -
    • If you've already sold your soul, you can sell it again to a different devil. You can even go back and forth for INFINITE POWER.
    • -
    - -

    12 January 2019

    -

    AzuleUtama updated:

    -
      -
    • Chef Excellence's Special Sauce uplink description updated to be more accurate.
    • -
    -

    Shadow-Quill updated:

    -
      -
    • Fixed the QMs PDA supply app not showing the correct cargo shuttle location.
    • -
    • Changed the capitalization of CentCom and Station in the supply PDA cartridge.
    • -
    -

    datlo updated:

    -
      -
    • Nuke ops, ERT, and ayyybductors will now properly lose disabilities on spawn.
    • -
    - -

    10 January 2019

    -

    Aurorablade updated:

    -
      -
    • Cap guns was checking for claiber type 'cap' when the ammo was set to caliber typer 'caps'. Fixed.
    • -
    - -

    09 January 2019

    -

    Dovydas12345 updated:

    -
      -
    • Fixed NT Rep and Blueshield office door buttons not having correct required access
    • -
    -

    DrunkDwarf updated:

    -
      -
    • Analyzers now show the amount of moles within pipes and tanks
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes glasses not properly masking eye-shine
    • -
    -

    datlo updated:

    -
      -
    • Added the Staff of Slipping to the wizard spellbook for 1 spell point, sprites by Mithrandalf.
    • -
    • Added the wizard clown outfit to the wizard vending machine.
    • -
    • Added the magic mirror to the wizard den, letting wizards swap to other species and change their appearance.
    • -
    • Added spare plasmaman suit, plasma tank, and vox internals to wizard robes racks for any wizard that wishes to change to these species.
    • -
    • Made the snack machine in wizard den free to use. (wizards don't take silly credits as currency)
    • -
    - -

    08 January 2019

    -

    Alonefromhell updated:

    -
      -
    • Added an "All" option to ghost hud vision.
    • -
    -

    AzuleUtama updated:

    -
      -
    • Renamed and reorganized the ammunition in the uplink to make it easier for Nuclear Operatives to find the right ammo for their gun.
    • -
    -

    datlo updated:

    -
      -
    • Fixed grey translator translating the entire server.
    • -
    • Fixed BSA size checks being reversed, causing the BSA to clip through walls or prevent construction.
    • -
    - -

    07 January 2019

    -

    Fox McCloud updated:

    -
      -
    • Fixes auto-injectors being free parapens
    • -
    - -

    06 January 2019

    -

    AffectedArc07 updated:

    -
      -
    • Emitter reflectors are a thing now
    • -
    -

    Alonefromhell updated:

    -
      -
    • Dark matter and Sorium blob attacks should no longer affect ghosts and cameras.
    • -
    • All heads now have a HUD implant according to their department.
    • -
    -

    AzuleUtama updated:

    -
      -
    • New cane shotgun assassination shells. These buckshot shells are coated with a mute toxin which will prevent anyone hit either calling for help or screaming in pain.
    • -
    • Old cane shotgun assassination darts.
    • -
    • Cane shotgun now uses its own internal magazine rather than copying the code for the improvised one. It also now starts with an assassination shell preloaded.
    • -
    -

    Citinited updated:

    -
      -
    • You can now build snowmen out of 10 snowballs, 2 logs, and a carrot.
    • -
    -

    Dovydas12345 updated:

    -
      -
    • Added office door buttons, which open the office doors, to CE, HoP, CMO, HoS, RD, BS, NT Rep offices.
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Christmas!
    • -
    -

    Mithrandalf updated:

    -
      -
    • Added toy handcuffs
    • -
    -

    TDSSS updated:

    -
      -
    • Variants of Suit Storage Units that are ID locked
    • -
    • SSUs can now be hacked. Old SSU maint panel menu removed.
    • -
    • IRC chassis now have titanium cost to produce on top of metal.
    • -
    -

    datlo updated:

    -
      -
    • Added new, different voice sets to Syndicate, Clown, Mime, and ERT/Dsquad mechs
    • -
    • Added voice modification kits to the exosuit fabricator, letting you swap a mech's onboard voice to another.
    • -
    • Added visual and audio warnings when your mech is running low on power
    • -
    • Added visual warning when your mech is locked by maintenance protocols
    • -
    • Capulettium fake death will now actually be convincing, fooling examine, medhud, and health analysers, but not body scanners.
    • -
    • Capulettium plus can now be used to manually fake your own death when you wish by resting, and wake up when you wish by toggling rest again.
    • -
    • Added fake death pill bottle to maintenance loot, contains 3 pills of capulettium plus.
    • -
    • Fixed a mech runtime when an empty mech used power.
    • -
    • Grey wingdings is now a disability, add it to your saved characters if you want to have them on.
    • -
    • Grey translator implant preference added. Translates speech to be comprehensible, the implant can be turned off and on at will.
    • -
    • Mutadone no longer removes genes that you have at round start, from your job, species, or disability you've picked in character creation.
    • -
    • Mutadone no longer removes powers gained from a completed DNA vault.
    • -
    • Removed syndicate uplink management consoles.
    • -
    • Nuclear ops now automatically get bonus TC from round start and war declaration split between their uplinks.
    • -
    • Nuke ops can now buy stacks of 50 TCs.
    • -
    • Added a regular internals box to the Honk Brand Infiltration Kit.
    • -
    • CC officers plasmamen now get an appropriate suit.
    • -
    • Updated admin-outfitted syndicates
    • -
    • Wizard forcewalls can now be walked through by the wizard summoning them.
    • -
    • Added a new spell to the wizard spellbook, "Greater Force Wall". Summons a larger wall than the regular one, but requires wizard robes.
    • -
    • Added one box of pill bottles to Scichem
    • -
    • Replaces one of the two crew monitor consoles in medical front desk by a medical record console.
    • -
    -

    improvedname updated:

    -
      -
    • Mindshield implant, is now shown by a green flashing outline of your job hud
    • -
    • Moves some huds around to make them not overlap
    • -
    • changes some icons
    • -
    • fixes two missing pixels on execute status
    • -
    -

    uc_guy updated:

    -
      -
    • Fixes active deswords being pocketable.
    • -
    - -

    31 December 2018

    -

    Aurorablade updated:

    -
      -
    • Fixes Slaughter demons not releaseing corpses on death.
    • -
    • Fixes tears in spacetime just kinda sitting there.
    • -
    -

    Citinited updated:

    -
      -
    • Air pumps will now switch off when the inserted tank is removed.
    • -
    -

    Shadow-Quill updated:

    -
      -
    • No longer get debug messages from Slaughter Demons dropping mobs on death
    • -
    • Removed a useless comment in chronosuit code.
    • -
    -

    datlo updated:

    -
      -
    • Mech flashbang, banana, and mousetrap launchers now properly throw the item at your target instead of dropping it at the mech's feet.
    • -
    • Fixed nuclear operatives burning/choking on spawn if your set character is a plasmaman/vox. (they get healed once the round is done setting up)
    • -
    -

    farie82 updated:

    -
      -
    • Changed the laser tag gun pathing in the code.
    • -
    • Removed the / from the encryptionkey object in code.
    • -
    • Fixes the runtime in admin tickets
    • -
    -

    uc_guy updated:

    -
      -
    • Fixed death alarms / cell timer / beepsky radios.
    • -
    - -

    30 December 2018

    -

    datlo updated:

    -
      -
    • Glowsticks now process fuel properly
    • -
    - -

    29 December 2018

    -

    Alonefromhell updated:

    -
      -
    • Glowsticks are now compatible with shadowlings.
    • -
    -

    Spartan updated:

    -
      -
    • Adds emergency glowsticks to emergency box. sound: Glowsticks and flares now make more relevant usage sounds.
    • -
    -

    farie82 updated:

    -
      -
    • at the end of a radiation storm the maint access doesn't get revoked if it was set to emergency before hand.
    • -
    - -

    28 December 2018

    -

    AzuleUtama updated:

    -
      -
    • "Grenades and Explosives" category added to the uplink. Anything classed as such in the uplink has been moved here for easier access.
    • -
    -

    Ionward updated:

    -
      -
    • missing drask crusader helm #10486
    • -
    -

    Kyep updated:

    -
      -
    • Added kangaroo, a new creature type that is initially passive, but can be dangerous if provoked.
    • -
    -

    Mitchs98 updated:

    -
      -
    • All movement / pull resistance has been moved over to tg's move resist system.
    • -
    • You now drop a pull by ctrl + clicking anywhere else on the screen, rather than the object/mob being pulled.
    • -
    • All atom movables now have move force and move resist, and pull force An atom can only pull another atom if its pull force is stronger than that atom's move resist.
    • -
    • Mobs with a higher move force than an atom's move resist will automatically try to force the atom out of its way. This might not always work, depending on how snowflakey code is.
    • -
    • As of right now, everything has a move force, pull force, and resist of 1000. Structures can be crushed with sufficiently big move_force.
    • -
    • Failing to move onto a tile will now still bump up your last move timer. However, successfully pushing something out of your way will result in you automatically moving into where it was. Makes moving much smoother.
    • -
    • Mobs that shouldn't be able to pull objects now use a better check to prevent it.
    • -
    -

    Spartan updated:

    -
      -
    • ERT Medics now spawn with a medical analyser upgrade.
    • -
    • Amber ERT now spawn with a flashlight.
    • -
    • Red Engineer ERT now have an Elite ERT Hardsuit.
    • -
    • Paranormal ERT now spawn with a seclite.
    • -
    • CE toolbelt renamed. grammar: Surgery Belt > surgery belt
    • -
    -

    TDSSS updated:

    -
      -
    • clumsy people are now properly bad at handcuffing
    • -
    • Holoparasites/Guardians using the say verb now use host communication
    • -
    -

    Tails2091 updated:

    -
      -
    • Mice can *squeak now.
    • -
    -

    datlo updated:

    -
      -
    • Added the ability for command to set emergency access on all station airlocks with the keycard authentification device. (ID swiper)
    • -
    • Added the Boots of Gripping to the wizard hardsuit, sprited by Ionward
    • -
    • Fixed a cast check missing plasmaman wiz suit, causing issues with spell icons for them
    • -
    -

    improvedname updated:

    -
      -
    • Syndi emergency box to nuclear opratives.
    • -
    • Moves the suicide pill to the emergency box
    • -
    • Adds a recipe for the toolbox to make it a suspicous toolbox
    • -
    -

    name here updated:

    -
      -
    • new hat in the autodrobe
    • -
    -

    uraniummeltdown updated:

    -
      -
    • RPDs should be available in hacked autolathes again
    • -
    -

    v0idp updated:

    -
      -
    • missiles shot from missile racks in mechs will no longer spin in air
    • -
    • banana cake and slice
    • -
    - -

    26 December 2018

    -

    Shadow-Quill updated:

    -
      -
    • Fixed being able to start multiple prayers using the prayer beads.
    • -
    -

    v0idp updated:

    -
      -
    • Syndicate officer will not show in card modification/identification consoles anymore
    • -
    - -

    25 December 2018

    -

    Ranged updated:

    -
      -
    • Mutadone removes dizziness immediately instead of taking 5 minutes
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Fixes "makes frantic gestures" invalid emote with mute people using spells
    • -
    -

    improvedname updated:

    -
      -
    • fixed a typo
    • -
    -

    v0idp updated:

    -
      -
    • no bork in swedish accent while muzzled anymore
    • -
    - -

    24 December 2018

    -

    Alffd updated:

    -
      -
    • Removed fart based mechanics.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Removes "name here" from PR template
    • -
    -

    datlo updated:

    -
      -
    • Added the grenadier belt for nukies, ported from tg, containing a LOT of various grenades to throw at people.
    • -
    • Added the gluon grenade (Freeze floors and irradiate) and the frag grenade.
    • -
    • Added Toxins tech to RND. Can only be improved by testing explosives in the toxins lab, and unlocks various atmospherics tanks and items in the protolathe.
    • -
    • Added the Bluespace Rapid Pipe Dispenser, allowing you to place pipes at a distance. Built in the protolathe after improving Toxins and Bluespace tech. Sprite made by Ionward.
    • -
    • Welding Gas Mask now requires toxins tech.
    • -
    • Syndicate Officer job now available for admins, along with a brand new office connecting to the SIT, SST, and nuke ops ready room.
    • -
    • Remapped SIT and SST starting areas to be next to nuke ops starting area. Added sleepers and a couple of other QOL stuff in their ready rooms
    • -
    • Added a holding cell to the SIT starting area
    • -
    • Added a teleporter available to SIT and SST if admin enables it, can go to and from the z2 area.
    • -
    • Added an armory SST can get if admin enables it. 2 bulldogs, 2 SMG, 1 sniper, 1 medigun, 1 rocket launcher and assorted ammo.
    • -
    • Added 3 dark gygaxes, tools, and welding fuel to the SST mechbay room (admin access required)
    • -
    • Added a new subtype of mech rechargers for CC zlevel that will always recharge an attached mech even without power/recharger monitor
    • -
    • Added SIT shuttle transit area
    • -
    -

    v0idp updated:

    -
      -
    • Syndicate Officer won't show in nt recruitment anymore
    • -
    - -

    19 December 2018

    -

    Citinited updated:

    -
      -
    • Fixes a bug preventing snow machine crates from being orderable at roundstart. Ho ho ho!
    • -
    -

    uc_guy updated:

    -
      -
    • Fixed anomalies being disabled by random radio traffic.
    • -
    - -

    18 December 2018

    -

    Citinited updated:

    -
      -
    • Adds the snow machine. Fill it up with water, turn it on, and watch it create a winter wonderland all on its own! For best results set your room's air alarm to the lowest value it can go to.
    • -
    • The snow machine is orderable from cargo during Christmas time.
    • -
    • You can use a shovel to clear away generated snow. Scrooge.
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Christmas!
    • -
    -

    Ionward updated:

    -
      -
    • updated santa hat sprite, use hat to toggle beard
    • -
    -

    Tails2091 updated:

    -
      -
    • Fixes vent crawl vision sticking around for simple_animals.
    • -
    -

    datlo updated:

    -
      -
    • Added a global cap on printing papers.
    • -
    - -

    17 December 2018

    -

    MarsM0nd updated:

    -
      -
    • Restores mech radial menu functionality.
    • -
    - -

    15 December 2018

    -

    MarsM0nd updated:

    -
      -
    • radial menu now works for normally implanted implants
    • -
    -

    datlo updated:

    -
      -
    • Added sprites to specie specific boxes made by shazbot
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Me button added to chatbar
    • -
    - -

    13 December 2018

    -

    Breenland updated:

    -
      -
    • Adds drask ability to have auto-accent.
    • -
    -

    Edefff updated:

    -
      -
    • increase rollie smoketime to accommodate new chem volume
    • -
    -

    Kyep updated:

    -
      -
    • Tweaked the syndicate depot to fix various bugs and unintended design things, as well as make some changes to improve fun value.
    • -
    • Computer and machine frames are no longer invincible, and can now be destroyed by hostile NPCs.
    • -
    -

    McDonald072 updated:

    -
      -
    • Fixed being unable to cast lightning with the action button.
    • -
    -

    Mitchs98 updated:

    -
      -
    • Add's Makiroll's! Larger sliceable variants of sushi that yield four rolls of sushi in the same time that it previously took for one. You can also eat the Makiroll itself for 4x the nutriment/protein of a regular roll of sushi. Requires the Sushi Mat to craft.
    • -
    • Add's the Sushi Mat. 3 start in the chef's vendor. New ones craftable with 5 wood and 5 cable coil.
    • -
    -

    Shadow-Quill updated:

    -
      -
    • Makes people who are miming/mute give a visible indicator of their communion.
    • -
    -

    Tails2091 updated:

    -
      -
    • trimmed 300ms delay from smash.ogg
    • -
    -

    datlo updated:

    -
      -
    • Removed access requirement on emagged fax machines
    • -
    - -

    12 December 2018

    -

    Kyep updated:

    -
      -
    • Fixed a few things that should not be possible with pAIs and AIs.
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Read only sec hud for IAA and blueshield
    • -
    -

    name here updated:

    -
      -
    • Fixed Bulldog and C20 having their ammo alarms only go off once per gun.
    • -
    - -

    11 December 2018

    -

    Alonefromhell updated:

    -
      -
    • Miniature energy gun now has an action icon for it's light toggle(like flashlight).
    • -
    -

    Azule Utama updated:

    -
      -
    • Syndicate Uplink now uses expandable and collapsible categories. General layout of the uplink has also been changed to work alongside this.
    • -
    -

    Birdtalon updated:

    -
      -
    • Species specific starting boxes.
    • -
    -

    Citinited updated:

    -
      -
    • Fixes a runtime caused by AIs watching dance machines
    • -
    • You can now tape much more than just paper!
    • -
    • You can now order a crate full of sticky tape
    • -
    • Maximum amount in a tape roll is now 25 (up from 10).
    • -
    • Fixes some issues and runtimes in floorcluwne code.
    • -
    • Admins will now be informed of a new floorcluwne's chosen target if one is provided via the event.
    • -
    • There's a button next to secure storage's blast doors now.
    • -
    -

    Darkmight9 updated:

    -
      -
    • Added overheal to nanopaste
    • -
    -

    Ionward updated:

    -
      -
    • fixed slight spriting errors
    • -
    • added some more grey headwear
    • -
    -

    Kyep updated:

    -
      -
    • Fixed runtime related to chaplains.
    • -
    • Player-controlled giant spiders will no longer unintentionally poison anyone they nuzzle on help intent. They can still poison people they bite.
    • -
    • Altered the warning you get when you try to put one bag of holding inside another, so it is absolutely clear what this does, and there is no chance someone can do so by accident.
    • -
    -

    MarsM0nd updated:

    -
      -
    • Arm implants use radial menues where suitable
    • -
    • Item actions can have icons different from the icon of the item
    • -
    -

    MrKicker updated:

    -
      -
    • Sorting of call list for holopads
    • -
    -

    Shadow-Quill updated:

    -
      -
    • Makes the chem-master update it's icon on power change, as well as showing the correct sprite after being loaded in.
    • -
    • Changed Oldstation Air Alarms/APCs to no longer give warnings to the main station.
    • -
    -

    TDSSS updated:

    -
      -
    • ghost spawn menu jump and spawn buttons now work.
    • -
    -

    Tails2091 updated:

    -
      -
    • Fixed typo for Schrodinger's cat.
    • -
    -

    datlo updated:

    -
      -
    • Display case burglar alarm no longer triggered if there's no power to equipment
    • -
    -

    gangelwaefre updated:

    -
      -
    • Aesthetic changes to Lumi's custom sprites
    • -
    - -

    10 December 2018

    -

    Farie82 updated:

    -
      -
    • Can't become 1 pixel big anymore due to genetics
    • -
    - -

    06 December 2018

    -

    Shadow-Quill updated:

    -
      -
    • Fixed protocol spelling in the Photon Projector description.
    • -
    -

    TDSSS updated:

    -
      -
    • Reverted holopad sorting to make holopads work again.
    • -
    - -

    01 December 2018

    -

    Kyep updated:

    -
      -
    • Fixed a couple of bugs with the special event pets triggered by admin bless command.
    • -
    -

    TDSSS updated:

    -
      -
    • Ancient Station asteroids now contain minerals and can be mined.
    • -
    -

    datlo updated:

    -
      -
    • Added 3 carrot seed packets to perma.
    • -
    - -

    30 November 2018

    -

    Azule Utama updated:

    -
      -
    • Fixed an ORM exploit which would let you smelt invalid stacks of alloys.
    • -
    -

    TDSSS updated:

    -
      -
    • Removed ballgag and assless chaps
    • -
    - -

    29 November 2018

    -

    Kyep updated:

    -
      -
    • Updated chaplains. They now spawn with their nullrod in their hand, and their soulstone in their locker. They now have the ability to bless other players. The more players they bless, the more likely admins are to answer their prayers. There are no longer any atheist chaplains. The chaplain items that reference atheism have been tweaked accordingly, e.g the atheist fedora is now the binary fedora. A few other items have also been tweaked. Paranormal ERT members now count as holy, like the chaplain, and red/gamma paranormal ERTs get a more powerful version of the nullrod, so they have a reason to use a weapon other than their gun.
    • -
    -

    TDSSS updated:

    -
      -
    • No more making infinite meat and crashing the server with gibbers
    • -
    - -

    28 November 2018

    -

    Kyep and FoS updated:

    -
      -
    • Updated hellhound with new sprites by FoS, slightly better AI, and more fixes/tweaks.
    • -
    -

    MrKicker updated:

    -
      -
    • Sort callable holopads by name
    • -
    -

    tigercat2000 updated:

    -
      -
    • You can now speak in multiple languages in the same message! This works for all forms of speech, including radios. Minus megaphones because fuck em.
    • -
    • Some mild formatting errors and inconsistencies that have historically been present within mob speech.
    • -
    • Holopads behaving a bit weirdly with how they interact with the typical say system
    • -
    - -

    27 November 2018

    -

    Azule Utama updated:

    -
      -
    • Power beacon made purchasable again in Nuke Ops uplinks.
    • -
    -

    Dovydas12345 updated:

    -
      -
    • Fixes being able to attach IV drips when incapacitated
    • -
    -

    Farie82 updated:

    -
      -
    • You can now actually make the rescue jaws
    • -
    - -

    26 November 2018

    -

    Citinited updated:

    -
      -
    • Adds the rubbish bin in front of the kitchen again
    • -
    -

    TDSSS updated:

    -
      -
    • Medbay secondary storage is now accessible to everyone with medbay access, hardsuits were put behind a windoor with CMO access to keep them at the same level of accessability.
    • -
    • Added and removed some items from medbay secondary storage.
    • -
    • Medical storage and secondary storage were renamed to be more accurate.
    • -
    -

    datlo updated:

    -
      -
    • Updated description of finger gun to point out you can holster the gun manually by using it in hand.
    • -
    • Fixed a bug where you couldn't learn finger gun if you already knew fake finger gun.
    • -
    • Power beacon cost reduced to 10 TC, and is now hijack-exclusive.
    • -
    • Guillotines can now be deconstructed with a welder.
    • -
    - -

    25 November 2018

    -

    Azule Utama updated:

    -
      -
    • Job-specific gear can no longer be discounted.
    • -
    • Discounted items now get an alternate log entry stating the item's new price.
    • -
    -

    KasparoVy updated:

    -
      -
    • Fixes Unathi Snout 2 not using the correct sprite.
    • -
    • Fixes Unathi Points Head not using the correct sprite.
    • -
    • Fixes Unathi Sharp Tiger Head and Face not using the correct sprite.
    • -
    • Fixes Unathi Tiger Head and Face not using the correct sprite.
    • -
    • Removes Unathi Sharp Points Head and enables Unathi Points Head marking for use on all Unathi head types.
    • -
    -

    MarsM0nd updated:

    -
      -
    • Coins will now always show a side on being spawned.
    • -
    -

    Reagent Scanner Changes updated:

    -
      -
    • Removed Mass Spectrometer and Advanced Mass Spectrometer
    • -
    • Reagent Scanner and Advanced Reagent Scanners can now identify blood types
    • -
    -

    datlo updated:

    -
      -
    • Added the Advanced Mimery Series to Syndicate Mime uplink.
    • -
    • Added a fake Finger Gun manual to the arcade prize machine.
    • -
    • Changed the look of the teleporter hallway from maintenance to dirty hallway.
    • -
    - -

    24 November 2018

    -

    Azule Utama updated:

    -
      -
    • Added uplink discounts. Traitor and Nuclear Operative uplinks now have a discounted gear section! 3 random items will be chosen to be 50% off (rounded down), 25% if they usually cost 20 or more TC. You can only buy a discounted item once per uplink. Ported from TG.
    • -
    -

    Eschess updated:

    -
      -
    • hardsuit helmets now unlink from the hardsuits upon being detached
    • -
    • syndicate hardsuit helmet combat mode can no longer be toggled on hand
    • -
    • fixes non-syndicate hardsuit helmet attaching/detaching runtimes
    • -
    -

    TDSSS updated:

    -
      -
    • Space ruin/gateway hardsuits now should all come with helmets
    • -
    • Telecom setup in wizard gateway can now be completed with the present stock parts.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Added reflective blobs, these blobs have a high chance to deflect energy projectiles while being vulnerable to ballistics and brute damage. Reflective blobs can be obtained by upgrading a shield blob.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Fancier Transpara-corner Nano take 2.
    • -
    • Nano's build-watching works on 512 again.
    • -
    • Nano scrolling issues with the power monitor (they existed before I touched this goddamnit I swear!!!)
    • -
    • Rewrote Nano's buildscripts and upgraded all the dependencies (again)
    • -
    - -

    23 November 2018

    -

    Azule Utama updated:

    -
      -
    • Additional check added to damage falloff code, will only delete bullets that reach 0 damage if they actually have a falloff value.
    • -
    -

    Kyep updated:

    -
      -
    • Dead mice no longer squeak.
    • -
    • Ghosts walking over living mice no longer makes them squeak.
    • -
    -

    TDSSS updated:

    -
      -
    • no more runtime spam each time a simple mob is attacked
    • -
    -

    datlo updated:

    -
      -
    • Replaced "illegal" and "weapon" in strange objects name
    • -
    - -

    22 November 2018

    -

    AlAtEX updated:

    -
      -
    • re-adds sprites for boxes that disappeared
    • -
    -

    AlAtEx updated:

    -
      -
    • Added a new medkit for IPCs
    • -
    • added a purple medkit
    • -
    • Added a repair kit box to start with for IPC's
    • -
    • Re-added the crowbar and extended tank to miner's boxes
    • -
    • added three new box images
    • -
    -

    Azule Utama updated:

    -
      -
    • Made laser tag guns work again.
    • -
    • Syndicate Cigarettes added to maintenance loot.
    • -
    -

    Eschess updated:

    -
      -
    • Adds ui button to toggle hardsuit helmet
    • -
    • syndicate hardsuit combat mode is activated only by the helmet button
    • -
    -

    Kyep updated:

    -
      -
    • Added hellhound, a dangerous new monster.
    • -
    -

    datlo updated:

    -
      -
    • Added the CQC manual to nuke ops and traitor uplinks, letting them remember some of the basics of CQC.
    • -
    - -

    21 November 2018

    -

    MrKicker updated:

    -
      -
    • Added generated sound files to sound/vox_fem , then added references to them in vox_sounds.dm
    • -
    - -

    20 November 2018

    -

    AffectedArc07 updated:

    -
      -
    • NTTC now has multiple job tag styles
    • -
    • NTTC now has option to make job tags colored
    • -
    • NTTC now has option to make nametags colored
    • -
    • NTTC now has options to make command members louder (bold)
    • -
    • The NTTC window title is no longer NTSL.
    • -
    -

    Azule Utama updated:

    -
      -
    • Fixed chameleon suit having two invalid options.
    • -
    -

    TDSSS updated:

    -
      -
    • Silencers now have a tech origin, give research levels when deconstructed
    • -
    • Moved gun attachments to their own folder, code-wise.
    • -
    -

    name here updated:

    -
      -
    • Fixed a runtime in a syndieteam radio.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Nano scrolling is 95% less buggy
    • -
    • NanoUI's Fancy Mode now less broken as hell remove: 512 support for Nano dev tools
    • -
    - -

    19 November 2018

    -

    Birdtalon updated:

    -
      -
    • Fixes a runtime in safe.dm
    • -
    -

    Citinited updated:

    -
      -
    • Alt-clicking a jumpsuit removes accessories from it
    • -
    • Removing an accessory now shows a small message
    • -
    -

    KasparoVy updated:

    -
      -
    • Brings the logging of plasma statue ignition up to the same spec at as welder tank explosions.
    • -
    • You can no longer ignite plasma statues with disablers.
    • -
    -

    Kyep updated:

    -
      -
    • Tweaked many of the special admin outfits. This means centcom officers are less likely to be seen wielding illegal syndicate gear, and subtle flaws with many other outfits (such as pirates lacking radio, singulo knights lacking a backpack, several outfits not showing up on secHUDs correctly, etc etc etc) have been addressed.
    • -
    • Added several new admin options for fax responses, blessings, and smiting.
    • -
    -

    Quantum-M updated:

    -
      -
    • Sleeping carp uplink description now points out that it is unable to be learned by vampires or changelings.
    • -
    • Holoparasite kit uplink description now points out that it doesn't work on vampires or changelings.
    • -
    • Attempting to learn sleeping carp as a changeling or vampire gives you a red warning message.
    • -
    • You can now refund the sleeping carp scroll to the uplink.
    • -
    -

    TDSSS updated:

    -
      -
    • A warning if slings are very close to ascension, so the crew can potentially still stop them
    • -
    -

    craftxbox updated:

    -
      -
    • add observer/incapacitated check for all sec/medhud actions
    • -
    -

    datlo updated:

    -
      -
    • Added antag alert sounds that play at roundstart for most major antagonists, ported from TG.
    • -
    - -

    17 November 2018

    -

    uc_guy updated:

    -
      -
    • Syndicate borgs are no longer pseudonymous on syndie radio.
    • -
    - -

    16 November 2018

    -

    Azule Utama updated:

    -
      -
    • Changed falloff damage to be usable on any desired projectile rather than just shotgun pellets. balance: X-ray lasers now use 100 charge per shot (previously 50). balance: X-ray laser guns now have falloff damage. The longer the laser is in the air, the lower its damage becomes.
    • -
    • Slight addition to X-ray laser's description.
    • -
    -

    Certhic updated:

    -
      -
    • Replaces radio freq magic numbers with constants
    • -
    -

    Farie82 updated:

    -
      -
    • Borgs can't get perma stunned anymore by goliaths and slings and such
    • -
    -

    Fethas updated:

    -
      -
    • The floors are not safe! HONK!
    • -
    -

    Jazz23 updated:

    -
      -
    • Added flasher buttons in perma brig as well as windoors in botany, the wardens office, and cargo. Also added blast doors to transit tube.
    • -
    • HoP's flasher button not working, CE's secure shutter button and transit tube lockdown button not working.
    • -
    -

    Kyep updated:

    -
      -
    • The admin verb to list SSD players now highlights players who are another player's antag target. Additionally it lets you despawn players whose body is already in cryo.
    • -
    • Fixed a bug which caused banning to fail in rare situations.
    • -
    -

    Mitchs98 updated:

    -
      -
    • You can no longer rip the hood part of a hoodie off of someone's head.
    • -
    • Bee Costume and Monk Robe icons now show up properly in your inventory.
    • -
    -

    Triiodine updated:

    -
      -
    • Hotfixes taser projectiles being borked due to X-Ray re-work.
    • -
    -

    tigercat2000 updated:

    -
      -
    • SPEEEEEEEED to the asset cache, making preloaded UI assets transfer much faster.
    • -
    • NTTC deserializing works again
    • -
    • NTTC regex works again
    • -
    • NTTC no longer spams admins
    • -
    • NTSL2 no more, it is officially NTTC
    • -
    • NanoUI's fancy mode is hot shit again!
    • -
    • NanoUI's fancy mode is no longer broken as hell!
    • -
    • 512 support for Nano dev tools
    • -
    - -

    15 November 2018

    -

    Azule Utama updated:

    -
      -
    • Fixed an exploit which allowed cultists to curse the shuttle more than twice. Steve can only take so much punishment ya know...
    • -
    -

    Certhic updated:

    -
      -
    • The scrollbar of NanoUI now looks more Nano-ish
    • -
    • The title bar of NanoUI now sticks while scrolling
    • -
    • changed the mouse hover behavior on the fancy NanoUI buttons
    • -
    -

    Dave-TH updated:

    -
      -
    • Internal bleeding is now represented by coughing (And occasionally vomiting) blood! Nifty!
    • -
    -

    uc_guy updated:

    -
      -
    • Fixed the passive effects of prayer beads and prayer bread.
    • -
    - -

    14 November 2018

    -

    KasparoVy updated:

    -
      -
    • Vulpkanin Earfluff can be selected in facial hair again.
    • -
    • Vulpine Fluff and Earfluff head accessories and facial hair now have correct icon states.
    • -
    -

    uc_guy updated:

    -
      -
    • Borgs no longer have infinite roller beds.
    • -
    - -

    13 November 2018

    -

    Birdtalon updated:

    -
      -
    • Fixes playtime self checker.
    • -
    -

    Certhic updated:

    -
      -
    • fixed a cigs runtime error
    • -
    -

    TDSSS updated:

    -
      -
    • Ancient station's lockdown is now lifted correctly.
    • -
    • Ancient station RD console can now be used.
    • -
    -

    craftxbox updated:

    -
      -
    • use mob voice instead of mob name for radios broadcasting signals.
    • -
    -

    datlo updated:

    -
      -
    • Prevent wizards from casting rod form inside the wizard den.
    • -
    - -

    12 November 2018

    -

    Azule Utama updated:

    -
      -
    • Fixed text errors in the descriptions for Booger cocktails and Feral cat grenades.
    • -
    -

    Birdtalon updated:

    -
      -
    • Verb to check your own playtime.
    • -
    -

    CornMyCob updated:

    -
      -
    • You can now unwrench and move the library machines/computers, chem master, chem heater, washing machine, pandemic and PDA painter
    • -
    -

    Farie82 updated:

    -
      -
    • Added the pressure damage reduction to mining bots. No more killing machines called mining bots.
    • -
    -

    variableundefined updated:

    -
      -
    • AI can now select the alien screen display
    • -
    • Nearly every single sprite accessories (species customization option) has been separated and refactored. Report missing hairstyle / screen / horns / frills / tails etc.
    • -
    • Desolate's peacekeeper fluff cyborg sprite is now his service sprite.
    • -
    - -

    11 November 2018

    -

    Azule Utama updated:

    -
      -
    • Borgs can no longer stunbaton into infinity. Their batons will now deactivate if they have no power left after hitting someone and cannot be turned back on until they recharge.
    • -
    -

    Eschess updated:

    -
      -
    • large cardboard boxes now show their size when examining
    • -
    • fulltile plasma glass windows now have armor
    • -
    • rised plastitanium windows integrity
    • -
    -

    Farie82 updated:

    -
      -
    • You can now hurt mining bots with welders on any attempt other than help
    • -
    • Can put suits and such back into the suit storage units
    • -
    • Fixed the tank/magboots storage part being called Breathmask storage, lazy copy pasta
    • -
    -

    Squirgenheimer updated:

    -
      -
    • Hatched alien larvas will default to being created on the turf of the mob instead of the mob's location, unless specifically allowed (like closets and spacepods)
    • -
    -

    tigercat2000 updated:

    -
      -
    • Ears are now an organ, which can be damaged, removed, and inserted!
    • -
    • Human icon code should perform massively better.
    • -
    - -

    10 November 2018

    -

    Citinited updated:

    -
      -
    • Prevents an infinite metal exploit using the autolathe.
    • -
    • Minimum returnable metal of ammunition boxes has been lowered from 2000 to 500.
    • -
    -

    Dovydas12345 updated:

    -
      -
    • Fixes being unable to slice certain food grown by hydroponics (pineapple, watermelon etc.)
    • -
    -

    Shazbot updated:

    -
      -
    • Some fancy new box sprites, props to Shazbot for the sprites
    • -
    • Old cuff box is gone
    • -
    -

    TDSSS updated:

    -
      -
    • Quarantine is now its own lawset.
    • -
    - -

    09 November 2018

    -

    Alonefromhell updated:

    -
      -
    • Most sheets held in hand should now display either a metal or reinforced glass icon where appropriate.
    • -
    • Holopad should no longer automatically revert to default sprite.
    • -
    -

    Azule Utama updated:

    -
      -
    • Small change to cursed heart's spellbook description.
    • -
    -

    AzuleUtama updated:

    -
      -
    • RCD now gives visible messages when building without enough ammo or on an invalid tile.
    • -
    -

    Citinited updated:

    -
      -
    • Fixes ghosts being able to make conveyors drain more power than they should.
    • -
    -

    Dave-TH updated:

    -
      -
    • Space levels is named now.
    • -
    -

    Mitchs98 updated:

    -
      -
    • Chemical implants now work and can be properly filled via beaker or syringe. Reagents inside can also be syringed out.
    • -
    -

    Warior4356 updated:

    -
      -
    • Thermal Drill, Diamond Tipped Thermal Drill, Safe Codes Paper, Safe Internals, Gives Captain Floor Safe, Gives Captain Safe Codes, Safe-cracking Kit
    • -
    • Removed Captain's Digital Safe
    • -
    • Changes safe contents
    • -
    • Added a safe drilling sound
    • -
    • Added drill and safe intenral sprites made by Shazbot194
    • -
    - -

    08 November 2018

    -

    Citinited updated:

    -
      -
    • Conveyors use less power now
    • -
    -

    Eschess updated:

    -
      -
    • fixes the NOR, NAND and XOR logical gates
    • -
    • reinforced plasma glass windows give you reinforced plasma glass sheets now
    • -
    • fulltile reinforced plasma glass windows now have armor
    • -
    -

    Farie82 updated:

    -
      -
    • Mining bots now function as expected when giving them a health upgrade. No more repairing without healing
    • -
    -

    Fel updated:

    -
      -
    • You can now craft wooden barrels with 30 pieces of wood! They can hold up to 300u of reagents.
    • -
    • Putting hydroponics-grown plants into the barrel lets you ferment them for alcohol! Some give bar drinks, while others simply give plain fruit wine.
    • -
    • Reagent containers like bottle & glass should be more consistent now.
    • -
    -

    Spartan updated:

    -
      -
    • Plastic bags and wet floor signs can now spawn in maint.
    • -
    • Plastic bags are now supplied to your syndicate uplink. Apply directly to head.
    • -
    -

    Wario4356 updated:

    -
      -
    • Mecha can now drill other mecha
    • -
    -

    Warior4356 updated:

    -
      -
    • Mecha drills now tell you when they can't drill
    • -
    -

    datlo updated:

    -
      -
    • Added the Toxins Payload Casing to crafting recipes, a new method of activating tank transfer valve bombs.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Mecha now use action buttons instead of ugly verbs.
    • -
    • Mecha weapons can now be selected through a radial menu brought up by Ctrl Clicking on the Mecha while you are piloting it.
    • -
    • Tooltips now appear on radial menu buttons when you hover over them. Seriously, why wasn't this a thing in the first place?
    • -
    • Action button icons are now located in their own file.
    • -
    • Captain and HoS can be nearsighted again.
    • -
    -

    variableundefined updated:

    -
      -
    • Baycard, including tarot cards to loadout
    • -
    • Baycard to prize machine
    • -
    • All non-syndicate card deck on map has been replaced with bay card.
    • -
    - -

    07 November 2018

    -

    Spartan updated:

    -
      -
    • Bluespace Crystals no longer use the entire stack when used on self to teleport.
    • -
    -

    Squirgenheimer updated:

    -
      -
    • toggling off global antag candidacy will disable you from being selected by the Create Antagonist verb.
    • -
    -

    TDSSS updated:

    -
      -
    • added mulebot control to captain's PDA again.
    • -
    -

    name here updated:

    -
      -
    • objective lists are now sorted for admins.
    • -
    -

    uc_guy updated:

    -
      -
    • IPCs and slimes now have an effect on the floor when bleeding.
    • -
    - -

    06 November 2018

    -

    R1f73r updated:

    -
      -
    • Added a death text to headslugs when they die
    • -
    -

    Squirgenheimer updated:

    -
      -
    • blob and autotraitor game modes will now check for Global Antag Candidacy when picking new antagonists after round start
    • -
    • Global Antag Candidacy button will now show up after round start
    • -
    -

    TDSSS updated:

    -
      -
    • Can no longer attempt to build tranquilite walls (and delete the wall in the process)
    • -
    -

    TatsumakiMagi updated:

    -
      -
    • target icon updates when lit by user
    • -
    -

    Triiodine updated:

    -
      -
    • Airlock sensors & vent system to west mining outpost (Safety first!)
    • -
    • Disposals inlet now directly goes to cargo _delivery_ (not conveyor)
    • -
    • More spawns for science nerds in accordance to highpop.
    • -
    • All conflicting C_tags, dispatch cops or AI should freely use all cameras now.
    • -
    • [delta] APC to virology mainroom
    • -
    • [delta] All unsimulated turfs are now simulated.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Fixes spacing in admin deletion logs
    • -
    -

    datlo updated:

    -
      -
    • Added syndicate themed internals to traitor spacesuit and hardsuit.
    • -
    - -

    05 November 2018

    -

    AzuleUtama updated:

    -
      -
    • Added Traitor's toolbelt
    • -
    • Replaced Military belt with Traitor's toolbelt in the uplink.
    • -
    • Price of new belt lowered to 2TC
    • -
    • Replaced Military belt with Traitor's toolbelt in maintenance loot.
    • -
    -

    Regen updated:

    -
      -
    • The tentacle changeling power now generates admin logs.
    • -
    -

    TatsumakiMagi updated:

    -
      -
    • Fixes adjacency and standing checks for cutouts
    • -
    - -

    04 November 2018

    -

    AffectedArc07 updated:

    -
      -
    • Makes status display font crispy. mmmmmmmmmmmmm
    • -
    -

    Citinited updated:

    -
      -
    • Fixes a bug in machines when switching between speedy and normal processing speeds.
    • -
    -

    Dave-TH updated:

    -
      -
    • Adds the access tuner, a syndicate device for interfacing with airlocks. Try it out!
    • -
    -

    Farie82 updated:

    -
      -
    • Clings now appear dead on medical huds when using regenerative stasis
    • -
    -

    R1f73r updated:

    -
      -
    • Admin Character names will no longer appear in adminhelps
    • -
    -

    TDSSS updated:

    -
      -
    • Allow , in names, Kidan of the world, rejoice
    • -
    • Made kidan random name generation less shitty
    • -
    -

    Triiodine updated:

    -
      -
    • ghost role sprites with a palette more depressed than the playerbase
    • -
    • medical doc spawn to ghost station
    • -
    • Xydonus's second fluff item
    • -
    - -

    03 November 2018

    -

    Certhic updated:

    -
      -
    • Added diona nymph action buttons
    • -
    • Added diona nymph resist alert when they're merged
    • -
    • Diona nymph can now initiate merge with the gestalt
    • -
    • Diona nymph can now leave their gestalt by resisting
    • -
    • Diona nymph can no longer attack its gestalt
    • -
    -

    Farie82 updated:

    -
      -
    • Security comments now work again. Sec hud arrests will now function as intended.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes exploit involving materials and the recycler
    • -
    -

    Jazz23 updated:

    -
      -
    • A method of uploading coordinates to perma teleporter circuit board.
    • -
    -

    variableundefined updated:

    -
      -
    • Tigercat2000 & variableundefined (Ansari) to the maintainer list.
    • -
    - -

    02 November 2018

    -

    Purpose updated:

    -
      -
    • After over 100 years in cryosleep, a few cryocells are starting to open... AncientStation ghost roles are now available.
    • -
    • Adds a ghost role menu, available under the Ghost menu
    • -
    • Adds an all-access Air Alarm for mappers to utilise.
    • -
    • Adds glowsticks. Currently only available in AncientStation.
    • -
    -

    variableundefined updated:

    -
      -
    • Attack log to stun gloves
    • -
    - -

    01 November 2018

    -

    Citinited updated:

    -
      -
    • A disposal nullspace bug.
    • -
    -

    Farie82 updated:

    -
      -
    • Repairing a mech now says you're doing it to the others balance: Mechs now take time to repair. No more spam repairing
    • -
    • Random news feed now does not contain random code.
    • -
    -

    Mitchs98 updated:

    -
      -
    • Lowers the spam you receive from entering a warm or cold pool. You will no longer receive 'The water is quite warm.' nearly every few seconds.
    • -
    • Headslugs no longer teleport out of closed lockers upon bursting.
    • -
    -

    Warior4356 updated:

    -
      -
    • Ghosts can no longer re-enter a drone that has been shut down.
    • -
    - -

    31 October 2018

    -

    Arkatos updated:

    -
      -
    • Fixes Rewriter drink description typo.
    • -
    -

    Jountax updated:

    -
      -
    • Renamed Ice Peppers to Chilly Peppers.
    • -
    -

    TatsumakiMagi updated:

    -
      -
    • fixed merch shop, arcade shop and the give command working from a distance
    • -
    - -

    30 October 2018

    -

    Dave-TH updated:

    -
      -
    • Adding a paper to a paper bundle no longer automatically opens the bundle.
    • -
    -

    Farie82 updated:

    -
      -
    • Items dropped in a space pod are now under the seat. No more magical dropping out of the pod
    • -
    • Cargo can now buy oil tanks.
    • -
    -

    Warior4356 updated:

    -
      -
    • Megaphone now handle speech impediments properly
    • -
    • Swiping an ID through a drone no longer causes a runtime and correctly shuts it down
    • -
    • Silicons are now able to open a door linked to a button regardless of proximity
    • -
    -

    uc_guy updated:

    -
      -
    • You can no longer table people through walls/doors/shutters.
    • -
    -

    warior4356 updated:

    -
      -
    • fixed the holosign in surgery1
    • -
    - -

    29 October 2018

    -

    Farie82 updated:

    -
      -
    • Round start time is now variable. Defaults to 240 if not filled in
    • -
    -

    Mitchs98 updated:

    -
      -
    • Re-Adds a Guest Pass terminal to Medbay front desk.
    • -
    -

    Squirgenheimer updated:

    -
      -
    • regular mining satchels will now only hold 10 slots of ore stacks instead of 50
    • -
    • Deleting mechs no longer causes a runtime
    • -
    • Mech speech bubbles should now follow the mech.
    • -
    -

    gatchapod updated:

    -
      -
    • Fixed airlocks electrocuting people remotely through open UI
    • -
    - -

    28 October 2018

    -

    Dovydas12345 updated:

    -
      -
    • Fixed being able to pull when incapacitated
    • -
    • Fixes catching two handed items with one hand.
    • -
    -

    Fox McCloud updated:

    -
      -
    • changes the oil can sprite
    • -
    • Colorful Reagent changes your blood color
    • -
    -

    Mitchs98 updated:

    -
      -
    • Adds the Security Jacket to the standard sec gear lockers, an alternative to the standard armor vest that covers more area but protects less. Style matters.
    • -
    -

    Normalyman updated:

    -
      -
    • Fixed being able to open containers via dragging, while being incapacitated.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Pulling fixed
    • -
    • Better way of fixing hostile mobs not attacking
    • -
    • Hostile mobs attack again instead of nuzzle
    • -
    -

    uc_guy updated:

    -
      -
    • Fixes shadowling game mode delaying the game ticker
    • -
    - -

    27 October 2018

    -

    AffectedArc07 updated:

    -
      -
    • Removed catgirls, be gone foul beasts
    • -
    -

    Alonefromhell updated:

    -
      -
    • Runtime in species.dm, 620 fixed
    • -
    • Stable LDM and Sorium creates their vortexes properly now.
    • -
    • Inject chems into all your favorite types of smokeables, TODAY!
    • -
    • Backend: Added dummy vortex reagents to prevent further runtimes.
    • -
    -

    Certhic updated:

    -
      -
    • fixed wrenched down unconnected pipes being invisible
    • -
    • fixes invisible diona observers
    • -
    • Fixes simple animals attacking while they were on help intent.
    • -
    -

    Farie82 updated:

    -
      -
    • Dusting a mob now dusts everything he holds and has equiped
    • -
    • fixes animals activating the paperfolding proc. No more runtimes there
    • -
    • One less piano runtime
    • -
    • fixes the runtime in the AI code. You now get messages if you lose power and stuf.
    • -
    • Fixes the runtime in Landmarks
    • -
    -

    TDSSS updated:

    -
      -
    • HoP's door remote has access to his office doors + supply doors now
    • -
    -

    tigercat2000 updated:

    -
      -
    • Pretty radial menu for the RCD!
    • -
    • SSoverlays human mobs
    • -
    • Catgirls!
    • -
    • /tg/'s catgirl refugees
    • -
    • Ears are now organs
    • -
    • The suffering of thousands of displaced kittens
    • -
    -

    uc_guy updated:

    -
      -
    • Fixed roller beds not going to their "down" position.
    • -
    • You can now tell if a borg has suicided by examining them
    • -
    - -

    26 October 2018

    -

    Mitchs98 updated:

    -
      -
    • Unary vents, scrubbers, passive vents, connectors, air injectors, and pipe caps now orientate as intended when using Orientate Automatically with an RPD.
    • -
    • Fixes #8036, Door controls not respecting range for pod doors.
    • -
    • Now when holding a flag it won't be stabbing into your characters face. Burning a flag also won't magically change its orientation.
    • -
    -

    dovydas12345 updated:

    -
      -
    • Fixes ghosts being able to unflip flipped tables.
    • -
    -

    uc_guy updated:

    -
      -
    • Syndicate communication channel is now pseudonymous.
    • -
    - -

    25 October 2018

    -

    Aurorablade updated:

    -
      -
    • welders will now fix external IPC leaking. My Bad.
    • -
    -

    Birdtalon updated:

    -
      -
    • User responses not being appended to admin tickets
    • -
    -

    Dave-TH updated:

    -
      -
    • Adds surgical trays! You can drag these cool tables around and the items placed on them come along for the ride! Nifty!
    • -
    -

    Farie82 updated:

    -
      -
    • Objectives now get fully removed when removing them admin style. Removing the assassinate cryo message if you were de antagged.
    • -
    -

    tigercat2000 updated:

    -
      -
    • PiP Hud Elements
    • -
    • AI PiP Multicam - Enabled by admins
    • -
    • Calling /New( with excess arguments is now properly directed to /Initialize(
    • -
    - -

    24 October 2018

    -

    Alonefromhell updated:

    -
      -
    • Mind check in pre_quip added, to prevent runtime.
    • -
    -

    Birdtalon updated:

    -
      -
    • Backend cleanup of assembly.dm and proximity.dm
    • -
    -

    Certhic updated:

    -
      -
    • Runtime error in CureIfHasDisability
    • -
    • Borg health is now updated after being repaired
    • -
    -

    Farie82 updated:

    -
      -
    • Tablets now spawn correctly. No more buying (seemingly) broken tablets
    • -
    -

    Fethas updated:

    -
      -
    • Ipcs bleed oil. Bleeding can be patched by welders and organ mainp surgery(if you have to heal an ipc via surgery we may as well take that out too).
    • -
    • Kidan biolum slightly brighter. tweak:Vox now become confused and unintellible(..more) on cort stack damage.
    • -
    -

    Warior4356 updated:

    -
      -
    • Safe tumbler 2 no longer makes I am open noise when turning tumbler 1.
    • -
    -

    dovydas12345 updated:

    -
      -
    • Added data disk to misc designs.
    • -
    -

    variableundefined updated:

    -
      -
    • Using reagent dispenser like fuel and water tank no longer give you an attack cooldown / animation.
    • -
    • Tracking for shadowling win rate. Improved parsability for other win/loss round type's win rate.
    • -
    - -

    23 October 2018

    -

    Alonefromhell updated:

    -
      -
    • You should now be able to put all your favorite chems in food again.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Reagents now GC slightly better
    • -
    - -

    22 October 2018

    -

    Dave-TH updated:

    -
      -
    • Fancy tables now properly smooth.
    • -
    -

    MrStonedOne updated:

    -
      -
    • Fixes a cause of lag in the Timer subsystem
    • -
    -

    Purpose updated:

    -
      -
    • Removes unused code in Nuclear gamemode.
    • -
    • Removes some empty icon files.
    • -
    • Fixes a typo in an SDQL parse warning.
    • -
    • Code improvement with timers in Revolution gamemode.
    • -
    -

    name here updated:

    -
      -
    • The autopsy scanner now works even when it does not know the weapon and/or the time of death.
    • -
    • Unused weapon chance code
    • -
    -

    uc_guy updated:

    -
      -
    • Removed logging ambiguity for uplink purchases.
    • -
    -

    variableundefined updated:

    -
      -
    • Component refactor from tg made by ninjanomnom has been ported over. Report unexpected issue (with autolathe / ORM)
    • -
    - -

    21 October 2018

    -

    Alonefromhell updated:

    -
      -
    • Fixed some formatting issues in post_equip.
    • -
    -

    Ansari updated:

    -
      -
    • Oculine processing should be less expensive now.
    • -
    -

    Desolate updated:

    -
      -
    • Refactors some reagent lists into global list
    • -
    -

    Farie82 updated:

    -
      -
    • Cyborgs can now refill welding tools and fire extinguishers using the recharging station
    • -
    • Oculine now updates the blindness status correctly
    • -
    • Added the Viral Injector. A virologist specific traitor item that acts like a sleepy pen but can transfer viruses. It's disguised as a functional pipette.
    • -
    -

    Purpose updated:

    -
      -
    • Moves Icon Smoothing to a Subsystem.
    • -
    • Atom code will no longer track a list atoms, for literally zero reason.
    • -
    • Fixes grammatical error in the suit storage unit
    • -
    -

    Shazbot194 updated:

    -
      -
    • all north facing in hand icons for flags.
    • -
    -

    Squirgenheimer updated:

    -
      -
    • Explosive holoparasite booby traps will now behave better, such as correctly triggering on mobs
    • -
    -

    Triiodine updated:

    -
      -
    • Skrell & Tajaran sechardsuit to paracode palette, from Bay12 palette.
    • -
    • TG & BS12 sec-hardsuits in all dmis
    • -
    -

    Warior4356 updated:

    -
      -
    • Final UI update was missed in Safe Refactor PR
    • -
    -

    name here updated:

    -
      -
    • Holodeck plating sprite is now back to the old one.
    • -
    -

    tigercat2000 updated:

    -
      -
    • We're going 512 boisssssssssssssss
    • -
    -

    variableundefined updated:

    -
      -
    • Improves the List free slots admin verb to show useful information.
    • -
    • Cyborg hypospray's attack log message should no longer be reversed.
    • -
    • How containers work is now standardized in the back-end. There might be unexpected or odd bugs with containers and reagent transfer, please report them.
    • -
    • Minor refactor of revenant code.
    • -
    • Some relative path & commented out code has been cleared up in code. Report unexpected issues.
    • -
    - -

    20 October 2018

    -

    Birdtalon updated:

    -
      -
    • Spacepods explosions are significantly reduced.
    • -
    -

    Dapocalypse updated:

    -
      -
    • Adds password protected files to modular computer.
    • -
    -

    Farie82 updated:

    -
      -
    • Guardian injectors now tell in their examination text if they are spend or not.
    • -
    • Added feedback on the RCD airlock access topic.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Updates the Garbage SS so it's less likely to induce lag
    • -
    -

    Purpose updated:

    -
      -
    • Suit storage units now contain magboots for relevant roles.
    • -
    • Adds the captains jetpack to his suit storage unit, so it is now stealable again on Delta.
    • -
    • Aluminum & Aluminium properly standardized.
    • -
    -

    craftxbox updated:

    -
      -
    • added check to make sure person downloading pAI isnt dead.
    • -
    -

    uc_guy updated:

    -
      -
    • It is no longer possible to duplicate uvents.
    • -
    -

    variableundefined updated:

    -
      -
    • Plating's icon is back to the old one once again.
    • -
    - -

    19 October 2018

    -

    Fox McCloud updated:

    -
      -
    • Fixes round-start sparks being stuck in maintenance
    • -
    -

    Purpose updated:

    -
      -
    • Fixed an issue with Space Vine mutations
    • -
    -

    SpaceManiac updated:

    -
      -
    • The body zone selector now indicates which body part you are about to select when hovered over.
    • -
    -

    TDSSS updated:

    -
      -
    • New exosuit equipment: The rescue jaws for the Odysseus lets it open doors, firelocks and even force powered doors. It can also be added to firefighter ripleys.
    • -
    -

    Triiodine updated:

    -
      -
    • new DNA Sampler Sprite
    • -
    -

    Warior4356 updated:

    -
      -
    • Added nanoui for safe. Added minor quality of life to safe.
    • -
    • Removed old UI from safe
    • -
    • Safe now is only Right - Left - Right. Safe is 0-99 rather than 0-71.
    • -
    • Added safe dial for it's nanoui.
    • -
    - -

    18 October 2018

    -

    IrkallaEpsilon updated:

    -
      -
    • Feral Cat grenades are now listed as job specific items.
    • -
    -

    Shazbot updated:

    -
      -
    • Shazbot's custom cyborg sprites.
    • -
    -

    Squirgenheimer updated:

    -
      -
    • Ghosting from cryopods with an inventory open should no longer cause a runtime
    • -
    -

    Triiodine updated:

    -
      -
    • disposals pipes sprite offsets & stray pixels.
    • -
    • id_decal icons
    • -
    • arcade id_decals using mind batterer sprite. (That's just silly.)
    • -
    - -

    17 October 2018

    -

    Alonefromhell updated:

    -
      -
    • Added a Nanotrasen Navy Uniform to the blueshields locker
    • -
    -

    Crazylemon updated:

    -
      -
    • Buildmode is now compatible with 511 clients.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Floodlights will now shut off if lacking a power cell.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes the Timer SS timing out when it shouldn't
    • -
    • Fixes reagent overdose runtimes
    • -
    -

    TDSSS updated:

    -
      -
    • Examining a borg tells you what module it has loaded
    • -
    -

    datlo updated:

    -
      -
    • Added the Honk Brand Infiltration Kit to Nuke Ops.
    • -
    - -

    16 October 2018

    -

    FalseIncarnate updated:

    -
      -
    • Corpse spawners (such as those on the Wild West away mission) now properly spawn corpses at roundstart that don't remain standing.
    • -
    - -

    15 October 2018

    -

    FreeStylaLT updated:

    -
      -
    • Crunchy sounds when bones are broken
    • -
    -

    Squirgenheimer updated:

    -
      -
    • Changelings will now wake up after using Regenerative Stasis.
    • -
    -

    TDSSS updated:

    -
      -
    • The maximal length of a name that won't be rejected as a 'bad name' has been raised.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Fixes stunbaton runtime (Stun() being called on a turf)
    • -
    • Borers with their "Dominate" window already open can no longer run across the map and successfully cast the spell on those people, they must be within 7 tiles (default view range)
    • -
    • Borers can no longer spam open the "Dominate" spell
    • -
    • Borers with their "Dominate" target window already open can no longer successfully target someone if they are dead
    • -
    • Borers no longer "slither up and probe people's ear canal" if they select the target of an "infect host" spell after they die
    • -
    -

    uc_guy updated:

    -
      -
    • You can no longer roll around when dead.
    • -
    - -

    14 October 2018

    -

    Purpose updated:

    -
      -
    • Makes it so that Screwdrivers & Wirecutters are no longer invisible in the map editor.
    • -
    • Fixes a gibbing runtime
    • -
    -

    taac updated:

    -
      -
    • added cryo cell description
    • -
    -

    uc_guy updated:

    -
      -
    • fixed runtime in IsBanned.dm
    • -
    -

    variableundefined updated:

    -
      -
    • Stacks are split by CtrlShiftClick instead of AltClick now.
    • -
    • A runtime that occurs with paper bundle being created with one or less paper.
    • -
    - -

    13 October 2018

    -

    Birdtalon updated:

    -
      -
    • Chem master now will show its de-powered state properly.
    • -
    -

    DarkPyrolord updated:

    -
      -
    • Changed attack log level for reagent forcefeeding from FEW to MOST
    • -
    -

    FlimFlamm updated:

    -
      -
    • Tweaked formatting of Newscaster stories
    • -
    • Fixes images displaying improperly on Newscaster stories
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Boxing logs moved to the ALL preference
    • -
    -

    alex-gh updated:

    -
      -
    • Species damage modifiers now only affect damage, not healing.
    • -
    • Races that took more damage from certain damage types no longer heal from that damage type faster. For example: Drask no longer heal from burn at double rate; Grey, Vox no longer heal from brute at increased rate (Note: IPC healing with welders/wires is not affected).
    • -
    • Kidan no longer heal from brute at a reduced rate.
    • -
    -

    uc_guy updated:

    -
      -
    • You can no longer get an infection and die during abductor surgery.
    • -
    • Voice analyzers no longer activate on noise.
    • -
    - -

    12 October 2018

    -

    Alonefromhell updated:

    -
      -
    • META - Cargo shuttle blast doors now reacts to the right button.
    • -
    • META - Cargo shuttle airlocks now bolt properly.
    • -
    • META - Cargo shuttle flaps are now airtight. All hail Cargonia.
    • -
    -

    Birdtalon updated:

    -
      -
    • Gamma ERT Paranormal gets their null rod.
    • -
    • Moves check_and_add() to reagents holder
    • -
    -

    DesolateG updated:

    -
      -
    • Refactors global var lists to use the global subsystem.
    • -
    -

    Farie82 updated:

    -
      -
    • Added the on_give proc for items. Was needed for the fixes
    • -
    • Giving two handed items like the DIY chainsaw and potted plants now works correctly
    • -
    • The DIY chainsaw, doomslayer chainsaw and the potted plants now do damage when given to somebody else and when picked up while the chainsaw was on.
    • -
    -

    Purpose updated:

    -
      -
    • Cyberiad's grimy tiles are now actually dirty and cleanable.
    • -
    • Delta's grimy tiles are now actually dirty and cleanable.
    • -
    • Ironsand is now visible in the Map Maker.
    • -
    • Away missions updated with the appropriate dirt/grime so that it is now cleanable.
    • -
    • Fixes stool's unique suicide message.
    • -
    • Fixes rollerbeds no longer going through plastic flaps.
    • -
    -

    TDSSS updated:

    -
      -
    • Removed Skrell discrimination, allows ! character in IDs (agent IDs or made via ID computer)
    • -
    -

    variableundefined updated:

    -
      -
    • Ore now represented by stack that holds up to 50 items. Should reduce lag with ORM greatly.
    • -
    • Satchel can only carry ten items instead of 50 items. You should end up carrying more ore in total however
    • -
    • Fire acting on ore means they would be refined with 50% efficiency.
    • -
    • Stack merges automatically if dropped on the floor, or a new stack is created. This doesn't happens on your body.
    • -
    • They also merge if you drag them over eachother.
    • -
    • Alt-click split a stack
    • -
    • You can throw sand into people's eyes! Pocket sand!
    • -
    • Phazon take 5 bluespace crystal to construct now instead of 1. remove: Transfer prompt when you click on a stack of the same type with a stack
    • -
    - -

    11 October 2018

    -

    Citinited updated:

    -
      -
    • Fixes an oversight in autopsy report drawer's description.
    • -
    -

    Farie82 updated:

    -
      -
    • NPC's now initialise correctly. Removing a lot of runtime errors.
    • -
    -

    Kyep updated:

    -
      -
    • Fixed the admin ERT panel not working correctly if the admin using it was playing as a carbon mob.
    • -
    -

    Stork Industries updated:

    -
      -
    • Fixes "Arachno-Man's" boots
    • -
    -

    Triiodine updated:

    -
      -
    • SLOT_MASK from necklaces.
    • -
    • thatdanguy23's fluff item
    • -
    - -

    10 October 2018

    -

    Alonefromhell updated:

    -
      -
    • You should no longer be able to relight a burned match by using a shoe.
    • -
    -

    Birdtalon updated:

    -
      -
    • Small runtime in tickets.dm
    • -
    • Mulebot teleportation exploit.
    • -
    • Iron sand icons now render correctly.
    • -
    -

    Citinited updated:

    -
      -
    • Emagging a locker will keep the original description instead of telling you it was emagged twice.
    • -
    • Examining airlocks displays the proper icon now
    • -
    • Holopads don't work when unanchored any more.
    • -
    -

    Purpose updated:

    -
      -
    • Fixes a few broken tiles in maintenance, by breaking those tiles properly.
    • -
    -

    Purpose & AndrewMontagne updated:

    -
      -
    • New grimy dirt sprites.
    • -
    • Dirty tiles now get dirtier if neighbouring tiles are also dirty.
    • -
    -

    Triiodine updated:

    -
      -
    • new sprites for cup-chicken soup, icecups, weight loss shakes.
    • -
    • cup to can of chicken soup.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Fixes PAIs
    • -
    • Ambulances work again
    • -
    -

    Warior4356 updated:

    -
      -
    • added Grey sprite for psysuit, made by dumbdumb
    • -
    -

    tigercat2000 updated:

    -
      -
    • Hovering over an inventory slot now shows an indicator for if that item can go in that slot or not. Pretty!
    • -
    • SSOverlays has been added, but not implemented!
    • -
    - -

    09 October 2018

    -

    Alonefromhell updated:

    -
      -
    • Edited the attack text of the teleport armor.
    • -
    -

    Birdtalon , LPSpartan, Shazbot, Memager updated:

    -
      -
    • Portable Body Analyzer for ERT
    • -
    • Muilti Lens Immolation gun for gamma ERT
    • -
    • PDW-9 sidearm for ERT
    • -
    • T4 Thermite Charge for Gamma ERT security
    • -
    • Sprites for gamma ERT suits
    • -
    • Red ERT loadouts
    • -
    • Gamma ERT loadouts
    • -
    -

    Citinited updated:

    -
      -
    • Conveyor belts have received a facelift!
    • -
    • Rotating a belt with a wrench now nicely rotates the belt for you
    • -
    • Click a lever with a lever to link their IDs. Click a belt with a lever to link that belt to that lever.
    • -
    • Deconstructing a syndicate console will no longer ruin it forever.
    • -
    -

    DesolateG updated:

    -
      -
    • Refactors the timer subsystems and bugfixes
    • -
    -

    Purpose updated:

    -
      -
    • Code improvements on mouse_opacity
    • -
    • Plating shadow faux 3d now works properly.
    • -
    -

    Purpose & AndrewMontagne updated:

    -
      -
    • Adds tile smoothing to plating. Plating should now be a bit more of a 3d look...
    • -
    -

    Purpose & Birdtalon updated:

    -
      -
    • Takes Runtime out of the oven.
    • -
    -

    Squirgenheimer updated:

    -
      -
    • fixed a potential runtime in the sentient animal event
    • -
    -

    Triiodine updated:

    -
      -
    • Tidied up nuclear shuttle's mini-medbay to better utilize the space provided.
    • -
    • Full Body-Scanner, surgery set, replacement limbs, bloodpacks to the nuclear shuttle's mini-medbay.
    • -
    • One of the nuclear shuttle's sleepers.
    • -
    -

    uc_guy updated:

    -
      -
    • Legless human mobs no longer scream non-stop when buckled into a chair.
    • -
    -

    variableundefined updated:

    -
      -
    • Poolcontroller performance are improved dramatically. Expect slightly reduced CPU use on beach gateway map
    • -
    • Poolcontroller will no longer work properly if you directly var-edit someone's location to inside a body of water and a decal's (However if the mob move right after it will still work)
    • -
    - -

    08 October 2018

    -

    Ansari, Birdtalon updated:

    -
      -
    • Updates resting procs, fixes getting people up from help intent.
    • -
    -

    Birdtalon updated:

    -
      -
    • Conservation of damage mechanic for set species
    • -
    • Changeling transform conserves damage when transforming to a different species.
    • -
    -

    Crazylemon updated:

    -
      -
    • Fixes AIs being unable to examine due to a runtime.
    • -
    • Fixes nearsighted glasses behavior being inverted (seeing worse with glasses).
    • -
    • Mining mobs now update their sprites on death.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Updates for damage on HUD elements are now instant for cyborgs and humans.
    • -
    • When dead, you can now see your surroundings with ghost vision and examine things around you.
    • -
    -

    Farie82 updated:

    -
      -
    • PANDEMIC can print a virus release form now. Viromancers REJOICE!
    • -
    -

    Purpose updated:

    -
      -
    • Adds the missing turfs under windows & doors on Mech Transport Space ruin.
    • -
    • Fixes improper turf in the shuttle crashed into one of the space ruins.
    • -
    • Fixing improper decals & missing turfs in the Space Bar space ruin, and some tiny fixes.
    • -
    • GasTheLizard Space Ruin now uses Decals properly.
    • -
    • MoonOutpost19 Away Mission now uses Decals properly.
    • -
    • Evil Santa Away Mission now uses Decals properly.
    • -
    • Fixes the corpse spawners in Space Battle Away Mission.
    • -
    • Space Battle Away Mission now uses Decals properly.
    • -
    • Prettier Donate/Karma buttons!
    • -
    • Adds new stair sprites.
    • -
    • Blackmarket Backpackers now uses Decals properly.
    • -
    • OneHalf Space Ruin now uses Decals properly.
    • -
    • CentComm Away Mission now uses Decals properly.
    • -
    • Cyberiad Z2 now uses Decals properly.
    • -
    • Space Hotel Away Mission now uses Decals properly.
    • -
    • Terror Spiders Away Mission now uses Decals properly.
    • -
    • Adds plasma window spawners for mappers.
    • -
    • Thrown stunbatons & improvised batons have a low chance to stun.
    • -
    • You can now alt click breath masks to pull them up & down.
    • -
    • You can no longer erroneously pull down a vox mask.
    • -
    • TravisCI now checks all space ruins & away missions for integration.
    • -
    -

    Triiodine updated:

    -
      -
    • Rsik's fluff katana ~~modkit~~
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Replaces Security's bomb suit with their cooler Security version
    • -
    • Fixes runtime in world.dm;127
    • -
    -

    tigercat2000 updated:

    -
      -
    • Made mind.dm 1/1000 less awful.
    • -
    -

    variableundefined updated:

    -
      -
    • NPCpool (SNPC) is now a subsystem.
    • -
    • NPCAI (For simple mob) is now a subsystem.
    • -
    • Customising SNPC no longer results in screaming death and a naked person.
    • -
    • Logging added to RD teleport gun, some projectile are always logged
    • -
    • EMPulse & Explosion can optionally log a cause for administrative purpose
    • -
    • Backend Attack logs now display coordinates of attacker & defender for forensic reconstruction.
    • -
    • Grill shock cooldown is 1 second instead.
    • -
    - -

    07 October 2018

    -

    Birdtalon updated:

    -
      -
    • Ammo boxes now return materials proportional to their contents when recycling, nullifying infinite ammo exploit.
    • -
    -

    Farie82 updated:

    -
      -
    • Fixing a disability now fixes the gene related to it if needed. No more free gene stability from blindness and such
    • -
    • fixed bluespace disposal bins
    • -
    • instant recall doesn't fuck up disposals
    • -
    • meteor shots now deconstruct the disposals unit, removing weird behaviour
    • -
    -

    Purpose updated:

    -
      -
    • Winged chairs now get placed back down correctly as winged chairs.
    • -
    • CyberiadAI Discord Bot now announces which station is being used.
    • -
    • Less things will refer to the NSS Cyberiad when not actually ON the NSS Cyberiad.
    • -
    • Decals now Initialize()
    • -
    -

    SkeletalElite updated:

    -
      -
    • Fixed grammar in meat spike's name
    • -
    • Chaos Holoparasite's abilities actually work
    • -
    -

    datlo updated:

    -
      -
    • Changelings with wingdings now permanently switch to regular speech after transforming
    • -
    -

    variableundefined updated:

    -
      -
    • All sharp items can cut sliceables like cheesewheel now.
    • -
    • Putting items inside sliceables is done by alt-click now.
    • -
    - -

    06 October 2018

    -

    Alonefromhell updated:

    -
      -
    • META - Cryogenics now has a Cellcharger.
    • -
    -

    Purpose updated:

    -
      -
    • Delta - Adds a Paramedic's Office.
    • -
    • Latejoining autotraitors should now have their uplinks again.
    • -
    • You can now pick up most chairs and beat colleagues with them. Careful too many whacks and they'll break.
    • -
    • Adds new bar stools.
    • -
    • Delta - Removes extra door in arrivals.
    • -
    -

    Squirgenheimer updated:

    -
      -
    • Victims of changeling swap forms and wizard mindswap can now re-enter their corpses
    • -
    - -

    04 October 2018

    -

    Alonefromhell updated:

    -
      -
    • Sensory Restoration should now work with Ocular Restoration.
    • -
    -

    Farie82 updated:

    -
      -
    • borgs can now heal their patients while there is a surgery going on.
    • -
    -

    Purpose updated:

    -
      -
    • Boxstation: Fixed a number of turf/decal/overlay issues
    • -
    • Boxstation: The poster in medbay maintenance now displays properly...
    • -
    • Boxstation: Xenobio slime cameras should no longer be able to see into maintenance.
    • -
    • Boxstation: Adds missing firelock to vacant office.
    • -
    • Boxstation: Moves Medbay AIR Alarms around to more functional locations.
    • -
    • Boxstation: Fixes 'fake grass' in the kitchen area.
    • -
    • Boxstation: Fixed several issues were Radiation Storm events could bleed into maintanence.
    • -
    • Boxstation: ALL catwalks should now be able to see space through the holes.
    • -
    • Delta - Adds fuel depo to the hanger.
    • -
    • Delta - Adds the Nullrod & Shard to the Chaplain's back office.
    • -
    • Delta - Fixes the invisible wardrobe in the dorms.
    • -
    • Delta - Adds a few art vendors across the station.
    • -
    • Delta - Adds the buttons to the Perma Airlock.
    • -
    • Delta - Doctors now have access to the patients rooms. Oops.
    • -
    • Delta - Adds the Coroner's spawn point in the morgue.
    • -
    • Delta - Increases blood packs in medbay, by random blood spawners.
    • -
    • Delta - Fixes the exit button of Medbay.
    • -
    • Delta - Increases the size of the atmos space loop.
    • -
    • Delta - No longer can maintenance fire lasers at the Supermatter....
    • -
    • Delta - Added some wiring to make it easier to emitter the SM.
    • -
    • Delta - Extends the wiring out of solars airlocks in atmos solars.
    • -
    • Delta - Atmos now have access to Atmos solars.
    • -
    • Delta - Adds an additional atmos void suit.
    • -
    • Delta - Adds two additional engineering void suits, but into secure storage.
    • -
    • Delta - Fixes the missing airlock cycling on an atmos airlock.
    • -
    • Delta - Adds the missing multi-tool to atmospherics.
    • -
    • Delta - Fixed Mixed Air & Gas Mix computers access to the tanks & sensors.
    • -
    • Delta - Can now cross parts of the transit tube.
    • -
    • Delta - Garbage disposal is now functional.
    • -
    • Delta - Disposals no longer fires trash into the atmos office.
    • -
    • Delta - Atmos techs now have access to the jetpacks in EVA.
    • -
    • Damaged plating when fixed, now loses the aesthetic damage too.
    • -
    • Yellow closets now use the correct icons.
    • -
    - -

    03 October 2018

    -

    Farie82 updated:

    -
      -
    • Your hands won't become the surgeons hands anymore in surgery
    • -
    -

    Fethas updated:

    -
      -
    • Cryostorage ghost role spawners for ruin/mapping/adminbus. Also refactors corpse landmark code.
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Remapped Medbay Lobby.
    • -
    • Moved the cell charger from Cryo to the break room.
    • -
    • Added a cell to Medbay's break room.
    • -
    - -

    02 October 2018

    -

    Birdtalon updated:

    -
      -
    • Small formatting fix in soulstone.dm
    • -
    -

    Kurgis updated:

    -
      -
    • The chief engineer jumpsuit no longer appears as a green suit when held in-hand.
    • -
    • Added a new in-hand sprite for the chief engineer jumpsuit from Polaris.
    • -
    -

    Purpose updated:

    -
      -
    • Delta Station, codenamed Kerberos has been acquired by Nanotrasen.
    • -
    • Wizard Academy now uses decals
    • -
    • Wizard Academy misplaced wires fixed
    • -
    -

    Tails2091 updated:

    -
      -
    • Claw Game is now a bit easier to use. Slower speeds, still receive prize when interrupted, and auto-close.
    • -
    • Claw Game has correct window size, centered buttons, general code cleanup.
    • -
    -

    name here updated:

    -
      -
    • Remove canvas and easel from Deltastation
    • -
    -

    tigercat2000 updated:

    -
      -
    • Chat no longer horribly breaks at the first high-ascii character.
    • -
    - -

    01 October 2018

    -

    Aurorablade updated:

    -
      -
    • adjusts to Arachno-Man suit fluff.
    • -
    -

    Birdtalon updated:

    -
      -
    • Admin ticket subsystem - migrates existing global datum.
    • -
    -

    Dapocalypse updated:

    -
      -
    • Added a grille cooldown to prevent alt-click spam someone on a grille to instantly husk people.
    • -
    -

    Farie82 updated:

    -
      -
    • Not being able to place chutes over tiles with multiple pipes.
    • -
    -

    Purpose updated:

    -
      -
    • CPU Performance in get_area proc
    • -
    • Excavates a few relics from area code.
    • -
    • Metastation - Escape Shuttle windows are now breakable again.
    • -
    • Metastation - Medbay camera no longer floating in mid-air.
    • -
    • Metastation - Adds the missing component analyzer to Robotics.
    • -
    • Metastation - Fixes the wiring issues in Medbay.
    • -
    • Metastation - Fixes the wiring issues in Virology.
    • -
    • Metastation - Fixes the lack of fungus on the map, placing it near water sources in maintenance.
    • -
    • Metastation - Fixes area definition, so that admins can now send people to cryo.
    • -
    • Metastation - Fixes bizarre map corruption from the Arcade PR which turned Coroners into a bit of an arcade....
    • -
    • Metastation - Law office's shutters now grant privacy properly.
    • -
    • Metastation - Fixes the lack of inflatables & pipe painter in Atmospherics
    • -
    • Metastation - Adds a second atmos locker, as one is lower than number of atmos slots available....
    • -
    • Metastation - Properly marks airless tiles by the hanger as airless.
    • -
    • Metastation - Hooks up Security's Camera Computer to the station's cameras...
    • -
    • Metastation - Fixes the floating fire alarm in Security.
    • -
    • Metastation - Fixes the detective's lack of Evidence Storage access...
    • -
    • Metastation - Captain, IAA and NT Rep's fax machines are hooked up properly. Bloody IT department...
    • -
    • Metastation - Security cannister attachment is now attached to the pipe grid.
    • -
    • Metastation - Bots now correctly patrol the station again.
    • -
    • Metastation - Updates the turfs & decals to use the correct decals.
    • -
    -

    Purpose & AndrewMontagne updated:

    -
      -
    • Tiles now retain the styling when damaged.
    • -
    • Tile damage now uses decals, and can be mapped easier.
    • -
    -

    TDSSS updated:

    -
      -
    • RnD server control console's data management now works, allowing for deletion of research levels and known techs.
    • -
    • fixed minor typos.
    • -
    • bluespace polycrystals can now correctly be broken down while floating in space.
    • -
    -

    variableundefined updated:

    -
      -
    • Nano Mob Hunter ported to StonedMC. Report unexpected issues.
    • -
    • Shuttle has been ported over to the StonedMC Subsystem.
    • -
    - -

    30 September 2018

    -

    Crazylemon updated:

    -
      -
    • Corrects a comment in the code regarding IPC damage.
    • -
    -

    Purpose updated:

    -
      -
    • Fixes various message format overflows.
    • -
    -

    Shazbot updated:

    -
      -
    • You can now remove KA mods from borgs.
    • -
    -

    TDSSS updated:

    -
      -
    • Plasma statues and walls are no longer ignited by laser tag guns or practice lasers.
    • -
    • Crowbars can no longer make pool water invisible.
    • -
    -

    datlo updated:

    -
      -
    • Made the poison pen available to traitor librarians
    • -
    -

    variableundefined updated:

    -
      -
    • One click antagonist giving antag to people in restricted job.
    • -
    - -

    29 September 2018

    -

    Dapocalypse updated:

    -
      -
    • Removes extra penlight given to plasmemes.
    • -
    -

    DarkPyrolord updated:

    -
      -
    • Pyro's fluff item
    • -
    -

    Kyep updated:

    -
      -
    • Fixed several bugs with blob, including lateround blobs not generating biohazard alerts, blobs missing out on early resources they should have, and a bug with blob storage being broken that prevented blobs getting any resources.
    • -
    -

    NoWolfie updated:

    -
      -
    • New Pyr'kus cult floor and wall sprite.
    • -
    -

    Triiodine updated:

    -
      -
    • Nukies spawning with cybernetic organs/limbs
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Removes canvases due to everybody crashing from them.
    • -
    -

    farie82 updated:

    -
      -
    • Headbutting the airlock is more consistent.
    • -
    • refactored the airlock code.
    • -
    • Using multitools and such on a door with a note now doesn't remove the note. Only grabbing with an empty hand now.
    • -
    - -

    28 September 2018

    -

    DarkPyrolord updated:

    -
      -
    • Fixes a ten year old atmos bug, fix will cause toxins bombs and plasma fires to be a little less lethal
    • -
    • Readds modkit sprites to items.dm to fix invis fluff item modkits.
    • -
    -

    Farie82 updated:

    -
      -
    • No more broken tile due to getting shot out of disposals.
    • -
    • Point blank shots not hitting the correct person. When multiple people are on the same tile.
    • -
    -

    Kyep updated:

    -
      -
    • The wild west away mission no longer offers hijack traitor status as a potential reward.
    • -
    • Deconstructing/reconstructing the space pod fab no longer turns it into a mech fab. No more mechanics building surprise mechs.
    • -
    • The spacepod fab circuit is now buildable in R&D.
    • -
    • Spacepod fabs now require mechanic access to use, like the mechanic R&D console does.
    • -
    -

    Purpose updated:

    -
      -
    • Mappers can now have Floodlights round-start enabled.
    • -
    -

    Tails2091 updated:

    -
      -
    • Refactored Hallucinations to match contribution guide standards a bit more.
    • -
    -

    Triiodine updated:

    -
      -
    • Fixes jade lipstick being lime.
    • -
    • Adds lime lipstick.
    • -
    • New storage implant icon
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Ambulances now have sirens!
    • -
    • Shadowlings no longer are able to target simple animals (mice)
    • -
    -

    farie82 updated:

    -
      -
    • fixed cling transformed humanoids looking rather pale.
    • -
    • Fixed emagged camera consoles not opening the tabs
    • -
    -

    uc_guy updated:

    -
      -
    • Vox auto equip the nitrogen tank when spawning if possible.
    • -
    • Nitrogen tanks no longer overwrite job items.
    • -
    -

    variableundefined updated:

    -
      -
    • Benjaminfallout's fluff item.
    • -
    • Qdel log is now re-added to the garbage subsystem to enable coders to investigate sources of hard delete.
    • -
    • When you remove a light tube while lying down, the light tube disappear. This no longer happens.
    • -
    • Latejoin AI no longer spawn in naked at arrival shuttles.
    • -
    • Not spawning in with your memory of bank account at roundstart...
    • -
    - -

    27 September 2018

    -

    Anasari updated:

    -
      -
    • You can now deconstruct a fire extinguisher cabinet to yield a single piece of metal. You can construct them for five pieces of metal, with extinguisher included. (Using metal construction menu)
    • -
    -

    Birdtalon updated:

    -
      -
    • Borg modules now add item action buttons if present.
    • -
    • Beepsky responds to attacking him with disarm intent.
    • -
    -

    CornMyCob updated:

    -
      -
    • Adds in a prompt for becoming a headslug.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Adds a fluff item for ELO
    • -
    -

    DesolateG updated:

    -
      -
    • Added a check to whispering adverbs to prevent double adverbs while whispering.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds mixing bowls, which allow you to cook multiple recipes at the same time! The dinnerware vendor comes pre-stocked with 10!
    • -
    • Adds 2 mixing bowls to the Food Crate from cargo should you need additional. This is the same crate that includes the extra bottle of enzymes.
    • -
    • Burned messes now scale their carbon and "????" content with both physical ingredients and directly inserted reagents while burning in the cooking machines.
    • -
    • Upgraded cooking machines now attempt to evenly distribute reagents from ingredients across all produced results, rather than just the original.
    • -
    -

    Farie82 updated:

    -
      -
    • You can remove notes from an airlock now with the grab intent using an empty hand.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes 128x128 menu location
    • -
    -

    Kyep updated:

    -
      -
    • Refactored shieldgen.dm, fixed a bug which could cause shieldgens to behave improperly under some rare conditions.
    • -
    -

    Purpose updated:

    -
      -
    • CPU Performance tweaks in the Bananaium floor honks & squeaks
    • -
    • Capitalisation correction in automated chef npcs
    • -
    • CPU Performance tweaks in the Xeno Hunter tackles
    • -
    • CPU Performance tweaks in Malf AI
    • -
    • NT Formal clothing now updates to the station names correctly.
    • -
    • Fixes typos in NT Formal clothing
    • -
    • Minimap is now updated
    • -
    • Holopads now use the correct amount of power.
    • -
    • CPU Performance tweaks in the Pipe Dispenser
    • -
    • Blobs now delete light fixtures correctly.
    • -
    • use_power variable is more clearly defined as non-boolean via defines.
    • -
    -

    TDSSS updated:

    -
      -
    • Atmospherics external airlocks can now be controlled by borgs and AIs
    • -
    -

    Triiodine updated:

    -
      -
    • righthand fork sprite being oriented wrong.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Fixes vending machine bank account security. You can now use them with a bank account security level above zero.
    • -
    • Fixes a bunch of \ tags
    • -
    -

    alex-gh updated:

    -
      -
    • Drask no longer take damage from cryokinesis
    • -
    • Cryokinesis deals less damage, but lowers the body temperature a lot more.
    • -
    • Autopsy scanner now prints all times in human readable format.
    • -
    -

    datlo updated:

    -
      -
    • Added the wizard spell Greater Knock, letting them remove all access restrictions on the Cyberiad and master door opening.
    • -
    -

    variableundefined updated:

    -
      -
    • drop_location & AllowDrop() has been ported over from tg. Report unexpected issues with dropping items.
    • -
    • When you late join, extra items you can't equip / hold spawn on the ground instead of in the lobby screen. Including vox medkit etc.
    • -
    • Plasmaman no longer get double the firepower when spawning in as Captain, BS, or sec roles.
    • -
    • Non-human's DNA (Except for IPC, of course) should show up properly in the DNA modifier now.
    • -
    - -

    25 September 2018

    -

    Birdtalon updated:

    -
      -
    • Secure console UI (security records) appears bigger by default.
    • -
    • One-click-antag now respects game-mode's protected jobs.
    • -
    -

    Fox McCloud updated:

    -
      -
    • adds support for 128x128 skin interface pixel size for 4K monitors
    • -
    -

    Purpose updated:

    -
      -
    • Space is now visible under corner pieces of the Intact Empty Ship ruin.
    • -
    - -

    24 September 2018

    -

    Triiodine, Desolate, updated:

    -
      -
    • Things without blood bleeding red when rolled over by a mulebot.
    • -
    - -

    19 September 2018

    -

    Birdtalon updated:

    -
      -
    • Screwdrivers now open fire alarms instead of wirecutters.
    • -
    - -

    18 September 2018

    -

    Birdtalon updated:

    -
      -
    • Laser tag ED-209 bots get the correct names upon construction.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • adds a missing italics tag to nano/templates/song.tmpl
    • -
    - -

    16 September 2018

    -

    Shazbot updated:

    -
      -
    • Adds in the ability to have multiple custom screens.
    • -
    • Adds in Lumi's custom faces.
    • -
    -

    dandykong updated:

    -
      -
    • Internal manipulation surgeries can now be performed on mouths after the head is augmented.
    • -
    -

    variableundefined updated:

    -
      -
    • Contribution.md now properly state that changelog is mandated for all PR.
    • -
    - -

    14 September 2018

    -

    Ty-Omaha updated:

    -
      -
    • Fixes logic with obscure proc adjust_bodytemperature
    • -
    - -

    11 September 2018

    -

    Aurorablade updated:

    -
      -
    • Adds a missing var to cult comms logging.
    • -
    -

    alex-gh updated:

    -
      -
    • It is now possible to heal robotic limbs and IPCs through View Variables
    • -
    -

    variableundefined updated:

    -
      -
    • pAI can no longer use name with special characters that cause their chat messages to disappear.
    • -
    - -

    09 September 2018

    -

    AffectedArc07 updated:

    -
      -
    • You can no longer gib everyone on the server by forcing admins to call verbs with NTSL
    • -
    -

    Agameofscones updated:

    -
      -
    • removes the equip region for the mask slot on holobadge-cords
    • -
    • changes implementation of https://github.com/ParadiseSS13/Paradise/pull/9471 to be smarter and more long term.
    • -
    -

    Kyep updated:

    -
      -
    • Fixed bad spawn points in the Wizard Academy away mission.
    • -
    • The two welding goggles that went missing from the table in atmos have been returned.
    • -
    -

    SkeletalElite updated:

    -
      -
    • The paper in the holoparasite kit now describes both of the Chaos holoparasite's modes
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Nightmare writhing now properly works
    • -
    • Fixes the wire under the door in med maint that led to a wall
    • -
    • Virology now has a hologram
    • -
    -

    nicetoolbox updated:

    -
      -
    • Prevent instant rev victory in rev gamemode
    • -
    • Cryo now heals all your mutated limbs
    • -
    -

    uc_guy updated:

    -
      -
    • Ghosts can no longer eject IDs from fax machines and ID computers.
    • -
    • Fixed exploit that allowed exiled mobs to return to the station
    • -
    -

    variableundefined updated:

    -
      -
    • One-click antag vampire showing up as a changeling on antag HUD.
    • -
    • Claw game should give you token for payment by card properly again.
    • -
    • Mime forcewall now properly last for 30 seconds instead of 10.
    • -
    • The cancel button actually work properly when editing memory now.
    • -
    • A wallet now shows a green card decal by default if there's a card inside.
    • -
    - -

    05 September 2018

    -

    IrkallaEpsilon updated:

    -
      -
    • Adds an attack cooldown on mirrors for all mobs. Yes simple mobs and Xenomorph larvaes included
    • -
    -

    variableundefined updated:

    -
      -
    • Economy code has been slightly refactored. Report issues.
    • -
    • EFTPOS no longer has a name.
    • -
    • All date on transaction log should be in long form like "1 January, 2500 22:00:00".
    • -
    • Negative number is represented by parentheses in transaction log, positive without (Opposite of before).
    • -
    • There's a higher chance of winning $10 in the slot machine now.
    • -
    - -

    04 September 2018

    -

    Flatty updated:

    -
      -
    • Additional icon scaling settings
    • -
    -

    FreeStylaLT updated:

    -
      -
    • New Kidan sprites and accessories
    • -
    -

    IrkallaEpsilon updated:

    -
      -
    • Atmos Grenades wont appear in Surplus anymore due to them virtually being unuseable due to OOC reasons in almost any case.
    • -
    -

    Kyep updated:

    -
      -
    • The power grid in the black market packers away mission has been fixed, and it is no longer possible to effectively skip the entire mission using a crowbar.
    • -
    • Lateround blobs now start off as an infected mouse. By moving around/ventcrawling as a mouse, they can find themselves a good nesting area before they turn into a blob core.
    • -
    • Meth (and ultra-lube, its equivalent for synthetics) now grant less of a speed bonus.
    • -
    -

    Shazbot updated:

    -
      -
    • Now you can actually make xeno borgs.
    • -
    -

    TDSSS updated:

    -
      -
    • Medbelts can now hold hyposprays.
    • -
    -

    Tails2091 updated:

    -
      -
    • Double welding a closet no longer removes welding tool. format: Changed 0 1 booleans to TRUE FALSE.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Secure fridges can be properly emagged
    • -
    • Secure fridges can now be EMP'd to override their access requirements
    • -
    -

    datlo updated:

    -
      -
    • Megaphone now uses the user's speech font (Wingdings/comic sans)
    • -
    -

    nicetoolbox updated:

    -
      -
    • Fixes Plasmamen wizards not counting as fully garbed
    • -
    -

    variableundefined updated:

    -
      -
    • Analyzer are now consistently spelled Analyzer instead of Analyser.
    • -
    • Hivelord remains send the proper feedback about its preservation method to database.
    • -
    • IPC no longer displays their UI / SE in console. Same goes for other invalid subjects. You also can't save their UI / SE anymore.
    • -
    - -

    31 August 2018

    -

    variableundefined updated:

    -
      -
    • Being incapacitated when changing IPC monitor now show a message properly.
    • -
    • Borg & AI say actually work properly now. They no longer become whisper.
    • -
    - -

    30 August 2018

    -

    Alffd updated:

    -
      -
    • Fix emote check of can_speak() to only return if the emote produces sound.
    • -
    -

    Kyep updated:

    -
      -
    • Fixed depot armory shield key not being properly randomized.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Decreases sechailer shitcode
    • -
    - -

    29 August 2018

    -

    Agameofscones updated:

    -
      -
    • Removes stray pixel in RD sechud.
    • -
    -

    Flatty updated:

    -
      -
    • You can now put items on people and take them off while you're riding that sweet, sweet wheelchair.
    • -
    -

    Kyep updated:

    -
      -
    • Fixed various bugs with spider structures (webs, cocoons, etc), such as them not triggering attack animations, not respecting melee cooldowns, being invulnerable to simple_animals and aliens, etc.
    • -
    -

    Superhats updated:

    -
      -
    • Adds Meson and Diagnostic HUD implants.
    • -
    • ERT equipment has been reviewed by Nanotrasen and changed to more appropriately assist the station when called.
    • -
    • Amber Janitor ERT Armor sprite now works.
    • -
    • Field Surgery Belt added for Code Amber Medical ERT
    • -
    -

    Triiodine (Agameofscones) updated:

    -
      -
    • Removed original paramedic EVA sprites
    • -
    • Replaced paramedic EVA sprites with medical hardsuit inspired set.
    • -
    • Added species variants _(Which did not exist before hand)_ to Unathi, Tajaran, Drask, Skrells, & Vulpkanins.
    • -
    • Added the same armor values the basic EVA suit gets (bio 100, rad 20), this puts the paramedic suit in standard with other NT soft suits. edit: Fixed a typo in the santasuit comment, because why not.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • NT Rep stamp no longer stamps as Central Command, they have their own stamp now.
    • -
    -

    variableundefined updated:

    -
      -
    • Cutting wires shouldn't cause a runtime error anymore.
    • -
    • You cannot bola people without at least two legs (on them) anymore.
    • -
    - -

    28 August 2018

    -

    Alffd updated:

    -
      -
    • Fixes emote code to preform mute checking in the same manner as say code.
    • -
    • Adds a new type of muzzle that will shock its wearer when pulsed by an assembly.
    • -
    • Adds a new type of voice trigger assembly that is activated by audible emotes.
    • -
    -

    Birdtalon updated:

    -
      -
    • Fixes torn down posters dropping hypothetical poster when their wall is deconstructed.
    • -
    -

    Flatty updated:

    -
      -
    • IPCs can also change their screen color in addition to the image now
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Harm intent attack animations are red instead of white
    • -
    -

    taukausanake updated:

    -
      -
    • Corrects formatting for the abductor objective messages
    • -
    -

    variableundefined updated:

    -
      -
    • Logging for prayer.
    • -
    • Silicons no longer broadcast their radio message to everyone in hearing range (Only those next to them). Yes, that's a bug, not a feature.
    • -
    - -

    26 August 2018

    -

    Agameofscones updated:

    -
      -
    • Mr. Chang vendor sprite (icon_state: chang).
    • -
    • Three new Mr. Chang vendor slogans.
    • -
    - -

    23 August 2018

    -

    Aurorablade updated:

    -
      -
    • Changes to air Subsystem to make it load faster taken from TG by SpaceManiac.
    • -
    • Attemps to cap dogs you can cough up to 10..then you cough up a plush fox. Totally normal.
    • -
    -

    Birdtalon updated:

    -
      -
    • Fixes unexpected item deletion upon changing species.
    • -
    -

    Kyep updated:

    -
      -
    • Fixed a few bugs (notably, grid check event raising alert level) in the depot.
    • -
    • Fixed hand_tele, bluespace tomatoes, etc not respecting the tele_proof flag of areas.
    • -
    -

    alex-gh updated:

    -
      -
    • Changeling fleshmend no longer overfills their blood.
    • -
    -

    variableundefined updated:

    -
      -
    • Admin logging for kinetic accelerator.
    • -
    • Implantcase no longer disappears when dropped or placed in bag.
    • -
    • Logging to borer infestation.
    • -
    • A runtime with admin ticket.
    • -
    • Defibrillator paddles snap away if you walk away from the defibrillator.
    • -
    • Fixes the discard action not displaying who discarded a card from a hand of card
    • -
    • Fixes deck of card not being removed properly from your pocket when you drag it over your sprite.
    • -
    - -

    18 August 2018

    -

    Crazylemon64 updated:

    -
      -
    • makes AA's map fix not annihilate every map PR in existence
    • -
    - -

    16 August 2018

    -

    AffectedArc07 updated:

    -
      -
    • Half the scrubbers actually work now
    • -
    -

    Birdtalon updated:

    -
      -
    • All obj/machinery is now below obj layer.
    • -
    • Prevents creation of 0u pills with Chem Master
    • -
    - -

    15 August 2018

    -

    tlc2013 updated:

    -
      -
    • The AutoDrobe now carries a Transylvanian Coat, imported straight from /vg/station for all your Dracula-cosplaying needs. Much like the false Wizard robes, it does nothing for the actual antagonist.
    • -
    -

    variableundefined updated:

    -
      -
    • Banangarang's medical fluff cyborg's hair colour inconsistency.
    • -
    • Comfrey now actually works for healing brute damage.
    • -
    - -

    09 August 2018

    -

    variableundefined updated:

    -
      -
    • banangarang's maid bot fluff sprites
    • -
    - -

    07 August 2018

    -

    Anasari updated:

    -
      -
    • Polaris card system partially ported. Credits to Jedr for the hand of card item_action sprites.
    • -
    -

    Kyep updated:

    -
      -
    • Simple_animal mobs now get a HUD button that lets them switch between HELP and HARM intents.
    • -
    • Replaced the Syndicate Supply Depot with a new version, rebuilt from scratch, that is much more challenging/interesting.
    • -
    • It is no longer possible to walk straight through decoy AI cores as if they were not there.
    • -
    • Syndicate grenade launcher turrets now actually launch grenades.
    • -
    -

    MarsM0nd updated:

    -
      -
    • Unathi can now tailwhip when they are supposed to be able to.
    • -
    • Tail whipping gets logged.
    • -
    - -

    06 August 2018

    -

    AffectedArc07 updated:

    -
      -
    • Barber no longer spawns with an extra pair of shoes in his bag
    • -
    -

    Tails2091 updated:

    -
      -
    • Fixed Therapy Dolls not working.
    • -
    • Made Prize Machine & Merch Sore readable.
    • -
    • Fixed capitalizations and typos in both lists.
    • -
    - -

    05 August 2018

    -

    Crazylemon64 updated:

    -
      -
    • Space ruins can no longer trap you upon border transition
    • -
    • There are now several levels of space ruins
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in medical hyposprays
    • -
    - -

    03 August 2018

    -

    Fox McCloud updated:

    -
      -
    • IPC Change monitor is now an action button
    • -
    • Slime Color change is now an action button
    • -
    • Fixes staff of change leaving behind unknowns
    • -
    • Fixes Shadowlings not having shock resistant and thermal vision
    • -
    • Fixes staff of change gibbing people
    • -
    -

    Shazbot updated:

    -
      -
    • Adds in the ability to unsaw sawn off riot shotguns. Change: Changes the riot shotgun icon.
    • -
    - -

    02 August 2018

    -

    variableundefined updated:

    -
      -
    • Nightmares now works. Sleep well.
    • -
    • Megaphone actually logs in say log now.
    • -
    - -

    01 August 2018

    -

    Citinited updated:

    -
      -
    • Heaters and freezers now have min and max buttons
    • -
    -

    CornMyCob updated:

    -
      -
    • The description for miniature energy guns is now accurate
    • -
    • The third person text of someone reinforcing an airlock is now accurate
    • -
    -

    Tails2091 updated:

    -
      -
    • Karma refund now uses switch statement.
    • -
    -

    datlo updated:

    -
      -
    • Updated syndicate hardsuit description.
    • -
    - -

    31 July 2018

    -

    Tails2091 updated:

    -
      -
    • Claw Game Prize Ball now drops more than one ticket like it should.
    • -
    -

    variableundefined updated:

    -
      -
    • fix a runtime error with bluespace projector
    • -
    - -

    30 July 2018

    -

    Tails2091 updated:

    -
      -
    • Changed wannabe for loop to a real for loop.
    • -
    - -

    28 July 2018

    -

    KasparoVy updated:

    -
      -
    • You can now safely augment the heads of pointy-snooted Unathi, although your mileage may vary.
    • -
    - -

    27 July 2018

    -

    AffectedArc07 updated:

    -
      -
    • You can no longer use embeds in NTSL
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Space hotel is back in business
    • -
    • Non-hotel SNPCs work again
    • -
    -

    Fox McCloud updated:

    -
      -
    • Extract posibrains should have the correct names now
    • -
    • Abductors can now purchase a mind device to speak into crewmembers minds or give directives to abductees
    • -
    • Abductors now have their own versions of the FixOVein, Bonesetter, and Bonegel. Credit to Triiodine for the sprites
    • -
    • Adds a new electric shock and chemical gland for abductors
    • -
    • viral gland generates random viruses and egg laying gland eggs now have random reagents in them
    • -
    -

    variableundefined updated:

    -
      -
    • Cyborg Analyzer no longer rounds off the damage number it displays.
    • -
    - -

    25 July 2018

    -

    variableundefined updated:

    -
      -
    • Fixes runtime error from medical kit change
    • -
    - -

    24 July 2018

    -

    Kyep updated:

    -
      -
    • Number of roundstart atmos suits in atmos increased from 2 to 4.
    • -
    - -

    22 July 2018

    -

    Fox McCloud updated:

    -
      -
    • Fixes monkeys not having their own HUD
    • -
    • Fixes monkey to human transformations missing their HUD
    • -
    • Fixes changing species unequipping items
    • -
    • Fixes organs not being rejuvinated properly by mitocholide
    • -
    • Fixes shadowlings not being forced to hatch
    • -
    • Having a robotic head will allow you to use buzz, ping, beep, and the likes
    • -
    • Claw sharpening now works
    • -
    • Abductors have their own headset instead of a syndicate one
    • -
    • Can put monkeys in the gibber
    • -
    • gibbing some species will now generate different types of hides (monkeys give monkey hides, unathi give lizard hides, the likes)
    • -
    • fixes Vox name generation based on the wrong syllables
    • -
    • consolidates diona name lists; you'll no longer be asked to rename your Diona when you start the shift
    • -
    • botany grown diona can no longer rename themselves (as is consistent with ghost roles)
    • -
    • Fixes DNA scrambler so it gives a proper randomized species name
    • -
    • Fixed an edge case were Vox would have a permanent nitrogen alert
    • -
    • Fixes operatives being bald most of the time
    • -
    • Adds beesplosion chemical reaction
    • -
    -

    and taukausanake updated:

    -
      -
    • Swarmers can no longer destroy active clone pods.
    • -
    - -

    17 July 2018

    -

    Citinited updated:

    -
      -
    • volume pumps can be dispensed by the RPD again
    • -
    -

    datlo updated:

    -
      -
    • Provided abductors with an infection free surgery table.
    • -
    - -

    16 July 2018

    -

    Citinited updated:

    -
      -
    • RPD behaviour has been slightly tweaked - for example you can now rotate / flip / delete individual pipes by clicking on them without affecting other pipes on that tile.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes hand labelers not being able to label storage objects
    • -
    • Cameras can now be destroyed with weapons that have a force of 12 or greater
    • -
    • Cameras have 2 wires as opposed to 6; camera focus and power wires still remain
    • -
    • You can use hand labelers on reagent containers now
    • -
    - -

    14 July 2018

    -

    Anasari updated:

    -
      -
    • Assuming there is heal left, bandages and ointments used on limbs now heal both the limb and the hand / foot. Bandages and ointments used on the torso now heal head, arms, and lower body. The one on lower body heals the legs too.
    • -
    -

    Aurorablade updated:

    -
      -
    • Adds Spess Koi and related event.
    • -
    -

    Citinited updated:

    -
      -
    • The tachyon-doppler array now has a logging interface, and can print off stored explosive logs. Brag to your friends about your bomb-making skills!
    • -
    -

    Fox McCloud updated:

    -
      -
    • Robotic brains have their own unique sprite and full flavortext's now
    • -
    • Fixed a bug where IRC's would have IPC names
    • -
    - -

    11 July 2018

    -

    Alffd updated:

    -
      -
    • Updates SM engine to modern standards
    • -
    • Ports SM monitoring system from Bay and TG
    • -
    • Adds station wide radiation alarm when crystal/shard goes critical
    • -
    • Tesla zapping
    • -
    -

    Citinited updated:

    -
      -
    • Fortune cookies now drop random fortunes if cooked with a blank piece of paper.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds constructable Integrated Robotic Chassis
    • -
    • Adds surgery to customize existing robotic limb appearances
    • -
    • Positronic brains renamed to robotic brains
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Added a Harmonica to Perma Brig
    • -
    -

    datlo updated:

    -
      -
    • Replaced instances of "Human" in ion laws by "Crew".
    • -
    • Fixed the ability of Service Borgs to spawn items on floors. Dosh!
    • -
    - -

    10 July 2018

    -

    Fox McCloud updated:

    -
      -
    • Can no longer take assisted organs at round-start (mechanical organs are still a go, but renamed to cybernetic organs)
    • -
    • Can now start the round with cybernetic lungs, liver, and kidneys
    • -
    • Can produce cybernetic eyes at R&D and mechfabs
    • -
    • Cybernetic internal organs no longer take reduced damage (this does not apply to augments)
    • -
    • Cybernetic internal organs can be rendered inoperable (this does not apply to augments)
    • -
    • Fixes mitocholide/oculine healing damage on cybernetic organs
    • -
    • Fixes being able to restart a dead heart in your hands or with a defib
    • -
    - -

    09 July 2018

    -

    Fox McCloud updated:

    -
      -
    • Enabled augmentation of the head
    • -
    • Adds cybernetic heart, lungs, liver, and kidneys to R&D and Robotics; also adds cybernetic upgraded lungs
    • -
    • Heads are no longer vital organs, but brains still are
    • -
    - -

    07 July 2018

    -

    Fox McCloud updated:

    -
      -
    • Stechkin pistols in maintenance no longer spawn with a broken magazine
    • -
    -

    Kyep updated:

    -
      -
    • Removed PDA chatrooms. NTNet Relay Chatrooms, part of modular computers, still exist.
    • -
    - -

    06 July 2018

    -

    Fox McCloud updated:

    -
      -
    • removes explosive lances
    • -
    -

    datlo updated:

    -
      -
    • Replaced duplicate labor shuttle console on the bridge by a mining shuttle console.
    • -
    - -

    04 July 2018

    -

    Citinited updated:

    -
      -
    • Spelling error in agent IDs
    • -
    - -

    03 July 2018

    -

    MINIMAN10000 updated:

    -
      -
    • Restrained spacepod passanger can now exit pending a 2 minute wait time without moving.
    • -
    - -

    02 July 2018

    -

    Citinited updated:

    -
      -
    • Canisters obey melee cooldown now
    • -
    -

    Crazylemon64 updated:

    -
      -
    • All MMI variants can now install an "MMI radio upgrade" in order to acquire radio capability when outside of any other chassis. It can be installed either directly on the MMI, or through an opened cyborg chassis. This radio can later be removed if desired by using a screwdriver on the MMI.
    • -
    • MMIs can now pull up the direct interface of the radio instead of a single-toggle verb
    • -
    • MMI radio control is now done via action button instead of via verb
    • -
    • The radio MMI no longer exists as a distinct item
    • -
    - -

    01 July 2018

    -

    Anasari updated:

    -
      -
    • Shuttle can be called at 30:00 instead of 25:00 during War Ops.
    • -
    -

    Citinited updated:

    -
      -
    • The chef can now process spaghetti into macaroni, and can make several derivative foodstuffs.
    • -
    -

    datlo updated:

    -
      -
    • Syndicate clowns can now purchase Clown Magboots. Keep honking through slips and atmos!
    • -
    -

    monster860 updated:

    -
      -
    • Adds the mining podbay (again)
    • -
    - -

    30 June 2018

    -

    Citinited updated:

    -
      -
    • Adds the conveyor belt placer and bluespace conveyor belt placer, allowing you to much more easily create conveyor belts. The former can be gotten at any autolathe, the latter must be researched first.
    • -
    • Use a conveyor belt lever on aforementioned item to link all belts inside the placer with that lever.
    • -
    - -

    27 June 2018

    -

    MINIMAN10000 updated:

    -
      -
    • Containment emitters
    • -
    • deferred processing of SMES
    • -
    - -

    26 June 2018

    -

    Alffd updated:

    -
      -
    • Additional logic to atmos throwing.
    • -
    - -

    23 June 2018

    -

    matt81093 updated:

    -
      -
    • death squid hitbox position
    • -
    - -

    19 June 2018

    -

    Anasari updated:

    -
      -
    • Gloves of the north star is now categorized under highly visible and dangerous weapon instead of pointless badassery. (Because it's actually good)
    • -
    -

    Fox McCloud updated:

    -
      -
    • Can cast spells on CentComm z-level during ragin' mages
    • -
    -

    MINIMAN10000 updated:

    -
      -
    • Cardboard drop counts
    • -
    - -

    17 June 2018

    -

    Fox McCloud updated:

    -
      -
    • Fixes wizards not spawning with their clothes and backpack
    • -
    • It no longer snows on away missions
    • -
    -

    variableundefined updated:

    -
      -
    • Nuclear challenge time limit now depends on round start time.
    • -
    - -

    13 June 2018

    -

    Aurorablade updated:

    -
      -
    • Fluff for Panzerskull
    • -
    -

    Fox McCloud updated:

    -
      -
    • Medibots now actually talk, like beepsky
    • -
    • Adds Plastic surgery; fix someone's face or give them a new identity!
    • -
    • Having more than 50 cloneloss will render you "Unknown"
    • -
    • head disfigurement requires you to have more than 50 combined brute and burn damage, rather than tracking it separately
    • -
    • Fixes Cryoxadone and Rezadone not fixing disfigurement, Fixes fluorosulfuric acid not causing disfigurement at proper thresholds
    • -
    • Fixes syndicate medibot not being constructable from tactical medkits
    • -
    • Syndicate medibot and the mysterious medibot are better at treating brute and burn damage
    • -
    • Radiation event reworked; graphics updated--effects may be a bit more deadly
    • -
    • Buffed DIY chainsaws damage slightly
    • -
    • You now flip about when you spin with a double e-sword
    • -
    • Adds surgical augment to R&D
    • -
    • Tools on surgical augment are slightly faster at surgery
    • -
    • Wishgranter grants "Avatar of the Wishgranter" instead of making you a superhero
    • -
    • Toxin damage is stealthier and will no longer cause stinging spam message
    • -
    -

    Kyep updated:

    -
      -
    • Additional job slots are now available at 80+ server population.
    • -
    -

    MINIMAN10000 updated:

    -
      -
    • Airlock electronics lock
    • -
    • Airlock electronics close button
    • -
    -

    Piccione updated:

    -
      -
    • Added Magboots to the Paramedic's EVA gear closet
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Shadowling dethrall has been shortened to scalpel, hemostat, retractor, shine light, cautery
    • -
    - -

    11 June 2018

    -

    FalseIncarnate updated:

    -
      -
    • Food on utensils now properly inherits the name of the source dish.
    • -
    • Joined Souls rune can now properly can summon restrained targets with 3+ invokers.
    • -
    - -

    09 June 2018

    -

    Fox McCloud updated:

    -
      -
    • Fixes holobarrier icons being missing
    • -
    - -

    08 June 2018

    -

    Alffd updated:

    -
      -
    • Adds an automated emergency var on air alarms for mappers
    • -
    -

    Anasari updated:

    -
      -
    • Fixes admin log for spray displaying (0,0,0) all the time.
    • -
    -

    Desolate updated:

    -
      -
    • ED-209 code corrected to work properly. Floorbot code corrected to work properly.
    • -
    -

    and Dumbdumb updated:

    -
      -
    • Unathi and Vox Sec Hardsuit update
    • -
    - -

    05 June 2018

    -

    Kyep updated:

    -
      -
    • The Terror Spider away mission now has spiders colonizing the west side of the map. Only the gateway room is safe.
    • -
    - -

    04 June 2018

    -

    Fox McCloud updated:

    -
      -
    • Hulk mutation no longer works at range (ie: punching/breaking windows/walls at range)
    • -
    • You must be on harm intent to damage things if you have hulk
    • -
    • Having hulk allows you to punch and damage just about anything
    • -
    -

    uraniummeltdown updated:

    -
      -
    • You can smelt titanium and glass together to form titanium glass for building shuttle windows
    • -
    • You can smelt titanium, plasma and glass together to form plastitanium glass for building plastitanium windows
    • -
    • Fulltile windows now smooth, windows crack as they get damaged and can be repaired with help intent welder
    • -
    • Windows have deconstruction hints and show whether they can be rotated or not
    • -
    • Plasma glass no longer gets auto-colored
    • -
    • RCDs can deconstruct airlocks again, they have no force now though
    • -
    • Wielded fireaxe does a lot of damage to windows and grilles instead of just deleting them
    • -
    • Glass stacks now use stack recipes instead of a custom menu
    • -
    - -

    31 May 2018

    -

    FalseIncarnate updated:

    -
      -
    • The singulo no longer feeds on attention.
    • -
    - -

    26 May 2018

    -

    Birdtalon updated:

    -
      -
    • Holoparasite guide updated to include newer models. Small tooltip added for charger models.
    • -
    • laser tag gun projectiles now play appropriate sound when striking.
    • -
    -

    Citinited updated:

    -
      -
    • Hopefully fixes all issues with disposals sending you to nullspace.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes not being able to propel yourself through space by farting if you possessed both superfart and toxic farts
    • -
    -

    Kyep and Bxil updated:

    -
      -
    • Prevents everyone and their mother from seeing through closed poddoors.
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Most things will now use the correct pronouns.
    • -
    • Newscasters properly check for feed channel creation and wanted issue creation
    • -
    • ERT should deploy properly without admins now.
    • -
    - -

    19 May 2018

    -

    Aurorablade updated:

    -
      -
    • Vet Coat Fluff item.
    • -
    • Spacepod mod kit now uses kit blueprints and not KITE blueprints (spelling error).
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds gloves of the North Star; get them on the uplink for 8 TC
    • -
    • Unarmed attacks now have their own icons, as does disarming.
    • -
    • Various mobs have their own custom icon attacks
    • -
    • Monkies now bite!
    • -
    - -

    18 May 2018

    -

    Fox McCloud updated:

    -
      -
    • Removes engineering and police tape
    • -
    • Adds security, atmospheric, and engineering holoprojectors
    • -
    -

    tigercat2000 updated:

    -
      -
    • You can now lock a facing direction with shift+middle mouse button, or lock your direction towards an object by clicking on it with shift + ctrl + middle mouse button.
    • -
    - -

    15 May 2018

    -

    Tayyyyyyy updated:

    -
      -
    • Pun pun is back!
    • -
    - -

    11 May 2018

    -

    Kyep updated:

    -
      -
    • It is no longer possible to create an infinite number of monkeys from the same monkey cube.
    • -
    - -

    09 May 2018

    -

    RyanSmake updated:

    -
      -
    • You can now jump on fax machines without the UI lying to you.
    • -
    - -

    07 May 2018

    -

    qwertyquerty updated:

    -
      -
    • The window title is custom now!
    • -
    - -

    06 May 2018

    -

    Kyep updated:

    -
      -
    • DeathSquad is now better equipped, and prompts eligible ghosts with a "Do you want to play as DeathSquad?" when called.
    • -
    • DeathSquad members (except team leaders) can now choose to spawn as either an organic DS member, or a DS borg.
    • -
    - -

    05 May 2018

    -

    Tayyyyyyy updated:

    -
      -
    • ERT members will have their proper name and appearance when cloned
    • -
    - -

    04 May 2018

    -

    RyanSmake updated:

    -
      -
    • You will now log in to the proper account you input to the ATM instead of the one associated with you.
    • -
    • Now ATMs will reconnect after a power outage.
    • -
    - -

    02 May 2018

    -

    CrazyLemon and Fox McCloud updated:

    -
      -
    • Fixes reagent smoke
    • -
    - -

    01 May 2018

    -

    Alffd updated:

    -
      -
    • Tell clients to rejoin after shutdown, before killing the server.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Removed programmable unloader circuit
    • -
    • Bomb testing range can now be utilized multiple times without worry of the bomb bouncing off and returning back to you
    • -
    - -

    30 April 2018

    -

    Fox McCloud updated:

    -
      -
    • Adds Guillotines: make them with plasteel, wood, and cable coil. Execute your comdom head of staff TODAY
    • -
    • Clapping now actually plays a clapping sound
    • -
    • Adds Blast cannon
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Medbay treatment center now has a wider entrance
    • -
    • Virology hallway is now publically accessible from Surgery waiting room, entrance is now double-doors.
    • -
    - -

    28 April 2018

    -

    MINIMAN10000 updated:

    -
      -
    • Developer express start
    • -
    - -

    26 April 2018

    -

    Fox McCloud updated:

    -
      -
    • Destroys uplink metagaming: Adds in F.R.A.M.E. cartridge
    • -
    • using raw telecrystal on an active uplink or yourself will use the entire stack at once
    • -
    • can purchase 5 and 20 unit TC bundles from the uplink
    • -
    • Removes radio icons when speaking over radio
    • -
    • Fixes cargo recycler never recycling items on its own
    • -
    • Fixes mech fabricator using an all white UI
    • -
    • Can upload alien alloy design to the ORM
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • You only need to click once to clean a floor
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Slimes can be injected with plasma reagent and epinephrine to control mutation chance. Plasma increases mutation chance 5% per 5u to a max of 50%, epinephrine decreases by 5% per 5u to a minimum of 0%
    • -
    • Slimes can change their face using new emotes
    • -
    • Slimes can steal nutrition from other slimes when attacking them
    • -
    • Slime docility potion no longer makes a simple animal slime, instead makes the target docile and never hungry
    • -
    - -

    25 April 2018

    -

    Fox McCloud updated:

    -
      -
    • Can make water bottles and caution signs out of plastic sheets
    • -
    • Increased cargo plastic sheet count to 50 and reduced cost to 10
    • -
    • Adds a recipe for making plastic sheets: oil, acid, and ash
    • -
    • Can now make a designs on the circuit imprinter that use metal and other exotic materials
    • -
    • Removed the acid cost from most circuit recipes
    • -
    • bluespace material requirement on a few parts: bluespace stock parts, phazon parts, bags of holding, and the likes all now require bluespace lattice.
    • -
    • Fixes invisible plushies and getting fluff item plushies
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • You can't see admin character names in PMs
    • -
    -

    Xhuis updated:

    -
      -
    • The Nanotrasen Meteorology Division has identified the aurora caelus in your sector. If you are lucky, you may get a chance to witness it with your own eyes.
    • -
    - -

    24 April 2018

    -

    Kluys updated:

    -
      -
    • Cleanblots not cleaning /obj/effect/decal/cleanable/trail_holder (blood trails)
    • -
    - -

    17 April 2018

    -

    Citinited updated:

    -
      -
    • Kitchen machinery no longer looks as if it is falling apart.
    • -
    -

    MINIMAN10000 updated:

    -
      -
    • Adds NOBLUDGEON to door_remote so the remote always triggers
    • -
    • Cable coils now allow you to transfer a part of the stack
    • -
    • Stack handling from cable.dm is removed as stack.dm already handles it
    • -
    • Changed cable coil message
    • -
    • The ability to change the color of cables
    • -
    • cableColor now follows the new cable_color format
    • -
    - -

    14 April 2018

    -

    Anticept updated:

    -
      -
    • Changed defib timer from 3 minutes to 5 minutes
    • -
    -

    MarsM0nd updated:

    -
      -
    • Single man up now looks and sounds the same as the global man up for that person.
    • -
    - -

    11 April 2018

    -

    KasparoVy updated:

    -
      -
    • Removes the job-restriction on the purely cosmetic Tajaran veils while those wth integrated HUDs remain unchanged.
    • -
    - -

    08 April 2018

    -

    Kyep updated:

    -
      -
    • Terror Spiders now have a new type in their roster (brown) and see the health status of humanoids (since some of their abilities depend on that status). The Terror Spider away mission has also been adjusted to smooth out areas of no challenge (safe spaces) as well as areas of nigh-impossible challenge (dozens of spiders stacking up together in the final room).
    • -
    - -

    07 April 2018

    -

    Alffd updated:

    -
      -
    • portable (stationary) scrubbers now remove 1/4th as much air per tick at maximum.
    • -
    -

    Birdtalon updated:

    -
      -
    • Nanocalcium can no longer be synthesised by bees or Odysseus
    • -
    • Silicons now have their diagnostic HUD removed correctly.
    • -
    • Defibs no longer give endless paddles.
    • -
    • Ether re-balanced into a more effective anaesthetic for surgery.
    • -
    • Atmos techs have access to tech storage and inner engineering tool room.
    • -
    -

    Citinited updated:

    -
      -
    • You can't play russian roulette without a head
    • -
    • using a russian revolver on another human will now hit them with the revolver instead of failing to play russian roulette with them.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Deletion of human mobs now properly deletes equipment balance: Hotel guards now dust on death balance: Hotel guards no longer drop equipment when stunned balance: Hotel guards now are able to use the tasers they hold
    • -
    -

    Dyhr updated:

    -
      -
    • Agent ID's now provide some presets for valid occupations.
    • -
    -

    Kyep updated:

    -
      -
    • SIT shuttle can no longer dock in scimaint.
    • -
    • Crew demotions and terminations now generate an automatic message to admins. All job changes are also logged.
    • -
    • Modular computers now support toggling priority on/off for jobs. The button for doing this in both normal and modular computers is now marked 'Pri', instead of the old '*'.
    • -
    -

    MarsM0nd updated:

    -
      -
    • Admins can make a fax machine recive the faxes Centcomm or the Syndicate does get.
    • -
    • Stops "Unknown" department to send to from coming up when a fax machine gets spawned.
    • -
    • Allows adding of departments to send to over a proc-call.
    • -
    -

    Spacemanspark updated:

    -
      -
    • Mining drones now have movement sprites.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Drones will no longer shatter glass tables
    • -
    • All small mobs can bump open public access doors
    • -
    - -

    06 April 2018

    -

    Fox McCloud updated:

    -
      -
    • Fixes medical cyborgs having one less stack than they should have they recharge
    • -
    • Fixes inconsistency in the medical stacks amounts (they should all be 6)
    • -
    - -

    05 April 2018

    -

    uraniummeltdown updated:

    -
      -
    • Aliens can pull facehuggers out of eggs again
    • -
    - -

    03 April 2018

    -

    & Deathride58 & Tigercat2000 updated:

    -
      -
    • Station time is now randomized [if enabled in game_options configuration].
    • -
    • A separate round time has been added to status panel. This will start at 00:00:00.
    • -
    • Night shift lighting [if enabled in the same configuration] will activate between station time 7:30 PM and 7:30 AM. This will dim all lights affected, but they will still have the same range.
    • -
    • APCs now have an option to set night lighting mode on or off, regardless of time.
    • -
    - -

    02 April 2018

    -

    Desolate updated:

    -
      -
    • New Cricket Borg module selection.
    • -
    -

    EldritchSigma updated:

    -
      -
    • Mech mounted Disablers are now printable with consistency.
    • -
    -

    Fethas updated:

    -
      -
    • Viruses Lycancoughy, Adv. Pierrots throat and Kingstons added.
    • -
    -

    IK3I updated:

    -
      -
    • You can now opt out of the syndicate recruitment semminar prior to boarding the station.
    • -
    -

    Kyep updated:

    -
      -
    • Syndifox and Syndicat can now do melee damage. Paperwork (cargo sloth pet) no longer can.
    • -
    • Syndifox and Syndicat are no longer controllable by players by default.
    • -
    • Poly (parrot in Engineering) now knows more phrases.
    • -
    -

    Shazbot updated:

    -
      -
    • Adds E-pistol crates to the cargo manifest Change: changes the HoP's E-gun to an E-pistol
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Borg power warning is on a 2 second cooldown
    • -
    - -

    01 April 2018

    -

    Tayyyyyyy, LP Spartan updated:

    -
      -
    • Once you up to red, it takes 5 minutes before the shuttle transit time is reduced to 5 minutes.
    • -
    - -

    30 March 2018

    -

    matt81093 updated:

    -
      -
    • fish duplication when pulling out multiple fish at once
    • -
    - -

    28 March 2018

    -

    Birdtalon updated:

    -
      -
    • Enforces size limits for placing items inside slicable food
    • -
    -

    Fox McCloud updated:

    -
      -
    • Nano UI will update a bit faster
    • -
    -

    MarsM0nd updated:

    -
      -
    • Record printouts now automatically get labled with the name of the person.
    • -
    - -

    25 March 2018

    -

    Alffd updated:

    -
      -
    • Logic checks to lessen death from flying objects due to atmospheric breaches.
    • -
    • Removes atmospheric stunning while thrown.
    • -
    - -

    24 March 2018

    -

    matt81093 updated:

    -
      -
    • Borgs no longer keep their special vision when reset with the reset module
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Deconstructing default RCD airlocks should work now
    • -
    - -

    22 March 2018

    -

    uraniummeltdown updated:

    -
      -
    • Airlocks now have security levels. Secure airlocks cannot be hacked straightaway. Vault doors and highsecurity airlocks have some security by default. You can make an airlock secure by applying metal and plasteel to it while the panel is open
    • -
    • As a slime, you can drag yourself onto a target to feed
    • -
    • Doors, tables and table frames can be destroyed by hitting them. Airlocks can be repaired by a welder on help intent.
    • -
    • You can butcher with any sharp item on harm intent
    • -
    • Grilles are stronger
    • -
    • Vault door assemblies cost 8 plasteel up from 6
    • -
    • Xenomorphs can open non-locked non-welded airlocks after some time
    • -
    • Firelocks can be welded open again, firelock [de]construction uses crowbar instead of welder
    • -
    - -

    21 March 2018

    -

    MarsM0nd updated:

    -
      -
    • Xray machines now have xray vision, and check contents of an item, instead of just the item.
    • -
    - -

    20 March 2018

    -

    MarsM0nd updated:

    -
      -
    • Stops a mug from being invisible
    • -
    - -

    19 March 2018

    -

    Birdtalon updated:

    -
      -
    • re-adds the inline "take" shortcut for adminhelps
    • -
    -

    Birdtalon, LPSpartan, Shazbot updated:

    -
      -
    • Nanocalcium - bone repair reagent. Adds bone repair kit to syndicate uplink containing Nanocalcium autoinjector.
    • -
    -

    Fethas updated:

    -
      -
    • Vulpkanin, Hunger drain increased slightly. rscadd:Diona now have hair by skittles.
    • -
    • Bedsheets can contribute to dream messages.
    • -
    • sometimes dreams will be nightmares.
    • -
    • Moves dream/nightmare strings to txt files. rscadd:sleeping has a small change to heal brute/fire. but you need a bed..and a bed sheet to be effective.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes Vulpkanin hunger drain rate being absurd
    • -
    -

    IK3I updated:

    -
      -
    • Comically sized mugs are slightly less comically sized
    • -
    • Lord Singuloth's wrath can no longer be bypassed by baking your input device.
    • -
    -

    Shazbot updated:

    -
      -
    • Adds an ammo counter to the icon and the in hand icon for the M90-gl
    • -
    • Lowers the price of the .357 for nukies
    • -
    - -

    16 March 2018

    -

    MarsM0nd updated:

    -
      -
    • You can now fix broken message monitors
    • -
    - -

    13 March 2018

    -

    Citinited updated:

    -
      -
    • Restricts RPD usage to certain station-side turfs.
    • -
    -

    Piccione updated:

    -
      -
    • Added marijuana cigarette packets to the Psych's locker.
    • -
    • Changed the taste message of a few food items
    • -
    - -

    12 March 2018

    -

    Fethas updated:

    -
      -
    • Full of skittles borg fluff
    • -
    - -

    08 March 2018

    -

    shazbot updated:

    -
      -
    • Fixes up Desolate's name on his other items.
    • -
    - -

    06 March 2018

    -

    Regen updated:

    -
      -
    • Removes the purple hair flower pin from loadout and general player access, because this is a fluff item.
    • -
    - -

    04 March 2018

    -

    Funce updated:

    -
      -
    • APC Interface lock UI works for silicons.
    • -
    - -

    03 March 2018

    -

    Birdtalon updated:

    -
      -
    • A few more items in the Psyche locker.
    • -
    -

    Citinited updated:

    -
      -
    • IPCs can now lose russian roulette without going to nullspace
    • -
    -

    DarkPyrolord updated:

    -
      -
    • Sliceable food items are no longer hammerspace capable
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds colored, departmental, and novelty mugs to the hot drinks machine and loadout menu under "Mugs".
    • -
    • Adds Head of Staff coffee mugs to their respective lockers.
    • -
    • Adds support for inserting items into vendors and having the vendor interact with said item when vending items.
    • -
    • Adds the ability to insert containers into the hot drink machine, filling the container with your purchase.
    • -
    -

    Fethas updated:

    -
      -
    • The booze o' mat now has wine..bags.
    • -
    -

    KasparoVy updated:

    -
      -
    • The eyes of humanoids who have XRAY vision mutation, sufficiently high darkview, synthetic eyes or eye implants now appear to shine in the dark.
    • -
    • Adds a way to 'cut' one icon's pixels out of another by using the get_icon_difference() proc.
    • -
    • get_location_accessible() now checks the appropriate flags when determining the accessibility of eyes.
    • -
    -

    Serket updated:

    -
      -
    • Death Wand can kill slimes and hopefully everything
    • -
    • Wizards can no longer mind-swap borgs
    • -
    • ERT Specops Office now comes with extra privacy (borgs can't open the ERT mech room, etc.)
    • -
    • Removed snow from Mr Chang's
    • -
    • Fixed a dethralling error causing message typos
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • AIs can view info of their synced borgs in the status panel
    • -
    - -

    26 February 2018

    -

    Birdtalon updated:

    -
      -
    • Removes printing photos on security consoles.
    • -
    - -

    21 February 2018

    -

    uraniummeltdown updated:

    -
      -
    • Added titanium and plastitanium. Mine the asteroid for titanium, make plastitanium by smelting together titanium and plasma
    • -
    • You can build shuttle floors and walls with titanium and plastitanium. Can also make shuttle airlocks by applying titanium to a non-mineral airlock
    • -
    • Shuttle windows have explosion resistance now
    • -
    • A few RnD recipes require titanium now
    • -
    - -

    20 February 2018

    -

    Alffd updated:

    -
      -
    • Reduce all atmospheric stuns by 80%
    • -
    • Cap the maximum atmospheric stun time to 4 seconds
    • -
    -

    Anasari updated:

    -
      -
    • Add paperplane. Alt-click or use a verb on a piece of paper in your hand to make them.
    • -
    -

    Birdtalon updated:

    -
      -
    • adds [time] tag for paperwork
    • -
    -

    Citinited updated:

    -
      -
    • You can now roll up flags.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in a Dance Machine
    • -
    • IEDs now have a blast radius again
    • -
    • Slap crafting of IEDs is gone; use personal crafting instead
    • -
    -

    HugoLuman updated:

    -
      -
    • coughing and sneezing sounds for the Drask
    • -
    -

    MarcellusPye updated:

    -
      -
    • Grays can now drink sulphuric acid without being burnt
    • -
    -

    Shazbot updated:

    -
      -
    • Fixes Patch's patch
    • -
    -

    Tayyyyyyy, bryanayalalugo updated:

    -
      -
    • News reporters can now add titles to their stories!
    • -
    - -

    05 February 2018

    -

    IK3I updated:

    -
      -
    • Next gen dining is now available at your local autolathe!
    • -
    -

    MarsM0nd updated:

    -
      -
    • Pod lock busters can now unlock pods
    • -
    • Pods can only be locked with a locking system installed.
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Energy swords, energy daggers, energy cutlasses, and energy axes emit light. Toy versions do not.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Multitile airlock opening/closing animation is no longer glitchy and paper/photos don't float in the air when opening/closing them
    • -
    - -

    02 February 2018

    -

    Fethas updated:

    -
      -
    • TG Port, ais now have an advanced diagnostic hud that lets them see the path a bot is taking.
    • -
    • Bots get access for 60 seconds to all doors to get to thier locations. rscadd:Pai controlled bots will get a notification they are being called. rscadd:all living mobs now can have a med hud.
    • -
    - -

    01 February 2018

    -

    Squirgenheimer updated:

    -
      -
    • Using the 'tear reality' rune as cult should now be punished when the invokers do not have the god summoning objective
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Players job banned from syndicate can no longer play emagged drones
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Examining an airlock assembly gives construction hints and shows what pen name is set. Mineral airlocks can have glass added to them.
    • -
    • Added public and external maintenance airlock assemblies to metal recipes
    • -
    • Maintenance, standard and external airlocks now have glass versions. Multi-tile airlock has a solid version.
    • -
    • Added more airlocks to RCD
    • -
    • You can attach paper and photos to airlocks, wirecutters to remove them
    • -
    • Airlocks open faster
    • -
    • Vault and high-security airlocks are made with 6 plasteel up from 4
    • -
    • Plasteel should have the correct amount of materials in it now
    • -
    - -

    29 January 2018

    -

    Fox McCloud updated:

    -
      -
    • Slime blueprints can now make an area compatible with Xenobio consoles, regardless of the name of the new area
    • -
    -

    MarcellusPye updated:

    -
      -
    • Changes the ghost preferences section of game preferences to display the currently active option instead of the inactive option.
    • -
    - -

    27 January 2018

    -

    IK3I updated:

    -
      -
    • Saving a chat log no longer hangs you.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Client FPS setting should save properly now
    • -
    - -

    26 January 2018

    -

    tigercat2000 updated:

    -
      -
    • Insta-movement works marginally better
    • -
    -

    uraniummeltdown updated:

    -
      -
    • You can now change your client FPS in Game Preferences
    • -
    - -

    24 January 2018

    -

    IK3I updated:

    -
      -
    • Cancel means Cancel on admeme console reports!
    • -
    • When eldritch gods, demons, handsy aliens, and incarnations of darkness tell you it's time to go, you go
    • -
    • Comms Console will tell you when the shuttle can't be recalled
    • -
    • Admemes can now designate whether a shuttle they call is recallable
    • -
    • Admemes can exercise their power to recall any shuttle, even in defiance of spooky ghosts!
    • -
    -

    Kyep updated:

    -
      -
    • Added config option to limit the amount of time shadowlings can remain unhatched before they start getting pushed to hatch.
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Energy beams of all types emit light.
    • -
    • Flashbangs emit a burst of light when detonated
    • -
    - -

    21 January 2018

    -

    KasparoVy updated:

    -
      -
    • Avoids wanton bloodshed by revising logic that checks for blood already in the splat zone.
    • -
    • Adds a helper proc with which you can get a list of all atoms of a type at a given location.
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Due to increasing amounts of spaghetti code in the cryptographic sequencer, emagging maintenance drones cripples their table pathfinding and removes their ability to pathfind under people's legs. Also, Nanotrasen has patched its drones to remove the hidden diamond drill module and rewritten its drone control code so that drones that don't call home and verify their programming after a certain amount of time are destroyed automatically.
    • -
    - -

    20 January 2018

    -

    uraniummeltdown updated:

    -
      -
    • Fixed issues with ethereal jaunt directions, wraith jaunt no longer shows the wizard effects
    • -
    • Guardians phasing in/out will properly show a little animation
    • -
    • The petting heart animation is smoother
    • -
    - -

    19 January 2018

    -

    Citinited updated:

    -
      -
    • Using a syndicate balloon while it's in your hand allows you to play with it.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Wooden holodeck table sprites show up properly
    • -
    • Table construction has been changed a bit, apply stack items (carpet, metal, glass, wood) to table frames to build tables instead of using table parts.
    • -
    • Slightly increased the health of racks and tables with low health
    • -
    • Holodeck tables will now smooth with one another
    • -
    • Holodeck tables and racks can be interacted with in more ways
    • -
    - -

    13 January 2018

    -

    Citinited updated:

    -
      -
    • The ocean and the pool are no longer colder than outer space.
    • -
    • Water now cools or heats you gradually, not all at once.
    • -
    -

    Kyep updated:

    -
      -
    • Refactored Paranormal/Janitor dress code, and Cyborg ERT spawn code.
    • -
    • Signing up for ERT, then going AFK, such that your AFKness prevents you and/or others spawning as ERT within a reasonable (2 minute) period of time, now generates a warning to online admins.
    • -
    - -

    11 January 2018

    -

    Bxil updated:

    -
      -
    • Economy accounts now use the correct date.
    • -
    -

    Citinited updated:

    -
      -
    • Jaunters work again.
    • -
    -

    Jountax updated:

    -
      -
    • Fancy shoes no longer cost one's entire loadout.
    • -
    • Sugarcane added to the MegaSeed Servitor. No more garden raids!
    • -
    -

    Kyep updated:

    -
      -
    • Department management (aka: demotion) consoles only worked for their respective head of staff. Captains, CC characters, etc could not use them.
    • -
    • Fixed two brown wooden doors in wizard academy away mission which had space turfs under them, leading to nasty results with fastmos.
    • -
    • Added deathsquid.
    • -
    • Further modified construction site layout, fixing various issues and making it easier to test new engine setups there.
    • -
    -

    Tayyyyyyy, FPK updated:

    -
      -
    • The more dark view you have, the more eye damage you take from flashing. Darkness amplifies this effect.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Freezers and other atmos machines will drop frame and parts correctly again
    • -
    - -

    07 January 2018

    -

    Kyep updated:

    -
      -
    • All mineral floor tiles no longer incorrectly show up as abductor flooring.
    • -
    - -

    05 January 2018

    -

    Kyep updated:

    -
      -
    • Improved wild west away mission. Fixes issues such as lack of magboots, and 'projectile gun's appearing. Adds some flavor items (syndie soap in shower, medkits in storage). Also adds syndie comms device which alters the mission depending on how it is used.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Construct shells have a new sprite
    • -
    - -

    04 January 2018

    -

    Anasari updated:

    -
      -
    • A lot of underused nuke op items made cheaper.
    • -
    • Syndicate hardsuit removed from nuke op because you already got one free.
    • -
    • Tactical medkit give you four synthflesh patch, no more stetho or lethal syringe.
    • -
    • RSG added to nuke op uplink. Dart gun no longer available.
    • -
    - -

    31 December 2017

    -

    Alffd updated:

    -
      -
    • Wire panels are now effected by the colorblindness disability
    • -
    • Wire panel color changes now support RGB hex values
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes arm implants being immune to EMPs.
    • -
    -

    FreeStylaLT updated:

    -
      -
    • A dedicated toxic pill sprite, Cyanide and Toxin pills now use it by default.
    • -
    -

    KasparoVy updated:

    -
      -
    • Blood splattered by projectiles hitting a mob now land one tile away in the direction of the splatter graphic. Blood splattered on walls/windows/etc. can be cleaned off with soap.
    • -
    • Xeno-blood splatter is now the appropriate colour.
    • -
    -

    Kyep updated:

    -
      -
    • IAAs now require 10h of playtime, instead of 5h, to unlock. The IAA job's alt title is now "Human Resources Agent" instead of "Lawyer" or "Public Defender". IAAs now start with basic access to all departments (sci/med/cargo/eng), so that they can more easily conduct investigations. Overall, their role has been clarified, to be explicitly on the side of NT, not simply that of defendants. Further, they're empowered to, and expected to, actually conduct investigations, and generally be better at their jobs.
    • -
    • The mech bay next to Robotics now has a robotic storage unit (cryopod for cyborgs).
    • -
    • The Construction Site (partially finished space station east of eng outpost) has been revamped. With basic power/atmos networks in place, it should now be much more viable to repair it during a round.
    • -
    • Added shutters to specops office next to ERT spawn. This prevents borgs remotely activating the admin-only buttons in that office.
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Crew pinpointers no longer lose signal when the target enters something like a sleeper or a mech
    • -
    -

    Vivalas updated:

    -
      -
    • It is now possible to directly inject spaceacillin into organs during surgery, and it only uses 5u to completely cleanse the organ,
    • -
    - -

    27 December 2017

    -

    Tayyyyyyy updated:

    -
      -
    • Repeated lines are now combined in the chat window. This can be disabled in chat window preferences.
    • -
    • Paramedic, Blueshield, and Medivends get crew pinpointers
    • -
    - -

    23 December 2017

    -

    Fethas updated:

    -
      -
    • Borers can no longer be possesed by ghosts using an antag hud.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Having a master, as a spider means you actually get a message who is your master now
    • -
    -

    Purpose2 updated:

    -
      -
    • Cartographers dispatched. NanoUI Minimap is now updated.
    • -
    -

    Santa's Lawyer updated:

    -
      -
    • Removed riot dart toys from under Christmas trees.
    • -
    - -

    21 December 2017

    -

    FalseIncarnate updated:

    -
      -
    • Adds fans under the doors at the North Pole.
    • -
    -

    Purpose2 updated:

    -
      -
    • You may no longer use strikethroughs/italics in OOC. This was causing backend server problems due to how shoddily BYOND is coded, and cannot be safely added right now.
    • -
    - -

    19 December 2017

    -

    Santa Claus updated:

    -
      -
    • Christmas cheer!
    • -
    • Grinch
    • -
    • missing emergency nitrogen / plasma tanks
    • -
    - -

    15 December 2017

    -

    uraniummeltdown updated:

    -
      -
    • Plants no longer take twice as many cycles to age
    • -
    - -

    05 December 2017

    -

    Kyep updated:

    -
      -
    • Removed peacekeeper borgs.
    • -
    - -

    04 December 2017

    -

    Tayyyyyyy updated:

    -
      -
    • IPCs no longer vomit next to rotting bodies
    • -
    -

    Terillia updated:

    -
      -
    • Fixes the litch Hat and Sandals
    • -
    - -

    02 December 2017

    -

    uraniummeltdown updated:

    -
      -
    • You can now create vault door assemblies with 4 plasteel sheets
    • -
    • Science airlocks have been added to metal recipes and the RCD
    • -
    • Airtight and Maintenance Hatch added to the RCD
    • -
    • Highsecurity airlock assemblies are built with 4 plasteel instead of 4 metal
    • -
    • All doors and doorlike things (firelock, airlock, windoor, blast door, shutters, spacepod door) run off the Environment Power Channel
    • -
    • Emagged airlocks have a different description on examining
    • -
    • Screwdrivering an airlock now displays a message. No more guessing if the panel is open or not.
    • -
    • Cult airlocks will keep their old name on being converted.
    • -
    - -

    01 December 2017

    -

    Fox McCloud updated:

    -
      -
    • Lungs are now responsible for breathing instead of a mob; mix and match lungs however you like!
    • -
    • Ripping out someone's lungs or them necrotizing will make a person suffocate; it will no longer kill them instantly
    • -
    • Drask no longer heal burn damage from breathing cold air (brute is still healed)
    • -
    • Lungs no longer rupture in low pressure
    • -
    • Not having lungs means you can't talk
    • -
    • remove the discrete internals button on the HUD; use the tank action button!
    • -
    • Fixes slimes dying by themselves
    • -
    - -

    30 November 2017

    -

    ExitGame updated:

    -
      -
    • vox quill rustle emote
    • -
    • species check
    • -
    -

    Fox McCloud updated:

    -
      -
    • shotgun pellets deal less damage the further they travel
    • -
    - -

    28 November 2017

    -

    Kyep updated:

    -
      -
    • It is no longer possible for Service borgs using the Rapid Service Fabricator to end up with negative energy.
    • -
    - -

    27 November 2017

    -

    uraniummeltdown updated:

    -
      -
    • Composting plants/pills into hydroponics trays transfers all reagents
    • -
    - -

    26 November 2017

    -

    FalseIncarnate updated:

    -
      -
    • The Syndicate has determined that subtle and stealthy items don't benefit from obvious names, and thus have rebranded their contortionist jumpsuit to something less eye-catching.
    • -
    • The Syndicate decided to be less stingy than Nanotrasen and made the contortionist jumpsuit out of flame resistant materials. You may burn, but the jumpsuit won't!
    • -
    -

    Fethas updated:

    -
      -
    • Penguins, Penguins in shambreos and Albino penguins are a thing.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes being able to recall Abductor-called shuttles
    • -
    • Fixes slime transformation potion not making you a real slime
    • -
    • Polymorph slimes are now random color
    • -
    -

    Jountax updated:

    -
      -
    • Can now add laceup shoes to your loadout.
    • -
    -

    Kyep updated:

    -
      -
    • Service borgs are now able to dispense a variety of fruit juices, as well as coffee and tea. Additionally, they can use a health scanner on crew, and the poisoned beer they get from being emagged is much more deadly. They can also create snackfood using their Rapid Service Fabricator.
    • -
    • When an admin creates a classified message manually, and selects 'no' to the 'notify crew' option, the incoming message will be announced via command radio, instead of a priority announcement that the whole crew sees.
    • -
    • ERT borgs can now speak on ERT radio, even after choosing a module.
    • -
    • ERT borgs are now always named as such, may only take modules that would be useful in an emergency, and always have their emagged modules unlocked. They also have an 80% chance to resist emagging their cover lock, so you will need to stun them with a flash before trying to emag them.
    • -
    -

    MarsM0nd updated:

    -
      -
    • Logs usage of stun talismans.
    • -
    • Stops rigsuits from shocking over distance.
    • -
    • Let's malfunction count down while not being actively worn, to avoid permanetly breaking it.
    • -
    • Allows boots to be worn under rigsuit boots.
    • -
    • Wirenames for the rigsuit wires if you can see them.
    • -
    • Rigsuits only slow you down when deployed, potentially less if active.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Gambling machines now payout again.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Particle effects pass over tables and grilles
    • -
    • Nanofrost smoke fading out actually works now
    • -
    • All smokes now fade out
    • -
    • Nanofrost smoke can now also weld scrubbers
    • -
    - -

    22 November 2017

    -

    Fox McCloud updated:

    -
      -
    • "Pick Up" from right clicking obeying the same rules as regularly clicking on it
    • -
    - -

    19 November 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes cult shuttle curse from being used more than twice and from extending shuttle call duration once nar-sie has been called/slaughter demons have been called.
    • -
    - -

    18 November 2017

    -

    MarsM0nd updated:

    -
      -
    • A (possibly non-existant) officer's beret does no longer incorrectly hide hair.
    • -
    - -

    13 November 2017

    -

    Alffd updated:

    -
      -
    • Fixes muzzles not preventing vampire biting unless the target was wearing the muzzle.
    • -
    • Makes throwing the ambulance with atmospherics almost impossible.
    • -
    -

    VexingRaven updated:

    -
      -
    • Fixes the message that appears when a mob being force-fed a snack finishes eating that snack.
    • -
    - -

    12 November 2017

    -

    Kyep updated:

    -
      -
    • It is now much harder for Command/HoS to get away with illegal executions. Admins are far more likely to notice people being set to execute, more detailed explanations of executions must be sent to CC, and admins are more able to intervene when an execution is obviously illegal.
    • -
    - -

    11 November 2017

    -

    FalseIncarnate updated:

    -
      -
    • Full windows are now 100% stronger than before, so you don't have to pick strength over security.
    • -
    • Full windows now take longer to deconstruct so they offer slightly better security against break-ins. Toolspeed does apply.
    • -
    • Full and directional windows can be built on grilles now, and you can even pick the direction! Technically both a tweak and an addition...
    • -
    - -

    10 November 2017

    -

    Allfd updated:

    -
      -
    • A new Anti-Bite muzzle has been added to the SecVendor. This muzzle can be locked through the strip panel and will prevent a vampire from feeding.
    • -
    • Holy water now causes vampires to vomit blood, before vomiting the water. After this holywater behaves as normal.
    • -
    -

    Anasari updated:

    -
      -
    • 79 hairstyles ported from Polaris.
    • -
    - -

    05 November 2017

    -

    Fethas updated:

    -
      -
    • changes the my tickets from a verb..to a prock. To quote lemons: F.
    • -
    -

    KasparoVy updated:

    -
      -
    • The Barber's dye bottle now works again.
    • -
    • The Barber's dye bottle can now colour alternate (facial) hair themes where applicable.
    • -
    - -

    04 November 2017

    -

    FalseIncarnate updated:

    -
      -
    • MANDATORY FUN! Arcades added to both stations!
    • -
    • Bottler units have been spotted on board both stations!
    • -
    • Arcade carpet tiles added to the prize counter for 150 tickets (credit to Goonstation for the turf icon).
    • -
    • Cyberiad bathrooms should have 100% fewer floating showers (behind curtains).
    • -
    • Showers have been fitted with mist-reducing showerheads. They should no longer generate infinite mist if rapidly toggled.
    • -
    • Cyberiad chemistry has had the extra APC removed. Now they only have one as standard.
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Medbay has been remapped
    • -
    • New Maint areas have been added south of Medbay.
    • -
    - -

    01 November 2017

    -

    FreeStylaLT updated:

    -
      -
    • Medbay has been remapped
    • -
    • New Maint areas have been added south of Medbay.
    • -
    -

    Kyep updated:

    -
      -
    • Freedom Operative suits no longer revert to a normal red syndi suit icon when you use their 'toggle hardsuit mode' option.
    • -
    -

    MarsM0nd updated:

    -
      -
    • Stops holograms from attempting to appear when they just disappeared because the AI became unable to keep it up.
    • -
    - -

    30 October 2017

    -

    NewSta updated:

    -
      -
    • There is now a "GitHub" button.
    • -
    • Modified the height of the "Donate" button to make it equal to that of other buttons.
    • -
    • The distance between the info and wiki buttons is now 30 px. All other buttons now have a 5px distance between them.
    • -
    • Fixed a typo in the wiki window.
    • -
    - -

    29 October 2017

    -

    Alffd updated:

    -
      -
    • Ion Rifles are no longer pistols
    • -
    - -

    28 October 2017

    -

    Anasari updated:

    -
      -
    • Some underappreciated traitor items had been made cheaper.
    • -
    -

    Kyep updated:

    -
      -
    • Vamp jaunt/shadowstep no longer works on z2.
    • -
    • Ghosts with sec hud enabled can now see mindshield, tracker and chem implants, as well as wanted status.
    • -
    -

    Landerlow updated:

    -
      -
    • Adds Sake to a hacked booze dispenser's menu.
    • -
    -

    Squirgenheimer updated:

    -
      -
    • Fixed a typo causing the inability to create the large energy crossbow in the protolathe.
    • -
    - -

    27 October 2017

    -

    Birdtalon updated:

    -
      -
    • Birdtickets: Adminhelp Ticketing System
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Silver Slime Core reactions can only summon forth drinks that actually contain a drink. Begone thirst!
    • -
    • Removes some "unsafe" chemicals from lists of potential chemicals for inclusion in things like random pills or bottles, added one to replace them.
    • -
    • Removes adminordrazine and nanites from vent clog, replaces nanites with syndicate_nanites.
    • -
    - -

    26 October 2017

    -

    Anasari updated:

    -
      -
    • Change some brain damage phrases. Add a lot of new one.
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Moves Ambulance's key to Paramedic's EVA locker from his clothing locker
    • -
    • Removed an unnecessary EVA helmet from Paramedic's EVA locker
    • -
    -

    Kyep updated:

    -
      -
    • Soviets (including Soviet Tourists, a non-antag filler role) no longer get all-access to the Cyberiad when they visit.
    • -
    • Freedom Operatives are now a support outfit that admins can equip players as.
    • -
    -

    TDSSS updated:

    -
      -
    • Added a shortcut to talk on ERT channel, namely ':$', bringing it in line with other channels.
    • -
    - -

    25 October 2017

    -

    Anasari updated:

    -
      -
    • Flavour text description in character setup now consistent with rules.
    • -
    • Grenade reagent are also logged when they are primed
    • -
    • TC from war op increased by 2 per player above 50.
    • -
    -

    Kyep updated:

    -
      -
    • ERTs now support janitor, paranormal, and cyborg ERT units, as well as specific slot configurations.
    • -
    • Heads of staff who are editing another admin's permissions in the admin panel can now toggle several permissions for a person without re-finding them in the list. Hitting 'cancel' at any point drops out of the loop. It also notifies admins whether they're toggling a permission on, or off.
    • -
    • ERT spawn area now shows ERT request reasons, and admins can enable the use of a teleporter or grav catapult without mechs.
    • -
    - -

    22 October 2017

    -

    Crazylemon64 updated:

    -
      -
    • Suiciding crewmembers are no longer capable of being cloned.
    • -
    -

    Fethas updated:

    -
      -
    • makes a better proc for doing spins (IE Ian chasing tail, etc) then was previous.
    • -
    -

    McCloud and Alffd updated:

    -
      -
    • Merge all LINDA and atmos machine functions into the air controller subprocess.
    • -
    • Air alarms in scrubbing mode will shut off when alarm enters danger state. If this occurs simultaneously with a max2 temperature alarm panic siphon will automatically activate.
    • -
    • High air pressure differences will throw objects and knock over station species.
    • -
    • Add magpulse to syndicate and death squad borgs.
    • -
    • Change all volume pumps to regular pumps in atmospherics to accommodate new LINDA speeds.
    • -
    • Change LINDA interval from 2 seconds to 400 milliseconds.
    • -
    • Removed unused control from flamethrower.
    • -
    • Set flamethrower release equal to fuel used.
    • -
    • Increased Reinforced Wall HP from 200 to 600.
    • -
    • Buff aliens against space wind.
    • -
    • Buff Terror Spiders against space wind.
    • -
    • Buff some blobmobs aginst space wind.
    • -
    • Frost requires heat to remove.
    • -
    - -

    15 October 2017

    -

    Citinited updated:

    -
      -
    • Clipboards now have more functionality. You can now stamp them, attach paper bundles to them, write on any contained paper by clicking on the paper's name using a pen, add pens directly to them, and rearrange what piece of paper is on top!
    • -
    • Full-sized plasma windows are fire-resistant, and full-sized reinforced windows are fully fireproof.
    • -
    • You can now remove facehuggers from corgis. Corgis that have been glomped by multiple facehuggers will now work as you'd expect them to.
    • -
    • Radiation mines no longer change the DNA of species that don't have it.
    • -
    • Firedoors and other doors will no longer close when a shuttle docks. Open firelocks can no longer be welded. Welded firelocks should no longer open under any circumstances.
    • -
    • Open airlocks no longer spark when you throw something conductive through them.
    • -
    -

    Fethas updated:

    -
      -
    • Many things use sleeping. Surgry pain fail fix.
    • -
    -

    Imsxz updated:

    -
      -
    • Ballistic mech weapons now all use the ammo system
    • -
    -

    Kyep updated:

    -
      -
    • Changing someone's sec status now prompts for a reason. The change, and the (optional) reason for it, is written to that person's sec record, and to the server logs. This applies to changes made by sec HUDs, and by records computers.
    • -
    • Magistrate/Captain/HoS/Warden can now use a sec records computer to set a person to "Execute" status. This status cannot be unset by HUDs, and broadcasts a notification to all online admins when it is set. It is intended to replace the "fax CC" requirement for executions. Persons with this status show up with a white 'X' as their sec hud icon.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Shadowlings are extinguished after hatching, allowing Plasmamen Shadowlings to not burn to death.
    • -
    • Shadowlings now passively heal eye damage, eye blurriness
    • -
    -

    Vivalas updated:

    -
      -
    • Splints now pop off after 2000 steps, or when taking a lot of damage to that limb. Getting surgery for those broken limbs might be a good idea now.
    • -
    - -

    14 October 2017

    -

    Anasari updated:

    -
      -
    • Explosive lance doesn't embed anymore.
    • -
    -

    Fethas updated:

    -
      -
    • ARMBANDS! REPRESENT! SEE THE LOADOUT!
    • -
    -

    Kyep updated:

    -
      -
    • HoPs/Captains opening/closing job slots is now announced to admins. No more HoPs opening 30 clown slots without admins noticing.
    • -
    -

    MarsM0nd updated:

    -
      -
    • Gives a choice whether to mangle black gloves, or to completely cut of the fingertips
    • -
    - -

    11 October 2017

    -

    Anasari updated:

    -
      -
    • Slot machine no longer earn money on average. Bet changed to 100.
    • -
    • All items can be used to smash windows instead of only those defined as weapons. (e.g. including guitar & flashlight)
    • -
    • Mulebot with pAI cannot knock people down anymore.
    • -
    -

    Birdtalon updated:

    -
      -
    • Terror spiders now respect antagHUD respawn restrictions.
    • -
    -

    Kyep updated:

    -
      -
    • mindslaving an antagbanned player now offers control of their mob to ghosts.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Can now place garbage in garbage cans without standing on top of them.
    • -
    -

    scrubmcnoob updated:

    -
      -
    • Cult must use teleport tailsman in active hands.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • New PACMAN portable generator sprites
    • -
    - -

    10 October 2017

    -

    Birdtalon updated:

    -
      -
    • Bees with no reagent will now work.
    • -
    - -

    07 October 2017

    -

    Birdtalon updated:

    -
      -
    • User interface tweaks to Brig timers.
    • -
    • Seconds converted to minutes and seconds in Brig radio and security console printouts.
    • -
    • Bees can no longer reproduce un-synthable reagents.
    • -
    -

    imsxz updated:

    -
      -
    • Aliens now always spawn as a pair when their infestation event begins.
    • -
    -

    scrubmcnoob updated:

    -
      -
    • Abductors can no longer use megaphones.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Adds new sprites to the unused and used eldritch whetstones. Sprites by Fury McFlurry.
    • -
    • Air tanks now have their own sprite, no longer looking like oxygen tanks
    • -
    • 10mm alt magazines have their own sprites
    • -
    - -

    06 October 2017

    -

    Birdtalon updated:

    -
      -
    • Bottler doesn't break after one use.
    • -
    - -

    05 October 2017

    -

    Birdtalon updated:

    -
      -
    • Re-adds missing light switch to robotics.
    • -
    - -

    02 October 2017

    -

    Imsxz updated:

    -
      -
    • Rapid re-hatch no longer kills shadowlings.
    • -
    • Vampires can no longer enthrall chaplains
    • -
    - -

    30 September 2017

    -

    Jovaniph updated:

    -
      -
    • Coroner now has their own locker in the morgue.
    • -
    -

    Landerlow updated:

    -
      -
    • Adds hydrocodone to the Cyborg Hypospray
    • -
    - -

    29 September 2017

    -

    Citinited updated:

    -
      -
    • Telescreens and entertainment consoles now have 'off' and 'broken' sprites.
    • -
    • Wooden TVs, engineering camera consoles, mining camera consoles, telescreens, and entertainment consoles now have their own circuit boards and can be reconstructed!
    • -
    • Using a multitool on a telescreen or entertainment monitor will now allow you to reposition it.
    • -
    -

    imsxz updated:

    -
      -
    • Subtle messages no longer begin with "old"
    • -
    - -

    28 September 2017

    -

    MarsM0nd updated:

    -
      -
    • Stops the electrified arm from combat and stunbaton implant from runtiming.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Changelings have a new power, Biodegrade, for 2 evolution points. For 30 chemicals you can vomit acid onto restraints, welded/locked lockers and spider cocoons to escape them.
    • -
    • Hivemind Link for changelings has been readded, it was removed in error
    • -
    - -

    05 September 2017

    -

    Kyep updated:

    -
      -
    • Adds alternative military shuttle, NT Navy troop transport.
    • -
    - -

    04 September 2017

    -

    Kyep updated:

    -
      -
    • Admins under the effects of 'invisimin' no longer show up on sec huds, medical huds, etc.
    • -
    - -

    03 September 2017

    -

    Birdtalon updated:

    -
      -
    • Flip emote has a small chance of a failure and 100% chance of embarrassing yourself.
    • -
    -

    Citinited updated:

    -
      -
    • You can now deconstruct the indestructible stool in the old bar's back room.
    • -
    • Security and bar maintenance airlocks are now decoupled.
    • -
    • The air vent at the fore of AI satellite now starts turned on.
    • -
    • Engineering equipment now only has one air vent, not three.
    • -
    • Added a missing bit of plating underneath the engineering shuttle's window.
    • -
    • Added a missing scrubbers pipe in Central Primary.
    • -
    • The camera and light fixture in the prisoner transfer centre are now wall-mounted instead of being attached to the blast doors.
    • -
    • Adds the Flaming Moe cocktail.
    • -
    • Shot glasses can now be set alight using something hot.
    • -
    - -

    02 September 2017

    -

    Landerlow updated:

    -
      -
    • Adds a recipe to create enzymes to cook with.
    • -
    - -

    01 September 2017

    -

    Birdtalon updated:

    -
      -
    • Fixed small bug with wall lockers not respecting distance.
    • -
    - -

    28 August 2017

    -

    Birdtalon updated:

    -
      -
    • Replaces civilian door remote in the Head of Personnel locker with a brand new remote with additional access to better suit the Head of Personnel's responsibilities.
    • -
    • Nanotrasen Mining Bots are no longer safe from EMPs.
    • -
    • Syndicate bee-case sound now only plays locally when opened.
    • -
    • You can open wall lockers with control click.
    • -
    -

    Birdtalon & Hylocereus updated:

    -
      -
    • Adds pineapples which can be grown in hydroponics, juiced or sliced and made into hawaiian pizza.
    • -
    • Adds hawaiian pizza to the pizza crate.
    • -
    -

    Fethas updated:

    -
      -
    • The cultist dagger has had its special removed, it still cuases small bleed and retains its embed chance.
    • -
    • Prayers now dsiplay the diety set by chaplains (if any) to admins in prayers, or eldergod if a cultist. Prayers are purple for normies, Red for cultist and blue for chaplains
    • -
    -

    Fox McCloud updated:

    -
      -
    • IPCs can now be dissected by adbudctors
    • -
    -

    Fox Mccloud updated:

    -
      -
    • Adds an accordian, glockenspiel, harmonica, recorder, saxaphone, trombone, xylophone, bikehorn, and piano synthesizer
    • -
    • pick up a big band supply pack of instruments at cargo for 50 supply points
    • -
    -

    Jovaniph updated:

    -
      -
    • Holodeck Energy Swords sound was change to simulate being attacked by a real energy sword.
    • -
    -

    Landerlow updated:

    -
      -
    • Adds six additional roundstart disabilities to choose from
    • -
    -

    matt81093 updated:

    -
      -
    • robot analyzer to medical module cyborgs for IPC diagnosing
    • -
    - -

    24 August 2017

    -

    Birdtalon updated:

    -
      -
    • Cultist structures can now be destroyed using melee and or projectiles
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes Diona, Plasmamen, and other races having internal bleeding
    • -
    - -

    16 August 2017

    -

    Citinited updated:

    -
      -
    • Adds the plasmaman flag; credit to Shadeykins for the original sprite! Buy it at the merch store and show your superiority over other, less flammable, species!
    • -
    • All flags should now have in-hand sprites.
    • -
    • Burning a flag while it is in your hand will now update your mob's sprite.
    • -
    • Fixes another issue with disposals sending things to nullspace.
    • -
    -

    Fethas updated:

    -
      -
    • Swarmers can now deconstruct simply by clicking, ctrl click to teleport.
    • -
    • you can now deactivate depowered swarmers with a screwdriver.
    • -
    • Swarmers can now consume swarmer shells for a refund.
    • -
    • swarmer lights are cyan.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Cluwning is far more difficult to remove
    • -
    • Cluwne mask cannot be melted with acid
    • -
    • Cluwne suit has no sensors
    • -
    -

    Kyep updated:

    -
      -
    • Admins now have a 'List SSDs' verb to list SSD players, and the ability to move them to cryo.
    • -
    - -

    15 August 2017

    -

    Birdtalon updated:

    -
      -
    • Medbots can now inject from their internal beakers.
    • -
    • Swarmers can no longer kill the AI with direct attacks.
    • -
    • Simple animal melee damage now has a sanity check for AI core.
    • -
    - -

    14 August 2017

    -

    AndrewMontagne updated:

    -
      -
    • Modular computers now print fields correctly.
    • -
    • Files on modular computers no longer vanish shortly after editing.
    • -
    • Modular computers printers now make printing noises.
    • -
    • You can no longer try and buy a tablet with a printer.
    • -
    • Cloning a file now works.
    • -
    -

    Birdtalon updated:

    -
      -
    • Spiderbots can now pass tables, making their Hide worthwhile.
    • -
    • Fixes interactions with cargo crates.
    • -
    -

    Citinited updated:

    -
      -
    • Nanotrasen's legal department clamped down on video cameras being misappropriated by crew, and as such cameras are now unable to broadcast from beyond the gateway.
    • -
    -

    Fethas updated:

    -
      -
    • Dethaws some IPC surgery issues.
    • -
    -

    taukausanake updated:

    -
      -
    • Adds an Atmospherics duffel bag that is yellow and blue
    • -
    • Adds sub-department colors to medical duffel bags and purple to Science duffel bags
    • -
    • Captain's lefthand west sprite corrected
    • -
    - -

    10 August 2017

    -

    KasparoVy updated:

    -
      -
    • Blood trails are now the same colour as the blood pools they came from when viewed by colour blind or noir shades wearing humanoids.
    • -
    - -

    09 August 2017

    -

    Purpose2 updated:

    -
      -
    • Adds a cycling airlock on the new mining mini outpost.
    • -
    • Re-adds the cycling airlock on mining outpost.
    • -
    • Fixes the broken atmos piping on mining outpost.
    • -
    • Fixes a lack of lighting on mining outpost.
    • -
    - -

    06 August 2017

    -

    Birdtalon updated:

    -
      -
    • Small wording change to syndicate collaborator greetings.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Botany nerfed; will need ambrosia gaia earth's blood to make a tray self-sustaining
    • -
    • Gene machine now requires heavy upgrading to make use of transferring high quality genes from one plant to another
    • -
    • Starthistle can now be grown
    • -
    • Adds in red and regular onions; slice them for onion rings; cook them for even more delicious onion rings
    • -
    -

    Kyep updated:

    -
      -
    • Playing as a smite/bless hunter, or syndie infiltration team member, now requires that you be traitor-eligible. IE: have enough playtime, and the preference enabled.
    • -
    -

    Purpose2 updated:

    -
      -
    • BoxStation: Adds a garbage receptacle by the kitchen. Don't forget to bus your plates.
    • -
    • BoxStation: Fixes an inappropriate access restriction on one part of an airlock, and ensures the buttons are visible.
    • -
    • BoxStation: Changes the now erroneous Science Shuttle Console on the bridge to a Labor Camp Shuttle Console.
    • -
    • Adds screwdrivers to Medical by the cell chargers for recharging the defibs.
    • -
    - -

    05 August 2017

    -

    Purpose2 updated:

    -
      -
    • Karma message will now point you in the right direction again.
    • -
    - -

    03 August 2017

    -

    Fox McCloud updated:

    -
      -
    • Internal organs can take damage again, brain damage can be fixed again, and you now take the proper damage from external sources to limbs, IPCs surviving EMPs, and robo limbs never malfunctioning
    • -
    - -

    02 August 2017

    -

    Fox McCloud updated:

    -
      -
    • removed a stasis book from the medical break room
    • -
    - -

    31 July 2017

    -

    Birdtalon updated:

    -
      -
    • Protolathe stock part printing no longer takes a lifetime.
    • -
    - -

    30 July 2017

    -

    FreeStylaLT updated:

    -
      -
    • Fixed erroneous pipes on z5
    • -
    -

    Kyep updated:

    -
      -
    • Evil-minded players can no longer use the Gateway's Mother of Terror spider to create an infestation on-station.
    • -
    - -

    29 July 2017

    -

    Fox McCloud updated:

    -
      -
    • Dead hearts now induce a heart attack
    • -
    • Fixed concentrated initro never metabolizing
    • -
    -

    FreeStylaLT updated:

    -
      -
    • replaces generic Mining z-level with Meta's
    • -
    -

    Purpose2 updated:

    -
      -
    • MetaStation: Adds the missing kitchen windows
    • -
    • MetaStation: Nerfs the Top Hat equivalent of the Sword in the Stone.
    • -
    • MetaStation: Adds a Pet Supply vendor, chefs now make sushi again!
    • -
    - -

    27 July 2017

    -

    Birdtalon updated:

    -
      -
    • Protolathe speed now increases when upgraded with manipulators.
    • -
    - -

    26 July 2017

    -

    Citinited updated:

    -
      -
    • The autopsy drawer's description makes more sense.
    • -
    - -

    25 July 2017

    -

    Birdtalon updated:

    -
      -
    • Reduces the volume of the electric guitars
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Antagonists will no longer get the objective to steal slime extracts and plasma tanks.
    • -
    • The Captain has a swanky high-tech jetpack now. Antagonists will try to steal this one instead of *any* jetpack.
    • -
    -

    Fox McCloud updated:

    -
      -
    • You can now point while voluntarily lying down
    • -
    • shotgun darts and syringe darts no longer react their reagents on hit (they will still transfer reagents)
    • -
    • removes cryostasis bag
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Removed sci outpost and dock from Metastation and Cyberiad
    • -
    • Added a Mining Outpost to the northernmost point of the Asteroid.
    • -
    -

    Kluys, Kyep & DarkLordpyro updated:

    -
      -
    • Emagged drones are now readily identifiable, as their lights turn red.
    • -
    -

    Kyep updated:

    -
      -
    • Eating as Ian (and other player-controlled corgis) is now rate-limited.
    • -
    • Reagents placed in shotgun shells will now react. It is no longer possible to make explosive shotgun darts by using regular darts like cryobeakers.
    • -
    • Admins' Smite command has been upgraded. No longer limited to Dark Priests, it can now send over a dozen different entities in search of its target, from the comic, like Greytiders, Tunnel Clowns, Masked Killers and Mime Assasins, to the serious, such as Syndicates, Soviets, Dark Lords and more. All come with a dust implant. These same characters can also be sent to protect specific crew members, so they aren't predictable.
    • -
    • The 'reaper' admin outfit now has a working briefcase.
    • -
    • Use of the 'Bless' command to bestow powers no longer causes genetic damage.
    • -
    -

    imsxz updated:

    -
      -
    • makes HONK rifle selfcharge
    • -
    -

    owenowen212 updated:

    -
      -
    • Adds the clownish language to honk squad members.
    • -
    - -

    24 July 2017

    -

    FlattestGuitar updated:

    -
      -
    • Adds a taste system! Drink or eat stuff to find out what it tastes like!
    • -
    -

    Kyep updated:

    -
      -
    • it is no longer possible to use a sentience potion to convert space pirates in the beach away mission to your side. Nor is this possible with other sentient NPCs, such as syndies or russians.
    • -
    - -

    23 July 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes cloners causing infections in clonees
    • -
    - -

    22 July 2017

    -

    Crazylemon64 updated:

    -
      -
    • Slipping now outputs a visible message instead of a personal one
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes IPCs and Diona being immune to weapon knockdown
    • -
    -

    Kyep updated:

    -
      -
    • Terror Spider away mission is now harder to cheese.
    • -
    • Loading a different character while in the lobby will now update the character name listed on the lobby screen. Same when you rename an existing character.
    • -
    • Blood decals are no longer movable. This means LINDA cannot move them, spiders cannot wrap them, etc.
    • -
    - -

    21 July 2017

    -

    Purpose2 updated:

    -
      -
    • MetaStation: Adds a brand new Medbay!
    • -
    • MetaStation: Adds the dogbeds to the CMO/HoS office
    • -
    • MetaStation: Adds Sergeant Araneus back to the HoS's office. HoS beware.
    • -
    • MetaStation: Adds a processing area to the brig.
    • -
    • MetaStation: Adds the Gamma Armory.
    • -
    • MetaStation: Adds two additional brig cells
    • -
    • MetaStation: Adds a morgue slab to the Brig Phys office
    • -
    • MetaStation: Morgue has a swanky new office, directly connected to Cloning.
    • -
    • MetaStation: Robotics gets gloves and masks.
    • -
    • MetaStation: Adds shutters to R&D and Genetics.
    • -
    • MetaStation: Adds a Paramedic's office.
    • -
    • MetaStation: Adds a fully function containment grid.
    • -
    • MetaStation: Moves Monitor Encryption key to the RD's office again
    • -
    • MetaStation: Dorms have glass doors and fewer tinted windows
    • -
    • Metastation: Engine Containment now has Blast Doors instead of Shutters.
    • -
    • Metastation: Execution chamber blast doors are no longer see-through.
    • -
    • Metastation: Only the appropriate plastic flaps should be see-through.
    • -
    • MetaStation: Botany is no longer all-access
    • -
    • MetaStation: Science gets access to the Science outpost again... for now...
    • -
    • MetaStation: Fixes camera network monitors
    • -
    • MetaStation: Church shutters block vision again
    • -
    • MetaStation: Adds the missing Armory shutter button.
    • -
    • MetaStation: Removes tinted windows from R&D & Genetics
    • -
    - -

    20 July 2017

    -

    Purpose2 updated:

    -
      -
    • Stops vampires spawning in the church.
    • -
    - -

    19 July 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes dismembering and some damage transfers (when limb damage is maxed out) being inconsistent
    • -
    • can no longer dismember groins
    • -
    • Cleans up human examine code to be better laid out and more consistent; minor grammatical changes and some fixes; consistency should be retained for species that lack a pulse. Soul departure now properly checks for if the person can re-enter their corpse or not. Also resolves issues with FAKE DEATH examination.
    • -
    • Adds in gunshot blood splattering
    • -
    - -

    18 July 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes blood volume being able to exceed 560
    • -
    -

    Purpose2 updated:

    -
      -
    • The Arrival's Trader Dock now cycles properly.
    • -
    - -

    16 July 2017

    -

    Ataman updated:

    -
      -
    • Fixed diona nymphs needing oxygen and getting cold.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Cable laying by clicking the cable you want to join to works now
    • -
    -

    KasparoVy updated:

    -
      -
    • Fixes a bug with Vampire Shapeshift where you didn't get a name appropriate to your species and clarifies the ability description.
    • -
    • Fixes a bug with DNA scramblers whereby you wouldn't get a name appropriate to your species.
    • -
    - -

    15 July 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes blood oddities with vampires
    • -
    -

    Kyep updated:

    -
      -
    • Mechs firing missiles no longer cause the missiles to drop at their feet, as if frozen in midair.
    • -
    -

    imsxz updated:

    -
      -
    • Edits the syndicate soft suit helmet's description to match the suit's.
    • -
    - -

    13 July 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes blood volume and type not showing up properly on health analyzer
    • -
    • Fixes exotic blood names being incorrect
    • -
    • fix examining/checking yourself/others for bleeding/bandaging
    • -
    • Everything that involves bandaging now properly uses the new blood system
    • -
    • Fixes species exotic blood being injected into a mob not increasing their blood volume (slimes rejoice)
    • -
    • Fixed faked deaths still allowing for bleeding
    • -
    • Fixes IV drips not transferring over the proper amount of blood
    • -
    • Embedded objects will cause additional bleeding
    • -
    • Adds in heparin, a drug that can cause bleeding
    • -
    • medical stacks can be used multiple times on the same limb
    • -
    • Blood depletes in the body a lot faster now, due to blood refactor changes
    • -
    -

    Shazbot-coding, Driker-Sprites updated:

    -
      -
    • Gives the clown their own jug
    • -
    - -

    12 July 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixed advanced scanners showing hidden viruses
    • -
    • Fixed changeling panacea curing beneficial viruses
    • -
    • removed blood decal infections
    • -
    • some diseases now bypasse species virus immunity (kuru, TB, and appendicitis)
    • -
    - -

    11 July 2017

    -

    Fethas and tigercat updated:

    -
      -
    • blood trails
    • -
    • blood is now eaiser to decrease/increase .
    • -
    • revamps about every method of adding blood to something, floors, walls, doors, PEOPLE.
    • -
    - -

    10 July 2017

    -

    AffectedArc07 updated:

    -
      -
    • APC frames now have the correct texture
    • -
    -

    Birdtalon updated:

    -
      -
    • Pool contractors have been back to school and can now spell "safety" on the controller correctly.
    • -
    • Minor change to blob description to address grammar issue.
    • -
    -

    Citinited updated:

    -
      -
    • Superfart once again works ass intended.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Radiation poisoning no longer permastuns, but deals burn damage now and has increased mutation chances
    • -
    • adds in electric guitars
    • -
    • can now craft violins and electric guitars
    • -
    • purchase electric guitars at the cargo store
    • -
    • service borgs now have an electric guitar, too
    • -
    • lowered the price of instruments, at cargo store, to 500
    • -
    • Fixed violins not having an in-hand icon
    • -
    - -

    08 July 2017

    -

    Citinited updated:

    -
      -
    • Rainbow and mime crayons will now change colour as intended.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Advanced mop slightly slower at cleaning and holds less reagents, but now regenerates water if turned on
    • -
    • Blood (on the floor) that has viruses in it will now properly infect you, if you get near
    • -
    -

    Kyep updated:

    -
      -
    • It is no longer possible to prioritize a job with no open slots, or close any job slots for a job that is already prioritized, as either of these actions could lead to a situation where a job is prioritized without people being able to join as it.
    • -
    - -

    05 July 2017

    -

    Purpose2 updated:

    -
      -
    • Anomalies will once again drop cores.
    • -
    - -

    04 July 2017

    -

    Birdtalon updated:

    -
      -
    • Traitor medical chemists can now access syndicate poison bottles.
    • -
    -

    Citinited updated:

    -
      -
    • AIs and cyborgs can now toggle liquid dispensers by ctrl-clicking them, and can make them dispense foam by alt-clicking.
    • -
    -

    Citinited & LightFire53 updated:

    -
      -
    • Adds the plasmaman coroner suit, the plasmaman geneticist suit, and the plasmaman virologist suit. Spooky purple skeletons everywhere rejoice!
    • -
    -

    Fethas updated:

    -
      -
    • Adds medical gowns to medical wardrobes.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Syndicate bombs now have visible timers for observers
    • -
    • Syndicate bombs tick more often
    • -
    • Syndnicate bombs can be deconstructed into plasteel if it is fully defused and has no bomb core
    • -
    • Can make Cryo, Pyro, and time released chemical grenades at R&D
    • -
    • Can make syndicate chemical bombs utilizing crafting
    • -
    • love just got more powerful; it now prevents a mob from being on anything other than help intent
    • -
    • IPCs can now process the love reagent
    • -
    • Adds in radio jammers to the traitor uplink
    • -
    • Adds in breathing tube augment to R&D
    • -
    • Adds in arm toolset augment to R&D
    • -
    • IPC cell charging device is now inside their right arm, as opposed to chest
    • -
    • IPC cell charging device can now be produced in mech fabricators
    • -
    -

    Ionward updated:

    -
      -
    • Greys now have properly fitting sprites for most head clothing items!
    • -
    -

    Kyep updated:

    -
      -
    • Gimmick Teams are now more configurable.
    • -
    -

    Vivalas updated:

    -
      -
    • "Tweaks" SecHUDs to only display criminal status of people if their face is uncovered or they have no ID.
    • -
    - -

    03 July 2017

    -

    Fethas updated:

    -
      -
    • fixes issue with hand teleporter not working in active hands
    • -
    -

    fludd12 updated:

    -
      -
    • Greys are now PROPERLY immune to sulfuric acid.
    • -
    • Greys don't pretend to touch their heads when they don't manage to anymore.
    • -
    - -

    01 July 2017

    -

    Fox McCloud updated:

    -
      -
    • Re-enables object embedding system; embedding objects now cause more damage than before
    • -
    • Adds in throwing stars kit to the traitor uplink
    • -
    • bullets no longer leave shrapnel
    • -
    - -

    30 June 2017

    -

    fludd12 updated:

    -
      -
    • Greys treat Sulfuric Acid as if it were water. They also treat water as if it were sulfuric acid.
    • -
    • Grey language is now Z-level wide, but requires you to be able to put a finger to your temple. (Requires at least one hand not disabled and not stunned.)
    • -
    • Remote Talk is buffed to have a range of two screens, and has some minor formatting changes!
    • -
    • Remote Talk no longer lets you magically know the true name of whoever you speak with.
    • -
    - -

    29 June 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes limbs being an open wound after augmentation
    • -
    -

    Kluys updated:

    -
      -
    • Bob ross painting in the captains office called "calming painting". -Also changes around the entertainment monitor and light switch to accomodate.
    • -
    • Clown painting was named "\improper mech painting"
    • -
    - -

    28 June 2017

    -

    Fox McCloud updated:

    -
      -
    • Fix's IPC head customization
    • -
    -

    Purpose2 and Re-Opened by Fethas updated:

    -
      -
    • Rare Sentience event, the mice now want coffee!
    • -
    - -

    27 June 2017

    -

    Alexshreds updated:

    -
      -
    • EMPs now disable radios for a period of time
    • -
    -

    Citinited updated:

    -
      -
    • Adds the Rapid Pipe Dispenser (RPD). All Atmospherics Technician lockers and the Chief Engineer's locker get one each.
    • -
    -

    Code Fethas and Sprites Phantasmicdream updated:

    -
      -
    • Fancy Victorian Clothes
    • -
    -

    FlattestGuitar updated:

    -
      -
    • defibs work even if you don't target the chest
    • -
    • Chaplain's soul stone is now opt-in.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Can now augment all non-head limbs with surgery
    • -
    • Can select the company design of a limb by using a robot part in your hands
    • -
    -

    Kyep updated:

    -
      -
    • Gamma ship now looks like a real supply pod/ship, doesn't encourage wizards/vampires to hide in it, and has been updated with a wall-mounted charger and smarter layout.
    • -
    • Fixed a bug causing gamma armory mech recharger to be unusable after gamma alert was declared.
    • -
    • Admins may now spawn 'Gimmick' teams, including Janitorial ERT, Paranormal ERT, and more. Any admin outfit, any mission, spawned anywhere.
    • -
    • Paranormal ERT outfit now exists. It acts like a red security ERT, except with focus on fighting paranormal threats.
    • -
    • Janitorial ERT now gets ERT headset, not centcom headset. Also, they now get a survival box, and a flashlight.
    • -
    • New 'department' shuttle now has more public-access seating.
    • -
    -

    ProperPants updated:

    -
      -
    • Plasmaman virologists now spawn with a medical plasmasuit instead of an assistant one.
    • -
    -

    Purpose2 updated:

    -
      -
    • Water coolers have been fitted with better bolts, enabling them to be loosened and moved.
    • -
    • Antag barbers scissors now have the same name as regular scissors.
    • -
    • AIs door open link is now [O] rather than [OPEN].
    • -
    • The Syndicate once more recognises the Coroner as a member of the medical team for purposes for uplink items.
    • -
    • The chef may now tap into the Syndicate's poison networks for use in his dishes.
    • -
    • The chef's supply crate now comes with another rolling pin. Stop misplacing these.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Karma returned to the Special Verbs tab
    • -
    - -

    26 June 2017

    -

    Crazylemon64 updated:

    -
      -
    • TK can now manipulate adjacent tiles. Use throw mode to override this if you want to move an object a single tile.
    • -
    • TK can now remotely manipulate item stacks.
    • -
    • TK can now remotely operate an RCD
    • -
    • TK now behaves more consistently regarding interacting with various objects remotely
    • -
    -

    Kyep updated:

    -
      -
    • ID card consoles can now be used to prioritize any on-station job, including head jobs and karma jobs.
    • -
    • Playing as a drone now requires 10h of playtime.
    • -
    • Admin-ghosts can now interact with (ie: activate) the drone fab without having to spawn in as engineer to do so.
    • -
    • Prioritized jobs now lose their priority status once all their slots are filled. In the event someone with a formerly prioritized job cryos, the HoP may want to re-prioritize the job.
    • -
    -

    Purpose2 updated:

    -
      -
    • Coroners are more battlehardened, and thus don't throw up around dead bodies anymore.
    • -
    - -

    25 June 2017

    -

    Kyep updated:

    -
      -
    • Trial admins no longer see a permissions error when opening player panel.
    • -
    - -

    24 June 2017

    -

    Allfd updated:

    -
      -
    • Ported growl and howl sounds from Goon
    • -
    • Added growl and howl emotes to Vulpkanin
    • -
    -

    Kyep updated:

    -
      -
    • Activating a dust implant no longer causes NODROP items to drop.
    • -
    -

    Purpose2 updated:

    -
      -
    • The *slap emote now has a cooldown like all other noise making emotes.
    • -
    -

    SamHPurp updated:

    -
      -
    • The Coroner will respect the CMO's Authoritah.
    • -
    - -

    23 June 2017

    -

    Kyep updated:

    -
      -
    • Smite/Bless commands are now restricted to Game Admins. (admins with R_EVENT)
    • -
    • Admins can now access telecomms while ghosted.
    • -
    -

    Vivalas updated:

    -
      -
    • Buckling mobs to beds now displays them correctly.
    • -
    - -

    22 June 2017

    -

    Crazylemon64 updated:

    -
      -
    • Cloners now malfunction if the original comes back to life
    • -
    -

    Purpose2 updated:

    -
      -
    • RCDs can no longer construct multiple airlocks on a single tile
    • -
    - -

    21 June 2017

    -

    tigercat2000 updated:

    -
      -
    • Changelings are now tentacle monsters. Give them a schoolgirl outfit.
    • -
    - -

    20 June 2017

    -

    Purpose2 updated:

    -
      -
    • Fixes Fluorine's non-functionality in plants.
    • -
    - -

    19 June 2017

    -

    Fox McCloud updated:

    -
      -
    • Diona nutrition bar should no longer flicker constantly
    • -
    - -

    18 June 2017

    -

    Citinited updated:

    -
      -
    • Using a screwdriver on a camera console will now deconstruct it instead of opening the camera window.
    • -
    - -

    16 June 2017

    -

    Alffd updated:

    -
      -
    • Makes kittens visible when resting
    • -
    -

    Fethas updated:

    -
      -
    • Public Wiggler Tail
    • -
    • Chaplains have some new clothes in thier locker.
    • -
    -

    Fox McCloud updated:

    -
      -
    • tweaked Revenant and slaughter demon movement speed
    • -
    • Spiderbots have been slowed down to human levels
    • -
    • Spiderbots melee attack consistently deals 2 damage, deals burn, and plays a sparks sound
    • -
    • Spiderbots no longer have a built in camera
    • -
    • Spiderbots now have 40 health (previously 10)
    • -
    • Attacking a spiderbot more consistent with other simple mobs
    • -
    • Healing a spiderbot with a welder now plays a sound and incurs a cooldown
    • -
    • Spiderbots can no longer carry items
    • -
    • Emagging a spiderbot makes it loyal to the person who emagged it. Additionally, it gains 20 extra health, its shocks will do 15 damage, and will explode on death
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Changed Araneus' spawn location so he wouldn't break tables at round-start anymore
    • -
    -

    Kyep updated:

    -
      -
    • HoPs can now set jobs as 'priority'. Priority jobs are highlighted on the latejoin screen. This allows HoPs to proactively broadcast that they need more people to fill those jobs - and reduces the chance of critical crew shortages.
    • -
    -

    Purpose2 updated:

    -
      -
    • Soylen Viridians are now correctly Soylent Viridians. Nanotrasen will still not confirm rumours of the contents of these nor Soylent Greens however.
    • -
    • Nanotrasen is now more consistent with brand management.
    • -
    • An array of typos, grammatical tweaks and other pedantic fixes.
    • -
    • Adds a jobs board to the Newscaster. See what roles are available before seeing the HoP!
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Autopsy Scanners will now print out Coroner Reports when a pen is used on them
    • -
    -

    alexkar598 updated:

    -
      -
    • Rename Spagetti to Spaghetti
    • -
    - -

    13 June 2017

    -

    KasparoVy updated:

    -
      -
    • Moves a hidden emergency locker to where it is visible.
    • -
    -

    Vivalas updated:

    -
      -
    • Brig timers will now update the records of those who are imprisoned in their cell, as long as their name is entered correctly.
    • -
    • Sentences and arresting officers are announced over the security channel by brig timers, as well as the names of those who end timers manually.
    • -
    - -

    10 June 2017

    -

    Alffd updated:

    -
      -
    • Ports Incoming5643's persistence features for Runtime from TG
    • -
    • Ports additional cat NPC emotes from TG
    • -
    -

    Citinited updated:

    -
      -
    • Disconnecting before the shuttle leaves after having spent karma will no longer prompt you to spend karma.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds Highlander Style, granted to the wielder of Highlander Claymores. This martial art allows you to deflect ranged attacks from the weapons of COWARDS. FOR THE HONOR OF THE HIGHLANDERS!
    • -
    • Highlander now equips combatants with a Highlander claymore instead of a normal claymore. FIGHT ON BROTHERS!
    • -
    - -

    09 June 2017

    -

    Alexshreds updated:

    -
      -
    • Taking mhelps no longer gives mhelping players your IC name
    • -
    -

    FlattyPatty updated:

    -
      -
    • Added forensics gloves for the Detective.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Paramedic door is no longer diamond
    • -
    • Fixes the backwards health analyzer sprite
    • -
    • Remove adrenaline and freedom implants from R&D
    • -
    • Added chem and tracking implants to R&D
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds some sanity checking to the RCS.
    • -
    • The cargo shuttle no longer permits RCS telepads.
    • -
    -

    Kyep updated:

    -
      -
    • glowshrooms are now destroyable with two hits from a wirecutter.
    • -
    • New 'department' shuttle, which can be sent by CC instead of the regular evac shuttle.
    • -
    • The gods have grown tired of prayers requesting freebies, and developed some new curses with which to smite those who would treat them like miracle vending machines.
    • -
    -

    alexkar598 updated:

    -
      -
    • Surgury holosign switch has correct icon at roundstart
    • -
    -

    tigercat2000 updated:

    -
      -
    • You can now zoom in with the Set View Range option in your Preferences tab!
    • -
    - -

    08 June 2017

    -

    Alexshreds updated:

    -
      -
    • Hyphema and Ocular Restoration are now possible to evolve from viruses
    • -
    - -

    07 June 2017

    -

    Fethas updated:

    -
      -
    • adds cardboard cutouts..now you can trick the station into thinkings it shadowlings!
    • -
    -

    tigercat2000 updated:

    -
      -
    • Luxury versions of the bluespace shelter capsule! Currently not obtainable.
    • -
    • Black Carpet can now be crafted using a stack of carpet and a crayon.
    • -
    • Black fancy tables can now be crafted using Black Carpet.
    • -
    • Shower curtains can now be recoloured with crayons, unscrewed from the floor, disassembled with wire cutters, and reassembled using cloth, plastic, and a metal rod.
    • -
    - -

    06 June 2017

    -

    DarkPyrolord updated:

    -
      -
    • Plasmamen should be able to become vampires on normal vampire rounds.
    • -
    -

    Fox McCloud updated:

    -
      -
    • adjust the mech tesla, immolator, and disabler techs to bring it in line with the tech refactor
    • -
    -

    Kyep updated:

    -
      -
    • Instagib lasers now work against non-carbon mobs, such as animals and borgs.
    • -
    -

    imsxz updated:

    -
      -
    • Sergeant Araneus now spawns at full HP.
    • -
    - -

    04 June 2017

    -

    Crazylemon64 updated:

    -
      -
    • Clone's hearts now start operational
    • -
    • EMP'd clone pods can now be emptied again
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Cell 6 is now connected to the atmos system properly.
    • -
    - -

    03 June 2017

    -

    FlattestGuitar updated:

    -
      -
    • PACMAN boards and pico manipulators now have proper research levels
    • -
    - -

    01 June 2017

    -

    Alexshreds updated:

    -
      -
    • Ian's hardsuit is no longer invisible
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Gamma armory no longer affected by brig events.
    • -
    • Outer armory windoor access has been lowered to Security Officer+, instead of Warden+.
    • -
    • Removed a redundant door in the brig's main hallway.
    • -
    • Removed a redundant fire alarm, placed it elsewhere in the north hallway.
    • -
    -

    Kyep updated:

    -
      -
    • ERTs no longer start penniless, unable to afford even basic food, or coffee.
    • -
    -

    Purpose2 updated:

    -
      -
    • Adds a build-time on Tables & Racks.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Upgrading the Exosuit Fabricator and Protolathe with the right parts will lower item costs
    • -
    • Added an item to Cargo that RnD can use
    • -
    • Tweaks the tech levels for many items and the required tech levels for their designs. This is to make RnD more of a station-wide effort.
    • -
    • RnD tech level skipping skips 1 level further
    • -
    • The Destructive Analyzer will only prompt the user if tech levels will not be increased.
    • -
    • The Experimentor can no longer raise tech levels of items. It can however discover the tech levels of strange objects.
    • -
    • Removes the Autolathe from the RnD Room.
    • -
    • Removed the Forensic Scanner from RnD. Cargo can order a Forensics crate now.
    • -
    - -

    31 May 2017

    -

    FalseIncarnate updated:

    -
      -
    • Shrimp and electric eels properly lay their own eggs again if they have a suitable partner.
    • -
    -

    Xantholne updated:

    -
      -
    • Virologists actually spawn with their skirt
    • -
    • Coroner now can finally spawn with some Medical loadout clothes.
    • -
    • Medical Doctors will stop spawning with Chemist/Virologist Skirts
    • -
    • CMOs won't spawn with a virologist skirt anymore.
    • -
    • Virologists and Chemists wont spawn with a Medical Doctor skirt anymore.
    • -
    - -

    30 May 2017

    -

    Fruerlund updated:

    -
      -
    • You can now take out pens by CTRL Clicking PDAs
    • -
    - -

    29 May 2017

    -

    Jovaniph updated:

    -
      -
    • Two welding goggles on in the atmos room
    • -
    -

    Purpose2 updated:

    -
      -
    • Increases the size of Megaphones.
    • -
    • Headset encryption keys are now 'small' items.
    • -
    -

    Tayyyyyyy, FlattestGuitar updated:

    -
      -
    • A targeting mode-esque message and sound when you point at something with a gun in your active hand
    • -
    - -

    28 May 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes various mobs moving around faster than intended
    • -
    - -

    27 May 2017

    -

    Crazylemon64 updated:

    -
      -
    • Cloning now can be halted at any point, but ejecting too early may result in clones with missing body parts.
    • -
    • Slime people now no longer spontaneously die
    • -
    - -

    26 May 2017

    -

    FlattyPatty updated:

    -
      -
    • Removes gateway hotel xeno embryo for the crew's safety.
    • -
    - -

    25 May 2017

    -

    FalseIncarnate updated:

    -
      -
    • Matter Eater now requires your mouth be uncovered before you can eat matter.
    • -
    -

    Fethas updated:

    -
      -
    • PLASMAMAN ATMOS SUITS ARE NOW THE SAME AS REGULAR ATMOS SUITS FLAG WISE! AND SO IS THE CE SUIT
    • -
    -

    Kyep updated:

    -
      -
    • Fixed some mapping bugs on Centcom, e.g: shuttle medbay no longer has black walls.
    • -
    -

    Purpose2 updated:

    -
      -
    • Metastation - Adds the Paramedic's cart and locker.
    • -
    • Metastation - Adds a backup set of paramedic keys in the CMO's office.
    • -
    • Metastation - Engine no longer hotwired.
    • -
    • Metastation - Turbine doors now function properly.
    • -
    • Metastation - Toxin Mixing's Controller is now accessible.
    • -
    • Metastation - Moved Containment out a single tile, to fix irregularities with Singularity setups.
    • -
    • Metastation - Reduced redundant redundancies in the Atmos/Wiring.
    • -
    • Metastation - removed blob spawn that was only a few tiles from Cryostorage....
    • -
    • Drones can now grip Tracker Electronics & Vending Refills
    • -
    -

    Tayyyyyyy, PhantasmicDream updated:

    -
      -
    • Skrell can put a pocket sized item in their head tentacles, which can be dislodged via stunning, stripping, or death
    • -
    • Skrell can no longer have their tentacles shaved off
    • -
    • Minor grammar fix for putting stuff that's too big into containers
    • -
    - -

    24 May 2017

    -

    Kyep updated:

    -
      -
    • Every head of staff now has a Department Management Console in their office. This is a very limited version of the ID console that they can use to demote people out of their departments, or move people between jobs in their department. These consoles cannot be used to hire anyone, or to accept cross-department transfers.
    • -
    - -

    23 May 2017

    -

    Fethas updated:

    -
      -
    • Lockets and necklaces to the loadout. Lockets can hold paper and photos
    • -
    • Fethas fluff item
    • -
    -

    Purpose2 updated:

    -
      -
    • Adds functionality for the Atmos/Engineering Minimap to update to the right station.
    • -
    - -

    22 May 2017

    -

    DarkPyrolord updated:

    -
      -
    • Rubber pellets should no longer embed.
    • -
    • Bananas fired from the staff of the honkmother should no longer embed, or be called bullets.
    • -
    -

    Kyep updated:

    -
      -
    • Adds mech-mounted variants of the existing tesla, immolator, and x-ray laser guns, with the same material and tech requirements. Admin-only Seraph mech also gets better weapons.
    • -
    - -

    21 May 2017

    -

    KasparoVy updated:

    -
      -
    • Fixes a bug where only the fat roundstart disability could be selected.
    • -
    - -

    20 May 2017

    -

    FlattestGuitar updated:

    -
      -
    • Adds a jobban-checking verb to the OOC tab.
    • -
    -

    KasparoVy updated:

    -
      -
    • You can now set your character's auto-accent at character creation. The verb still exists in the OOC tab.
    • -
    -

    Kyep updated:

    -
      -
    • Antag roles now have playtime requirements.
    • -
    -

    Kyep: updated:

    -
      -
    • Updated CC map.
    • -
    -

    Xantholne updated:

    -
      -
    • The Coroner now has an actual job icon.
    • -
    - -

    19 May 2017

    -

    IK3I updated:

    -
      -
    • Empath stops telling you how much it hurts to not be human
    • -
    -

    MarsM0nd updated:

    -
      -
    • NanoUI map now shows the up-to-date map.
    • -
    -

    Purpose2 updated:

    -
      -
    • Coroner no longer alt title for MD
    • -
    • Adds Coroner job as its own job.
    • -
    • Adds a swanky new office for the Coroner.
    • -
    - -

    18 May 2017

    -

    FreeStylaLT updated:

    -
      -
    • Added a Newscaster to Brig Toilet.
    • -
    -

    Purpose2 updated:

    -
      -
    • Adds a subtle chat-window reminder for karma on Shuttle departure. Disable/enable via preferences tab.
    • -
    • Removes the ugly round-end karma popup.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Deaf people cannot hear tape recordings anymore
    • -
    - -

    17 May 2017

    -

    Fethas updated:

    -
      -
    • MORE GREY SPRITES!
    • -
    -

    FlattestGuitar updated:

    -
      -
    • You can now silence shoes just by using some duct tape on them! Shoe rags no longer exist.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Neuro-toxin bar drink weakens after 13 cycles as opposed to instantly
    • -
    -

    Purpose2 updated:

    -
      -
    • Makes the new posters actually spawnable.
    • -
    • Fixes far more spelling errors than there ever should have been on the posters.
    • -
    -

    Travelling Merchant updated:

    -
      -
    • Adds a hiss emote for Unathi.
    • -
    - -

    16 May 2017

    -

    FlattestGuitar updated:

    -
      -
    • Brig lockers now have radios and prisoner IDs. As per SOP!
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Fixed broken disposals in brig.
    • -
    • Returned missing Sergeant Araneus to HoS office.
    • -
    • Fixed missing floor tiles in the execution hallway in Brig.
    • -
    • Remapped the entire Brig.
    • -
    -

    Kyep updated:

    -
      -
    • changed security officer job slots from 5 to 7.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • You can now resist out of straightjackets
    • -
    • Straightjacketed people can be handcuffed
    • -
    - -

    15 May 2017

    -

    TullyBurnalot updated:

    -
      -
    • Disposal Bin Light now works with thrown items
    • -
    • Fixes typos with cowboy items
    • -
    - -

    13 May 2017

    -

    Fethas updated:

    -
      -
    • fixes a redundent add_cultist proc so cult memorize objectives works on new converts.
    • -
    • fixes an istype with IS_GAMEMODE_CULT
    • -
    • Narsie now will sometimes make a door a cult door..i thought i had that in the first time.
    • -
    • runed metal can now be only used on cult girders.
    • -
    -

    KasparoVy updated:

    -
      -
    • Fixes a sprite issue with the Unathi Dorsal Frill's webbing.
    • -
    - -

    12 May 2017

    -

    Fethas updated:

    -
      -
    • Makes thrall examine use MASKCOVERMOUTH and HIDEFACE flags
    • -
    • fixes hudsunglass goof with vox.
    • -
    -

    Xantholne updated:

    -
      -
    • Changes name from dark brown to brown for the default cowboy boots
    • -
    • Gives a hint that the cowboy shirts are meant to be clipped on to your uniform
    • -
    - -

    11 May 2017

    -

    Fethas updated:

    -
      -
    • Greybarber suit sprite.
    • -
    • Removes sec access from the paramedic
    • -
    -

    Fox McCloud updated:

    -
      -
    • can no longer make lethal medical patches with droppers
    • -
    • dripping reagents on someone with a dropper now incurs a 3 second delay like syringes
    • -
    - -

    09 May 2017

    -

    Fethas updated:

    -
      -
    • a ton of grey clothing sprites.
    • -
    - -

    08 May 2017

    -

    Purpose2 updated:

    -
      -
    • Adds a wire to the modular console on the bridge, fixing the Power Grid program.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Examine a reinforced wall for deconstruction and repair hints.
    • -
    - -

    07 May 2017

    -

    GunDOSMk1 updated:

    -
      -
    • Adds Unathi cobra hood
    • -
    -

    Purpose2 updated:

    -
      -
    • Fixes the broken wiring re-electrifying the bridge window.
    • -
    • Adds the missing scrubber in Genetics holding pen
    • -
    -

    Twinmold updated:

    -
      -
    • No longer able to put grabs into kitchen equipment (deep-fried grab).
    • -
    • No longer able to put grabs inside of display cases.
    • -
    - -

    06 May 2017

    -

    Allfd updated:

    -
      -
    • Thrown mobs will not step on broken glass while being thrown.
    • -
    -

    Fethas updated:

    -
      -
    • Fixes sacreficed your target not triggering the next objective.
    • -
    • YOU CAN NOW ONLY CONVERT HUMANS NOT MICE!
    • -
    • bloodspill tiles changed from base 100 (plus random number based on players) to 70.
    • -
    • Adds Tajaran veils as a loadout options
    • -
    • Racial loadout tab
    • -
    -

    LightFire69 updated:

    -
      -
    • Added a pretty plasmaman suit
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Removed Robocop, Paladin, NT Default as roundstart lawsets.
    • -
    - -

    05 May 2017

    -

    Fethas updated:

    -
      -
    • Magistrate, IAA, and BS will now spawn with the correct color dpet satchal and duffel
    • -
    - -

    01 May 2017

    -

    Fethas updated:

    -
      -
    • There will now be an visual indicator to annouce that an incomming shuttle is about yo wreck you.
    • -
    - -

    30 April 2017

    -

    scrubmcnoob updated:

    -
      -
    • Combat Shotguns now more expensive in cargo.
    • -
    • Shotgun ammo_boxes are now named and sprited as speedloaders that can speedload into a shotgun. Normal shotgun ammo boxes are just storage items for shells.
    • -
    • Adds in shotgun ammos readily available to be ordered from cargo in bulk and allows the ordering of Riot shotguns.
    • -
    • Adds in a Dragonsbreathe shotgun ammo box.
    • -
    • Tranq darts now have a sprite.
    • -
    - -

    29 April 2017

    -

    FalseIncarnate updated:

    -
      -
    • Popcorn jellybeans require jellybeans to make.
    • -
    • Gum is no longer invisible, but is still very chewy.
    • -
    -

    Phantasmic Dream Art, Fethas PR updated:

    -
      -
    • Updates the shadowling sprite. Sprite by Dreamy
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Examine a girder for (de)construction hints
    • -
    • Projectiles have a chance to pass through some girders
    • -
    • You can construct rough iron (false) walls with rods, wood (false) walls with wooden planks on a girder
    • -
    • Screwdriver a displaced girder to deconstruct it
    • -
    • Increased displaced girder health, decreased reinforced and cult girder health
    • -
    • False wall construction is no longer instant
    • -
    • Girder (de)construction messages should read better
    • -
    - -

    28 April 2017

    -

    Alffd updated:

    -
      -
    • Adds Paperwork the sloth to cargo.
    • -
    - -

    27 April 2017

    -

    Kyep updated:

    -
      -
    • Changed "suggested client version" from 510 to 511.
    • -
    - -

    26 April 2017

    -

    FalseIncarnate updated:

    -
      -
    • Glowshrooms (and their subtypes) can be mass-cleared by scythes just like vines.
    • -
    -

    pinatacolada updated:

    -
      -
    • dirty surgery environments get you nasty infections
    • -
    • ghetto surgery internal organ disinfection with alcohol
    • -
    • dead limb revival surgery step
    • -
    - -

    25 April 2017

    -

    Flattest updated:

    -
      -
    • Animated progress bars!
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Runed girders have a clearer and bigger icon
    • -
    • Girder subtypes are properly named, "reinforced girder" and not "reinforced"
    • -
    • Summoned cult walls do not drop a girder or runed metal to prevent runed metal farming
    • -
    • Cult walls no longer have blood or human remains in them
    • -
    • Harvesters can smash more things and can summon cult walls and floors
    • -
    • Fixed not being able to make a cult wall with runed metal + runed girder
    • -
    • Runed girders will need to be deconstructed with a welder (or plasma cutter or jackhammer) instead of a wrench. Cultists can hit them with their tomes to instantly demolish them.
    • -
    - -

    24 April 2017

    -

    Flattest updated:

    -
      -
    • Sleepers spit out their victims when deconstructed now.
    • -
    - -

    23 April 2017

    -

    Citinited updated:

    -
      -
    • You can now fully insulate reinforced floors using a sheet of plasteel.
    • -
    • Certain floors in the turbine, incinerator, and toxins are now thermally insulated.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Reverts Norgad's east maintenance overhaul
    • -
    -

    IK3I updated:

    -
      -
    • flipping aliums now have a cooldown
    • -
    • Aliums have some more sounds to play with
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • You can no longer use space pod verbs when restrained, dead, or otherwise incapacitated.
    • -
    - -

    21 April 2017

    -

    Anticept updated:

    -
      -
    • Alternate Job Preference now defaults to "Return to Lobby if Preferences Unavailable". Only affects new players.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Tesla can now damage blobs
    • -
    • Tesla causes machinery to overload and explode when zapping it
    • -
    • Tesla dissipates energy more slowly and is easier to charge up (making it more deadly when released)
    • -
    • Tesla will now dust mobs it bumps into
    • -
    • Tesla coils now have wires that can be pulsed to generate a tesla zap
    • -
    -

    Lady-Luck updated:

    -
      -
    • Makes several balance adjustments to existing syndicate bundles, generally making them more worthwhile.
    • -
    • Adds an Allies Cocktail object for the Bond bundle.
    • -
    • Adds the 'gadgets' syndicate bundle.
    • -
    • Removes the 'lordsingulo' and 'murder' syndicate bundles.
    • -
    -

    Spacemanspark updated:

    -
      -
    • Permits hoodies to carry flashlights.
    • -
    -

    Twinmold93 updated:

    -
      -
    • Adds attack options for deep fryers, grills, and ovens. Those breaking into the kitchen beware.
    • -
    -

    alexkar598 updated:

    -
      -
    • you can now click on things underwater
    • -
    -

    monster860 updated:

    -
      -
    • Adds an in-game way of viewing poll results
    • -
    • The player poll window automatically pops up if there is an active poll you haven't voted on.
    • -
    • Adds an browser popup for creating new polls
    • -
    • Your account needs to be at least 30 days old in order to vote on polls
    • -
    - -

    19 April 2017

    -

    IK3I updated:

    -
      -
    • Chaplain now spawns with his bible
    • -
    -

    Xantholne updated:

    -
      -
    • You now correctly spawn with the CMO Skirt if selected in loadout menu
    • -
    - -

    17 April 2017

    -

    KasparoVy updated:

    -
      -
    • The God-emperor of Mankind diskette's UI works again.
    • -
    • DNA UI injectors will now immediately update a person's eye colour.
    • -
    -

    Krausus updated:

    -
      -
    • You can no longer squeeze non-match objects into matchboxes.
    • -
    - -

    16 April 2017

    -

    FalseIncarnate updated:

    -
      -
    • Potential collaborators for traitors now are informed they are potentially a collaborator for a potential increase in them potentially helping the traitors potentially do potentially bad things. Potentially.
    • -
    • Potential collaborators are given a single code word and response set so they can discretely find out that their best friend is a filthy traitor.
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds secondary (facial) hair colours to the genome (UI). There are 6 new blocks.
    • -
    • Characters with secondary (facial) hair colours won't find they've turned black after cloning anymore.
    • -
    -

    Kyep updated:

    -
      -
    • Plasma dust no longer creates plasma gas on objects or turfs during reactions.
    • -
    -

    Twinmold93 updated:

    -
      -
    • Missing sprite for pod pilot Drask now added.
    • -
    -

    Xantholne updated:

    -
      -
    • Adds Medical Beret available via loadout menu
    • -
    -

    ZomgPonies updated:

    -
      -
    • Fixes Superhero ID cards
    • -
    • Fixes Griffin missing his Freedom Implant
    • -
    • Fixes ElectroNegmatic's Ability not working at all.
    • -
    • Changes LightnIan's ability into a non-damaging stun lasting 2 ticks, with the amount of people affected depending on how long you hold the power in for.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • You can now create heat-proof glass airlocks by using a sheet of reinforced glass on the assembly during construction. Regular glass airlocks just require a sheet of glass.
    • -
    - -

    11 April 2017

    -

    FalseIncarnate updated:

    -
      -
    • Damage done to the shuttle engines by a shadowling's "Extend Shuttle" ability now prevent the shuttle from being recalled to CentComm.
    • -
    - -

    09 April 2017

    -

    Fox McCloud updated:

    -
      -
    • abductor glands now act as actual hearts; removing them induces heart failure
    • -
    • plasma gland no longer gibs you, but makes you vomit plasma instead
    • -
    • bodysnatcher gland no longer gibs you, but will deal brute damage instead
    • -
    • bloody gland will now drain blood instead of dealing brute damage
    • -
    • species change gland will now change your species until the gland is removed
    • -
    • adjusted the origin tech on a few gland
    • -
    • heart attacks will once again paralyse you and do slightly more brute damage
    • -
    • body snatch clones look more like their originator
    • -
    • Abductors can no longer use guns (minus their own alien energy gun)
    • -
    • Sending someone with an abductor teleport via the console will stun them for 3 cycles (doesn't apply with the advanced camera console)
    • -
    • Abductors can now purchase additional abductor vests
    • -
    • Abductors can lock/unlock vests
    • -
    • Purchasing supplies from the abductor console will no longer increase the amount of experiments you must do
    • -
    • Wonderprods will not induce sleep in those who are stunned OR sleeping
    • -
    • altered the origin tech of abductor tools
    • -
    • Can make abductor surgery tables from regular tables by adding silver sheets to an abductor table frame
    • -
    • Added a bunch more abductee objectives
    • -
    • abductors no long scream like girls
    • -
    • High capacity cells have 10,000 charge instead of 15,000
    • -
    • Mech equipment power costs minorly adjusted
    • -
    • APCs charge a bit faster
    • -
    • EMPs less effective against pods and mechs
    • -
    • Fixes not being able to recharge modular laptops/tablets
    • -
    -

    Purpose2 updated:

    -
      -
    • Welders must now been fueled and active to cut lattices.
    • -
    - -

    06 April 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes autopsy report printing; print reports by clicking the device itself
    • -
    -

    davipatury updated:

    -
      -
    • Rapid Cable Layer now have an autolathe design.
    • -
    - -

    05 April 2017

    -

    KasparoVy updated:

    -
      -
    • Adds a Tajaran facial hair style.
    • -
    • Adds a few new frill styles for Unathi.
    • -
    • Adds some new horn styles for Unathi.
    • -
    • Adds a couple new facial hair styles for Vulpkanin.
    • -
    • Adds a few new hair styles for Vulpkanin.
    • -
    • Updates Vulpkanin Adhara & Kajam hairstyles.
    • -
    -

    Purpose2 updated:

    -
      -
    • Can now take photos of the Blueprints to count as a completed objective.
    • -
    • Cryostorage console now stores the Null Rod & all variations.
    • -
    • Mime mech is now 'Reticence' as it should be
    • -
    • Fixes missing cult's Berserker Robe sprite.
    • -
    • Cryostorage console no longer stores hundreds of bomber jackets, and now stores hardsuits
    • -
    • Cryostorage console now catches and stores most unique objective items.
    • -
    • Corrects some typos and grammar.
    • -
    • You can now light cigarettes with Wands of Fireball, at the cost of your eyebrows.
    • -
    -

    Twinmold93 updated:

    -
      -
    • Buying poison pen will actually give you the poison pen now.
    • -
    - -

    04 April 2017

    -

    FalseIncarnate updated:

    -
      -
    • Adds FullofSkittles's custom pAI sprites. Thanks FoS!
    • -
    • Custom sprites for cyborgs, AI, AI holograms, and pAI units no longer are restricted to a single name. Get your money's worth by using that borg sprite regardless of your version number!
    • -
    - -

    03 April 2017

    -

    Kyep updated:

    -
      -
    • Ghosts manifested by cultists are no longer invincible, and an exploit allowing them to be made permanent has been fixed.
    • -
    - -

    02 April 2017

    -

    KasparoVy updated:

    -
      -
    • Nuclear Operatives/ERT Members/Abductors will no longer spawn in with genetic quirks.
    • -
    • Thrown objects that cross a tile with non-full windows will no longer hit the window even if it isn't visually obstructing the path.
    • -
    • Shooting guns (i.e. tasers) in the above circumstances means that the taser shots won't be blocked by windows that aren't visually obstructing the path.
    • -
    -

    Kyep updated:

    -
      -
    • Adjusted Black Market Packers away mission. It now has some danger to it (carp), some more interesting stuff to find (syndi lab) and a challenge (fix the ship powergrid).
    • -
    • Slight adjustment to word lists based on our rules.
    • -
    • Removed thunderdome armor from centcom away mission.
    • -
    • Cultists now get a new sacrifice target when the current one cryos.
    • -
    - -

    31 March 2017

    -

    Krausus updated:

    -
      -
    • Blobs are no longer nearly guaranteed to immediately tear themselves apart upon spawning.
    • -
    -

    Kyep updated:

    -
      -
    • Access to jobs is now based solely on Playtime, NOT days since BYOND account was registered.
    • -
    - -

    30 March 2017

    -

    Crazylemon64 updated:

    -
      -
    • Cult shifter should work now
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Strange Reagent only deals clone damage on a successful revival.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Non-designated drinks now mix their colors from the reagents within them
    • -
    • Autopsies can now be performed without needing to cut someone open
    • -
    • Adds modular receiver to the maintenance loot system
    • -
    • Receivers can now be produced in hacked autolathes; no longer available in R&D protolathes.
    • -
    • removes the random "scary" sounds that play when walking about
    • -
    -

    KasparoVy updated:

    -
      -
    • You can now slam drinks/bottles/flasks by click-dragging them onto yourself while it's in your active hand.
    • -
    -

    Kyep updated:

    -
      -
    • The moonoutpost19 away mission should now be finishable, and more enjoyable to attempt.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Emagging a closed firelock does not permanently break it anymore, only opens it.
    • -
    • Emagged windoors should be able to be screwdriver+crowbar'd again.
    • -
    • Powered grilles now have a chance to zap you when you throw an object at them.
    • -
    - -

    29 March 2017

    -

    Purpose2 updated:

    -
      -
    • 'Roundstart malfunctioning' cameras now appropriately have their wires cut.
    • -
    • AI core camera can no longer be a 'roundstart malfunctioning' camera on both Box & Meta Stations.
    • -
    - -

    28 March 2017

    -

    KasparoVy updated:

    -
      -
    • Skrell can now choose undergarments (undershirts, underpants, socks) at character creation and dressers.
    • -
    • Vox are now 20% less resilient to brute damage due to their light, porous and flexible skeletons.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Quick-replacing non-wooden tiles will only work with a crowbar in inactive hand instead of any item
    • -
    - -

    27 March 2017

    -

    Crazylemon64 updated:

    -
      -
    • Away mission power works now.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes some stacks not wanting to stack with similar stacks (such as space cash)
    • -
    -

    KasparoVy updated:

    -
      -
    • Skrell have been greyscaled and darkened. You can now colour your Skrell characters as you please.
    • -
    • Kidan can now select from multiple different antennae head-accessory styles.
    • -
    • Kidan male/female bodies now have differences, namely mandible/torso structure.
    • -
    • Skrell flesh is now blue (like their blood), though you'll only ever see this under certain circumstances if they're dismembered.
    • -
    -

    Kyep updated:

    -
      -
    • The invisible floors in the engineering area of the UO45 away mission are no longer invisible. Previously, you had to crowbar up a seemingly invisible floor to make a wire appear.
    • -
    • Fixed several Terror Spider bugs. Including the notorious 'spiders can get stuck in vents' bug, the 'spiders ignore mechs' bug, and the 'prince is cheesable' bug.
    • -
    • Adjusted White & Empress spider abilities - webs spun by white spiders are now infectious.
    • -
    -

    Purpose2 updated:

    -
      -
    • Adds the Psychiatrist's bed/sofa for 5 metal.
    • -
    • Wooden chairs broken by animals no longer drop metal.
    • -
    • Abductors no longer have Syndicate ties.
    • -
    • Fixes material loss on some chair/bed/stool deconstruction types.
    • -
    • IPCs can no longer be DNA Scrambled.
    • -
    • Health analysers clunk again when upgraded
    • -
    • Resolves further grammatical/typo issues.
    • -
    - -

    26 March 2017

    -

    FalseIncarnate updated:

    -
      -
    • Re-adds the telescopic scythe, the pinnacle of covert reaping technologies. Currently admin-spawn only, for use in the most dire of harvest times.
    • -
    • Scythes (normal and telescopic) should once again clear swathes through all but the hardiest of vines when in proper reaping configurations, and heavily damage those they don't outright destroy.
    • -
    • Ankle-high piles of dirt will no longer prevent you from stepping over them.
    • -
    -

    KasparoVy updated:

    -
      -
    • You can no longer climb through interdimensional rifts into cryopods.
    • -
    • Revenants can see properly in the dark again.
    • -
    -

    Kyep updated:

    -
      -
    • Adjusted Beach awaymission so it now includes deadly (but rewarding) pirate area.
    • -
    • Adjusted the centcom away mission to make it viable.
    • -
    • Deleted 'listening post' away mission.
    • -
    -

    Purpose2 updated:

    -
      -
    • QoL: Newly built APCs come unlocked.
    • -
    • QoL: Chief Engineer's locker has more building permits.
    • -
    • Assorted grammatical fixes.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Splints will display the proper sentence when applying them
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Metastation: Fixed Gateway airlock access and Command Hallway vendor areas, virology smartfridge is correctly stocked, mass drivers now have tiny fans, Sec spacepod keys work on the Sec pod, Airlocks should have the correct icon, Firelocks/Windoors/Shutters should be layered correctly, Shutters should be facing the right direction
    • -
    • Drone fabricator consoles search for a fabricator in the same area instead of 3x3 range.
    • -
    - -

    25 March 2017

    -

    Crazylemon64 updated:

    -
      -
    • All pens are now certified crayon-wax free!
    • -
    -

    Kyep updated:

    -
      -
    • Pipes in the Wizard Academy have been banished back under the carpet, where they belong.
    • -
    - -

    24 March 2017

    -

    KasparoVy updated:

    -
      -
    • Red wire-cutters and red crowbars now appear correctly in-hands again. imgadd: The medical wrench and all the brass tools (screwdriver, crowbar, wrench, wire-cutters, welder) now have in-hand sprites of their own.
    • -
    • Adds TG's inhand icons for screwdrivers, crowbars, wrenches, wire-cutters and welders.
    • -
    • Slime People can wear underwear, undershirts and socks.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • IV Drips are no longer dense objects, you can walk over them.
    • -
    • You can change gold and silver tiles into fancy versions by using them in hand.
    • -
    - -

    23 March 2017

    -

    FalseIncarnate updated:

    -
      -
    • Fish breeding has been tweaked to support fish refusing to cross-breed and improved egg chances with same-species parents.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Floors are now fully properly cleaned with mops and soap
    • -
    • Adds in emergency welding tool, fork, trays, drinking glasses, shot glasses, shakers, butcher cleavers, and riot darts to the autolathe
    • -
    • Adds all basic stock parts to the autolathe
    • -
    • re-arranges the autolathe menu to be more logical
    • -
    • light bulbs no longer require metal to produce
    • -
    • Incision management system can now cauterize
    • -
    -

    KasparoVy updated:

    -
      -
    • Unathi Security, Medical, Engineering and Syndicate side-facing hardsuit sprites have undergone weight reduction.
    • -
    -

    Kyep updated:

    -
      -
    • Chaplain's armor is no longer riot-grade. In addition, their nullrods do less damage.
    • -
    -

    MarsM0nd updated:

    -
      -
    • Conveyor switches can now set to left-only direction toggling.
    • -
    -

    Norgad updated:

    -
      -
    • Maintenance areas near arrivals, science, and the bar have been revamped.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Station lighting has less lighting power, this is not noticeable apart from maint and 1 bulb rooms being a bit darker.
    • -
    • Tweaked the potency scaling for glowshroom/glowberry light; high-potency plants no longer light up a huge area, but are slightly brighter.
    • -
    • Added Shadowshrooms as a glowshroom mutation. They do exactly what you'd expect.
    • -
    - -

    22 March 2017

    -

    Crazylemon64 updated:

    -
      -
    • Rod form is now at half speed, and has a warning sound.
    • -
    -

    FlattestGuitar updated:

    -
      -
    • When a person's limb is dying, it will no longer notify the whole server of the ordeal
    • -
    • Welding tools no longer tell you about their span classes
    • -
    -

    KasparoVy updated:

    -
      -
    • Deconstructing beds now yields the same amount of metal as was used to make the bed.
    • -
    • The PA console will no longer appear as though it is fully constructed at the start of the round.
    • -
    • Ore Redemption Machines no longer eat IDs when deconstructed.
    • -
    • Ore Redemption Machines and Mining Equipment Vendors now spit out whatever IDs were in them when they lose power.
    • -
    -

    Krausus updated:

    -
      -
    • Personal crafting is now usable again for those with an Internet Explorer version below 11.
    • -
    - -

    21 March 2017

    -

    Crazylemon64 updated:

    -
      -
    • Strange reagent now has a volume floor requirement to activate, induces clone damage, and may cause further trouble...
    • -
    -

    KasparoVy updated:

    -
      -
    • No-one escapes nuclear hellfire.
    • -
    • Secure fridges/freezers are now lead-lined and have thus become nuke resistant.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Baseball bats added to the game, are craftable from 5 wood planks.
    • -
    • Baseball burgers can be made with a baseball bat and a bun, either microwaved or table-crafted.
    • -
    - -

    20 March 2017

    -

    Jovaniph updated:

    -
      -
    • Tajaran EVA Suit Sprites
    • -
    -

    KasparoVy updated:

    -
      -
    • Gloves can be snipped again.
    • -
    -

    Purpose2 updated:

    -
      -
    • Fixes assorted wording / capitalisation / grammatical problems.
    • -
    • Fixes the exploit to produce infinite cable coil from airlocks.
    • -
    -

    Tayyyyyyy updated:

    -
      -
    • Added GPS devices to pod pilot and mechanic's offices
    • -
    - -

    19 March 2017

    -

    Jovaniph updated:

    -
      -
    • Voxes can now wear soft caps.
    • -
    -

    Krausus updated:

    -
      -
    • Pest spray bottles are no longer invisible.
    • -
    -

    Kyep updated:

    -
      -
    • Wood doors in wild west map no longer constantly open/close
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Shipping errors can sometimes cause the supply shuttle to receive an extra crate when ordering supplies.
    • -
    • Added dog beds! Can be made with 10 wood planks and deconstructed with a wrench. Ian's Bed added to Cyberiad and Metastation.
    • -
    - -

    18 March 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes abductor surgeries
    • -
    -

    Jovaniph updated:

    -
      -
    • Unathi EVA suits
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Shades now have directional sprites.
    • -
    • Attacking with glass shards now hurts your hand if not wearing gloves. Does not affect robotic hands though.
    • -
    - -

    16 March 2017

    -

    FlattestGeetar updated:

    -
      -
    • Workboots are now in the loadout system.
    • -
    • Ports winter boots from /tg/
    • -
    -

    Jovaniph updated:

    -
      -
    • New sounds to Firelocks and Airlock External
    • -
    • Door closing sound to Airlocks - from yogstation
    • -
    -

    Markolie updated:

    -
      -
    • Fixed revenant night vision not working.
    • -
    • Fixed the "X attacked Y" message showing up when welding vents.
    • -
    • Fixed the follow button on the cell door timer radio message not working.
    • -
    • Fixed the Jaws of Life being unable to force unpowered doors.
    • -
    • Fixed a number of preference options being unavailable when modifying preferences while observing.
    • -
    • Fixed an issue where deleting security records wouldn't clear that player's wanted status properly.
    • -
    • Fixed the cult "first meal" sacrifice objective not counting properly. Also clarified what this objective actually entailed.
    • -
    • Fixed IPC's ocassionally being selected as a changeling "escape with X identity" target.
    • -
    • The character records and disabilities menus in the preferences menu no longer uses the plain white background, but uses the better looking blue layout instead.
    • -
    - -

    15 March 2017

    -

    uraniummeltdown updated:

    -
      -
    • Plastic flaps can be deconstructed with tools and constructed using 5 sheets of plastic.
    • -
    • You can now damage grilles by throwing things at them.
    • -
    • You can rebuild broken grilles by using a metal rod on them.
    • -
    • Metal rods maximum amount reduced from 60 to 50.
    • -
    - -

    14 March 2017

    -

    uraniummeltdown updated:

    -
      -
    • Strong supply talismans can now summon 5 sheets of runed metal.
    • -
    - -

    13 March 2017

    -

    Kyep updated:

    -
      -
    • Syndicate mobs in the Wild West are no longer so stupid that they trip over, and die to, their own mines. This also means that they won't set their own buildings on fire anymore.
    • -
    • Phazons' phase ability now works again.
    • -
    • Phazons' toxin injector melee damage type (a weak melee attack) now works again.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Clicking on a tile with another tile and a crowbar or screwdriver in hand directly replaces the tile.
    • -
    - -

    12 March 2017

    -

    Crazylemon64 updated:

    -
      -
    • Kudzu should now be less of (but still) a station-destroying force of nature.
    • -
    • Bluespace kudzu now only pierces a single layer of walls before losing its "charge".
    • -
    • Aggressive spread now does not bust rwalls, but does attack obstructing objects in its path.
    • -
    • Kudzu now only spreads on space turfs when it has specific mutations to do so.
    • -
    • Kudzu events should be more interesting on their own.
    • -
    -

    Jovaniph updated:

    -
      -
    • Adds Vulpkanin EVA suit sprite
    • -
    -

    Kyep updated:

    -
      -
    • Adjusted Wizard Academy to make it both more lethal, and more rewarding.
    • -
    -

    Markolie updated:

    -
      -
    • The system for picking ghosts to inhabit cultist slaughter demons now shows a confirmation prompt like most other role checks.
    • -
    • Fixed an issue where you could join as a cultist slaughter demon despite having antagHUD enabled.
    • -
    • Fixed an issue where it was possible to weld statues without any fuel.
    • -
    • It is no longer possible to spam the firelock force message.
    • -
    -

    Twinmold93 updated:

    -
      -
    • Employment record laptop to Head of Personnel's Office. Moves package wrap that was there to meeting room to be paired with the hand labeler there.
    • -
    - -

    11 March 2017

    -

    Developed by XDTM, ported by davipatury updated:

    -
      -
    • Hallucinations have been modified to increase the creepiness factor and reduce the boring factor.
    • -
    • Added some new hallucinations.
    • -
    • Fixed a bug where the singularity hallucination was stunning for longer than intended and leaving the fake HUD crit icon permanently.
    • -
    -

    Flatty Patty updated:

    -
      -
    • all the tools have icons again
    • -
    -

    FlattyPatty updated:

    -
      -
    • Improved Nanotrasen click manufacturing procedures now allow the flashlights to make that classic clicking sound you know and love.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Buckshot now does a max of 70 damage, down from 90
    • -
    -

    KasparoVy updated:

    -
      -
    • Fixes a bug with certain tail markings rendering when they shouldn't.
    • -
    -

    Markolie updated:

    -
      -
    • Firelocks forced by AI's, cyborgs at range or admin ghosts will now autoclose if there's still an atmospherics alarm present.
    • -
    • Regular (non-heavy) firelocks will now properly respond to explosions (100% chance of being destroyed at severity 1 explosions and 50% at severity 2). Heavy firelocks are still only destroyed in severity 1 explosions.
    • -
    • Added a visible message to forcing airlocks with the Jaws of Life.
    • -
    -

    davipatury updated:

    -
      -
    • Ported Modular Computers from /tg/.
    • -
    • Ported Rapid Cable Layer from /vg/.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • EVA has 2 more EVA Suits
    • -
    • Removed Vox-only EVA suits (the grey ones in EVA)
    • -
    • Vox can now wear EVA suits
    • -
    - -

    10 March 2017

    -

    Jovaniph updated:

    -
      -
    • Recitence no longer makes a sound when turning
    • -
    -

    Markolie updated:

    -
      -
    • The DNA Vault station goal will now be marked as completed properly.
    • -
    • Multi-tile airlocks will now change their direction properly.
    • -
    • The atmos skirt loadout item will now be equipped properly on round start.
    • -
    • Fixes the inhand disabler sprite pointing the wrong way in some directions.
    • -
    • The Janicart will no longer act as a jetpack.
    • -
    • You can now resist out of a borer's control again.
    • -
    • Fixes the general antag ban not working on certain conversion antagonists.
    • -
    • Fixes removing the trunk from underneath a chute/bin causing all sorts of issues.
    • -
    • Fixes alt titles not showing up on ID's.
    • -
    • Mineral doors no longer block atmos (like they're supposed to).
    • -
    • Fixes the cortical borer hivemind talk not working.
    • -
    • Fixes detomatix cartridges not working *from* PDA's with an uplink (it now no longer *on* a PDA with an uplink to prevent blowing up fellow traitors).
    • -
    • Fixes NODROP interaction with secure closets.
    • -
    • Fixes some stray fruit at the Syndicate base on Z2.
    • -
    • Fixes an incorrect camera network in the courtroom.
    • -
    • Fixes an issue where AI's would go blind upon travelling into space.
    • -
    • The cortical borer hivemind talk key is now "bo".
    • -
    • Attempting to blow up an undetonatable PDA (such as the captain's) will now show a warning message. It will also no longer use up a charge.
    • -
    • Animals can now open mineral doors and mineral doors will no longer be closable if there's a mob inside.
    • -
    • Matter grippers can now carry firelock electronics as well as bluespace crystals (for construction).
    • -
    • Removes the pipe fitting on the table from atmospherics as it was broken.
    • -
    - -

    09 March 2017

    -

    Crazylemon64 updated:

    -
      -
    • Adds an "ethereal beacon", an admin-only structure usable to attract ghosts to an area.
    • -
    • Adds several transformer machines to streamline the ghost-to-PC process.
    • -
    -

    LordJike updated:

    -
      -
    • Space Fries are now made by deep-frying potato wedges instead of processing them.
    • -
    • Introducing carrots inside the food processor gives you carrot wedges now.
    • -
    • Now you can make carrot fries by deep-frying carrot wedges instead of formerly processing the whole carrots.
    • -
    -

    Markolie updated:

    -
      -
    • Tools now have a "usesound" and "toolspeed" variable which allows different tool (levels) to have different sounds and speeds.
    • -
    • Robots spawn with tools that are twice as fast as regular tools.
    • -
    • Abductor agents now spawn with a toolbelt with specialized abductor tools that are very fast.
    • -
    • Abductor surgery tools are now much faster.
    • -
    • Abductor (surgery) tools can now be constructed in R&D with a sufficiently high "abductor" research level.
    • -
    • The abductor multitool will now display what each wire does.
    • -
    • Admin ghosts can now interact with wires and see what each wire does.
    • -
    • Adds a set of unique tools for the Chief Engineer that he is given in a unique toolbelt at roundstart. These tools are faster and can be created in R&D with a sufficiently high R&D level.
    • -
    • The AI detector has been refactored to have much more robust AI tracking.
    • -
    - -

    08 March 2017

    -

    Alffd updated:

    -
      -
    • Farting on a bible now puts you at the mercy of the gods.
    • -
    • Removed automatic biblefarting gibbing.
    • -
    -

    FlaaaaaattestGuitar updated:

    -
      -
    • Magistrate now starts their shift with a pair of white gloves as well as Bridge and Meeting Room access.
    • -
    -

    Fox McCloud updated:

    -
      -
    • money is now far easier to use, and distribute in amounts you would like
    • -
    -

    Kyep updated:

    -
      -
    • Changed event probabilities, aiming for a more fun late game. In general, events that do very little (e.g: meaty ores, rogue drones) are less likely. Events that will keep people on their toes (e.g: anomalies) are more likely. Events that might cause people to observe rather than joining the round (e.g: Xenos) are less likely.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Wizard Hardsuit helmet and suit now have inhand sprites
    • -
    - -

    07 March 2017

    -

    Crazylemon64 updated:

    -
      -
    • IPCs now come with a power cord implant to use to recharge from APCs.
    • -
    • IPCs can now be genderless.
    • -
    -

    Kyep updated:

    -
      -
    • Deleted 'challenge' away mission.
    • -
    -

    MarsM0nd updated:

    -
      -
    • Cultists get shoes on usage of the armor talisman.
    • -
    • Cultists only get equipment if they have the slot for it free, weapons are always spawned.
    • -
    • The tome does a more fitting description of the talisman of armor.
    • -
    - -

    05 March 2017

    -

    Kyep updated:

    -
      -
    • Added Poison Pen, a stealthy way of applying a contact-based poison to paper. Available to Syndicate HoPs, QMs, and Cargo Techs.
    • -
    • Antags whose objectives are manually announced by an admin, or altered automatically as a result of their target cryoing, will now hear a warning sound. The sound is the same as the 'crew transfer vote called' sound. Additionally, the text notice for changed objectives is more obvious.
    • -
    -

    MarsM0nd updated:

    -
      -
    • The grey satchel uses now the correct sprite instead of the leather one.
    • -
    - -

    04 March 2017

    -

    Markolie updated:

    -
      -
    • Ghosts can now interact with ore dispensers, mining equipment vendors and laptop vendors.
    • -
    • Admins can now interact with crates, closets, false walls and conveyor switches if they have advanced interaction enabled.
    • -
    -

    davipatury updated:

    -
      -
    • Newscaster now uses Nano-UI.
    • -
    • Tank dispenser now uses Nano-UI.
    • -
    • Passive gate, pump and volume pump now uses Nano-UI.
    • -
    • Atmospherics filter and mixer now uses Nano-UI.
    • -
    • Wires now uses Nano-UI.
    • -
    - -

    03 March 2017

    -

    FlauntestGuitar updated:

    -
      -
    • You will now be prompted on a karma purchase to confirm that you clicked what you wanted to click
    • -
    -

    uraniummeltdown updated:

    -
      -
    • You can now change the input/output directons for Ore Redemption Machines by using a multitool on them with the panel open.
    • -
    • Bluespace RPED beams have a new sprite
    • -
    - -

    01 March 2017

    -

    Crazylemon64 updated:

    -
      -
    • Kudzu vines now can yield materials if carefully tended to
    • -
    -

    Fethas updated:

    -
      -
    • 2 second cooldown on the rest verb. You are not Neo, knock it off.
    • -
    • StopResting and StartResting Procs are not on the rest verb.
    • -
    • Various metastation fixes.
    • -
    -

    KasparoVy updated:

    -
      -
    • Plasmaman multiverse sword copies are now properly equipped (suit, helmet, internals, etc.)
    • -
    • Vox multiverse sword copies are now peoperly equipped (internals).
    • -
    -

    Kyep updated:

    -
      -
    • Fixed several Terror Spider things that should not be possible, like recharging wireless guns, the 'evil-looking spiderlings' instant meta, and spiderlings spacing themselves.
    • -
    • Several Terror Spider balance and fun tweaks, such as giving the Prince of Terror a new webbing ability, and ensuring queens/mothers can break open vents, so they cannot be completely shut out late-round.
    • -
    -

    Purpose2 updated:

    -
      -
    • Enables Cargo to order Wood planks
    • -
    - -

    28 February 2017

    -

    KasparoVy updated:

    -
      -
    • Plasmaman suits will now only auto-extinguish if you're actually on fire (and not just taking a shower).
    • -
    - -

    27 February 2017

    -

    uraniummeltdown updated:

    -
      -
    • Mineral statues are here! Use 5 sheets of any mineral including sandstone to make one. Be careful around plasma and uranium statues!
    • -
    • The mime's office now comes with a statue too.
    • -
    • Updated plasma, uranium and diamond floor sprites to TG's newer ones.
    • -
    - -

    26 February 2017

    -

    Crazylemon64 updated:

    -
      -
    • Immovable rod events now vanish after going through the station once
    • -
    • Firelocks can now be operated by AIs again
    • -
    • Barbers and captains get the right stuff now
    • -
    • It's now possible to have random floors or walls when mapping
    • -
    -

    KasparoVy updated:

    -
      -
    • Fixes a bug where you could get a part of a rigsuit stuck to your hand by deploying it twice.
    • -
    • Improves the readability of some rigsuit verbs.
    • -
    -

    Kyep updated:

    -
      -
    • players will no longer spawn with loadout items their job has no access to.
    • -
    • AI & Borg upload consoles now have to be on the station zlevel to work.
    • -
    -

    davipatury updated:

    -
      -
    • ATM now uses Nano-UI.
    • -
    - -

    25 February 2017

    -

    Crazylemon64 updated:

    -
      -
    • Telecomms monitor is now infused with fastitude
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Escape has been re-bushed.
    • -
    -

    KasparoVy updated:

    -
      -
    • Reagent plasma has a weak healing effect on Plasmamen when injected and will not poison them.
    • -
    • Reagent oxygen is as toxic to Vox as reagent plasma is to just about anyone.
    • -
    • Plasmamen now join the shift with 2 suit auto-extinguisher refill cartridges which, individually, will fully refill an empty Plasmaman suit's autoextinguisherl.
    • -
    • Plasmaman suits now auto-extinguish and will be able to do so 5 times before they can be refilled by a cartridge.
    • -
    • Plasmamen no longer burn in a vacuum or in plasma-pure environments.
    • -
    -

    davipatury updated:

    -
      -
    • Security Records now uses Nano-UI.
    • -
    - -

    24 February 2017

    -

    FalseIncarnate updated:

    -
      -
    • Corn and bananas can be properly deepfried into their special results again.
    • -
    • Rice can be properly ground into a reagent again.
    • -
    • Hydroponics trays once again are equipped with Bee-proof lids to keep unwanted pollination to a minimum. This only works if you actually toggle the lid closed though!
    • -
    • Plants age slightly slower, so your space farming should no longer feel like it outpaces a meth'd up blue hedgehog in sneakers.
    • -
    -

    Kyep updated:

    -
      -
    • Fixes blob spawns prompting players twice.
    • -
    -

    Markolie updated:

    -
      -
    • Mining pod weapons are once again functional. Compared to regular kinetic accelerators, the weak projectile has one additional range (3 --> 4). The regular projectile's damage is increased (40 --> 50) and deals more damage in pressurized environments (50% instead of 25%). The enhanced projectile is able to fire its kinetic projectile AoE against turfs and mobs.
    • -
    • Fixed an issue where it was impossible to log out from fax machines.
    • -
    • It is no longer possible to steal ID cards from identification computers/fax machine using telekinesis at range.
    • -
    • The follow link on death alarms now works.
    • -
    • Fixes an exploit where players could use the ambulance trolley to teleport.
    • -
    • The chef now properly shows a chef hat on character preview.
    • -
    • The nuclear ops game mode will no longer always result in a major crew victory.
    • -
    • Players with their face covered will no longer show their flavor text upon examine.
    • -
    • Fax machines now have an "Eject ID card" verb so you can remove the inserted ID when it is depowered.
    • -
    • Firelocks are now more lethal.
    • -
    • Firelocks now crush players standing inside them when they finish closing.
    • -
    • Firelocks can no longer be instantly opened by hand: it requires thirty seconds and will autoclose in five seconds if there is still an atmospherics alert present in the area. They can no longer be closed by hand. Heavy firelocks can not be forced by hand.
    • -
    • Atmospherics technicians can once again remotely modify all settings on air alarms through the central atmospherics console.
    • -
    -

    Purpose2 updated:

    -
      -
    • Captain's crown is now part of the random hats crate, and no longer spawns in their locker.
    • -
    -

    Twinmold93 updated:

    -
      -
    • Ability to label bloodpacks with a pen, so you can now label a bloodpack from donations without a handlabeler.
    • -
    • Bloodpacks will now change name to say if they are empty or not.
    • -
    -

    davipatury updated:

    -
      -
    • EFTPOS now uses Nano-UI.
    • -
    • Medical Records now uses Nano-UI.
    • -
    • Employment Records now uses Nano-UI.
    • -
    - -

    23 February 2017

    -

    Krausus updated:

    -
      -
    • Ghost candidate alert boxes ("Do you want to play as a thing?") will now have "No" as the leftmost, default option, which you will accidentally pick when it pops up while you're trying to type, but at least you won't be stuck as the thing when you didn't actually want to be that thing.
    • -
    -

    Markolie updated:

    -
      -
    • The meteor shield satellite station goal coverage goal has been increased tenfold.
    • -
    - -

    22 February 2017

    -

    KasparoVy updated:

    -
      -
    • You can now toggle on/off the gladiator helmet's face-shield with an action button. This is totally cosmetic. imgadd: Adds a bunch of new helmet sprites for Vox.
    • -
    • Slightly adjusts the Vox knight armour sprites (not the Templar armour) to look nicer with the new helmets.
    • -
    • The Admin 'Select Equipment' debug verb now appropriately equips Armalis when the 'Vox' option is selected.
    • -
    - -

    21 February 2017

    -

    Crazylemon64 updated:

    -
      -
    • Autolathes can be hacked again
    • -
    -

    KasparoVy updated:

    -
      -
    • Removes rogue super-bright pixel at top of Vulpkanin Adhara hairstyle north and south facing sprites.
    • -
    -

    Kyep updated:

    -
      -
    • Deleted clown planet away mission.
    • -
    • blobs now spawn with a player in control, instantly. There is no longer a 30 second period where they exist, but nobody is controlling them.
    • -
    • blobs now get extra time after spawn, before they are announced.
    • -
    -

    Markolie updated:

    -
      -
    • Megaphones can no longer be used by mute people.
    • -
    • Rechargers will no longer recharge stacks beyond their max amount or restack 0.5 sheets.
    • -
    • Ranged guardians now have a proper one second cooldown instead of 0.1 seconds.
    • -
    • Cult can no longer soul stone manifested ghosts.
    • -
    -

    davipatury updated:

    -
      -
    • Autolathe now uses Nano-UI.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Shuttle engines should now face the correct way
    • -
    - -

    20 February 2017

    -

    Markolie updated:

    -
      -
    • The chaplain on the Cyberiad map now has a one-use soulstone.
    • -
    • The chaplain's soul stone on MetaStation can now only be used once.
    • -
    -

    davipatury updated:

    -
      -
    • Shuttle Console now uses Nano-UI.
    • -
    -

    tigercat2000 updated:

    -
      -
    • The AI has a button next to radio messages to open the door closest to the speaker. ;AI, Open this fucking door!
    • -
    - -

    19 February 2017

    -

    Markolie updated:

    -
      -
    • Claw games no longer eat up all glass sheets in the stack when constructed.
    • -
    - -

    18 February 2017

    -

    Alffd updated:

    -
      -
    • Fixes missing entries in species/station for Vox cough and sneeze.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Centcomm has begun enforcing stricter security protocols after a recent influx of fax responses from Clown impersonators
    • -
    • Mind transfer abilities work again
    • -
    • Centcomm is no longer obnoxiously pedantic, regarding BSA deployment
    • -
    -

    Krausus updated:

    -
      -
    • End-of-round sounds will now play just in time for them to end as the server reboots, rather than starting the moment it reboots.
    • -
    -

    Kyep updated:

    -
      -
    • Added a 'take' option to ahelps/mhelps, so admins/mentors can quickly let the asker know their question is being looked at.
    • -
    -

    Markolie updated:

    -
      -
    • Vending machines, newscasters, biogenerators, plant DNA manipulators, seed extractors, bots, fax machines, photocopiers, AI slippers, cell door timers, airlocks, pipe dispensers and atmospherics machinery that open a window can now be viewed by ghosts.
    • -
    • Admins can now interact with mass driver, crematorium, ignition, light, flashers and flasher switches and door switches, as well as airlocks, windoors, firedoors and atmospherics machinery that do not open a window if they have advanced admin interaction enabled (under the "Admin" tab).
    • -
    • Slicing disposal pipes now shows a progress bar.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Shuttle engines have new sprites.
    • -
    - -

    17 February 2017

    -

    Crazylemon64 updated:

    -
      -
    • Space vines now have a mutation that lets them grow in a more intelligent manner
    • -
    -

    Ported by Markolie, developed by AnturK updated:

    -
      -
    • Station Goals have been ported from /tg/. These optional goals are big projects given to the station by Central Command, requiring interdepartmental cooperation and a huge number of resources to complete.
    • -
    • Three station goals have been added: bluespace artillery construction, meteor shield satellite network and DNA vault.
    • -
    • Fixes the "Messages" tab of the communications computer.
    • -
    - -

    16 February 2017

    -

    Crazylemon64 updated:

    -
      -
    • Slime people and Dionae now make sounds when coughing
    • -
    -

    KasparoVy updated:

    -
      -
    • Welding goggles and welding gas masks now properly affect your vision.
    • -
    -

    davipatury updated:

    -
      -
    • changed urnaium to uranium in wt-550 auto gun uranium magazine design
    • -
    -

    uraniummeltdown updated:

    -
      -
    • The wizard has a new spell, Rod Form, which allows him to transform into an immovable rod.
    • -
    • Ethereal beings no longer cause bananium floor tiles to squeak.
    • -
    - -

    15 February 2017

    -

    Alexshreds updated:

    -
      -
    • Coughing and sneezing now plays sounds.
    • -
    -

    Ausops updated:

    -
      -
    • Internals and plasma tanks have been resprited.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Phlogiston now ignites consistently upon application
    • -
    -

    FlimFlamm updated:

    -
      -
    • New decals for boxes. Just apply a pen to change them (while they're open)!
    • -
    -

    KasparoVy updated:

    -
      -
    • You can now choose to speak anonymously in deadchat from round-start game preferences.
    • -
    • Your decision to speak anonymously in deadchat now persists between ghostings.
    • -
    • Vox tails won't change colour when other Vox spawn in anymore.
    • -
    -

    Markolie updated:

    -
      -
    • Mine bots once again only do ten damage in pressurized areas
    • -
    -

    Twinmold93 updated:

    -
      -
    • Blob Conscious Split now properly scales the requirement of blob tiles to win.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Borers now have action buttons
    • -
    • Borer names are now dependent on generation
    • -
    - -

    14 February 2017

    -

    Developed by Cyberboss, ported by Markolie updated:

    -
      -
    • Progress bars will now stack vertically.
    • -
    • Progress bars will no longer be affected by lighting.
    • -
    -

    DrunkDwarf updated:

    -
      -
    • Adds a section to the Airlock menu of the RCD to allow specifying the name of the new Airlock
    • -
    -

    Fethas updated:

    -
      -
    • You can no longer put anything THAT IS ALREADY A CULTIST IN A SOULSTONE....AT ALL.
    • -
    • Readds missing beserker robe sprite.
    • -
    • Cap growth serum at 1.5
    • -
    -

    Fox McCloud updated:

    -
      -
    • Xenobiology console should be more responsive when using/exiting using it
    • -
    • Xenobiology console can now be loaded with a bag
    • -
    • Using monkey cubes on the Xenobiology console no longer makes you attempt to utilize the console
    • -
    -

    Markolie updated:

    -
      -
    • The kinetic accelerator sprite modkits now apply properly when the kinetic accelerator is empty.
    • -
    • Welding tools now once again have a proper in-hand when turned on.
    • -
    - -

    13 February 2017

    -

    Crazylemon64 updated:

    -
      -
    • Achieving higher growth rates on kudzu will result in a faster-growing vine when planted
    • -
    -

    Fethas updated:

    -
      -
    • Metastation: The escape shuttle doors should no longer be security access only.
    • -
    • Metastation: Hooks up disposals door control.
    • -
    • Cyberiad: Untriggers Neca and makes the floor tiles in the emergecny wing sec area plating.
    • -
    • Cyberiad: Moves the cargo mail room table onto the otherside of the window so you can actually OPEN IT.
    • -
    -

    Fluff12 updated:

    -
      -
    • Greys can now choose to speak in wingdings or not. The Voice option is right below Species in character creation if Grey is selected - make sure you have it set to what you want!
    • -
    -

    Fox McCloud updated:

    -
      -
    • improves the tatortot sprite
    • -
    -

    Kyep updated:

    -
      -
    • Playtime requirements for IAAs have been set at 5 hours (similar to Sec Officer). Playtime requirements for Captains and AI have been increased from 10 hours to 20 hours.
    • -
    • Mech-mounted teleporters are no longer massively overpowered. They now consume a huge amount of energy to use, to the point that crew mechs with them can only use them a few times. They can no longer be spammed. Dark Gygax mechs used by nuclear operatives get a better version of the teleporter, which has around 40 uses, and is more precise.
    • -
    • Fixed several bugs related to Terror Spider webs.
    • -
    • Terror Spiders have been rebalanced. Spiders are no longer spaceproof, princes are now proper minibosses, and more.
    • -
    • Several new classes of Terror Spiders (green, white, purple, queen, mother) have been added - including types which can breed. This creates new strategy around nest defense.
    • -
    -

    Markolie updated:

    -
      -
    • Fixed a number of genetics powers not working.
    • -
    • Posibrains can no longer whisper when silenced.
    • -
    • Syndicate turrets will no longer target the Syndicate pAI found on their outpost.
    • -
    • Fixed the "Swedish" disability occasionally hiding parts of speech.
    • -
    • Mouthless players can no longer eat crayons (such as IPC's).
    • -
    • Instruments can now be interacted with while buckled.
    • -
    • Emagging a single fax machine will no longer give all fax machines access to the Syndicate destination.
    • -
    • Evidence bags will now always show the item inside of them.
    • -
    • Spacepods leaving a trail of humans instead of ion trail effects.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Nuclear Operatives can customize the Declaration of War.
    • -
    • The RSF has a unique sprite.
    • -
    - -

    12 February 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes erroneous access on inner morgue door which was granting people with morgue access, access to the entirety of medical bay
    • -
    -

    Kyep updated:

    -
      -
    • added two more mining hardsuits to the mining outpost.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Whetstones have been resprited
    • -
    • Drying racks have new sprites.
    • -
    - -

    11 February 2017

    -

    Markolie updated:

    -
      -
    • Ports over the remaining Lavaland loot items from /tg/ (most developed by KorPhaeron).
    • -
    • Refactors the kinetic accelerator to use modkits instead of subtypes: these unique mods (such as more range or shorter cooldown) can be purchased from the mining vendor or built by R&D or robotics (developed by KorPhaeron).
    • -
    - -

    10 February 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes not being able to bloodcrawl in most sources of blood
    • -
    • Fixes slaughter demon whisper not working at all
    • -
    • Drying rack drying now properly uses NanoUI instead of a right-click verb
    • -
    • Fixes produce appearing stuck in a drying rack when it was empty
    • -
    • Fixes a few failed icon updates with the drying rack
    • -
    -

    KasparoVy, Krausus updated:

    -
      -
    • Adds the colourblindness gene. It is eye-dependent, and can be transferred from person-to-person with the eye organ.
    • -
    • Colourblindness can be detected by the advanced medical scanner just like blindness and short-sightedness.
    • -
    • Vulpkanin and Tajara can now choose to be uniquely colourblind in exchange for fantastic darksight. The default option is colour vision but low darksight.
    • -
    • Selecting mechanical or mechanically assisted eyes at character creation grants full colour vision, but standard Human darksight. This overrides the colour vision preference.
    • -
    • Mechanical(ly assisted) internal organs such as hearts and eyes are now appropriately named, and have appropriate sprites.
    • -
    • Vulpkanin and Tajara monkey-forms (Wolpins and Farwas) are incurably colourblind but have excellent darksight as they get nearly the same organs as their greater forms.
    • -
    • Increases reliability of turning into a monkey.
    • -
    • Fixes a bug with changelings lesser-forming, transforming and humanforming into a different identity.
    • -
    -

    Markolie updated:

    -
      -
    • Firelocks can now be constructed and deconstructed.
    • -
    • Firelocks no longer show a confirmation message when being opened.
    • -
    • Various map fixes (vents, scrubbers, firelocks and intercoms). Also removes the firelocks covering the windows in escape/cargo.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Ported Goonstation slash /vg/ lighting. Pretty.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Quantum Pads are now buildable in R&D!
    • -
    • Quantum Pads, once built, can be linked to other Quantum Pads using a multitool. Using a Pad which has been linked will teleport everything on the sending pad to the linked pad!
    • -
    • Pads do not need to be linked in pairs: Pad A can lead to Pad B which can lead to pad C.
    • -
    • Upgrading a Quantum Pad will reduce the cooldown, charge-up time, and power consumption.
    • -
    • Quantum Pads require a bluespace crystal, a micro manipulator, a capacitor and a cable piece.
    • -
    • Events now scale better with population.
    • -
    • Enabled immovable rod, slaughter demon and morph events.
    • -
    - -

    08 February 2017

    -

    Fox McCloud updated:

    -
      -
    • Grinding wheat and other products produces the proper reagents again
    • -
    - -

    07 February 2017

    -

    Fox MCCloud updated:

    -
      -
    • Tank transfer valves have in-hand icons
    • -
    • Tank transfer valves with large tanks (ie: jetpacks) cannot fit in backpacks
    • -
    -

    Fox McCloud updated:

    -
      -
    • fixes xeno eggs taking damgae from disablers
    • -
    • adjusts most botany plant reagents to have "plantmatter" as opposed to nutriment
    • -
    • Blumpkins now have plasma in them
    • -
    • Fixes plant grown diona not being allied with plants and vines
    • -
    • Water coolers now dispense cups when clicking on them with a free hand
    • -
    • reagent tank dispensing amount based on the container instead of the tank
    • -
    • Fixes beaker spilling when placing a beaker into an ice cream machine
    • -
    • Adds in 100,000 unit water tanks to cargo for 12 points
    • -
    • regular water tank cost reduced from 8 to 6 points
    • -
    • Monkey cubes in boxes no longer start off wrapped
    • -
    • All monkey cube boxes at cargo are the same price
    • -
    • Fixes Nymphs not being able to cross over top of hydroponics trays
    • -
    • Diona fertilizing and weed eating is handled by clicking on the tray as a nymph rather than verbs
    • -
    -

    KasparoVy updated:

    -
      -
    • Storage implants are now checked for steal objective items.
    • -
    -

    Kyep updated:

    -
      -
    • AI holograms now transfer between holopads as the AI moves around.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Engineering and Science crates now have new sprites
    • -
    • Changelings can recall the memories of an absorb victim
    • -
    • Changelings will recall some speech of their absorb victims
    • -
    • You can now create floor tiles from minerals. Be careful around plasma and uranium floors though.
    • -
    - -

    06 February 2017

    -

    Fox McCloud updated:

    -
      -
    • Fixes traitor banana peels having no sprite
    • -
    • Stunprods are constructed with igniters instead of wirecutters
    • -
    • Stunprods will spark when you stun someone with them
    • -
    • Expands the amount of cryodorm pods
    • -
    -

    KasparoVy updated:

    -
      -
    • IPC names with numbers now load correctly from SQL.
    • -
    -

    Kyep updated:

    -
      -
    • Autoprocess cloners will no longer clone people who cryo and ghost out, or otherwise deliberately remove themselves from the round.
    • -
    • Dead miners in UO45 away mission are no longer naked.
    • -
    • ERT and SST shuttle consoles now require the appropriate access to use.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • You can interact with an ore box by using an advanced mining scanner on it.
    • -
    • Xenobiology Console is now constructible, board has been added to the Circuit Imprinter.
    • -
    • Plasmaman IAA/Lawyers now have a unique suit.
    • -
    • AI control beacons are a new item created from the exosuit fabricator. When installed into a mech, it allows AIs to jump to and from that mech freely. Note that malfunctioning AIs with the domination power unlocked will instead be forced to dominate the mech.
    • -
    • Changelings have a new default ability: Hivemind Link. This lets you bring a neck-grabbed victim into the hivemind for a few minutes. You can talk to your victims and perhaps persuade them to help you, give you intel, or even a PDA code. Victims in crit will be stabilized.
    • -
    • Added new AI core sprites from TG
    • -
    • Added Vox rad suit, bombsuit hood, paramedic EVA suit sprites from /vg/
    • -
    • You can click AI displays as an AI to change them
    • -
    - -

    05 February 2017

    -

    Fethas updated:

    -
      -
    • Brings unholy water in line with its description.
    • -
    -

    Fox McCloud and Core0verload updated:

    -
      -
    • Dramatically overhauls the botany system; features more user friendly gene modification methods, more control over attributes and reagents in your plants, and more
    • -
    • Adds in drying rack for drying growns for smoking with rolled papers
    • -
    • Store spare seeds in the seed extractor
    • -
    • Adds in cloth; make clothing, satchels, backpacks, duffelbags and more.
    • -
    • Upgrading hydroponics trays impacts how quickly plants degrade
    • -
    • Bees slightly more effective at increasing plant yields
    • -
    • Overall growth rate of plants dramatically increased
    • -
    • Adds in the ability to construct bonfires with wooden logs; perfect for keeping you our your fellow spessman warm---forever
    • -
    • Adds in a few new bartender drinks and recipes, such as chocolate pudding, vanilla pudding, and pumpkin spice
    • -
    • Can now wear some flowers/ambrosia in your hair
    • -
    • Combining genes form different plants has unique effects (For instance, the battery gene with the recharging gene allows you to make insanely potent batteries)
    • -
    • Vines are now purely handled by the Kudzu plant
    • -
    • Botanists have been given morgue access
    • -
    -

    Ported by Markolie, developed by KorPhaeron and others from /tg/. The Hierophant was developed by ChangelingRain. updated:

    -
      -
    • Megafauna and their rewards have been added to the code. These are not on the map yet.
    • -
    • Fireball is now a targeted spell instead of a dumbfire spell.
    • -
    • Most spells, wands and staffs now have unique spell sounds.
    • -
    • Added a new nullrod type, the "spellblade".
    • -
    • Added bows, arrows and quivers. Currently only available for admins.
    • -
    • Added cockroaches. Currently only available for admins.
    • -
    • Added support for BYOND medals. Currently disabled.
    • -
    • Added a number of Lavaland objects (flora, basalt, food and stacks). Currently only available for admins.
    • -
    • Earmuffs can now be produced in autolathes.
    • -
    • Syndicate gun turrets are now subtypes of regular turrets: this makes them controllable with Syndicate ID's and improves their targeting.
    • -
    • Diona and Shadow People now receive a warning when they're not exposed/exposed to light.
    • -
    • The sniper AP rounds that Nuke Ops can purchase now have a chance of dismembering limbs.
    • -
    • Shadow People can now switch their night vision properly.
    • -
    • Certain messages in chat weren't showing up in their proper (large) size, such as the Nar'Sie spawned message. This has been resolved.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Supply ID skin is now selectable in the Agent ID and ID Computer
    • -
    - -

    03 February 2017

    -

    DrunkDwarf updated:

    -
      -
    • Set the Mr Chang's vending machine to be refillable
    • -
    • Added a Supply Crate to the Vending section of the Cargo Request Console for Chinese Refill Canisters
    • -
    - -

    02 February 2017

    -

    Alexshreds updated:

    -
      -
    • Deconstructing closets yields the proper amount of metal
    • -
    -

    Kyep updated:

    -
      -
    • Using the 'summon narsie' rune as cult, when you don't have the objective to do so, is now punished by the cult's god. Just as using the 'call forth the slaughter' rune, when you don't have the objective to do that, is already punished.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Engineering Cyborgs now have a digital copy of the station blueprints.
    • -
    - -

    31 January 2017

    -

    Ar3nn updated:

    -
      -
    • cursed cluwne mask now allows internals to be fed through it
    • -
    -

    FalseIncarnate updated:

    -
      -
    • All requests consoles can print off a single-use, pre-tagged Shipping Package for sending a single item via disposals to a destination of your choosing.
    • -
    • Shipping Packages can be used to tag packages wrapped with wrapping paper, in case you don't have access to cargo's destination tagger.
    • -
    • Requests Consoles log the printer and destination of all shipping labels printed from that particular console. There currently is no way to clear your mailing history, so mail responsibly.
    • -
    -

    Fethas updated:

    -
      -
    • Fixes a rune runtime.
    • -
    -

    FlattestGuitar updated:

    -
      -
    • adds an admin-only laser carbine
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Your game window will now flash on receiving Admin PMs, being revived, and ghost roles. You can disable this in Game Preferences.
    • -
    - -

    30 January 2017

    -

    Alexshreds updated:

    -
      -
    • No more double traitor 241 Special
    • -
    - -

    29 January 2017

    -

    uraniummeltdown updated:

    -
      -
    • You can now take items directly out of a storage item in your backpack.
    • -
    - -

    27 January 2017

    -

    Alffd updated:

    -
      -
    • Adds missing hat and shoe sprites that were inadvertently deleted.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in stungloves (inaccessible to players)
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Injecting a rainbow slime extract with blood will create a consciousness transference potion.
    • -
    • Injecting a metal slime extract with water will create 15 sheets of glass and 5 sheets of reinforced glass.
    • -
    • Slime potions now check for proximity.
    • -
    - -

    26 January 2017

    -

    FalseIncarnate updated:

    -
      -
    • Plasma dust can now be used to rig lights and power cells, like the plasma reagent, with explosive results.
    • -
    -

    Fethas updated:

    -
      -
    • Adds two new holy weapon skins for people who belive in ghosts and worshipers of the silentfather.
    • -
    -

    FreeStylaLT updated:

    -
      -
    • AI sat transport tubes are no longer misaligned
    • -
    - -

    25 January 2017

    -

    FlattestGuitar updated:

    -
      -
    • Fixes shadowlings thrall scaling
    • -
    -

    scrubmcnoob updated:

    -
      -
    • Shadowling Thrall count now scales to a max of 25.
    • -
    • Shadowling Thralls lose lesser glare
    • -
    - -

    23 January 2017

    -

    FalseIncarnate updated:

    -
      -
    • Returns the ability to remove vacant soil with shovels and spades, and adds the ability to dig up plants in soil to remove them instantly.
    • -
    -

    Stratus updated:

    -
      -
    • NT Enforcer .45 pistol.
    • -
    • .45 and 9mm rubber bullets.
    • -
    • New shotgun ammo boxes.
    • -
    - -

    18 January 2017

    -

    AndriiYukhymchak updated:

    -
      -
    • multitool can now be used to swap directions of TEG's circulator
    • -
    -

    Fethas updated:

    -
      -
    • Adds in the check numbers proc to converting, I missed it from VG.
    • -
    • Removed a redundent sacrefice objective check AND fixed the sacrfice objective check so it actually PICKs on mode start.
    • -
    • changed the color of manfested ghost humans to grey...huehuehuehuehue(serously it helps tell them apart better).
    • -
    • mass convert objective now picks between 9 and 15 as a target instead of based on round pop..cuase 30 MIGHT be a bit much.
    • -
    • adds admin cult tools Bypass phase (missed this off vg) and cult mind speak(YOUR GOD IS DISPLEASED GIT GUD). Might be better in secret panel but it confuses me.
    • -
    • Removes errent invisaible animals from the narnar escape shuttle template.
    • -
    -

    KasparoVy updated:

    -
      -
    • Characters with the obese disability are now fat beneath their clothes.
    • -
    -

    Markolie updated:

    -
      -
    • Admin announcements are no longer sent to player in the lobby.
    • -
    • Regular announcements can now only be heard if you the player is alive, not deaf and in range of an enabled radio.
    • -
    - -

    17 January 2017

    -

    Crazylemon64 updated:

    -
      -
    • Joined Souls works now
    • -
    • Scribing the end rune now no longer is impossible
    • -
    -

    Krausus updated:

    -
      -
    • Fixed the exciting new emoji breaking chat entirely for IE8 users. :clap:
    • -
    - -

    16 January 2017

    -

    Alexshreds updated:

    -
      -
    • Revenants can now breathe in space.
    • -
    • Can no longer exploit RCDs for metal
    • -
    -

    Krausus updated:

    -
      -
    • You can now use pills and patches on people with full bellies.
    • -
    • The Randomized Character Slot option now actually works.
    • -
    - -

    15 January 2017

    -

    Funce updated:

    -
      -
    • dual-port air vents can now be unwrenched
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Broken and Burned bulbs are no longer forced on with every overload.
    • -
    • Only non-broken and non-burned bulbs actually break and spark on an overload.
    • -
    • Fixes a single syntax error in the Shadowling Ascendant descriptive text.
    • -
    - -

    14 January 2017

    -

    Crazylemon64 updated:

    -
      -
    • Bibles can now reveal runes as they did before
    • -
    -

    Krausus updated:

    -
      -
    • Players will no longer be informed of what cult may or may not exist on round start.
    • -
    - -

    13 January 2017

    -

    DarkPyrolord updated:

    -
      -
    • Removes the joy mask
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Cyborg tools (and other non-droppable tools) cannot be transferred to an open, empty Display Case
    • -
    • Jobs receive links to SOP and their Department SOP at roundstart. Space Law and Legal SOP links added to Security members, Magistrate and IAAs
    • -
    -

    uraniummeltdown updated:

    -
      -
    • You can see what sting you have equipped as changeling.
    • -
    • All species except IPCs can now be changelings and be affected by their genetic abilities.
    • -
    • Arm Blade can now pry open powered airlocks
    • -
    • Transformation Sting now costs 3 points and requires 50 chemicals
    • -
    • You can no longer transform people into Vox with Transformation Sting.
    • -
    • Removed Engorged Chemical Glands, Changelings now have the ability by default
    • -
    - -

    12 January 2017

    -

    TullyBurnalot updated:

    -
      -
    • Graffiti now have hidden (Admin-only) fingerprints added to them
    • -
    - -

    11 January 2017

    -

    Crazylemon64 updated:

    -
      -
    • Ghosts can now see if they're allowed to respawn or not at a glance
    • -
    • Cyborg sight modes are now actions, instead of items
    • -
    • Mining drones can now use meson sight again
    • -
    • It's no longer opposite day for the karma reminder preference
    • -
    -

    Lady Luck updated:

    -
      -
    • office laptops are now traversable
    • -
    -

    Markolie updated:

    -
      -
    • simple_animals now have an attack cooldown when attacking mechas.
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Atmos Console Boards now show in Computer Boards of Circuit Imprinter
    • -
    - -

    10 January 2017

    -

    Crazylemon updated:

    -
      -
    • Giant spiders now have their own role pref
    • -
    -

    Crazylemon64 updated:

    -
      -
    • pAIs can now adjust their radios
    • -
    • pAIs can now more reliably hear nearby whispers
    • -
    • pAIs can now whisper while inside a PDA
    • -
    • pAIs can no longer change their icon from being dead, while dead
    • -
    • Non-respawnable players are no longer prompted to submit a pAI when the opportunity is available
    • -
    • Borg sight modules work again
    • -
    -

    Fox McCloud updated:

    -
      -
    • different alert levels for how full you are from starving all the way to fat
    • -
    • There is now satiety and nutrition; being satisfied and full has a number of positive benefits; being unsatisfied and hungry has negative side effects
    • -
    • Some foods have vitamins in them which provide little nutrition, but greatly increase your satisfaction
    • -
    • Some food reagents have had their nutritional values tweaked
    • -
    • reagent numbers tweaked on most food items
    • -
    • Fixes the floral gun not properly working on Diona
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Wand of Death now reliably kills people by adding 300 Burn Damage. This includes self-casting
    • -
    • Minor flavour text visible on impact of target
    • -
    • pAI HUDs are now visual-only, restricting their access to editable records
    • -
    -

    pinatacolada updated:

    -
      -
    • IV drips now have adjustable rates
    • -
    -

    uraniummeltdown updated:

    -
      -
    • Mimes can now choose name on entry just like Clowns
    • -
    • Added many new costumes to the Autodrobe!
    • -
    - -

    09 January 2017

    -

    Crazylemon64 updated:

    -
      -
    • The operating table now checks for both either `lying` or `resting` - so surgery will work no matter what on unconscious people lying on your table.
    • -
    -

    Kyep updated:

    -
      -
    • Antags should no longer get bounced to lobby at round start in certain rare situations.
    • -
    - -

    07 January 2017

    -

    Markolie updated:

    -
      -
    • False walls now block atmospherics, unless it's open.
    • -
    - -

    06 January 2017

    -

    Crazylemon64 updated:

    -
      -
    • pAI UIs no longer break
    • -
    • The chem dispenser's UI now displays the remaining energy again
    • -
    • Shuttles no longer make buckling useless
    • -
    • You should no longer go mute randomly
    • -
    • You can now opt out of all requests on a role for a round
    • -
    • Morgue trays now have descriptions that correspond to each of the morgue light states
    • -
    • Waking up no longer auto-cancels resting.
    • -
    -

    Fethas updated:

    -
      -
    • ports parts TG neo-oldcult rscadd:Ports parts of cult from VG
    • -
    -

    KasparoVy updated:

    -
      -
    • Grey sprites have been tidied up and no longer have any random pixels hanging off.
    • -
    • Grey species-fitted tattoo sprites and the last Vox species-fitted tattoo sprite.
    • -
    -

    Krausus updated:

    -
      -
    • SDQL2 can now directly manipulate clients.
    • -
    -

    Kyep updated:

    -
      -
    • Mobs in vents no longer see vents/scrubbers as unwelded when they are welded, and vice versa.
    • -
    - -

    03 January 2017

    -

    KasparoVy updated:

    -
      -
    • The Vulpkanin Anita hairstyle no longer has rogue extra-bright pixels.
    • -
    -

    Kyep updated:

    -
      -
    • Added tracking for how much playtime each player has.
    • -
    • Added the ability to lock jobs based on playtime. E.g: must play for 10 hours to unlock HoS.
    • -
    - -

    02 January 2017

    -

    KasparoVy updated:

    -
      -
    • Particle Accelerators ordered from Cargo can now function.
    • -
    • Wrenching powerless machines in a powered area will no longer require you to toggle the lights (or whatever you did before to sort this).
    • -
    -

    Krausus updated:

    -
      -
    • The syndicate nuke and pinpointer locker will once again spawn into their ship, rather than into space near the station.
    • -
    -

    Kyep updated:

    -
      -
    • Terror Spiders can no longer create more than one web on a tile.
    • -
    - -

    01 January 2017

    -

    Kyep updated:

    -
      -
    • Added basic, AI-less versions of some Terror Spiders.
    • -
    - -

    31 December 2016

    -

    Crazylemon64 updated:

    -
      -
    • The home gateway now will send ghosts to the other end by default, now
    • -
    - -

    30 December 2016

    -

    Crazylemon updated:

    -
      -
    • The shuttle manipulator can now only be used by admins
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds Nano-Mob Hunter GO! PDA game cartridges and related stuff. Grab a cartridge from the cartridge vendor or loadout and join in on the hunt!
    • -
    • Adds Nano-Mob Hunter GO! Battle Terminals to the Holodeck and a Nano-Mob Hunter GO! Restoration Terminal to medbay's lobby.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes cyborg cryo oddities
    • -
    -

    KasparoVy updated:

    -
      -
    • Taking off noir glasses while noir mode is on will now give you your colour vision back.
    • -
    - -

    29 December 2016

    -

    Fethas updated:

    -
      -
    • Alternate shuttle/ferry template system from TG
    • -
    • Shuttle Manipulator
    • -
    • Better shuttle kills
    • -
    -

    Markolie updated:

    -
      -
    • The camera console has been refactored so there's no longer a delay when switching cameras.
    • -
    • The camera console should no longer lag for several seconds.
    • -
    - -

    25 December 2016

    -

    FalseIncarnate updated:

    -
      -
    • Santa's back and with-holding all your presents! Head through the gateway and show the Fat Man the strength of your holiday spirit (and advanced weaponry, you'll be needing that)!
    • -
    -

    KasparoVy updated:

    -
      -
    • Cameras will no longer be able to take photos of stuff outside your line of sight.
    • -
    • Cameras will now render disguises as you see them.
    • -
    - -

    23 December 2016

    -

    Crazylemon64 updated:

    -
      -
    • Welding overlays now update instantly
    • -
    • Being inside various structures will now obscure your vision
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes X-Ray not doing anything
    • -
    • Fixes nightvision not granting what its name implies
    • -
    • Fixes species/human darksight doing absolutely nothing
    • -
    -

    KasparoVy updated:

    -
      -
    • Characters will now be correctly assigned their species' genetic quirks at spawn.
    • -
    • Cloning will now correctly assign a characters species' genetic quirks.
    • -
    • Changing a character's species (via C.M.A. or whatever might call the set_species proc) will now correctly assign their species' genetic quirks.
    • -
    -

    Markolie updated:

    -
      -
    • Ruins no longer trigger power alarms.
    • -
    - -

    20 December 2016

    -

    TullyBurnalot updated:

    -
      -
    • Neurotoxin Spit now causes the spitter to move in space
    • -
    • Proximity Wet Floor Sign Mines can no longer appear in Surplus Crates
    • -
    - -

    14 December 2016

    -

    Fox McCloud updated:

    -
      -
    • Fixes the personal crafting cost of ED-209's being too expensive
    • -
    - -

    13 December 2016

    -

    TullyBurnalot updated:

    -
      -
    • Medbots no longer run after injured mobs if buckled. They also inform nearby players of this
    • -
    - -

    12 December 2016

    -

    Kyep updated:

    -
      -
    • Xenomorph resin walls no longer take damage from disabler beams. Only proper BRUTE or BURN damage hurts them now.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Throwing mobs behind you force moves them to behind you before actually throwing them, preventing throw-shoving
    • -
    - -

    09 December 2016

    -

    KasparoVy updated:

    -
      -
    • You can now define whether a hair style will cover glasses or not. Only long hair styles should cover glasses (default behaviour).
    • -
    • You can now define whether a facial hair style/head accessory will be rendered on top of hair or not.
    • -
    • Glasses no longer render on top of all hair styles, only sufficiently short ones.
    • -
    - -

    08 December 2016

    -

    Kyep updated:

    -
      -
    • Ensures cryo pods will properly auto-eject people whose organic parts (limbs) have been healed, but who still have damaged mechanical limbs.
    • -
    • Disabler shots no longer damage mechs.
    • -
    • On impact, both taser and disabler shots now produce a message saying that the mech is undamaged by them, instead of a message saying they 'hit'.
    • -
    • Fixed runtimes created when SIT, ERT, and some other mobs are spawned.
    • -
    • Fixed a bug causing SITs to be spawned with one less person than desired in some cases.
    • -
    - -

    07 December 2016

    -

    Markolie updated:

    -
      -
    • Verbs have been cleaned up: all karma verbs can now be found under "OOC" instead of "Special Verbs". Most admin verbs have been moved out of "Special Verbs" as well.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Unpowered Mining Vendors no longer accept IDs
    • -
    • Ore Redemption Machine and Mining Vendor can now be deconstructed if unpowered
    • -
    - -

    06 December 2016

    -

    Markolie updated:

    -
      -
    • The track button on the AI crew monitor now works.
    • -
    • Permanent door electrification by alt-clicking a door as an AI or setting it manually now works again.
    • -
    - -

    05 December 2016

    -

    KasparoVy updated:

    -
      -
    • Resolves an issue where cloned vampires could no longer drain blood, burn in the chapel or use their powers properly.
    • -
    - -

    04 December 2016

    -

    KasparoVy updated:

    -
      -
    • Resolves an issue with changeling regenerative stasis where changelings who initiated it while alive and died during the waiting period did not come back to life. Now they will, as intended.
    • -
    - -

    03 December 2016

    -

    Kyep updated:

    -
      -
    • the anti-ERP warning message on PDA message consoles is now accurate.
    • -
    - -

    01 December 2016

    -

    Crazylemon64 updated:

    -
      -
    • Cryo tubes no longer let you excessively multiply the efficiency of touch chems
    • -
    -

    KasparoVy updated:

    -
      -
    • The character preview icon in character creation is now more detailed and less blurry.
    • -
    • ID cards now show tails, body accessories and tail markings correctly.
    • -
    -

    Twinmold93 updated:

    -
      -
    • Pilots of spacepods will no longer be sent to the void when the space pod is destroyed in any method.
    • -
    • Pilots of spacepods will now get the same warnings for damage/core destruction that passengers get.
    • -
    - -

    29 November 2016

    -

    KasparoVy updated:

    -
      -
    • Head, body and tail markings are now loaded correctly from genes (UI).
    • -
    • Changes to a person's skin-tone gene are now immediately apparent.
    • -
    - -

    28 November 2016

    -

    Allfd updated:

    -
      -
    • Fixes an issue with the processing of GitHub changelog emoji in the php webhook.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • The RCD no longer shall work as a remote permissions control
    • -
    -

    KasparoVy updated:

    -
      -
    • Pressing the light switch in one OR will no longer turn off the lights for both.
    • -
    • The fire alarms in each OR now work independently of each-other.
    • -
    • The second operating room now has its own APC and wiring.
    • -
    - -

    26 November 2016

    -

    Fox McCloud updated:

    -
      -
    • Fixes faint emote doing nothing
    • -
    • Fixes Mickey Finn's Special Brew not functioning properly/not making you fall asleep
    • -
    - -

    23 November 2016

    -

    Fethas updated:

    -
      -
    • Fixes human jetpacks..maybe...
    • -
    -

    FlattestNerd updated:

    -
      -
    • the e20 will now get logged when it goes BEWM, as it should.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes double-breaking news newscaster
    • -
    - -

    22 November 2016

    -

    KasparoVy updated:

    -
      -
    • You now stutter when you're in shock/crit and when you've got the nervous disability as you used to.
    • -
    -

    Twinmold93 updated:

    -
      -
    • Runtime caused by lack of settlers in the Orion arcade game.
    • -
    - -

    20 November 2016

    -

    KasparoVy updated:

    -
      -
    • The DNA SE injectors one can find in the abandoned mining crates now correctly activate/deactivate the powers they may contain.
    • -
    - -

    15 November 2016

    -

    KasparoVy updated:

    -
      -
    • Adding cable to multiple computer frames at the same time while not having the correct amount of cables will no longer cause busted coils with a negative number of cables.
    • -
    - -

    13 November 2016

    -

    Fox McCloud updated:

    -
      -
    • Fixes BSA having peculiar results.
    • -
    - -

    07 November 2016

    -

    Crazylemon updated:

    -
      -
    • Status effects should work a little more consistently now
    • -
    -

    Crazylemon64 updated:

    -
      -
    • The mech-mounted plasma cutter can now be constructed again
    • -
    • Space pod lasers can now be constructed again
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes hunters not being weakened when crashing into a shield/wall
    • -
    • Fixes xeno stuns half the time intended
    • -
    • Fixes stopping, dropping, and rolling not properly weakening Xenos/Hulks
    • -
    -

    KasparoVy updated:

    -
      -
    • Fixes a bug where changing your alt head required two icon updates to show.
    • -
    • Fixes a bug where you couldn't choose head marking styles that would ordinarily be available regardless of your alt head.
    • -
    • Fixes a bug where Tajara couldn't choose undergarments.
    • -
    • Resolves an issue with the Vulpkanin Jagged hairstyle missing a pixel.
    • -
    -

    Twinmold93 updated:

    -
      -
    • Fixes a runtime issue caused by using the detective's scanner on the space hotel cleaver.
    • -
    • Scrubber pipe missing segment behind the operating theatres.
    • -
    - -

    23 October 2016

    -

    KasparoVy updated:

    -
      -
    • Refactors markings. Now split into head, body and tail markings.
    • -
    • Refactors morph again. Changes made while morphing are now reflected instantly on your sprite.
    • -
    • Darkens Vulpkanin and Tajara for improved colour fidelity. Species base colour changed to compensate. Add 27 to R, G and B values if Vulp, 15 if Taj to keep the same colour on your character.
    • -
    • Darkens Vulpkanin facial fur patterns for improved colour fidelity. Add 23 to the R, G and B values of your facial hair/head accessory to keep the same colour on your character.
    • -
    • Darkens Unathi frills and horns. Add 27 to the R, G and B values of your frills and 21 for horns to keep the same colour on your character.
    • -
    • Vulpkanin tails are now split-rendered. Tails overlap hair when facing north, but are overlapped by hair when facing all other directions. No other differences, only affects the fluffy husky tail.
    • -
    • The heads of tiger markings have been isolated and can now be coloured independently.
    • -
    • Hair can now cover facial hair, and glasses are no longer covered by facial hair and head accessories. Means that two-piece Vulpkanin facial fur patterns won't almost entirely cover whatever glasses they're wearing.
    • -
    • Tajaran head and facial hair have been darkened. Add 28 to the R, G and B values of your Tajara head/facial hair to keep the same colour on your character.
    • -
    • Vulpkanin head hair and one facial hair style has been darkened. Refer to PR notes for darkening factors.
    • -
    • The HAS_MARKINGS flag now represents all marking locations. The HAS_location_MARKINGS flags are for specific locations (head, body, tail).
    • -
    • Improves the quality of some Vulpkanin/Tajara/Unathi mask sprites.
    • -
    • Naked Humans and Skrell will no longer have exposed flesh poking out their wrists when facing east or west. Male Humans now no longer lack a butt pixel when facing east or west.
    • -
    • Mutated limbs now render correctly as soon as they're mutated.
    • -
    • Mobs will now correctly appear as fat/skinny.
    • -
    • Species with TAIL_OVERLAPPED will no longer wag tail at max speed when facing north.
    • -
    • Species with TAIL_OVERLAPPED and body accessories won't crash the game when they wag.
    • -
    • Tiger Head and Face markings adjusted so they don't look ugly on certain species' ears.
    • -
    • Fixes issue where Unathi dorsal stripe didn't render.
    • -
    • Tajaran ears are no longer in their hair sprites, but on their actual heads.
    • -
    • The adminbus body accessory now overrides the TAIL_OVERLAPPED flag and will now be rendered correctly on a body regardless of species bodyflags.
    • -
    • Changing a person's species via CMA will no longer result in a mob with all the same cosmetic attributes as the old species.
    • -
    • Dressers now have species fitting checks for undergarments. Drask are now able to wear undershirts and underwear like they were originally meant to.
    • -
    • Adds some head markings for Tajara and Vulpkanin.
    • -
    • Adds body marking(s) for Tajara, Vulpkanin, Unathi and Drask.
    • -
    • Adds tail markings for Vox and Vulpkanin.
    • -
    • Adds 5 Tajaran hairstyles.
    • -
    • Adds a tweaked version of an existing Vox hairstyle. Shouldn't clip with certain jackets as much.
    • -
    • Adds a hairstyle for Humans, Unathi and Vulpkanin.
    • -
    • Adds a facial hairstyle for Vulpkanin.
    • -
    • Adds secondary hair (head and facial) themes. Skrell can now colour their tentacle cloths independently, the beads in the Tajaran/Hippie braid hairstyles can be coloured and the same with the webbing in Unathi frills. Can be changed at nanomirrors, via morph and CMA.
    • -
    • Adds alternate heads. Unathi can now choose a head with a sharp snout. Can be changed via morph and CMA.
    • -
    • Helper procs to convert a hex colour into either R, G, or B.
    • -
    • Markings, body accessories, head accessories, alt heads and their colours (if they have colours) can now be randomized at the character preferences screen.
    • -
    • Adds a system that attempts to fit mobs with alternate heads with appropriate mask sprites. The sprites just need to be suffixed with the alt_head suffix in sprite_accessories.dm.
    • -
    • Adds mask sprites tweaked to fit the new Unathi alternate head to go along with the new alt. head mask fitting system.
    • -
    - -

    15 October 2016

    -

    Crazylemon64 updated:

    -
      -
    • The R&D console should now no longer freeze on the "Syncing Database" message or whatever.
    • -
    • Borg coolers and SMES boards can be made again
    • -
    • Maroon now works
    • -
    -

    FlattestGuitar updated:

    -
      -
    • pAIs no longer turn into debris when wiped
    • -
    • SNPCs no longer get targeted by assasinate objectives
    • -
    • fixes a hallucination runtime, actually making one more aspect of being high as f*** work for the first time in ages
    • -
    • NODROP items will no longer attempt to be dropped if your hand is broken
    • -
    -

    Fox McCloud updated:

    -
      -
    • Cloners will now put you inside the cloned body when it is fully grown as opposed to initially created
    • -
    • Examining a cloner will tell you the clone progress
    • -
    • Observers can now see a visual countdown of the cloning status progression
    • -
    • Atmos grenades cost increased from 6 to 11
    • -
    • Mice now have sprites when worn
    • -
    • Fixes various ghost alerts having barely visible icons
    • -
    • Fixes items being in two locations at once when loading things into the bio-generator or reagent grinder.
    • -
    -

    GeneralChaos81 updated:

    -
      -
    • Ability to place and remove conveyor belts and levers.
    • -
    -

    KasparoVy updated:

    -
      -
    • Botany, viro and xenobio bottles will no longer be invisible.
    • -
    -

    Krausus updated:

    -
      -
    • Fixed full chat panes scrolling unpredictably when trying to view old messages.
    • -
    • Fixed camera monitors immobilizing you if you reconnect while using one.
    • -
    • Fixed selecting datum types through SDQL2 never returning any datums.
    • -
    - -

    16 September 2016

    -

    Aurorablade updated:

    -
      -
    • *fart now has newtonian move if you have the Superfart power
    • -
    -

    Coldflame updated:

    -
      -
    • Adds three new variants of 10mm ammunition, AP, HP, and Incendiary. Currently admin-only.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Research data disks now have a description and name attached to them automatically, to make working with them less obnoxious.
    • -
    • Loading design disks now has a sound effect.
    • -
    • You can no longer feed non-design disks into the autolathe and destroy them on accident.
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • Due to budget cuts expensive fax machines have been replaced with cheaper versions in some departments. Only essential personnel can fax Central Command. See your local IAA for details.
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Added emergency nitrogen and plasma tanks, you can find two of each in the medical storage
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Updated Metastation's AI Sat, brig and escape shuttle
    • -
    • Updated other Meta areas to match most recent build. (Chapel, some maint, etc. - minor changes.)
    • -
    • Updated Cyberiad's AI Sat to latest tg version, lots of changes there - basically an entirely new Satellite.
    • -
    -

    IcyV updated:

    -
      -
    • Adds new bottle sprite
    • -
    • Fixes many bottles being locked to a single icon
    • -
    • Buckets can be worn as hats.
    • -
    -

    Improvedname updated:

    -
      -
    • Adds 4 epinephrine autoinjectors to nanomedplus vending machines
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds a Science departmental beret that you can obtain via the loadout system.
    • -
    -

    Krausus updated:

    -
      -
    • Fixed species-restricted items sometimes failing to "equip" to restricted species' non-equipment slots.
    • -
    • Players using very old versions of Internet Explorer will now receive explicit warnings that they're not supported.
    • -
    • View Variables will now consistently view the variables of what it's intended to.
    • -
    • Admins can now use the 'msay' command to speak directly to all mentors.
    • -
    • Added a new command, "Toggle Mentor Chat", to give mentors temporary access to 'msay'.
    • -
    • Fixed never being able to properly respond to a PM from a stealthed admin.
    • -
    -

    Kyep updated:

    -
      -
    • SST and SIT now have their own radio frequency.
    • -
    -

    LittleBigKid2000 updated:

    -
      -
    • The God Emperor of Mankind disk now works properly
    • -
    -

    TheDZD updated:

    -
      -
    • Xenomorph hunters' leap ability is now always blocked by shields rather than only 50% of the time.
    • -
    • Xenomorph hunters' leap ability being blocked now stuns them as if they had hit a wall. The leap still goes on a 3 second cooldown as normal.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Adds fluff item "Tacticool EyePro"
    • -
    - -

    01 September 2016

    -

    Crazylemon updated:

    -
      -
    • Dying of low blood is no longer capable of causing eternal death
    • -
    • Having your body brought back to life will no longer break your health doll
    • -
    -

    monster860 updated:

    -
      -
    • Fixes hotel SNPC's getting access that they shouldn't get.
    • -
    - -

    29 August 2016

    -

    Crazylemon updated:

    -
      -
    • You can now mend incisions after having cut open someone's ribcage.
    • -
    • Abductor surgery works again
    • -
    • Face repair surgery works again
    • -
    • The `to_chat` messages are now more descriptive when given a bad target
    • -
    • Admins can now VV by a ref string, directly via a verb
    • -
    • VV now builds its HTML using lists, making it much faster to open
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • Upgrades the newscaster's liquid paper printing apparatus. Newspapers printed are higher quality now.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Mining Drones can now toggle meson vision on or off, a light, switch attack modes, or even drop their own ore
    • -
    • Ash storms no longer impact sheltered areas and mining mobs are immune to ash storms
    • -
    • Adds in two new end-round sounds
    • -
    • Fixes drones not being able to bump open doors
    • -
    -

    Fox McCloud and KorPhaeron updated:

    -
      -
    • Adds in mining shelters
    • -
    • Adds in a few more dice types and ensure dice are packed in bags and not pill bottles
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Added additional coating to Turbine room.
    • -
    • Fixed leftover vent in Brig Physician's office
    • -
    • Fixed missing coated rwalls in Incinerator
    • -
    -

    Krausus updated:

    -
      -
    • Girders are no longer bulletproof.
    • -
    • Changelings' Swap Form ability now actually deducts its cost upon use, and shouldn't arbitrarily fail to work properly.
    • -
    • Fixed setting status display alerts through communications consoles.
    • -
    -

    Kyep updated:

    -
      -
    • Fixes 'SSD!' warning appearing in attack logs for admins, when the target player was dead and had ghosted out of their body
    • -
    -

    TheDZD updated:

    -
      -
    • Bookcases no longer force you to take out a book after clicking them
    • -
    • Fixes assorted things logging attacks incorrectly.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • AIs can no longer interact with nuclear bombs (Syndicate-brand included). AIs can still see the countdown
    • -
    • Mobs without appendixes can no longer contract appendicitis
    • -
    • Holosigns cannot be pulled around
    • -
    - -

    19 August 2016

    -

    Crazylemon updated:

    -
      -
    • pAIs should now save
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Repairing burn damage to robotic limbs now consumes cable in the process. Each length used repairs 3 burn damage, up to 15 damage per click.
    • -
    • Repairing brute damage to robotic limbs now uses 1 fuel per repair (click). Heal amount unchanged.
    • -
    • Self-repairing with cables or welders now incurs a 1 second delay between click and heal completion. Being repaired by a friend is still no delay (but requires a friend).
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in the Kinetic Smasher as a mining purchase
    • -
    • Fixes slap emote text being the wrong partial color
    • -
    • Fixes the attack text of simple animals attacking human mobs
    • -
    -

    IcyV updated:

    -
      -
    • Adds in an amount of new graffiti
    • -
    • Fixes the issue of other graffiti only being able to be done in black.
    • -
    -

    Krausus updated:

    -
      -
    • Flavor text and records are no longer horrifically butchered when saved in the database.
    • -
    -

    TheDZD updated:

    -
      -
    • Lowered genetic instability damage thresholds by 5 across the board. Effectively meaning that you can have one additional minor power without shifting into the next threshold.
    • -
    • Lowered the rate at which damage scales with instability, and the decreased upper cap on each damage type.
    • -
    • The base activation probability for powers is now 100%, rather than 45%. Abilities affected include everything except Cloak of Darkness, Chameleon, No Breathing, Hulk, Telekinesis, and X-Ray Vision, which all have their own independent activation chances (varying from 5% to 10%).
    • -
    • Increases activation chances of TK (10% to 15%), No Breathing (10% to 25%), Cloak of Darkness (10% to 25%), Hulk (5% to 15%), X-Ray Vision (10% to 15%), and Chameleon (10% to 25%).
    • -
    - -

    18 August 2016

    -

    Alexshreds updated:

    -
      -
    • pAIs can see the crew manifest again.
    • -
    • Engineers and Atmos Techs have access to the ORM
    • -
    -

    Ar3nn updated:

    -
      -
    • dusting playermobs now generates remains fitting for their race.
    • -
    -

    Chakishreds updated:

    -
      -
    • You can now click on objects in a gassy room at the expense of ninja floors.
    • -
    -

    Chopchop1614 updated:

    -
      -
    • fixes transformation sting not working.
    • -
    • transformation sting now checks if the target has DNA or not
    • -
    -

    Crazylemon updated:

    -
      -
    • Alt+Click should be quicker now
    • -
    • The Alt+Click panel vanishes only when you alt click a turf distant from yourself
    • -
    • Adds `json_to_object_arbitrary_vars`, a proc intended for use with SDQL
    • -
    • Eye color is tracked on the eyes only, instead of on the body.
    • -
    • The CMA panel no longer runtimes when you change species.
    • -
    • Deserializing a human now preserves hair and eyes.
    • -
    • Associative lists in VV now display properly again
    • -
    • Admins can now click on the DI panel buttons to debug the corresponding controller in VV
    • -
    • Fat people are now fat when naked.
    • -
    • Encased mobs can now examine
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Makes teleportation checks more consistent, which will ensure that teleporting in the away mission no longer works.
    • -
    • People on the space ruins level no longer count as dead for assassinate objectives.
    • -
    • Space border turfs will now regain their destination when over-written and replaced on the edge of the map
    • -
    • The space manager will no longer runtime if a space ruin writes on the edge of the map
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • ERT gloves reverted to how they used to be.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • WOLOLO! Traitor Chaplains can now WOLOLO with the new Missionary Staff and Robes. WOLOLO!
    • -
    -

    Fethas updated:

    -
      -
    • The whitelist will respect addons better, didn't even have to make a ban appeal..
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Detective's coolness variable cranked up to 14.5, they will no longer vomit over corpses.
    • -
    • Now you're less likely to vomit over a corpse if you're a normal human being.
    • -
    • golems now have their master saved in attack logs
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in formal captain's uniform and armor
    • -
    • Adds rapier to captain's locker
    • -
    • Adds lace up shoes to captain's locker
    • -
    • Adds crown to captain's locker
    • -
    • Dramatically speeds up conveyor belts
    • -
    • Appendicitis and Disease Outbreak events will no longer impact clientless mobs
    • -
    • Fixes bandolier being invisible on spawn
    • -
    • Removes the jukebox from the bar
    • -
    • Detective Scanner, Fedora Tipping, Pontificating, and Cap Flipping are now action buttons
    • -
    • Cane Gun and NT Rep's cane now acts as actual canes
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Fixed missing space transition tiles in emergency shuttle transit
    • -
    • Fixed lack of prisoner access to lower part of labor camp shuttle
    • -
    • Changed UO45's and MO19's away missions' external tiles to just airless ones.
    • -
    • Changed MO19's exterior to be more rock than ground, this is to make Linda cry less when this mission is passed.
    • -
    -

    General Chaos updated:

    -
      -
    • Ports TG's mech bay recharger code.
    • -
    -

    IcyV updated:

    -
      -
    • Adds an exploding chameleon flag for traitors.
    • -
    -

    KorPhaeron and Fox McCloud updated:

    -
      -
    • Merges Malf AI into traitor AI
    • -
    • Malf AI's starting CPU reduced from 100 to 50
    • -
    • Hacking APCs gives 10 additional CPU
    • -
    • Hacking APCs throws an alert to the AI when it's hacking that automatically clears when hacking is complete (sounds too)
    • -
    • Traitor AI's start off with a syndicate headset
    • -
    • Adds doomsday device module for AI's for 130 CPU; when activated, it will purge the station of all life if the AI is not destroyed after 7.5 minutes
    • -
    • Adds in AI upgrade modules which allows you to giving hacking abilities to the AI or allow it to have increase surveillance capabilities
    • -
    -

    Krausus updated:

    -
      -
    • Karma spending is now slightly more straightforward and sanity-checked.
    • -
    • Ghosts can now see non-crew antagonists in the Award Karma listing.
    • -
    • You can now ctrl+click on yourself to stop pulling something.
    • -
    -

    Kyep updated:

    -
      -
    • Added Syndicate Infiltration Teams (SITs), which are like Syndicate Strike Teams (SSTs) but focusing on stealth rather than direct combat. Useful for getting ghosts into rounds, spicing up rounds, having traitors with teamwork, and new kinds of traitor objectives like kidnap.
    • -
    • Fixed bug that Dust implants had no icon.
    • -
    -

    LittleBigKid2000 updated:

    -
      -
    • The arrivals checkpoint camera monitor is now connected to some camera networks by default.
    • -
    • Talking swords can now be understood by their wielders, and everyone else.
    • -
    • Engineering cyborgs now have floor painters. Absolutely nothing bad can happen because of this.
    • -
    -

    Norgad updated:

    -
      -
    • Coated Reinforced Walls now have unique sprites
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Trash Bags fit in satchels/bags/duffelbags, but cannot be transported after being filled up.
    • -
    • Advanced Mops clean faster, can clean more
    • -
    • Holosign Projectors can create more signs
    • -
    • Ghosts can no longer create dirt
    • -
    • Dirt creation slowed down. "Clean Station" may actually be remotely possible now
    • -
    • Janitorial Closet tidied up
    • -
    • Can fill Light Replacers with boxes directly
    • -
    • Can recycle 3 broken/burnt bulbs into a functioning one
    • -
    • Can no longer cheat around NODROP by inserting NODROP lightbulbs into Light Replacers
    • -
    • Ghosts can no longer trip Proximity Sensors
    • -
    • Ghosts can no longer trip Infrared Sensors
    • -
    • Effects (like hallucinations) can no longer trip Proximity and Infrared Sensors
    • -
    • IDs are no longer dropped if their owner cryos with the ID inside a PDA inside a bag (very specific, yes)
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Allows sechailer phrases to be selectable
    • -
    • Quick-equipping a PDA will now prioritize the PDA slot before the ID slot.
    • -
    -

    taukausanake updated:

    -
      -
    • Gives proper mix_messages for Uplink, Synthignon, and Synth 'n Soda drinks
    • -
    -

    tristan1333 updated:

    -
      -
    • Spacepod paint
    • -
    - -

    08 August 2016

    -

    Ar3nn updated:

    -
      -
    • Telekinesis no longer is subject to meatspace problems
    • -
    -

    Chakirski updated:

    -
      -
    • Added animal AI holograms.
    • -
    • .45 Magazine sprites for the M1911 are now longer invisible.
    • -
    • Hoodies no longer look like labcoats while in hand.
    • -
    • Ectoplasm spawns in cult mining rooms instead of an invisible "weapon".
    • -
    • Duffel bag descriptions and names no longer contain "duffle".
    • -
    • Syndicate medical duffel bags can now be seen while in hand.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Adds a "Save" buildmode for admins to preserve their creations for later. This is currently in an early stage, so don't be surprised by errors!
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Holy Water will no longer make you stutter for ages if you're not a cultist
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes Orion Ship message being unheard when held in-hand
    • -
    • Adds headphones into the game as a loadout item
    • -
    • Removes fireproof core malf AI power
    • -
    • upgrade turrets malf AI power CPU reduced from 50 to to 30
    • -
    • Overload machine cost increased from 15 to 20
    • -
    • Override machine cost increased from 15 to 30
    • -
    • can override/overload field generators again
    • -
    • Machine uprisers will slowly die if they aren't attacking someone
    • -
    • Adds in Hostile lockdown malf AI power for 30 CPU
    • -
    • Adds break air and fire alarms malf AI powers for 50 and 25 CPU respectively
    • -
    • AI's no longer have flood mode on air alarms by default
    • -
    • Adds in lip reading malf AI power for 30 CPU
    • -
    • Allows accessories to hypothetically grant armor to their wearer
    • -
    • Greytide spear illusions actually have an attack sound now
    • -
    • fixes the wormhole event being much shorter than intended
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Walls now melt when hot
    • -
    • Added actual coated rwalls - you can make them by clicking on an existing rwall with at least 2 plasteel in hand. Has infinite temp resistance.
    • -
    • Replaced all fake coated rwalls with new rwalls in both metastation (where they should be) and boxstation
    • -
    • Bandaging someone no longer stabs your eyes with bright green
    • -
    • Fixed repainted-to-wood metal flooring in courtroom - it's now actually wood
    • -
    • Fixed windoor in witness stand facing the wrong way
    • -
    -

    KasparoVy updated:

    -
      -
    • Traitors with the Maroon objective will no longer succeed if their target is in a locker on the shuttle.
    • -
    • Traitors with the Assassination objective will no longer fail if their target is assassinated/borged/debrained but on a Z-level greater than the derelict.
    • -
    -

    Krausus updated:

    -
      -
    • Fire will now totally consume you, rather than timidly hiding under your clothes.
    • -
    • Admin freeze overlays should no longer disappear from humans until they're actually unfrozen.
    • -
    -

    LittleBigKid2000 updated:

    -
      -
    • Adds cheap sunglasses. They provide no flash protection, but are available in the loadout and clothesmate.
    • -
    -

    Pinatacolada updated:

    -
      -
    • Makes the swedish gene spit out weird swedish chars and sounds
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Fixes "is too cumbersome to carry in one hand" from showing up to other players.
    • -
    -

    Yurivw updated:

    -
      -
    • Condimaster now actually makes bottles. Removed: Unused options in admin secret menu are now removed.
    • -
    -

    chopchop1614 updated:

    -
      -
    • fix bluespace crystals exploit
    • -
    - -

    03 August 2016

    -

    Fox McCloud updated:

    -
      -
    • Fixes a rare case where the singularity would escape containment when properly set up+contained
    • -
    -

    Krausus updated:

    -
      -
    • Non-respawnable ghosts will no longer qualify for mid-round rejoining (event antags, golems, posibrains, etc). Drones, PAIs, and ERTs are exceptions to this.
    • -
    • Cryodorms will no longer produce respawnable ghosts for the first 30 minutes of the round.
    • -
    • Fixed the spooky arrival shuttle. Cryo'd ghosts will now appear above their cryo pod, in the spooky cryodorms.
    • -
    • Cryodorms will now despawn you 90% faster if you willingly enter one.
    • -
    • Suiciding in the first 30 minutes of a round will no longer allow you to ghost and be respawnable.
    • -
    • Becoming a non-respawnable ghost lasts the entire round, even if you ghost in a respawnable manner later on.
    • -
    • You can no longer spam pinging posibrains, and cannot ping them at all if you cannot volunteer for one.
    • -
    • Missing limbs will now be grayed out on your health doll.
    • -
    -

    chopchop1614 updated:

    -
      -
    • Fixed the C4 labcoat exploding bug
    • -
    - -

    01 August 2016

    -

    Crazylemon64 updated:

    -
      -
    • Admins are now able to print a map of the z levels.
    • -
    • Admins are now capable of scrambling the z levels' transitions.
    • -
    • Janiborg trash bags no longer fit down disposals when empty
    • -
    -

    Fethas updated:

    -
      -
    • (Maybe?)..We actually check if the race HAS BLOOD before trying to suck them
    • -
    • Due to various complaints from tajarans having hand cramps, glove makers have removed plasteel from the fabric.
    • -
    • Plasmaman can no longer be vampires.
    • -
    • Removes the mask check on both victim AND vampire, also makes the message a bit more obscure, so it's up to your imagination of where you are biting them and with what.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Medical stacks now have 6 uses
    • -
    • Medical stacks now heal 25 burn/brute
    • -
    • Applying a medical stack to others is instant, no matter what
    • -
    • Applying any medical stack to yourself has a 2 second delay
    • -
    • Applying a splint to yourself has a 10 second delay
    • -
    • No more RNG fumbling of putting splints to yourself
    • -
    • Confirmation for applying medical stacks is now green
    • -
    • Advanced Medkits now have 2 trauma kits, 2 burn kits, a health analyzer, 1 roll of gauze, and medipen.
    • -
    • Amount of splints in medical vendors increased from 2 to 4
    • -
    • Fixes weird icon updates when getting healed by medical kits
    • -
    • Adds in object burning system that allows things to be lit on fire
    • -
    • being on fire should heat you up a bit quicker and do a bit more damage
    • -
    • Novaflowers ignite you rather than uselessly heating you up
    • -
    • Adjusts a few pyrotechnic chems to better fit with other tweaks to fire damage
    • -
    -

    IcyV updated:

    -
      -
    • Adds a unique axe for Atmos-traitors
    • -
    -

    Krausus updated:

    -
      -
    • Probably fixed some very specific items messing up View Variables for no adequately explicable reason.
    • -
    • Fixed round-end antagonist report failing to print due to null objectives.
    • -
    -

    Kyep updated:

    -
      -
    • Added atmos grenade kit to traitor uplink.
    • -
    • Fixed bug with adv pinpointers and CMO hypospray theft objectives. Fixes #5232
    • -
    -

    TheBeoni updated:

    -
      -
    • Adds "unique" jumpsuit for Pod Pilot so they can finally stop using security one Added picture because i do not like that red label
    • -
    -

    TheDZD updated:

    -
      -
    • Shadowling ascendance and badmins pressing the "Destroy All Lights" button should no longer bring the server to its knees.
    • -
    • Broken lights will no longer re-break.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Using ATMs leaves fingerprints behind
    • -
    -

    Twinmold updated:

    -
      -
    • Nuke Ops airtank connected to pipenet now.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Readded colored cable-cuffs.
    • -
    • Making stacks of metal rods now updates the icon correctly.
    • -
    - -

    28 July 2016

    -

    A Giant-Ass Mountain of Salt updated:

    -
      -
    • Re-adds PDA slot.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Adds an explosion buildmode
    • -
    • "Drop Everything" in VV no longer causes limbs to fall to the ground.
    • -
    -

    FlattestGuitar updated:

    -
      -
    • IAAs can now select the classic secHUD in loadouts
    • -
    • adds bananas and suit jackets to the loadout system
    • -
    • adds dress shoes and fancy sandals to the loadout system
    • -
    • Miners can now get the mining coat from loadouts
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes organ repair surgery saying an organ wasn't damaged when it actually was
    • -
    • Removes the 1 burn heal from regular ointment
    • -
    • Regular bandages will now disinfect (in addition to stopping bleeding as they previously did)
    • -
    • Fixes a few crafting recipes not having the proper category
    • -
    • Fixes laser slugs not firing lasers
    • -
    • Adjusts the damage/consistency of improvised slugs
    • -
    • Adds in craftable bolas; throw them at someone to slow them down
    • -
    • Secvend starts off with e-bolas
    • -
    • Can make spears with personal crafting now
    • -
    • Fixes teacups and some other drinks having no sprite, in-hand, or object
    • -
    • adds alt-click rotating of chairs, disposal pipes, windows, the PA, emitters, and windoor assemblies
    • -
    • Cablecuffs are now made by opening the cable stack's crafting menu by using it in your hand
    • -
    • Fixes cablecuffs not having a unique in-hand icon
    • -
    • Fixes cable coils not having a unique in-hand icon
    • -
    • All cablecuffs will be red, regardless of what they're produced from
    • -
    • Fixes an unlimited metal exploit
    • -
    • IV Drip sprites updated; has visual feedback for if it's injecting or taking blood
    • -
    • IV Drip injection rate dramatically increased
    • -
    • Warning ping for when someone is low on blood
    • -
    • Support for species with exotic blood type
    • -
    • Alt-Click to toggle between modes
    • -
    • Sensory restoration virology symptom no longer has anti-stun properties nor heals brain damage, but has a lower acquisition level
    • -
    • Damage convert heals individual limbs instead of healing overall damage (actual impact is low)
    • -
    • Librarian now starts off with a bookbag
    • -
    • Bookbag can now hold Bibles, cult tomes, books, and spellbooks
    • -
    • Can empty a bookbag into a bookshelf
    • -
    • Fixes an exploit where you could generate wood out of thin air
    • -
    • Fixes blobspores doing more damage than intended
    • -
    -

    Fox-McCloud updated:

    -
      -
    • Adds in a few makeshift items/weapons: molotovs, grenade lances, golden bikehorn, paper bags, and DIY chainsaws
    • -
    • Fixes some personal crafting behaving as other than intended
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Fixed brig cell block APCs not getting power
    • -
    • Fixed space buggery Kyet made :angry:
    • -
    • Fixed missing light near labor shuttle dock
    • -
    • Fixed wrongly placed cobweb in solitary
    • -
    • Fixed basketball court not having a basketball
    • -
    • Added windows to brig processing entrance
    • -
    • Re-added the missing EOD and biohazard lockers in Armory
    • -
    • 6 gas masks from Armory
    • -
    • Added grid check into random events.
    • -
    -

    Krausus updated:

    -
      -
    • The voting panel now uses the browser datum, which means it looks nicer.
    • -
    • The voting panel now updates while a vote is in progress.
    • -
    • When a vote is started, it will now include a link to open the vote panel, as an alternative to typing in "vote".
    • -
    • Custom votes will now show full voting results upon completion.
    • -
    • Admins should no longer lose the "cancel vote" link in the voting panel.
    • -
    • View Variables should probably stop crashing admins.
    • -
    • The RnD console now shows an overlay while you're waiting for it to do work, rather than using a separate wait screen.
    • -
    • Admins now have click shortcuts for opening a player panel, showing mob info, and viewing variables. Specifics are in Hotkey Help.
    • -
    -

    Kyep updated:

    -
      -
    • Admins can now see attacks against SSD players more easily.
    • -
    • Clarified the text you get when examining a SSD player.
    • -
    • It is now possible for admins to remove a person's vamp thrall status.
    • -
    • Adds Vox, Greytide & Soviet loadouts to admin Select Equipment verb.
    • -
    • Fixes an issue with spy loadouts, and excessive access on loadouts in general
    • -
    -

    Spacemanspark updated:

    -
      -
    • Cardboard boxes now have their own specific name in the cardboard sheets menu.
    • -
    -

    TheDZD updated:

    -
      -
    • Fixes tempgun not recharging.
    • -
    • Fixes tempgun beams costing one tenth of what they are supposed to.
    • -
    • Admin-only jobs check for R_EVENT now, instead of R_ADMIN, as event-related tools should.
    • -
    • Mentors should no longer get spammed by the library checkout computer on occasion.
    • -
    • Mentors should no longer get spammed by mirrors due to body accessories.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • AI Integrity Restorers now destroy any AIs inside if they get EMP'd
    • -
    • AI Integrity Restorers can be deconstructed if broken via explosions. This kills the AI inside
    • -
    -

    Twinmold updated:

    -
      -
    • Can no longer destroy pods with anything other than brute and burn weapons.
    • -
    • Can no longer pull someone out of a pod when no one is actually in the pod.
    • -
    • Can now melee attack pods with weapons when harm intent is on.
    • -
    • Vox Objective 4 now calculates the kills vox raiders actually have, instead of always complete.
    • -
    -

    Ty-Omaha updated:

    -
      -
    • Gives Combat Gloves to Code Red ERT agents.
    • -
    • Gives Code Gamma Engineering ERT agents Combat Gloves.
    • -
    -

    monster860, clusterfack, and DeityLink updated:

    -
      -
    • Adds space parallax
    • -
    -

    tigercat2000 updated:

    -
      -
    • Removes space parallax, due to server overhead, input lag & bugs
    • -
    - -

    21 July 2016

    -

    Alffd updated:

    -
      -
    • Added a 6th Vulpkanin tail option.
    • -
    • Fixes animations, side view, and pixel fill for Vulpkanin tail 6
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Engineers can properly show up for work with their hats and coats to keep warm.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Tajarans and Unathi can now wear all shoe and glove types
    • -
    • Glove clipping removed except for black gloves, which makes them fingerless gloves
    • -
    • Adds sandals as a loadout option
    • -
    • Adds in simple animal mob spawners
    • -
    • Adds shielded hardsuit to the nuke ops uplink for 30 TC
    • -
    • Implements the powerfist and adds it to the uplink for 8 TC
    • -
    • Removed drinking glass shattering (regular bottle shattering is still a thing)
    • -
    • Captain's flask is now gold instead of silver
    • -
    • Bottles have a throwforce of 15
    • -
    • can crack eggs into drinking glasses
    • -
    • Detective's flask starts out with 30 units of whiskey
    • -
    • removes redundant object verbs that have an action button
    • -
    • Fixes up mindswap spell so it behaves more properly
    • -
    • Fixes genetic abilities action buttons not properly clearing
    • -
    • Fixes simple animals, silicons, and brains becoming perma deaf from flashbangs and other sources
    • -
    • ACTUALLY FIXES MINING APC
    • -
    • Fixes brig cell timers not having the option to flash people
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Added new syndicate item Chameleon SecHUD to uplink store, available for all antags. It can morph into various eyewear while being a flashproof sechud.
    • -
    -

    Kyep updated:

    -
      -
    • Added new syndicate costumes to "select equipment" admin verb.
    • -
    -

    TullyBBurnalot updated:

    -
      -
    • More beds outside the Operating Theaters, Pajama Wardrobes outside and inside the Operating Theaters, an extra NanoMed Vendor, one Disposal Chute per OR, table with cards
    • -
    • Sinks moved closer to Surgical Tables, moved light fixtures in the Operating Theaters, tables with surgical tools now made of glass for maximum style points and Xenomorph Larva Whack-A-Mole
    • -
    -

    monster860 updated:

    -
      -
    • Brig timer UI reopening after being closed fixed.
    • -
    - -

    20 July 2016

    -

    Allfd updated:

    -
      -
    • Added hologram fluff sprites
    • -
    -

    Ar3nn updated:

    -
      -
    • Gets rid of some weird lattices floating in mid-space
    • -
    -

    Chakirski updated:

    -
      -
    • Adds M.E. Reaper sprite.
    • -
    • AI can now choose a 32x64 reaper hologram.
    • -
    • Cigarette packs no longer show near-duplicate messages when examined.
    • -
    -

    CrAzYPiLoT updated:

    -
      -
    • Ports randomized space ruins from /tg/ station. There is a number of maps which can be spawned at any location on the empty z-level at roundstart, and up to three random ones will be chosen each round. Credits to KorPhaeron.
    • -
    • Lays the groundwork for a future lavaland implementation, if we choose to have it.
    • -
    • Adds a feature to the map loader where areas with the right var set can be distinctly initialized on map load - meaning separate APCs, and the like.
    • -
    • Using a z-level specific initialization freeze system, large elaborate maps like the cyberiad can be loaded without a single runtime, with minimal impact on the round elsewhere.
    • -
    • Adds a delete mode to the "Fill" buildmode - just alt-click for the second corner, and everything within will be removed.
    • -
    • Adds a "Jump To" function in VV, which is useful for getting an idea of what exactly you're looking at.
    • -
    • Added view count to newscaster feeds and messages.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Abductors consoles link correctly again
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • Plastic explosives are now a subtype of grenades. Shouldn't be any noticable difference for players.
    • -
    • Plastic explosives no longer use the wire datum. You may directly attach an assembly holder (Such as a remote signaller + igniter assembly)
    • -
    • Adds X-4 shaped charges, designed for breaching explosively without harming the user. Pick some up at your local nukies r us.
    • -
    • Replaces tablecrafting with personal crafting, click the hammer icon by your intent selector to use it.
    • -
    • Removes the PDA slot, your PDA can now go in your ID slot (Again).
    • -
    • You can now alt click to remove an ID from a PDA, for quick interaction while it's in your ID slot.
    • -
    • Adds an overlay for an ID while it's inserted into your PDA.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds new Bottler machine for making unique beverages! Order one from cargo today!
    • -
    • Adds 6 new drinks obtainable via the Bottler. Get brewing!
    • -
    • Grapes now can be properly juiced again, as they now have the right kitchen tag.
    • -
    • Adds effects to the Paradise Pop reagents. Drink them all to unlock their powers!
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in fans which can block atmospherics passing over them
    • -
    • All mass driver blast doors have a fan underneath them, allowing you to use them repeatedly instead of once
    • -
    • Fixes medical, security, and employment records not being displayed
    • -
    • Adds in a weather system
    • -
    • Removes most of the miner's uniform equipment from their lockers and puts it in a miner's wardrobe
    • -
    • Miners start off with a lot of their clothing equipment equipped to them
    • -
    • Miners now have unique headset sprites
    • -
    • Miners no longer have lanterns, but a seclite; they can attach this to their kinetic accelerators now
    • -
    • Miners have workboots instead of black shoes
    • -
    • Miners no longer have a default mining scanner but an advanced one that works at reduced range (5 instead of 7) and has a longer cooldown between pulses (5 instead of 3.5)
    • -
    • removed extra mining hardsuit from the outpost
    • -
    • removed medikit spam from outpost; now just a toxin kit and a regular medical kit
    • -
    • Bluespace crystals now earn you points and can be refined into bluespace polycrystal sheets
    • -
    • Spare vouchers from QM and HoP removed
    • -
    • removed armor from the fake tactical turtleneck
    • -
    • Can scan vending machines with your PDA to pay for items (if there's an ID in your PDA)
    • -
    • Sleepers no longer require a console to build, only the sleeper itself
    • -
    • Clicking on the sleeper brings up the menu that was previously brought up for the console
    • -
    • Adds in syndicate sleepers--these sleepers are not only syndie themed but also allow the user to inject chems into themselves while inside the sleepers
    • -
    • Sleepers can now inject silver sulfadiazine
    • -
    • removes cryofeeds from cryodorms and adds in 2 more cryopods
    • -
    • Fixes pre-spawned loaded belts not having proper overlays
    • -
    • nanites will no longer purge chems, but will now heal internal organ damage, attempt to mend fractures, and will no longer cure beneficial viruses
    • -
    • cold and hot drinks should now properly heat you up or cool you down (this also goes for medical reagents)
    • -
    • beer no longer reduces jitteriness
    • -
    • toxins special and antifreeze heat you up
    • -
    • banana juice and banana honk now heals monkeys
    • -
    • Fixes atrazine not killing nymphs
    • -
    • mining autoinjectors no longer poison you
    • -
    • combat hypospray now has omni+epinephrine+teporone
    • -
    • stimpack is now meth+coffee instead of meth+epinephrine
    • -
    • Cheese and synth meat amount creation scales with volume of the reaction
    • -
    • sprinkles now heals all members of sec (brig phys, sec pod pilot, magistrate, and IAA are no longer left out)
    • -
    • Fixes syndi+shielded+hos hardsuit sprite issues
    • -
    • Fixes wizard's who have a regular satchel set in their prefs winding up with none
    • -
    • Spellbooks are automatically bound to wizards at round start (no more ragin' exploitative mages)
    • -
    • Fixes mining outpost lacking an APC
    • -
    • Fixes being able to exploit and turn artificial bluespace crystals into regular bluespace crystals
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Added courtroom, left of brig.
    • -
    • Remapped brig
    • -
    • Moved prisoner processing and evidence storage to the right of brig, next to Detective's office.
    • -
    • Changed current processing to Interrogation and a hallway.
    • -
    • Re-mapped Conference and Locker rooms.
    • -
    • Lots of other minor tweaks to brig.
    • -
    • Seriously, way too many small changes to list here, go and have a look at the brig yourself.
    • -
    • Removed temp. detainment and observation from brig.
    • -
    -

    KasparoVy updated:

    -
      -
    • Wearing a suit will no longer cause runtimes due to the way suit-collars are handled.
    • -
    • The north direction sprite of the Vulpkanin 'Patch' facial hair style won't hang a pixel off the head anymore.
    • -
    -

    Krausus updated:

    -
      -
    • All admins can now see "admin log" messages.
    • -
    • Admins can now toggle "admin log" messages on or off.
    • -
    • Admins will no longer be notified about ghosted admins jumping around.
    • -
    • Beating on simple animals will no longer be twice as noisy as intended.
    • -
    • Emergency Response Teams are now usable again.
    • -
    -

    Kyep updated:

    -
      -
    • adds botany, basketball court, individual cells, library computer and more to perma. Makes it far less boring.
    • -
    • Tracking implants are now useful, showing the implanted person's general location, and health status, on prisoner consoles.
    • -
    • The NODROP flag now works correctly on jumpsuits.
    • -
    • Improved admin 'select equipment' verb. ERT option now works, costumes get IDs and proper headsets, two new costumes added, and some outfits minorly tweaked (e.g: tunnel clowns get toolbelts).
    • -
    • Prevented NPCs being made into objective targets.
    • -
    -

    LittleBigKid2000 and TullyBBurnalot updated:

    -
      -
    • Stethoscopes can now be used to tell if a person's heart or lungs are damaged, or if they have any at all. Now they're actually useful instead of telling you the obvious in a vague way.
    • -
    • Stethoscopes can no longer be used to hear the heartbeat and breathing of a person that doesn't have a heart or lungs.
    • -
    -

    Tauka Usanake updated:

    -
      -
    • Adds a Hydroponics HUD and a night vision version of it that can both be created in R&D. It provides additional details on plants in hydro trays and soil plots. Shows the health, nutrient, water, toxin, pest, and weed level of the plant as well as whenever it is ready to be harvested or is dead.
    • -
    -

    TullyBBurnalot updated:

    -
      -
    • Handless cuffing no longer possible. Can still cuff people with one hand
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Mobs with PSY_RESISTANCE are no longer valid targets for REMOTE_VIEW
    • -
    • When emagged, Photocopiers now have a cooldown if used to copy butts
    • -
    -

    Twinmold updated:

    -
      -
    • Fixes removing ID cards from laptops with the Eject ID verb.
    • -
    -

    monster860 updated:

    -
      -
    • A bunch of interfaces now use /datum/browser.
    • -
    • The ChemMaster now uses the asset cache, eliminating the enormous lag spike when you first use it. Yey!
    • -
    • Fixes the window not closing when selecting an icon for the chem-master
    • -
    • Fixes the chem master window not updating when selecting an icon
    • -
    • The chem-master icon selection window now has a 4x5 grid of icons.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Gas tanks now have an action button for accessing their interface.
    • -
    • You can now shift-click on movable HUD elements (such as action buttons) to reset them to their initial position.
    • -
    • Implants with limited uses, such as freedom implants, now delete themselves when they run out of uses.
    • -
    - -

    13 July 2016

    -

    Ar3nn updated:

    -
      -
    • Adds a silence button to newscasters, which will silence the regular update sounds
    • -
    -

    Chakirski updated:

    -
      -
    • Adds new bacon sprites.
    • -
    • Bacon can now be cooked from the grill. Just grill raw bacon.
    • -
    • Raw cutlets are now sliceable into raw bacon strips.
    • -
    • Plasma and N20 look more gassy.
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • Greys no longer speak in wingdings.
    • -
    • Greys now have a species-specific language.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Overall borg power useage has been lowered
    • -
    • Borgs who have completely run out of power can now still move around/see/talk, but they will be unable to interact with machinery/doors around them; they can still bump open doors, however. Borgs with no cell are still completely paralyzed and can't do anything.
    • -
    • IPCs are now properly impacted by space's burn damage
    • -
    • NT Rep's cane stuns for less and invokes a cooldown between use, similar to telebatons
    • -
    • Oxygen damage number changed a bit; damage is based upon volume lost more now
    • -
    • Species that have blood but are oxygen immune will now take tox damage
    • -
    • Health analyzers will now work with species with exotic blood and inform the user what type of exotic blood they have
    • -
    • Other machinery that display blood levels (op table, sleepers, advanced scanners, etc) will now work with exotic blood
    • -
    • Changeling regen will now properly restore blood if you have exotic blood fix Fixes being blurry for 20+ minutes when you were low on blood for a mere 3 minutes
    • -
    • Heart damage impacting blood volume removed
    • -
    • Nutrition draining when low on blood removed
    • -
    • Station cinematics shouldn't have inventory overlays over top of the animation
    • -
    • Station cinematics should properly clear off the screen and delete now
    • -
    • pAIs are no longer valid targets for gun turrets (like on the syndicate ship)
    • -
    • Adds in Rathen's secret, a new spell for the wizard that AoE stuns
    • -
    • Removed borg jetpacks
    • -
    • Adds in borg ion pulse system; borgs with ion pulse enabled consume extra power for each turf they move but can travel on space. Can upgrade any borg, at R&D with an ion pulse upgrade
    • -
    • Adds in cyborg self repair upgrade: very slowly repairs cyborgs at the cost of extra power. Available at R&D
    • -
    • Mining cyborg module tweaked slightly: GPS, shovel, mini welding tool and mini extinguisher added, wrench and screwdriver removed
    • -
    • reset borg module removes speed boost
    • -
    • Fixes borg's stun arm bypassing shields
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds Vox compatible versions of all jumpskirts.
    • -
    • Adds Vox compatible version of the CMO jumpsuit.
    • -
    -

    Krausus updated:

    -
      -
    • Players will ALMOST DEFINITELY never get stuck as plants anymore. I mean it this time!
    • -
    • Fixed morgue trays not updating themselves when you ghost into/out of your body.
    • -
    -

    Kyep updated:

    -
      -
    • Changed access requirement on lethal injection locker to sec access (same access required for the chair its right next to.
    • -
    • Changed access requirement on exile implant locker to armory access.
    • -
    • Ghosts no longer miss out on ERTs due to not knowing it was called, or not being able to find the verb. They are now prompted about joining an ERT when one is called.
    • -
    • Fixed a condition where 'we are assembling an ERT' message is broadcast, but no ERT is generated.
    • -
    • Typo fixes in ERT messages.
    • -
    • Entering a cryo pod, then deliberately selecting OOC->Ghost, and clicking yes on the prompt, will now instantly send you to long-term storage, removing you from the round, despawning your body, freeing your job slot, and giving a new objective to any antag that had you as a target.
    • -
    • Announcements about someone entering long-term storage via a cryopod now include that person's rank.
    • -
    • When an antag target cryos, the message the antag gets about their objectives changing is now clearer.
    • -
    -

    TheDZD updated:

    -
      -
    • Adds "salts" as a say verb for deadchat ghosts.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Universal Recorder added to NT Rep Locker
    • -
    • Box of recorder tapes added to NT Rep and IAA Locker
    • -
    • Fax Guide added to Captain, HoS, HoP, NT Rep and IAA Lockers
    • -
    • Butt copy alert added to photocopiers
    • -
    • Butt copy alert comes with *ping noise
    • -
    • Photocopiers start with 60 toner
    • -
    -

    Twinmold updated:

    -
      -
    • Vampires with sleeping carp (traitor+vampire rounds) can now suck people's blood like normal.
    • -
    -

    monster860 updated:

    -
      -
    • The ChemMaster now uses NanoUI! Yey!
    • -
    • Alerts are no broken ghostly outlines
    • -
    - -

    09 July 2016

    -

    Chakirski updated:

    -
      -
    • Adds disabled_component() to cyborgs.
    • -
    • EMPs now disable binary communication for as long as the stun time.
    • -
    • Syndicate thermal imaging glasses (mesons) can now be prescription upgraded like normal mesons.
    • -
    • Green glasses from the AutoDrobe can now be prescription upgraded.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Deepfryers are no longer arcane mysteries, and can be (de)constructed and upgraded.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Grenade have a chance to explode when the person holding them is shot
    • -
    • Flamethrowers can release their tank's contents if the person holding them is shot
    • -
    • Can no longer self-trigger blocked shield events (ie: no self-harm to trigger a reactive teleport armor)
    • -
    • Hugging someone/shaking them up bypasses shield checks (oh no, hugs of death)
    • -
    • Riot shields have a +30% chance to block thrown projectiles
    • -
    • Hunter pounces are now a thrown attack as far as shield go, and yes, can be blocked by riot shields now
    • -
    • Energy shields no longer block anything other than beam and energy projectiles
    • -
    • Being able to be pushed is based on the block chance of the item you're holding instead of it just being based on riot shields
    • -
    • Adds in cursed wizard heart, purchase it from the wizard's spell book for 1 point, but be wary of not keeping the heart beating...
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Added a bunch of new items to maint, some rare uplink gear included. (see PR for full list)
    • -
    • made gas masks, nothing and extinguishers less common in maint
    • -
    -

    Krausus updated:

    -
      -
    • Players probably won't get stuck as plants forever anymore. Probably.
    • -
    • Refactored job ban checking, which should massively reduce round start-up time.
    • -
    • Job bans/unbans will now take effect instantly, rather than at the next server restart.
    • -
    -

    TheDZD updated:

    -
      -
    • DNA injectors no longer always activate powers that are supposed to have a chance to activate.
    • -
    • Dionae can no longer activate the radiation disability, nor the run superpower except via adminbus.
    • -
    • Adds genetic instability, which causes a variety of negative effects, including toxin damage, burn damage, cloneloss, and even gibbing. Effects get worse as stability gets lower, burn damage starts below 85 stability, tox and clone below 70, and gibbing once you're below 40.
    • -
    • Adds Curse of the Cluwne touch attack spell, which wizards can pick, heavily based off of the same spell from Goonstation. Said spell adds an unremovable honk tumor to the target, gives them NODROP neon green clown gear, makes them stutter, makes them almost eternally fat, confuses them, makes them clumsy and speak in Comic Sans, and severely brain damages them. Use it on a cluwne however...
    • -
    • Fixes a bug where honk tumors would cause NODROP items to still be moved, despite being unable to be unequipped.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • Botanist access to the morgue revoked
    • -
    • Added custom messages for evil faxes
    • -
    • Added unique text body for each non-evil fax template
    • -
    • Added a "Keep up the good work" fax template
    • -
    • Added a "ERT Instructions" fax template
    • -
    • Photocopiers can be emagged
    • -
    • Emagged photocopiers deal 30 burn damage to all mobs copying their butts
    • -
    • Deconstructing Comfy Chairs yields 2 metal sheets
    • -
    • Boxes no longer allowed inside evidence bags to prevent them going into themselves
    • -
    • Monocles are now prescription upgradable
    • -
    • Monocles added to Loadout selection
    • -
    • Spinning a revolver's chamber makes a noise again
    • -
    • Revenants can actually be killed now.
    • -
    • AntagHUD activation disqualifies player from rebooted drones
    • -
    • Sergeant Ian hat now visible
    • -
    -

    Twinmold updated:

    -
      -
    • Fixes the inconsistency of getting 2 metal rods when you wirecutter a destroyed grille down to 1.
    • -
    - -

    07 July 2016

    -

    Ar3nn updated:

    -
      -
    • Adds tech levels to RnD console main menu
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Chicks no longer lose their souls (literally) when becoming adults.
    • -
    • Intercoms, fire alarms, and air alarms no longer contain internal portals to a realm of infinite cables and circuit boards.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Space lube damage removed and duration reduced from 7 to 5
    • -
    • Azide and CLF3+Firefighting foam now play a bang sound when mixed
    • -
    • Can now pet pAI's with help intent
    • -
    • Fixes sechuds and nightvision sechuds having flash protection
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Added windows and a missing firelock to Genetics/Cloning
    • -
    • Tweaked layout of Genetics slightly
    • -
    • Added photocopier to R&D.
    • -
    • Tweaked RD's office layout slightly
    • -
    • Changed access on Tcomms' external airlocks' buttons to be same as general Tcomms access
    • -
    • fixed the airless tiles in Assembly Line's windows
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds improved Vox mask/goggle sprites.
    • -
    • Adds Vox-compatible versions of most suits.
    • -
    • Adds species-fitting and icon override handling to clothing accessories and suit collars.
    • -
    • You can now open/close Clown Officer and Soldier coats.
    • -
    • Adds by-species tail hiding.
    • -
    • Tidies up and refactors the way the Captain's space helmet shows Vox hair but hides every other species'.
    • -
    • Reactive armour's sprite will now update as soon as you turn it on/off or EMP it.
    • -
    -

    Krausus updated:

    -
      -
    • Fixed borers dying in hosts who happened to be somewhere cold, such as space. Even if their host was in a space suit.
    • -
    • Fixed borers forgetting to detach from a host when it died.
    • -
    • Fixed borers being able to assume control of a dead host.
    • -
    • Fixed dead borers in a host being able to speak with the host and ghosts.
    • -
    • Fixed employees starting every shift at least 3 minutes late. You aren't getting paid to stand around, people!
    • -
    • Fixed animal beatdowns being twice as noisy as they should be.
    • -
    • Pod lock busters should now properly bust pod locks.
    • -
    • The late-stage effects of the "sensory destruction" disease symptom should now properly destroy your senses.
    • -
    • Autotraitor should now continue picking new in-game traitors, instead of picking one and dying.
    • -
    • Lacking a head no longer makes you immune to becoming a husk or skeleton.
    • -
    • Security and medical records should probably stop crashing people.
    • -
    • Altering details on an Agent ID Card will now actually update what's seen when examining the card.
    • -
    -

    Kyep updated:

    -
      -
    • Fixes NT Special Ops Officer's headset so he can correctly hear, and talk on, the Special Ops (deathsquad) channel.
    • -
    • Fixed oversight in keycard authentication devices that incorrectly treated trialmins like fullmins, resulting in situations where calling an ERT became impossible.
    • -
    • If an ERT request gets no answer for 5 minutes, admins now get a one time reminder that it was sent.
    • -
    -

    TheDZD updated:

    -
      -
    • Burst fire selection is now a proc, as it was meant to be, rather than a verb.
    • -
    -

    TullyBurnalot updated:

    -
      -
    • AI can no longer interact with IV Drips
    • -
    • Robots can no longer remove beakers/blood bags from IV Drips
    • -
    • Fixed clown door deconstruction
    • -
    • Fixed mime door deconstruction
    • -
    - -

    02 July 2016

    -

    Fethas updated:

    -
      -
    • adds comfirmation dialogs to transforms from player panel
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in laughter demons
    • -
    • Can summon laughter demons as a wizard
    • -
    • Chem master can produce instantaneous medical patches if all chems are safe
    • -
    • Can now purchase sniper rifle and associated ammo on uplink during nuke ops
    • -
    • Most melee and laser armor values halved or reduced; some bullet armor reduced slightly
    • -
    • Slowdown on most armor and spacesuits reduced by 1 (chaplain armor is still slow though)
    • -
    • Mining armor caps out at 60 melee resist as opposed to 80
    • -
    • Ling melee armor reduced; bullet and laser values buffed a bit and slowdown removed
    • -
    • Chameleon jumpsuit has a little bit of armor
    • -
    • Detective's forensic jacket now has identical armor to the native detective jacket
    • -
    • Armor penetration added to energy swords, chainsaws, scythes, and spears
    • -
    • Fixes stun batons, telebatons, and abductor batons piercing/bypassing shields
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Adds appropriate battle yells to sleeping carp
    • -
    -

    KasparoVy updated:

    -
      -
    • Engineer boots that've had their toes cut open now have a sprite.
    • -
    • Vox now have engineer workboot sprites.
    • -
    • Removes unused SWAT boot sprites that were really just copypasted jackboot sprites.
    • -
    -

    Krausus updated:

    -
      -
    • The late-join job listing is now big enough to show all the jobs at once, and organizes them into labeled categories.
    • -
    • Fixed Hotkey Help and hotkey mode toggle messages not appearing.
    • -
    • The late-join job listing will now ignore (mis)clicks for the first second after popping up.
    • -
    -

    Kyep updated:

    -
      -
    • "Loyalty" implants are now known as "Mindshield" implants
    • -
    • Admins playing CC jobs can no longer get antag status from autotraitor.
    • -
    -

    Tastyfish updated:

    -
      -
    • There's essentially a completely new space hotel map! Explorers rejoice!
    • -
    -

    TheDZD updated:

    -
      -
    • Chance for vampires to burn in the chapel has been greatly reduced (from a 35% chance down to 8% per tick).
    • -
    • Vampires do not scream from chapel/space burning until they actually start catching fire.
    • -
    • Threshold for vampires to catch fire from space/chapel burning changed from 60 health to 50 health.
    • -
    • Fire stacks from vampire burning no longer apply twice 35% of the time while below the health threshold.
    • -
    -

    VampyrBytes updated:

    -
      -
    • No more *me emoting from your corpse!
    • -
    -

    monster860 updated:

    -
      -
    • Fixes ghosts having a generic icon when darkness is toggled off
    • -
    -

    tigercat2000 updated:

    -
      -
    • There's a new tab in the character setup screen, "loadouts". This allows you to spawn with a limited number of preset items.
    • -
    • Character setup now uses #defines for the different tabs.
    • -
    - -

    28 June 2016

    -

    CrAzYPiLoT updated:

    -
      -
    • Replaced the current recycler sound with a new one.
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • Adds workboots to be worn by engineers.
    • -
    • Fixes the scanner's search functionality.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • To save on adhesive costs, Nanotrasen has stopped gluing stools to the floor. The resulting bodily injuries probably won't cost more than the glue.
    • -
    -

    Fethas updated:

    -
      -
    • you can now pick up potted plants and stealth
    • -
    -

    FlattestGuitar updated:

    -
      -
    • changes some alcohol values, the weaker ones are no longer as weak
    • -
    • refactored alcohol, you can now take short breaks between sips and still pass out in a gentlemanly manner
    • -
    • different species have different levels of alcohol resistance, check in with your bartender for more information
    • -
    • The medical HUD will now be a bit smoother. Neat.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Warden starts off with a pair of Krav Maga Gloves
    • -
    • New Steal objective: steal the warden's krav maga gloves
    • -
    • Clonepods will automatically suck in nearby meat
    • -
    • Slime processors will automatically suck in nearby dead slimes
    • -
    • Actually fixes vamp chaplains
    • -
    • Fixes clumsy check on guns not working properly, resulting in people with glasses shooting themselves in the foot
    • -
    • pAI candidates can now see who requested them
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds Yi to Vox-pidgin syllables. (Port from VG.)
    • -
    • Adds framework for icon-based skin tones. (Port from VG.)
    • -
    • Adds Vox-compatibility for all remaining eyewear.
    • -
    • Raiders now get a random skin tone and eye colour on spawn.
    • -
    • Species default hair, facial hair and head-accessory colours can now be defined.
    • -
    • Newly created Vox mobs will spawn with the same hair colour as they used to have pre-greyscaling.
    • -
    • Noir vision will no longer grey out the HUD. (Port from VG.)
    • -
    • Tails will not be coloured if the person's species doesn't have skin colour.
    • -
    • Vox hair (head and facial) have been greyscaled and can now be customized by the full colour range.
    • -
    • IPC parts from the mech fabricator won't turn IPCs invisible upon attachment anymore.
    • -
    -

    Krausus updated:

    -
      -
    • Added a custom runtime error handler.
    • -
    • Added an in-game runtime viewer.
    • -
    -

    Kyep updated:

    -
      -
    • Admins now hear boink sound when faxed, command sends ERT request, etc
    • -
    • Admins can reply to faxes via radio
    • -
    • Admins can reply to faxes with pre-written fax templates
    • -
    • Admins can reply to faxes with 'evil faxes', special faxes that have negative effects on their intended recipient (and nobody else)
    • -
    • Admins can now join as "Nanotrasen Navy Officer", and "Special Operations Officer". They spawn on adminstation and ERT office, respectively. They are not announced and do not appear on crew manifest.
    • -
    • "Select equipment" verb outfits tweaked for consistency with the above job outfits
    • -
    • Teleporter on admin station now works.
    • -
    • Added antag-only warning to bee briefcase, to reduce chances of traitors killing themselves with it.
    • -
    -

    LittleBigKid2000 updated:

    -
      -
    • Space explorer corgis can now safely explore space
    • -
    -

    Norgad updated:

    -
      -
    • Maintenance around the incinerator has been expanded.
    • -
    • Engineering maintenance finally has an APC.
    • -
    • The incinerator has been moved eastward, there is now a construction area in it's previous location.
    • -
    -

    Tastyfish updated:

    -
      -
    • Cryo tubes, sleepers, and body scanners now eject random items the occupant dropped, upon the occupant being ejected.
    • -
    -

    TheDZD updated:

    -
      -
    • Adds an adminbuse gun that fires gun mimics, you can varedit the gun's `mimic_type` var to any gun path, and it'll fire that gun as mimics. By default it fires stetchkin pistol mimics.
    • -
    • Fixes minor issues caused by some guns having text paths for power cells.
    • -
    • Fixes some runtimes and inconsistencies with the telegun and temperature gun.
    • -
    • The Tesla engine has acquired a grudge for lockers, and will now smite any in its path.
    • -
    • Unstable bluespace teleportation devices have been removed from energy guns, meaning they should no longer teleport from one hand to another when switching firing modes.
    • -
    -

    Twinmold updated:

    -
      -
    • You can once again resist borer control with the Resist verb.
    • -
    -

    VampyrBytes updated:

    -
      -
    • Emotes can now be accessed through verbs as well as say *
    • -
    • Emotes accessed through say * no longer take parameters after a -
    • -
    • Emotes now take parameters through input boxes
    • -
    • Emotes now have support for blind and deaf characters
    • -
    • Emotes now personalise messages
    • -
    • Flip can now be targeted with or without a grab
    • -
    • All emotes that are affected by being muzzled now make the user make some kind of noise
    • -
    • monkeys now have access to all the emotes that the npc tries to perform
    • -
    • Leap genetics ability lets you jump over things
    • -
    -

    monster860 updated:

    -
      -
    • UI now gets it's own plane
    • -
    • RnD console now uses NanoUI! Sweet!
    • -
    • Fixes tranquillite being outside the box in the materials list. Mimes are supposed to be trapped inside a box, not outside one.
    • -
    • Replaces the weird unicode "x" character in some design names with the actual letter "x" so that it doesn't fuck up NanoUI
    • -
    • RCD gets a UI
    • -
    • RCD-built airlocks can now receive different types and accesses.
    • -
    • You can now shift-click to examine as silicon, instead of ctrl-shift-clicking, which is something absolutely no one would guess.
    • -
    • Pulsing multiple doors' "open door" wires at the same time using a remote signaller now actually opens them at the same time.
    • -
    • Fixes wormhole projector not having an icon.
    • -
    • Wormhole projector has 0 failchance now.
    • -
    • Portals made by wormhole projectors can be removed via a multitool
    • -
    • Fixes ghost being able to request docking at trader ship consoles
    • -
    -

    tigercat2000 updated:

    -
      -
    • Ported goon HTML chat from /vg/ / Goon
    • -
    • All uses of \black have been removed
    • -
    • All uses of \icon have been replaced with bicon()
    • -
    -

    tkdrg updated:

    -
      -
    • Admins now have a verb to wipe all scripts from telecomms.
    • -
    - -

    19 June 2016

    -

    DaveTheHeadcrab updated:

    -
      -
    • Defibs now must be used within 3 minutes of death.
    • -
    • Combat defibs now induce heart attack when you stun with them (Emagged defibs have a 10^ chance to do this)
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in the ability to make latex glove balloons (cable coil+latex glove)
    • -
    • Fixes latex gloves not having an in-hand icon for the left hand
    • -
    • Telephones will now ring when activated in-hand
    • -
    • Force on telephones removed
    • -
    • The break room privacy shutters now apply to all windows in the medical break room and not just the ones out front
    • -
    • His Grace grants massive stamina regeneration
    • -
    • pre-made styptic, silver sulfadiazine, and synth flesh patches now apply instantly
    • -
    • Styptic and Burn patches now have unique icons
    • -
    • Partially fixes graffiti so it's actually visible
    • -
    -

    FreeStylaLT updated:

    -
      -
    • changed its to it's in lockbox description
    • -
    • changed \red to formatting
    • -
    • changed stetchkin's price from 9 TC to 4 TC, suppressor's from 3 TC to 1 TC
    • -
    -

    KasparoVy updated:

    -
      -
    • Secure briefcase now has the same flags, hitsounds, attack verbs, throw speed and carrying capacity as a regular briefcase. Yes, it can hold paper bins now.
    • -
    • Dethralling a Shadowling thrall that has darksight activated clears their darksight.
    • -
    -

    LittleBigKid2000 updated:

    -
      -
    • The vox raider's base is now filled with nitrogen instead of regular dusty air.
    • -
    -

    TheDZD updated:

    -
      -
    • Teaches camera assemblies the meaning of the word "respect" (for NODROP items).
    • -
    • Sates the insatiable hunger that orange shoes once had for secborg cuffs.
    • -
    • Cryodorms will no longer kick you to lobby if you have logged off when they despawn your body, they will now always ghost you.
    • -
    • The defense values on the riot armor helmet is now identical to those on the riot armor suit.
    • -
    • Knight armor (including the chaplain's crusader armor) now has a slowdown of 1 instead of no slowdown.
    • -
    -

    Twinmold updated:

    -
      -
    • Fixes being able to eat cybernetic implants so you cannot eat them/force feed them to people.
    • -
    • Lowers the range of Malfunction from 4 tiles to 2 tiles, due to ability to insta-kill IPCs/incapacitate those with mechanical hearts.
    • -
    • Lowers amount of confusion given from Revenants from 50 to 20 per Defile.
    • -
    • Sets a maximum confused amount from the Revenant's Defile ability (now 30).
    • -
    • Makes Syndicate Bombs show a more accurate time remaining until detonation.
    • -
    -

    monster860 updated:

    -
      -
    • Makes stock parts build 5x faster
    • -
    • Adds a last-second loop-back sort pipe so that items with a mail tag don't end up on the disposals conveyer, and get flushed right back around. This enables an item to be sent from anywhere on the station to anywhere else on the station without going through the disposals conveyer.
    • -
    • Fixes a bug where drones can get stuck if they have their destination set to the RD office. This also fixes the bug where attempting to send a package from the test lab always ends up in the RD office.
    • -
    -

    tkdrg, Delimusca, Aranclanos, TheDZD updated:

    -
      -
    • Gun mimics (including wand, staff, projectile guns, and energy guns) created by the staff of animation will shoot things.
    • -
    • Mimics created by the staff of animation now have googly eyes.
    • -
    • Fixes the disturbing lack of death caused by wand of death projectiles.
    • -
    - -

    12 June 2016

    -

    CrAzYPiLoT updated:

    -
      -
    • Fixed the long-lasting bug of handcuffed people keeping their chainsaws.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • No more language message-spam on roundstart
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • Adds a new icon for the detective's scanner.
    • -
    • Detectives scanner now has access to DNA and fingerprint records.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds three new chaplain weapons: pirate saber, multiverse sword, and possessed/talking sword
    • -
    • Fixes not being able to sheath the claymore in the Crusader Armor
    • -
    • Adds in a mocha drink
    • -
    • Fixes ice being unobtainable for the jobs that use it most
    • -
    • Fixes laser armor losing its reflecting ability
    • -
    • Fixes the lack of progress bars for more stack-based construction
    • -
    • Fixes Experimentor producing coffee machines instead of cups
    • -
    • Can deconvert mindslaves by removing their mindslave implant
    • -
    • Can deconvert Vampire thralls by feeding them holy water
    • -
    • Fixes mindslaves not having a HUD for the master and mindslave
    • -
    • Fixes being able to duplicate just about anything in the Experimentor
    • -
    • Fixes not being able to use tank transfer valves or one tank bombs in the Experimentor.
    • -
    • Fixes infinite-throw spam
    • -
    • Fixes being able to resist out of grabs by moving (that is to say, it'll actually work now)
    • -
    • Fixes passive grabs using the wrong HUD icon
    • -
    • Tabling duration reduced from 5 to 2
    • -
    • Can no longer wield double-bladed energy swords as a hulk
    • -
    • Fixes on map stools having the wrong offsets, making it look like you're not sitting on them
    • -
    -

    FreeStylaLT updated:

    -
      -
    • Added (Enabled) Mind Batterer for Traitors
    • -
    • Fixed uplink implant description (Said 5 when actually gave you 10 TCs)
    • -
    -

    Glorken updated:

    -
      -
    • Shifts Zeng-Hu left leg over in order to regain thigh gap.
    • -
    • Chops off a pixel on Bishop feet so that they fit into shoes.
    • -
    -

    KasparoVy updated:

    -
      -
    • Old placeholder IPC butt sprite replaced with the finished QR-code sprite.
    • -
    -

    Krausus updated:

    -
      -
    • Fixes ghosts failing to follow mobs that move in unusual ways
    • -
    • Fixed tape allowing mobs with sufficient access to move through solid objects.
    • -
    -

    Many -tg-station Coders, TheDZD updated:

    -
      -
    • Old gun code is now gone.
    • -
    • Ports the vast majority of TG's gun code and their guns (any previously unavailable guns, and newly-added guns will remain unavailable to players). Expect some changes that might not be listed here due to the sheer scope of this refactor.
    • -
    • Probably some new bugs.
    • -
    • A lot of old gun bugs.
    • -
    • Mouth suiciding with a gun no longer instantly kills you, you fire the gun at yourself at 5x damage (assuming it even did damage to begin with).
    • -
    • Mouth suicide shooting does not work on harm intent.
    • -
    • You can now bash people with guns while on harm intent instead of shooting them point-blank.
    • -
    • You can now mouth suicide other people, doing so still takes the full 12 seconds to mouth suicide, but has the same 5x damage multiplier.
    • -
    • Vox spike throwers are real guns that fire spike bullets now, instead of just being fake guns that threw spikes. They do 25 damage per hit, have 30 armor piercing, cause a 1 second stun (not the kind that drops you to the floor), and cause some bleeding. They have 2 round burst fire as well, and have 10 shots per clip. A new should should recharge every 20 or so seconds.
    • -
    • Xray lasers now have a maximum range of 15 tiles.
    • -
    • Zoomed guns now actually fire accurately while zoomed.
    • -
    • Using Suicide with guns now actually does gun-like things.
    • -
    • The clown no longer deletes guns if he fucks up with them due to being clumsy.
    • -
    • Emitters no longer become inaccurate over long ranges.
    • -
    • Power gloves now override middle-click and alt-click when worn.
    • -
    • Power gloves give a notification when worn.
    • -
    • Power gloves now have special examine text when examined by an antagonist.
    • -
    • Proto SMGs now only have a 21 shot clip.
    • -
    -

    Spacemanspark updated:

    -
      -
    • Adds the ability to make a more irritated buzz noise at people as a synthetic. The original buzz is still there.
    • -
    -

    Tauka Usanake updated:

    -
      -
    • Adds more belt icon overlays
    • -
    -

    Twinmold updated:

    -
      -
    • Nar'Sie AI Hologram and Error Sprite
    • -
    • Fixes space pod equipment variable. Can now properly install/uninstall equipment.
    • -
    • Check Seat verb no longer pulls out installed equipment.
    • -
    • You can now have a passenger in your pod if you have a passenger seat.
    • -
    -

    monster860 updated:

    -
      -
    • Adds comical implant. It is an implant that causes you to have a comic sans voice. It can be made in the protolathe using bananium.
    • -
    • The comical implant now spawns by default inside IPC clowns
    • -
    • Fixes the window getting stuck when you try to drag or resize a NanoUI window too fast with Fancy NanoUI enabled
    • -
    • Fixes a small quirk with the resize handle.
    • -
    • Fix javascript error in cargo UI
    • -
    -

    pinatacolada updated:

    -
      -
    • removes atmos tech SOP from supply SOP
    • -
    • Fixes defibing people without a heart
    • -
    • Fixes defib saying it didn't work stopping a heart attack when they do
    • -
    - -

    02 June 2016

    -

    CrAzYPiLoT updated:

    -
      -
    • Fixed a text problem in virtual gameboard description.
    • -
    • Made gameboards deconstructable and movable.
    • -
    • Added a light to gameboards. Pretty!
    • -
    -

    Crazylemon64 updated:

    -
      -
    • There will no longer be a mountain of startup runtimes when people have custom languages.
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • Removes xenobio golem rune creation sound
    • -
    • Added overlays for sec belts that reflect the items stored therein.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes Chapel and Chaplain's office not having a light switch
    • -
    • Fixes mass driver only being usable once due to weird pressure
    • -
    • Fixes chapel being overly dark near coffins
    • -
    • Fixes not being able to sheath the claymore in the Crusader Armor
    • -
    -

    IK3I updated:

    -
      -
    • crate cargo system
    • -
    • passenger seat system
    • -
    • loot box secondary cargo system (install it and your pod has a standard inventory)
    • -
    • lock busters for the CE and Armory
    • -
    • incappacitated people can't operate the door controls anymore
    • -
    • Items dropped in a pod can now be scrounged up
    • -
    • security can rip you out of an unlocked pod
    • -
    • The pod code isn't full of tumors any more
    • -
    -

    Tastyfish updated:

    -
      -
    • Holsters now have an action button while on your suit again.
    • -
    -

    monster860 updated:

    -
      -
    • Adds the following words to the AI announcer: active, airlock, alcohol, arrival, arrivals, becoming, between, blob, briefing, camp, chair, chapel, closet, cyberiad, declared, detective, diona, dock, docked, docking, docks, drask, drunk, emag, equipment, evacuation, experimentor, gateway, hail, hallway, holoparasite, honk, hull, ian, imminent, interested, intruders, kida, kidan, labor, library, mime, mimes, miner, miners, mining, n2o, nuke, office, op, operational, ops, pod, pods, poly, pun, renault, representative, runtime, scrubbers, sequencer, skree, skrek, skrell, space, spider, spiders, still, stupid, swarmer, swarmers, sword, technology, teleport, teleported, teleporter, teleporting, tesla, tool, unathi, vacant, vault, vents, vulpkanin, weld, window, windows, yet
    • -
    - -

    31 May 2016

    -

    CrAzYPiLoT updated:

    -
      -
    • Fixes potential exploits involving door remotes.
    • -
    • Adds another type of remote door control.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Allows Chaplain to select a wide new range of null rod customizations
    • -
    • Slightly increases null rod damage (15->18)
    • -
    • Fixes abductors speaking other languages
    • -
    • Fixes traitors getting less TC on some game modes
    • -
    -

    QuinnAggeler updated:

    -
      -
    • All lazarus revived mobs become valid for pet collaring
    • -
    -

    Tastyfish updated:

    -
      -
    • Adds a suicide for light tubes.
    • -
    • Progress bars, buttons, and several of the values in UI's are now animated.
    • -
    • Deconstructing glass tables now gives a stack of 2 sheets of glass.
    • -
    -

    monster860 updated:

    -
      -
    • Upgrading the experimentor will no longer reduce the chance of upgrading an item's tech
    • -
    • Guest passes can now be attached to an ID card.
    • -
    • Adds a HoP guest pass computer, which is like a normal guest pass computer, but using an ID with ID computer access will allow it to issue guest passes with any access.
    • -
    • Adds the HoP guest pass computer to the HoP office.
    • -
    • Moves the guest pass computer in robotics to RnD.
    • -
    - -

    25 May 2016

    -

    CrAzYPiLoT updated:

    -
      -
    • Adds an unread change notification.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Removes Dragon's Breath Recipe
    • -
    • Removes Ghost Chilli Juice
    • -
    • Fixes buckled flipping over someone
    • -
    -

    IK3I updated:

    -
      -
    • Sleepers, scanners, and borg chargers no longer remove you from existence when destroyed
    • -
    • Hostile mobs are no longer fooled by your clever scanner and recharger tricks
    • -
    - -

    24 May 2016

    -

    CrAzYPiLoT updated:

    -
      -
    • Adds the ability to attach signalers to bear traps. Stealthy hunting!
    • -
    -

    Crazylemon64 updated:

    -
      -
    • You can now fasten the circulators in the TEG kit with a wrench - no adminbus needed to set it up, now
    • -
    • You can now rename cassette tapes with a pen.
    • -
    • You can now wipe data from a tape from its right-click menu.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds 4 new types of fudge for the chef to make: Peanut, Chocolate Cherry, Cookies 'n' Cream, and Turtle Fudge.
    • -
    • Normal fudge recipe now uses milk instead of cream.
    • -
    • Mutant/Modified/Enhanced plants will no longer infinitely increase their name length, and instead will be simply "mutant", "modified", or "enhanced" plant as determined by the last type of modification they were subject to.
    • -
    • Bees can no longer phase through hydroponics lids, giving botanists a way to finally stem the tide of pollination.
    • -
    • Premade beeboxes now spawn with the right type of bees, specifically of the worker caste.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Donk pockets have more omnizine, but only upon fully consuming the donk pocket
    • -
    • swarmers will drop an artificial bluespace crystal on death
    • -
    • Orion Trail guards now drop an energy shield and C20R on death
    • -
    • Reviving simple animals with strange reagent will prevent them from dropping any further loot
    • -
    -

    KasparoVy updated:

    -
      -
    • Rejuvenating a mob now unbuckles them correctly (if they're buckled to something).
    • -
    • Rejuvenating a mob will no longer remove their hair.
    • -
    • Rejuvenating a mob will no longer permanently blacken their eyes.
    • -
    • Rejuvenating a mob will no longer remove their prostheses with fleshy limbs, it will just fix the prostheses.
    • -
    • Rejuvenating a mob will not remove organs/limbs belonging to other species if said organs/limbs are in the same place(s) as the mob's default organs/limbs would be.
    • -
    • Fixes a runtime when trying to flip with an object other than a grab in your hand.
    • -
    • Doing a 'cybernetic repair' procedure on the head of a disfigured IPC will re-figure them.
    • -
    • Rejuvenating a mob will only regrow organs/limbs that are missing (by comparison to the standard organs for their species).
    • -
    • The regenerate_icons proc will now update skin tone and body accessories properly.
    • -
    • Organ rejuvenation now clears disfigurement and closes open wounds.
    • -
    • Rejuvenating a mob will end all in-progress surgeries.
    • -
    • Vox get their cortical stacks back, since the non-implant ones don't interfere with the Heist game-mode.
    • -
    • Rejuvenating a long-dead or husked mob will now clear the appropriate mutations.
    • -
    -

    QuinnAggeler updated:

    -
      -
    • Species disguise variable for clothing items
    • -
    • Species disguise string, "High-tech robot," for cardborg suit and helmet
    • -
    • ABSTRACT flagged clothing items will not be displayed on examination
    • -
    -

    Tastyfish updated:

    -
      -
    • Removes n2 pills healing vox oxyloss, and o2 pills poisoning vox.
    • -
    -

    monster860 updated:

    -
      -
    • Adds the floor painter. Sprite by FlattestGuitar
    • -
    - -

    20 May 2016

    -

    Fox McCloud updated:

    -
      -
    • Fixes Chaplains being able to be vampires
    • -
    • Cryopods will now always display the occupant's name
    • -
    -

    KasparoVy updated:

    -
      -
    • Fixes a runtime with Dioneae by repathing their limbs.
    • -
    -

    QuinnAggeler updated:

    -
      -
    • Makes dehydrated space carp description more accurate and informative
    • -
    -

    monster860 updated:

    -
      -
    • Adds the permanent teleporter. Use the circuitboard on a teleporter hub to set the target before constructing it.
    • -
    - -

    17 May 2016

    -

    AugRob updated:

    -
      -
    • Add screwdriver sound when opening/closing panels on airlocks
    • -
    -

    Fox MCCloud updated:

    -
      -
    • Removes "harm" traitor objective
    • -
    • Increases non-escape/hijack/die objectives from 1 to 2
    • -
    • Tweaks available objectives to traitors a bit
    • -
    -

    Fox McCloud updated:

    -
      -
    • Players can no longer see how many players have readied up or who has readied up
    • -
    • Hulks, Shadowlings, and Golems can no longer use laserpointers
    • -
    • Adds in the ability to flip over someone with *flip
    • -
    • Fixes and improves foam to better interact with reagents
    • -
    -

    KasparoVy updated:

    -
      -
    • Refactors hair so it's on the head (organ).
    • -
    • Adjusts some Vox hair style names so they're consistent with all others.
    • -
    • Refactors Morph and the order by which options are presented.
    • -
    • Players with heads of a different species than the body will now only be able to access the head accessories, hair/facial hair styles of the head's species.
    • -
    • Fixes some typos.
    • -
    • Fixes a bug where hairgrownium made you bald and super hairgrownium only changed the hair/facial hair styles of Humans.
    • -
    • Fixes a bug where Morph wouldn't correctly set eye colour or skin tone.
    • -
    • Fixes a typo that didn't really have any negative effect on the beard organ to begin with.
    • -
    • Fixes bugs where Alopecia and Facial Hypertrichosis disease symptoms wouldn't update player sprite correctly.
    • -
    • Adds a new Vox hairstyle.
    • -
    • You can now change your head accessory (and its colour), body markings (and their colour), and body accessory if you're a species that has such things via the Morph genetic power and C.M.A. (the bathroom SalonPro Nano-Mirrors and admin verbs).
    • -
    -

    monster860 updated:

    -
      -
    • Fixes sleep() in telecomms
    • -
    • Windows can now be constructed and deconstructed using RCD's.
    • -
    - -

    10 May 2016

    -

    Crazylemon64 updated:

    -
      -
    • Ragin' Mage creation works correctly again.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds a Briefcase Full of Bees as a Botanist-only traitor item (10 TC)
    • -
    • Fixes worker bees having an insatiable desire to murder bots. (Syndi-bees still murder them though)
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Robots now slur and stutter robotically
    • -
    • Adds tape gags. Click on someone with a roll of tape to shut them up!
    • -
    -

    Fox McCloud updated:

    -
      -
    • Removes material efficiency upgrades from the mech fab and protolathe
    • -
    • Ore redemption machine sheets/points per ore scaled from 1 up to 2 (down from 1 up to 4)
    • -
    • Fixes materials exploit duplication
    • -
    • Fixes the protolathe locking up under some circumstances
    • -
    • Updates the laser cannon to be range based: the further its projectile travels, the more damage it does. Base damage greatly reduced.
    • -
    • removes fungus from mushrooms
    • -
    • adds fungus to "mold" plant
    • -
    • adds mold seeds to hydro vendor
    • -
    • bumps up ???? reagent from 1 to 5 on bad recipes
    • -
    • Adds in 3 disease: Grave Fever, Space Kuru, and Non-contagious GBS
    • -
    • Adds Reagent to cause Space Kuru and Non-contagious GBS to traitor poison bottles
    • -
    • Initropidril now has a recipe
    • -
    • Adds a number of new reagents
    • -
    • Brain burgers now contain prions instead of mannitol
    • -
    • Scientists and chemists can no longer purchase traitor poison bottles
    • -
    • random drug bottles now have a much wider range of reagents in them
    • -
    • Fixes UI On slot machine saying it costs 5 credits when it's 10
    • -
    • Fixes abductors having tails
    • -
    • Fixes traitor scissors having a different hair-cutting sound
    • -
    • Fixes simple animals not dying right away when they reach zero health
    • -
    • Fixes a few farm animals, simple xenos, and a hivebot from having incorrect health
    • -
    • Buffed health pack usage on simple animals (should heal roughly 20 damage on them, per use)
    • -
    • Emotes no longer need to be purely lowercase to work
    • -
    • Chaplain can now select a green book as his Bible
    • -
    • Adds in His Grace, a hijack-only traitor item for the Chaplain
    • -
    -

    IK3I updated:

    -
      -
    • Added key and tumbler based pod locks
    • -
    • Made Pod Locks and keys buildable in Pod Fabricator
    • -
    • Made Pod Keys recoverable from cryo
    • -
    • Added lock to Security Pod
    • -
    • Added a key for Security Pod to HoS and Pod Pilot Offices
    • -
    • New sprites for several pieces of pod equipment
    • -
    • Using a multitool on a decalock now gives usable info
    • -
    -

    NTSAM updated:

    -
      -
    • Fixes the stuttery rainbow screen for IPCs.
    • -
    • Fixes the green IPC screen.
    • -
    -

    QuinnAggeler updated:

    -
      -
    • Adds a sound emote for the Drask
    • -
    • Gives Drask the ability to eat soap
    • -
    • Adds a racial flag for the Drask
    • -
    • Makes syndicate, paramedic, clown, and EVA helmets display correctly on Drask
    • -
    -

    tigercat2000 updated:

    -
      -
    • The station blueprints can now show you where wires/pipes/disposal pipes are supposed to go.
    • -
    - -

    04 May 2016

    -

    CrAzYPiLoT updated:

    -
      -
    • Adds gameboards to bar and permabrig.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • AIs are no longer created for temporary messages.
    • -
    -

    Fethas updated:

    -
      -
    • Sniper Rifles for nuke ops.
    • -
    • you can now actually shove heads on spears again.
    • -
    • Before i removed the traitor chemist item i cleaned up the harm reaction code paths.
    • -
    -

    FlattestGuitar updated:

    -
      -
    • cheap lighters only damage your hand if you fail to properly use such a complicated contraption, not the whole body
    • -
    • ports /tg/ Foam Force guns, now you can shoot foam at your enemies /with style/
    • -
    -

    Fox McCloud updated:

    -
      -
    • Slime batteries now self-recharge.
    • -
    • Adds in door wands--control doors from range
    • -
    • Each head of staff (and the QM) starts off with a door wand to control the doors in their respective departments
    • -
    • Fixes nutrition alert icon kicking in too early
    • -
    • Adds in a new hairstyle
    • -
    • Fixes cig icons not updating under some circumstances
    • -
    • Updates the Tesla; it will now have to be "fed" or it can run out of energy; the rate at which it gains additional energy balls and power has been greatly lowered.
    • -
    • energy ball will now be drawn towards the singularity beacon
    • -
    • fuel tank explosions a bit stronger and will arc tesla blasts further
    • -
    • Tweaked some game mode population requirements to enhance general game mode balance and player experience.
    • -
    • Reworks overdosing to have more unique effects and also scale, in part, on volume
    • -
    • Epinephrine, Atropine, and Ephedrine have a lower OD threshold
    • -
    • Saline penetrates the skin
    • -
    • Synaptizine and Teporone now have OD threshold
    • -
    • Adds in berserker disease (treat with haloperidol)
    • -
    • Adds in Jenkem, a nasty gross drug made with toilet water
    • -
    • Adds in food poisoning; get it from eating poorly made food, from salmonella, or fungus
    • -
    • Adds in the Shock Revolver, a replacement for the stun revolver remove: removes the stun revolver remove: removes the prototype SMG+ammo from the protolathe
    • -
    -

    IK3I updated:

    -
      -
    • Can no longer holster items with No-Drop active.
    • -
    • Saves prosthesis users from Tox-Comp's wrath
    • -
    -

    KasparoVy updated:

    -
      -
    • Disembodied prosthetic heads that aren't monitors won't make you go bald when they're re-attached.
    • -
    • 'Optic' markings will disappear when your head gets removed, and reappear if it gets re-attached.
    • -
    • Disembodied prosthetic heads that aren't monitors will now be rendered with hair & facial hair.
    • -
    • Disembodied prosthetic heads with optical markings (markings with the head set as the origin) will be rendered with those markings.
    • -
    • Animated hair styles (e.g. screens) and head accessories (e.g. 2/3 new antennae) will now be animated properly.
    • -
    • 3 more antennae.
    • -
    • An alt. and monitor head model for every prosthetic brand but Zeng-hu. Morpheus only gets an alt model, not another monitor.
    • -
    • Animated optical markings to fit the new alt. heads.
    • -
    • Screen styles for the alt. Hesphiastos head.
    • -
    • Companies that make prosthetic body parts can (and do) now offer separate models for qualified recipients.
    • -
    • Removed the frames from screen styles in order to allow the same styles to be applied to all monitor heads.
    • -
    -

    LittleBigKid2000 updated:

    -
      -
    • Booze dispensers can now dispense synthanol
    • -
    -

    Norgad updated:

    -
      -
    • Adds a disposals chute to the Mechanic's Workshop
    • -
    -

    QuinnAggeler updated:

    -
      -
    • Adds the Drask as a 30KP race
    • -
    • Adds their language, Orluum
    • -
    • Adds a stylecolor for their language
    • -
    • Adds their butts (for photocopying)
    • -
    • Adds, at last, another race with skin tone (humies move over)
    • -
    • Adds a reason to make bad ice puns
    • -
    • Adds a check for brain death (brain damage of 120 or more) to the proc responsible for reviving IPCs
    • -
    -

    pinatacolada updated:

    -
      -
    • Makes fridge boards be selectable by screwdriving them
    • -
    • Virology fridge now accepts syringes, beakers, and bottles
    • -
    • Plasmamen security now spawn with their suit slot items in their bags
    • -
    • Pod pilots spawn with taser in the suit slot
    • -
    • removes armor from plasmamen magistrate suits
    • -
    - -

    25 April 2016

    -

    CrAzYPiLoT updated:

    -
      -
    • Adds buildable holographic gameboards that, when opened, produce a fully-functional JavaScript chess interface, which includes a chess AI. If you win, it will produce 80 tickets for your spending!
    • -
    -

    FlattestGuitar updated:

    -
      -
    • a human's species is now visible on examination
    • -
    -

    Fox McCloud updated:

    -
      -
    • Improves attack animations with items, making it more clear who's attacking you and with what
    • -
    • Updates Revolution game mode so it better scales with total player population
    • -
    • Head revs start off with a flash, spraycan, and chameleon security HUD
    • -
    • Add chameleon security hud, which is basically sec shades with the ability to disguise as a number of regular glasses
    • -
    • Updates mining loot crates to feature far more actual loot
    • -
    • Mining loot crates are now opened by inputting a 4 digit password and have 10 tries to guess the password string
    • -
    • Fixes bees, mech syringes, and darts not properly calling INGEST for a reagent
    • -
    -

    Meisaka updated:

    -
      -
    • The light on/off function for drones works again, toggling between lowest setting and off.
    • -
    • Guardians can toggle their lights off and on again.
    • -
    • AI, pAI, robots and drones can now use *yes emote without extra ss on the end.
    • -
    • emote *help for silicons updated/added.
    • -
    • *twitch_s emote changed to *twitches, incorrect variations of some emotes can no longer be used.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Added 4 new HUD styles, "Operative", "Plasmafire", "Retro", and "Slimecore"
    • -
    • You can now view HUD changes in real-time, by going to Preferences (top right tab) > Game Preferences and changing the HUD style (limited to humans).
    • -
    • There are now three HUD styles you can get via the f12 button- Full, which contains all of your buttons, Minimal, which only contains a few essential buttons, and None, which is a completely blank screen.
    • -
    • Removed the remaining aiming code due to maintainability issues and incompatibility with HUD styles.
    • -
    • Mobs with HUD's now use a unique subtype instead of an anti-OOP else-if chain.
    • -
    • Refactored how objects (IE, stuff you pick up) is rendered to the HUD. This should fix the reoccuring "stuff on my screen that definately isn't meant to be there" bug, but keep an eye out for things that do not appear.
    • -
    - -

    20 April 2016

    -

    Crazylemon64 updated:

    -
      -
    • Bureaucracy crates now contain granted and denied stamps.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Anomalies will now be properly neutralized by signals that match their code and frequency, instead of using the default frequency and their code.
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Adds shot glasses.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Removes the ability to put a pAI into securitrons and ED-209's
    • -
    • Drinking glasses now have an in-hand sprite
    • -
    • DNA injectors no longer have a delay when used on yourself
    • -
    • DNA injectors no longer delete on use, but become used, much like auto-injectors
    • -
    • Fixes a bug where you can exploit the genetic scanner to get multiple injectors
    • -
    • Fixes not being able to cancel creating an DNA injector
    • -
    • remove spacesuits causing injections to the head to take longer
    • -
    • FIxes heat resist mutation not making you immune to high pressure, fire, or high temperatures
    • -
    • removes some not-well-known damage resists from cold/heat mutations
    • -
    • Re-maps botany a bit to make it more bee and botanist friendly
    • -
    • Adds in Abductors Game Mode
    • -
    -

    MarsM0nd updated:

    -
      -
    • Embeded object removal is now done with hemostat again
    • -
    • Borgs are able to do embeded object surgery
    • -
    -

    Tastyfish updated:

    -
      -
    • Makes the server startup substantially faster.
    • -
    -

    monster860 updated:

    -
      -
    • Crowbarring open a spesspod doors is no longer broken
    • -
    -

    tigercat2000 updated:

    -
      -
    • -tg- thrown alerts have been added. This means you get an alert when buckled or handcuffed or many many other things happen to you. It then gives you a tool tip when you hover over it, and it may or may not do something when you click it. Have fun!
    • -
    - -

    14 April 2016

    -

    Aurorablade updated:

    -
      -
    • Removes the !!FUN!! of having headslugs gold core spawnable.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Added in sounds (instead of a chat-based message) for when airlocks are bolted/unbolted
    • -
    • Added in sound for when airlocks deny access
    • -
    • cutting/pulsing wires will play a sound
    • -
    • ups nuke ops game mode population requirement from 20 to 30
    • -
    • Adds in mining drone upgrade modules to increase their health, combat capability, or reduce their ranged cooldowns
    • -
    • Adds in mining drone "AI upgrade" a sentience potion that only works on mining bots
    • -
    • Mining bots should be less likely to shoot you when attacking hostile mobs
    • -
    • Killer tomatoes actually live up to their name now and are hostile mobs
    • -
    • Killer tomatoes are an actual fruit now; activate it in your hands to make them into a mob
    • -
    • Killer tomatoes are directly mutated from regular tomatoes instead of blood tomatoes
    • -
    • Increased the yield of regular tomatoes by 1
    • -
    • Tweak some stats on the killer tomato seeds
    • -
    • Fixes the blind player preference not doing anything
    • -
    • Adds portaseeder to R&D
    • -
    • Scythes will conduct electricity now
    • -
    • Mini hoes play a slice sound instead of bludgeon sound
    • -
    • Plant analyzer properly has a description and origin tech
    • -
    • Can have hulk+dwarf mutations together
    • -
    • Can have heat+cold resist together
    • -
    • Can only remotely view people who also have remote view
    • -
    • Fixes cold mutation not having an overlay
    • -
    • Hallucinations will no longer tick down twice as fast as they should nor will they spawn twice as many hallucinations as they should
    • -
    • Incendiary mitochondria no longer asks who you want to cast it on (it always is meant to be cast on yourself)
    • -
    • Fixes permanent nearsightedness even when wearing prescription glasses
    • -
    -

    KasparoVy updated:

    -
      -
    • Head accessories now behave like facial hair: They will no longer be hidden by clothing items that BLOCKHEADHAIR (have the BLOCKHEADHAIR flag).
    • -
    • Wearing a piece of clothing that blocks head hair will no longer make head accessories (facial markings/horns/antennae) invisible until an icon update is triggered while the headwear is off.
    • -
    -

    Meisaka updated:

    -
      -
    • law manager no longer freaks out with Malf law
    • -
    -

    Tastyfish updated:

    -
      -
    • The /vg/ library computer interface has been ported, giving a much better use experience.
    • -
    • Books can now be flagged for inappropriate content.
    • -
    -

    TheDZD updated:

    -
      -
    • Removes shitty Caelcode bees.
    • -
    • Hydroponics can now manage bee colonies, bees produce honeycombs that can be ground to obtain honey, a decent nutriment+healing chemical
    • -
    • Hydroponics can inject a queen bee with a syringe of a reagent to alter her DNA to match that reagent, meaning all honeycombs produced will contain that reagent in small amounts
    • -
    • Bees with reagents will attack with that reagent. It takes 5u of a reagent to give a bee that reagent.
    • -
    • Added the ability to make Apiaries and Honey frames with wood
    • -
    • Added the ability to make Royal Bee Jelly from 10 Mutagen and 40 Honey
    • -
    • Added the ability to make more Queen Bees from Royal Bee Jelly by using it on an existing Queen, to split her into two Queens
    • -
    • Removes some snowflakey mob behavior from bears, snakes and panthers.
    • -
    • Hudson is feeling punny.
    • -
    • Hostile mob AI should now be a bit more cost-efficient.
    • -
    -

    monster860 updated:

    -
      -
    • Adds area editing, link mode, and fill mode to the buildmode tool
    • -
    - -

    12 April 2016

    -

    FalseIncarnate updated:

    -
      -
    • Adjusting the setting of a vendor circuit board is no longer random, but instead provides a select-able list.
    • -
    • Vendor Circuit Board design moved from the Circuit Imprinter to the Autolathe, acid requirement replaced by metal.
    • -
    • Burnt matches can no longer light cigarettes, pipes, or joints.
    • -
    -

    Fethas updated:

    -
      -
    • Nukes the cargo train code rscadd:Adds simple vehicle framework and converts secway/janicart/snowmobiles/bikes/cars/ambulance to it rscadd:Adds space speedbike, red and blue versions, yes you WILL need a spacesuit rscadd:Maps janicart and secway onto metastation (but not ambulance no pareamedic garage, no i am not mapping that)
    • -
    • You should now be able to operate on IPC eyes, SHOULD bugfix:hopefully surgery on diona works right
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in TraitorVamp; game mode that's essentially like TraitorChan, but with a Vampire instead of a Changeling
    • -
    • Vampires cannot use holoparasites
    • -
    • Malf AI will automatically lose if it exits the station z-level
    • -
    -

    Tastyfish updated:

    -
      -
    • All cats can kill mice now.
    • -
    • E-N can't suffocate.
    • -
    • Startup time is now shorter.
    • -
    • Removed the Station Collision away mission from rotation, due to multiple conceptual and technical issues.
    • -
    - -

    07 April 2016

    -

    Crazylemon64 updated:

    -
      -
    • Removes an offset from the advanced virus stealth calculation, causing viruses to be more stealthy than the sum of their symptoms.
    • -
    • Mulebots will now send announcements to relevant requests consoles on delivery again.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds logic gates, for doing illogical things in a logical manner.
    • -
    • Adds buildable light switches, for all your light toggling needs.
    • -
    • Fixes a resource duplication bug with mass driver buttons.
    • -
    -

    Fethas updated:

    -
      -
    • maybe makes them last longer...maybe..and fixes the event end message
    • -
    -

    Fox McCloud updated:

    -
      -
    • Maps in the slime management console to Xenobio
    • -
    • Reduces Xenobio monkey box count from 4 to 2
    • -
    • Fixes weakeyes having a negligible impact
    • -
    • Can spawn friendly animals with a new gold core reaction by injection with water
    • -
    • Hostile animal spawn increased from 3 to 5 for hostile gold cores
    • -
    • Swarmers, revenants, and morphs no longer gold core spawnable
    • -
    • Fixes invisible animal spawns from gold core/life reactions
    • -
    • Adds tape to the ArtVend
    • -
    • Can no longer use sentience potions on bots
    • -
    • Added in Plasma Dust reagent, acquired by grinding plasma sheets; it's more toxic than regular plasma and generates plasma gas when spilled onto turfs.
    • -
    • Slimecore reactions now require plasma dust as opposed to dispenser plasma
    • -
    • Added in new Rainbow slime; inject with plasma dust to get a random colored slime. Acquire by having 100 mutation chance on a slime when it splits.
    • -
    • Monkey Recycler can produce different types of monkey cubes; change the cube type by using a multitool on the recycler
    • -
    • Epinephrine/plasma reagents changing mutation rate has been removed
    • -
    • Mutation chance is inherited from slime generation to slime generation as opposed to being purely random.
    • -
    • New reactions added for red and blue extracts: red generates mutator, which increases mutation chance, and blue generates stabilizer, which decreases mutation chance.
    • -
    • Slime glycerol reaction removed
    • -
    • Slime cells are now high capacity cells (more power than before)
    • -
    • extract enhancer increases the slime core usage by 1 as oppose to setting it to three
    • -
    • slime enhancer increases slime cores by 1 as opposed to setting the core amount to 3
    • -
    • Chill reaction lowers body temperature slightly more so it doesn't just wear off instantly
    • -
    • Reduces Xenobio plasma sheets from 8 to 3 and removes that pesky boombox
    • -
    • Processors no longer produce 1 more slime core than intended
    • -
    • Less blank/spriteless/empty foods from the silver core reaction
    • -
    • Virology mix reactions now use plasma dust as opposed to plasma
    • -
    • Statues can no longer move/attack people unless they're in total darkness or all mobs viewing them are blinded
    • -
    • statues are invincible to anything other than full out gibbing.
    • -
    • Statues flicker lights spell range increased
    • -
    • Blind spell no longer impacts silicons
    • -
    • Fixes statues being able to attack/move whenever they feel like it, regardless of client statues
    • -
    • Fixes blind spell impacting the statue
    • -
    -

    Tastyfish updated:

    -
      -
    • Beepsky is no longer a pokemon.
    • -
    • pAI-controlled Bots now reliably speak human-understandable languages over the radio.
    • -
    • More floor blood for the blood gods. (Or rather, as much as there was supposed to be.)
    • -
    -

    tigercat2000 updated:

    -
      -
    • Items in your off hand will now count towards access.
    • -
    - -

    02 April 2016

    -

    Crazylemon64 updated:

    -
      -
    • Metal foam walls will now produce flooring on space tiles
    • -
    • Syringes will now draw water from slime people.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Let's you know when your container is full when filling from sinks.
    • -
    • Prevents splashing containers onto beakers and buckets that have a lid on them.
    • -
    • Pill bottles can now be labeled with a simple pen.
    • -
    • Beakers/buckets (and pill bottles) now accept 26 character labels from pens.
    • -
    -

    Fethas updated:

    -
      -
    • Various spells have had a tweak to stun/reveal/cast, some other number stuff...
    • -
    • Nightvision
    • -
    • harvest code is now in the abilites file.
    • -
    • New fluff objectives
    • -
    • Hell has recently remapped its blood transit system and you can now once again crawl through blood. We are sorry for the-GIVE US YOUR SOUL!
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Alcoholic beverages now have proper levels of ethanol in them. Good luck passing out after a beer.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in the Lusty Xenomorph Maid Mob; currently admin only.
    • -
    • Fixes xenomorph brains having the wrong sprite, no origin tech, and incorrect name
    • -
    • removes xenomorph egg from hotel
    • -
    • upgrades are no longer needed to for the available toys in the prize vendor
    • -
    • Implements Advanced Camera Consoles. A type of camera console that function like AI's vision style. Non-buildable/accessible.
    • -
    • Adds in Xenobiology Advance Cameras. A type of camera console that functions like advanced cameras, but only works in Xenobiology areas; can move around slimes and feed them with the console as well. Also non-buildable/accessible (for now).
    • -
    • Adds in cerulean slime reaction that generates a single use blueprint. On use it colors turfs a lavender color
    • -
    • Adds disease1 outbreak event
    • -
    • Adds appendecitis event
    • -
    • Roburgers now properly have nanomachines in them
    • -
    • Re-adds nanomachines
    • -
    • Experimentor properly generates nanomachines instead of itching powder
    • -
    • Fixes big roburgers having a healing reagent in them
    • -
    • Adds nanomachines to poison traitor bottles
    • -
    • Tajarans can now eat mice, chicks, parrots, and tribbles
    • -
    • Vulpkanin and Unathi can now eat mice, chicks, lizards, chickens, crabs, parrtos, and tribbles
    • -
    • fixes spawned changeling headcrab behavior
    • -
    -

    KasparoVy updated:

    -
      -
    • Incisions made at the beginning of embedded object removal surgery can now be closed in the same procedure.
    • -
    -

    ProperPants updated:

    -
      -
    • Maint drones have magboots.
    • -
    • Removed plastic from maint drones. Literally useless for station maintenance.
    • -
    • Increased starting amounts of some materials for maint drones and engi borgs.
    • -
    • Reduced the number of lines taken by Engineering cyborgs calling on materials stacks.
    • -
    • Operating tables can be deconstructed with a wrench.
    • -
    • Fixed and shortened description of metal sheets.
    • -
    -

    Tastyfish updated:

    -
      -
    • Bots can now be controlled by players, by opening them up and inserting a pAI. *beep
    • -
    • MULEbots can now access the engineering destination.
    • -
    • All MULEbot destinations should now have the correct load/unload direction, meaning the crates won't be dumped inside the flaps.
    • -
    • Diagnostic HUD's now give health and status information about bots.
    • -
    • MULEbot rampage blood tracks are now rendered correctly and handle UE traces as appropriate.
    • -
    • Bots should (hopefully) lag the game less now.
    • -
    • Beepsky contains 30% more potato.
    • -
    • Action progress bars are now smooth.
    • -
    • Clicking a filled inventory slot's square with an open hand now clicks the item in the slot.
    • -
    • Status displays now display the time when in Shuttle ETA mode and no shuttle activity is happening.
    • -
    • Shuttle ETA countdowns on status displays are now amber.
    • -
    • pAI's can now use the PDA chatrooms.
    • -
    • Adds treadmills to brig cells, to give the prisoners something productive to do.
    • -
    -

    TheDZD updated:

    -
      -
    • A lot of the guns and armor in the station collision, space hotel, academy, and wild west away missions have been removed/replaced.
    • -
    • Removes that fucking facehugger from station collision.
    • -
    -

    tigercat2000 updated:

    -
      -
    • Virus2 has been removed.
    • -
    • Virus1 is back. Viva la revolution.
    • -
    • You can now have up to 20 characters.
    • -
    - -

    26 March 2016

    -

    Fox McCloud updated:

    -
      -
    • Adds in dental implant surgery. Implant pills into people's teeth.
    • -
    • Major rebalance and Shadowling update (https://github.com/ParadiseSS13/Paradise/pull/3986 for details). In general, Shadowlings can no longer enthrall or engage in Shadowling like behavior, pre-hatch. Post-hatch, shadowlings are much more powerful, with a ride array of New abilities such as extending the shuttle or making thralls into lesser shadowlings. Shadowling gameplay should not revolve almost entirely around darkness, as opposed to pre-hatch shenanigans.
    • -
    • Robotics now has a "sterile" surgical area for performing augmentations
    • -
    • Adds the FixOVein and Bone Gel to the autolathe
    • -
    • ensures all surgical tools have origin tech on them; lowers origin tech on FixoVein
    • -
    -

    KasparoVy updated:

    -
      -
    • Slime People can now wear underwear.
    • -
    • Slime People can now wear undershirts.
    • -
    -

    TheDZD updated:

    -
      -
    • NT has removed trace amounts of a highly-addictive substance from the "100% real" cheese used in cheese-flavored snacks. As a result, incidence rates of crewmembers becoming addicted to Cheesie Honkers should reduce to zero.
    • -
    • After receiving complaints about crewmembers often being unable to physically function without a back-mounted barrel of coffee, NT has replaced station all sources of coffee on the station, including coffee beans themselves with a largely decaffeinated version. It was funny the first time almost every crewmember aboard the NSS Cyberiad was lugging around their own oil barrel filled with coffee, it wasn't so funny, nor good for productivity the eighteenth.
    • -
    - -

    25 March 2016

    -

    Crazylemon64 updated:

    -
      -
    • You now will actually have the correct `real_name` on your DNA.
    • -
    • No more roundstart runtimes regarding IPC hair.
    • -
    • Mitocholide rejuv will work more usefully now.
    • -
    • Limbs and cyborg modules will no longer appear in your screen.
    • -
    • Cyborg module icons are now persistent throughout logging in and out.
    • -
    • Various cyborg modules, like engineering, now use the proper icon.
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Adds confetti grenades.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes Sleeping Carp combos not having an attack animation
    • -
    • Fixes several chems not properly healing brute/burn damage, consistently, as intended
    • -
    -

    KasparoVy updated:

    -
      -
    • Unbranded heads and groins no longer invisible.
    • -
    • Zeng-hu left leg will now be in line with the body when facing south.
    • -
    - -

    22 March 2016

    -

    Crazylemon64 updated:

    -
      -
    • Repairs all sorts of eldritch occurences that happen when you put an organic head on an IPC body, as well as some decapitation bugs
    • -
    • Makes heads keep hair on removal
    • -
    • Amputated limbs from a DNA-injected individual now will keep their appearance of the DNA-injected person
    • -
    • Wounds will vanish on their own now
    • -
    • Admins now have an "incarnate" option on the player panel when viewing ghosts for quick player instantiation
    • -
    • Fixes a runtime regarding failing a limb reconnection surgery
    • -
    • Copying a client's preferences now overrides the previous mob's DNA
    • -
    • A DNA injector is now more thorough, and affects the DNA of mobs' limbs and organs
    • -
    • DNA-lacking species can no longer be DNA-injected
    • -
    • Brains are now labeled again
    • -
    • Splashing mitocholide on dead organs will make them live again.
    • -
    • The body scanner now detects necrotic limbs and organs.
    • -
    • pAIs and Drones are now affected by EMPs and explosions while held.
    • -
    -

    Fethas updated:

    -
      -
    • Adds a surgery for infection treatmne/autopsys that is simply cut open, retract, cauterize
    • -
    • fixes a dumb error in internal bleeeding surgerys
    • -
    • Chaos types no longer random teleport, but will make the target hallucinate everyone looks like the guardian.
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Adds a snow, navy and desert military jacket.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Removes random 1% chance to heal fire damage
    • -
    • Removes passive healing from resist heat mutation
    • -
    • Regen mutation heals every cycle (albeit less, on average), but doesn't cost hunger
    • -
    • Fixes not being able to speak over xeno common or hivemind when you receive the Xeno hive node
    • -
    • Adds in the ability to transfer non-locked metal+glass only designs from the protolathe to autolathe
    • -
    • Changes Outpost Mass Driver to prevent accidental spacings
    • -
    • Shadow people no longer dust on death, are rad immune+virus immune, and can be cloned. Slip immunity removed
    • -
    • Shadowlings no longer get hungry or fat and no longer dust on death
    • -
    -

    KasparoVy updated:

    -
      -
    • The ability to change your head, torso and groin as an IPC in the character creator. Non-IPCs cannot access the parts.
    • -
    • Head, torso and groin sprites for all mechanical limb/bodypart brands but Morpheus and the unbranded ones (since those already exist) from Polaris.
    • -
    • Faux-eye optics for non-Morpheus heads.
    • -
    • The ability to change optic (eye) colour if you've got a non-Morpheus head.
    • -
    • The ability to choose human hair styles (wigs) and facial hair styles (postiche) with non-Morpheus heads. Non-Morpheus heads cannot choose screens. Conversely, Morpheus heads cannot choose wigs or facial hair.
    • -
    • Two hair styles from Polaris.
    • -
    • The ability for IPCs to wear undergarments (shirts and trousers).
    • -
    • Antennae (colourable) for IPCs.
    • -
    • IPC monitor adjustment verb will now adjust optic colour if the head is non-Morpheus.
    • -
    • Combat/SWAT boots can now be toecut and jacksandals can't.
    • -
    • ASAP fix to what would've broken the ability to configure prostheses in character creation.
    • -
    • Adjusted masks no longer block CPR (including bandanas).
    • -
    • You can no longer run internals from adjusted breath masks (or airtight adjustable masks in general).
    • -
    -

    Regens updated:

    -
      -
    • Robotic hearts will now properly give the mob a heart attack instead of just damaging it when EMP'd
    • -
    • Assisted organs will now also take damage from EMP's
    • -
    • Internal robotic and assisted organs will now actually take damage from EMP's
    • -
    -

    Tastyfish updated:

    -
      -
    • Adds PDA chatrooms. Post memes! Talk to your fellow collaborators! Get caught!
    • -
    • You can now set the PDA messenger to automatically scroll down to new messages.
    • -
    • Pet collars now act as death alarms and can have ID's attached to them.
    • -
    • All domestic animals can now wear collars.
    • -
    • You can now make video cameras at the autolathe.
    • -
    -

    TheDZD updated:

    -
      -
    • Fixes an instance of old code being so incredibly, unbelievably, makes-me-want-to-stab-myself-in-the-eye-edly idiotic.
    • -
    -

    TravellingMerchant updated:

    -
      -
    • Kidan have new sprites!
    • -
    -

    tigercat2000 updated:

    -
      -
    • Nukeops now have an assault pod, they can use it for 30 TC. Loud and mean.
    • -
    • Lighting overlays can no longer go below 0 lum_r/g/b
    • -
    • Shuttles will work with lighting better.
    • -
    • Wizards can no longer teleport to prohibited areas such as Central Command.
    • -
    - -

    16 March 2016

    -

    Crazylemon64 updated:

    -
      -
    • Being in godmode now makes you immune to bombs
    • -
    • Science members now get compensated when they ship tech disks to centcomm.
    • -
    • Science crew are no longer paid when they "max" research.
    • -
    • Roboticists now get credit for making RIPLEYs and Firefighters
    • -
    • Slime people can now regrow limbs on a more lax nutrition requirement
    • -
    • Enhances the nutripump+ to let slime people regrow limbs with it active
    • -
    • Skeletons, slime people, IPCs, and Diona no longer leave blood when hit
    • -
    • Rejuvenating a slime person will no longer clog up their "blood"
    • -
    • Slime people will now regenerate "blood" from having water in their system
    • -
    • The decloner can now be created again
    • -
    • Environment smashing mobs can now destroy girders.
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • Removes the check for species on the update_markings proc.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Xeno-botany is now more user-friendly, and less random letters/numbers.
    • -
    • Hydroponics now has a connector hooked up to the isolation tray and a new connector in their back room for those strange plants that like spewing plasma or eating nitrogen.
    • -
    • You can now (finally) build the xeno-botany machines, and science can print off their respective boards.
    • -
    -

    Fethas updated:

    -
      -
    • Syringes are no longer sharp
    • -
    • byond likes direct pathing so item/organ/internal not item/organ even if it shouldn't be in the internal_organs list. This was preventing the list from doing stuff correctly.
    • -
    • fixed ipc organ manipulation surgery, you can now insert a replacment ipc organ directly instead of needing a screwdriver in your main hand
    • -
    • nanopaste now will repair organs with robotic >= 2 instead of > 2 cuase i am an idiot
    • -
    • Fix, hopefully, for a runtime for clientless mobs whos head are cut off...
    • -
    • Hopefully fixes issues with diona eyes
    • -
    • Though shalt not eat robotic organs..including cybernetic implants..
    • -
    • ITS SURGERY_STEP/DETHRALL NOT SURGERY_STEP/INTERNAL/DETHRALL
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Adds three new synthanol drinks
    • -
    • Drinking synthanol is now a bad idea if you're organic
    • -
    • A glass of holy water now looks like normal water
    • -
    -

    Fox McCloud updated:

    -
      -
    • Adds in drink fizzing sound
    • -
    • Drink/bartender recipes use this new fizzing sound in addition to a few other recipes
    • -
    • Adds in a fuse burning sound
    • -
    • Bath salts, black powder, saltpetre, and charcoal use this sound now
    • -
    • Adds in a matchstrike+burning sound
    • -
    • Lighting a match triggers this new sound
    • -
    • Adds in scissors cutting sound
    • -
    • Cutting someone's hair uses this new sound
    • -
    • Adds in printer sounds
    • -
    • printing off papers from various devices typically uses these sounds
    • -
    • Adds computer ambience sounds
    • -
    • black box recorder and R&D core servers both play this sound at random rare intervals
    • -
    • Reduces the tech level (and requirement) for nanopaste
    • -
    • Reduces the tech level (and requirement) for the plasma pistol
    • -
    • Removes Nymph and drone tech levels
    • -
    • Reduces tech levels on the flora board
    • -
    • Adds tech level requirements to mech sleepers, mech syringe guns, mech tasers, and mech machine guns
    • -
    • Increases tech cost of the decloner
    • -
    • Removes the pacman generators
    • -
    • Removes emitter
    • -
    • Removes flora machine (functionless anyway)
    • -
    • Removes the pre-spawned nanopaste
    • -
    • Removes space suits
    • -
    • Removes excavation gear
    • -
    • Replaces the soil with actual hydroponic trays (more aesthetic than anything)
    • -
    • Removes most external asteroid access from the station
    • -
    • Excavation storage is now generic science storage
    • -
    • removed the plasma sheet
    • -
    • Fixes augments not showing up in R&D unless specifically searched for
    • -
    • Fixes some augments being unavailable in mech fabs
    • -
    • Fixes augments having no construction time
    • -
    • Fixes xenos not gaining plasma when breathing in plasma
    • -
    • Fixes plasma reagent not generating plasma for a person
    • -
    • Screaming has different sounds based on being male or female
    • -
    • Implements Goon's screaming sounds.
    • -
    • Screaming tone is now based on age of character instead of being random
    • -
    • Ups the cooldown on screaming from 2 seconds to 5 seconds
    • -
    • Removes chance for Whilhelm scream
    • -
    • Borgs can now scream
    • -
    • Monkey's now have a unique screaming sound
    • -
    • IPCs now scream like cyborgs
    • -
    • Updates slot machines to have higher jackpots and more payouts with more interesting sounds
    • -
    • Adds X-Ray, Thermal, Anti-tun, and Reviver implants to the nuke ops uplink (augments come with one auto-implanter) rcsadd: Adds in augment auto-implanter, which inserts and implant without surgery
    • -
    • tweaks a large number of chems; behaviors are largely retained, but new flavor messages, probabilities, etc may be present; overall, you can expect chems to do the same thing
    • -
    • Tabun re-replaced with Sarin rcsadd: New reagent: cholesterol: if overdosed on, it can cause a heart attack--fatty foods, cheese, eggs, and some meats all produce cholesterol in your body.
    • -
    • Mixing Sarin, Meth, or Cyanide will poison in a very small area of the reaction if you're not on internal OR not wearing a gas mask
    • -
    • Chemist warddrobe now has two gas masks
    • -
    • Teslium will now impact synthetics AND organics
    • -
    • Fixes facehuggers hugging already infected people
    • -
    • Fixes facehuggers hugging people while dead
    • -
    • Fixes Embryo's developing twice as fast as they should
    • -
    • Fixes up some behaviors with xeno eggs
    • -
    • Xeno acid can now melt through floors and the asteroid
    • -
    • Xeno's now play the gib sound when actually gibbed
    • -
    • Implements Changeling headcrabs/headspiders
    • -
    • Fixes xenos not throwing their organs when gibbed
    • -
    • Fixes swallowed mobs not being ejected when a human is gibbed
    • -
    • Adds in spider eggs reagent, an infectious reagent that requires surgery to correct
    • -
    • Fixes EMPs causing eye implant users to be permanently blind
    • -
    • Increases bag of holding's storage capacity
    • -
    • Removing a heart no longer kills the patient instantly, but induces a heart attack
    • -
    • Demon hearts will not work
    • -
    • Should now actually be able to re-insert hearts
    • -
    • Reworks addictions to bettter differentiate them betweeen overdosing and make them more realistic.
    • -
    • changes which chems are addictive, currently, the follow reagents are now addidctive: meth, crank, krokodil, bath salts, space drugs, perfluoradecalin, omnizine, coffee, nicotine, fliptonium, ultra lube, surge, fake cheese, weird cheese, ephedrine, diphenhydramine, teporone, and morphine
    • -
    • sleepers help you recover from addiction faster
    • -
    • Can now make cable coils in autolathes
    • -
    • Fixes the slot machine announcements not displaying properly
    • -
    -

    Tastyfish updated:

    -
      -
    • The super fart mutation now gives you a spell-like ability instead of augmenting the emote.
    • -
    • Vampire abilities are now in their own Vampire tab, as well being action buttons at the top, like spells.
    • -
    • Cloning a vampire no longer makes them lose their abilities.
    • -
    • Vampires can no longer hypnotize chaplains.
    • -
    • Being a full vampire (500+ total blood) actually makes you immune to holy water reliably now.
    • -
    • Some old away missions are back: Academy, Black Market Packers, Space Hotel, Station Collision, and Wild West. Go out and round up some hostiles!
    • -
    • Shuttle consoles now pair up to the engineering, mining, research, or labor shuttle when built or used before pairing, as long as the shuttle is near the console, or the shuttle is moved to be nearby.
    • -
    -

    monster860 updated:

    -
      -
    • Mining station now has a podbay.
    • -
    • Ore scooping module for the spacepod.
    • -
    • Three mining lasers for spacepod: Basic, normal, and burst.
    • -
    • Shooting weapons south or west of spacepod will actually hit adjacent targets now, and won't shoot through walls anymore.
    • -
    -

    taukausanake updated:

    -
      -
    • Mice can now be picked up like diona
    • -
    - -

    08 March 2016

    -

    Crazylemon64 updated:

    -
      -
    • Slime people are now more vulnerable to low temperatures.
    • -
    • Slime people are able to slowly regrow limbs at a high nutrition cost.
    • -
    • Slime people now slowly shift color based on reagents inside of them - disabled by default, toggle it with an IC verb
    • -
    • Slime people's cores are more vulnerable to damage
    • -
    • Species-related abilities now properly are removed - no more vox hair stylists, unfortunately.
    • -
    -

    Fethas updated:

    -
      -
    • the nest buckle now looks for the right organ path
    • -
    • Fixed some sprites.
    • -
    • No more putting no drops in rechargers,
    • -
    -

    Fox McCloud updated:

    -
      -
    • Implement's goon's gibbing sound
    • -
    • Implement's goon's gibbing sound for robots/silicons
    • -
    • Removes old gibbing sound
    • -
    -

    Spacemanspark updated:

    -
      -
    • Lazarus Injector's can now be emagged to activate their special features, alongside using EMPs on them.
    • -
    -

    Tastyfish updated:

    -
      -
    • Mimes now have a new ore, Tranquillite, used to bring peace and quiet to the station.
    • -
    • There are also permanent invisible walls and silent floors that can be made from tranquillite.
    • -
    • The Recitence mech is now buildable!
    • -
    • The Recitence mech is now playable!
    • -
    • Mid-round selection for various creatures and antagonists now consistently asks permission.
    • -
    -

    TheDZD updated:

    -
      -
    • Adds justice helmets with flashing lights and annoying sirens.
    • -
    • Adds crates containing said helmets.
    • -
    • Also includes a version of the helmet that can only be spawned by admins, and just has a single red light in the center instead of the stereotypical police blinkers.
    • -
    -

    monster860 updated:

    -
      -
    • Space pod transitions are now fixed.
    • -
    - -

    07 March 2016

    -

    Crazylemon64 updated:

    -
      -
    • People with VAREDIT can now write matrix variables
    • -
    • People with VAREDIT can now modify path variables
    • -
    • Refactors the variable editor code somewhat.
    • -
    • The buildmode area tool now shows reticules of what you've selected.
    • -
    • Switching mobs while using the buildmode tool no longer screws up your UI.
    • -
    • Refactors buildmode so it's no longer a special-case system.
    • -
    • Adds a copy mode to build mode, which lets you duplicate objects.
    • -
    • Any mob in buildmode can work at the fastest possible rate.
    • -
    • Fixed a problem where the icons of a person would not correctly update when changing gender.
    • -
    • One's hairstyle only adjusts on gender change if it's incompatible with your new gender.
    • -
    • Fixed a bug where a person's icon would only be updated if their sprite had a new layer added or removed.
    • -
    • You no longer lose your name when monkeyized and reverted - you'll still look like a monkey while you're a monkey, though.
    • -
    • Your organs will now match your gender when you are cloned.
    • -
    • Skeletons (when a body rots) no longer retain a fleshy torso.
    • -
    • Putting people in an active cryotube now produces the message on insertion, rather than release.
    • -
    • An EMP'd cloning pod will now display its sprites correctly.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Water Balloons can be filled from more sources than just beakers and watertanks.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes the "yeah" glasses so the sound doesn't vary and a message is displayed, on use
    • -
    • Noir mode only activates when the glasses are equipped to your actual eyes
    • -
    • Noir Glasses mode can be toggled on or off (defaults to off)
    • -
    • Mimes can no longer use spells and continue speaking
    • -
    • Mime abilities are now spells with proper icons
    • -
    • Mime wall now last 30 seconds, up from 5
    • -
    • forecfields/invisible walls now block air currents
    • -
    • Adds the Sleeping Carp scroll to the uplink for 17 TC
    • -
    • Fixes Shadowlings being able to use guns
    • -
    • Fixes sleeping carp scroll users being able to use guns
    • -
    • Fixes the Experimentor throwing one item at a time
    • -
    • Experimentor menu now automatically refreshes after use
    • -
    • Lowers surgery times across the board
    • -
    • Removes scalpels causing 1 damage on successful surgery
    • -
    • Removes random chance to fracture ribs on a successful surgery
    • -
    • Mining drills now have an edge
    • -
    -

    KasparoVy updated:

    -
      -
    • Jackets who have the verb available but are not intended to be adjusted will not have the action button available.
    • -
    • You can now adjust breath masks while buckled into beds and chairs.
    • -
    • Known issues with adjusted jackets using the wrong sprites.
    • -
    • Blueshield coat in hand and item icons.
    • -
    • Hulks now rip apart adjustable and droppable jackets. The items stored in the jackets get dropped on the ground.
    • -
    -

    Tastyfish updated:

    -
      -
    • Infrared emitters can now be rotated while already in an assembly via the UI popup.
    • -
    • The infrared emitter can no longer be hidden inside of boxes and still work.
    • -
    • The beach now has a border and is splashier.
    • -
    • Gives Psychiatrist a paper bin, clipboard, and multicolored pen.
    • -
    • Gives the Librarian / Jouralist a multicolored pen.
    • -
    • Gives the NT Representative a clipboard.
    • -
    • The ethanol-based neurotoxin drink is now called Neuro-toxin to avoid being confused with the deadly toxin.
    • -
    -

    VampyrBytes updated:

    -
      -
    • Fixes emotes ending with s needing 2. Emotes now work with grammatical options eg ping or pings, squish or squishes
    • -
    • Updated emote help with missing emotes. Help will also show any species specific emotes for your current species
    • -
    - -

    26 February 2016

    -

    FalseIncarnate updated:

    -
      -
    • Chocolate can now make you fat, as expected.
    • -
    -

    Fox McCloud updated:

    -
      -
    • stamina damage now regenerates slightly faster
    • -
    • Adds in whetstones for sharpening objects
    • -
    • Kitchen vendor starts off with 5 salt+pepper shakers
    • -
    • Can now point while lying or buckled
    • -
    • Fixes Capulettium Plus not silencing
    • -
    • Fixes slurring, stuttering, drugginess, and silences last half of what they should
    • -
    -

    KasparoVy updated:

    -
      -
    • Jackets that start open are recognized as actually being open already now. This fixes a bug with certain items that don't have an open state, or cases where it ended up giving an item the wrong icon (one that didn't exist)
    • -
    -

    Spacemanspark updated:

    -
      -
    • Fixes synthetics from giving off the proper message in the chat box when using the *yes and *no emotes.
    • -
    -

    Tastyfish updated:

    -
      -
    • Wheelchairs, janicarts, and ambulances can now go through doors according to the user's driver's access.
    • -
    - -

    24 February 2016

    -

    Crazylemon64 updated:

    -
      -
    • The defib should be more reliable on people who have ghosted
    • -
    • The defib will now give a message if the ghost is still haunting about
    • -
    • Attacking someone with an accessory will now let you put things on them without having to strip them.
    • -
    • Borers will now properly detach upon death of a mob they are controlling
    • -
    • Borers can now see their chemical count while in control of a mob
    • -
    • Borers can now silently communicate with their host - this is not available to the host until the borer has either begun to communicate, or has taken control at least once - this is to avoid spoiling that the borer exists
    • -
    • Borers won't be able to talk out loud inside of a host, by default - they can remove this safeguard with a verb under their borer tab. Borer hivespeak is unaffected.
    • -
    • Borers infesting and hiding are now silent.
    • -
    • Made borer's chem lists more nicely formatted
    • -
    • No more superspeed attacking simplemobs
    • -
    • New players now show up properly under the "who" verb when used as an admin
    • -
    • Mining drones will now automatically collect sand lying around
    • -
    • RIPLEYs can now drill asteroid turfs for sand
    • -
    • You can now load exosuit fuel generators with items containing their material - this means you can fuel yourself off of ores, but this will be highly inefficient and cost you mining points later on, as you can't take fuel back out.
    • -
    • You can now load the fuel generators from an ore box.
    • -
    • The plasma generator now produces 3x as much power from the same amount of fuel - this lets it even remotely compete with the uranium generator.
    • -
    • You can now light cigarettes off of burning mobs.
    • -
    • Exosuit tracking beacons now fit in boxes - prior, they were far too large for even a backpack, as they shared the same size as all other mecha equipment
    • -
    • Miners can now collect ore by walking over it with an ore satchel on.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds prize tickets as a replacement for physical arcade prizes.
    • -
    • Adds a buildable prize counter to exchange tickets for prizes.
    • -
    • Adds a bike. Despite what Prof. Oak might claim, you can ride it indoors.
    • -
    • Adds colorful wallets, for that old school arcade pride.
    • -
    • Fixes accidental removal of plump helmet biscuit recipe.
    • -
    • Temporarily adds a prize counter to the bar (Cyberiad) or dorms (MetaStation), and adds a max upgrade one to the Ninja Holding Area (Cyberiad z2)
    • -
    • Fixes Metastation. Seriously fixed a lot, just read the PR description for the full list.
    • -
    -

    FlattestGuitar updated:

    -
      -
    • Adds IPC alcohol and a few derivative drinks
    • -
    • IPCs can now drink and be fed from glasses
    • -
    -

    Fox McCloud updated:

    -
      -
    • Laser eyes mutation no longer drains nutrition
    • -
    • splits the EMP kit into two things: the standard EMP kit (2 grenades and an implant), and the EMP flashlight by itself
    • -
    • nerfs heart attacks so they do less damage
    • -
    • Pickpocket gloves now put the item you strip into your hands as opposed to the floor
    • -
    • Picketpocket gloves can now silently strip accessories
    • -
    • Pickpocket gloves will no longer give a message for messing up a pickpocket
    • -
    -

    KasparoVy updated:

    -
      -
    • Adjusting masks while they are not on the face will no longer turn off internals.
    • -
    • Adjusting masks while they are not on the face will now cause the mask to hide/reveal the wearer's identity the next time it's worn as intended.
    • -
    • Adds the ability to open/close bomber jackets.
    • -
    • Adds a security bomber jacket. This jacket inherits the protection and storage capabilities as a standard Security vest with additional bomber jacket benefits.
    • -
    • Adds UI button in top left of screen for jacket adjustment.
    • -
    • Replaces the standard bomber jacket in the Pod Pilot bay with the Security version.
    • -
    • Centralizes jacket/coat adjustment handling.
    • -
    • All jackets start closed by default.
    • -
    • Geneticist duffelbag on-mob sprite (for all species).
    • -
    • Vox-fitted backpacks, satchels, ERT backpacks, duffelbags and defib unit.
    • -
    • Refactors back-item icon generation.
    • -
    • Typo in the description of Santa's sack.
    • -
    • Missing punctuation and gender macros in the description of the bag of holding.
    • -
    • The tweak to back-icon generation fixes a bug where the wrong sprite name was being used to generate back-item icons.
    • -
    -

    PPI updated:

    -
      -
    • Adds the ability to hide papers in vents. You can now leave a romantic love letter, exchange information in secret, or hide papers infused with the power of nar'sie from sight.
    • -
    -

    Regen1 updated:

    -
      -
    • Adds the Immolator laser gun, a modified laser gun with 8 shots that will ignite mobs, can be made in R&D
    • -
    -

    Spacemanspark updated:

    -
      -
    • Adds *yes and *no emotes to Synthetics. Glory to Synthetica.
    • -
    -

    Tastyfish updated:

    -
      -
    • The PDA system has been completely redone behind the scenes! It should be functionally similar, although there is now a Home and Back button at the bottom as appropriate.
    • -
    • All of the heads now have multicolored pens.
    • -
    • EngiVend now has 10 camera assemblies.
    • -
    • Borgs can now use vending machines.
    • -
    • There are now picture frames that can be made from the autolathe or wood planks for papers, photos, posters, and canvases!
    • -
    -

    pinatacolada updated:

    -
      -
    • Makes the Protect Station AI law board no longer consider people that damage the station crew, instead of human
    • -
    -

    ppi updated:

    -
      -
    • When revealed Revenants will not be able to move at the maximum move speed, nor be able to pass through any solid object, like walls, windows, grills, computers and mechs.
    • -
    - -

    13 February 2016

    -

    Crazylemon64 updated:

    -
      -
    • Relaxes the check on what atoms you can follow to any movable atom
    • -
    • Mages are now more ragin
    • -
    • Admins can now adjust the total number of wizards at runtime by tweaking either max_mages, or players_per mage
    • -
    -

    DaveTheHeadcrab updated:

    -
      -
    • Adds new worn icons for duffelbags to better reflect their size, compliments of WJohn at /tg/
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds burritos, made from cutlets, beans, rice, capsacin oil (hotsauce), cheese, and flat dough (because we lack proper tortillas) in the microwave.
    • -
    • Adds chimichangas. You know you want a deep-fried burrito.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Updates some spell icons with better/higher quality icons
    • -
    • Updates unarmed attacks to allow for more customization
    • -
    • Updates martial arts so they factor in specie's attack messages and sounds
    • -
    • Re-balances Sleeping Carp fighting style
    • -
    • Re-balances Bo Staff
    • -
    • Rebalances Golem: they should now be spaceproof, fire+cold proof, rad proof, virus immune, clonable, parapen+syringe gun immune, deal increased melee damage. Their armor has been reduced to 55 melee across the board, their slip immunity removed, pain immunity removed, and they're slightly slower
    • -
    • Fixes Ei Nath generating two brains
    • -
    • Ensures the Necromatic Stone generates actual skeletons
    • -
    • Can now strip PDA/IDs from Golems
    • -
    • Fixes sleeping carp grab not being an instant aggressive grab
    • -
    • Fixes an exploit with declaring war on the station
    • -
    -

    KasparoVy updated:

    -
      -
    • Orange and purple bandanas for all station species.
    • -
    • The ability to colour bandanas with a crayon in a washing machine.
    • -
    • Refactors the bandana adjustment system.
    • -
    • Minor adjustments to Tajaran and Unathi bandana east/west sprites.
    • -
    • Adjusting a bandana will now take if off of your head/face and put it in an available hand. If both hands are available, it goes in the selected hand.
    • -
    • Adjusting a coloured bandana will no longer revert it to the original coloured icons anymore.
    • -
    • Adjusting a bandana from mask-style to hat-style means the bandana won't obscure your identity anymore.
    • -
    • Greys now use re-positioned smokeables. They no longer smoke out the eyes.
    • -
    -

    TheDZD updated:

    -
      -
    • Fixes spacepods being able to shoot through walls.
    • -
    • Lowers spacepod weapons fire delay.
    • -
    • Increases spacepod weapons energy costs.
    • -
    • Makes spacepods move at speeds not rivaling those of photon beams. They are now a hair bit faster than a person with a jetpack.
    • -
    • Reduces battery costs for spacepod movement.
    • -
    - -

    10 February 2016

    -

    Crazylemon64 updated:

    -
      -
    • The cloner now checks for NO_SCAN on the brain when scanning - unclonable species are now truly unclonable. You are still able to revive them with a brain transplant and a defib, however.
    • -
    • A tier-4 DNA scanner linked to a cloning system will now be able to reproduce a body from a brain's DNA, in event of the original corpse being gibbed or similar.
    • -
    • Species with organic limbs and NO_BLOOD will no longer bleed (though still on hit - write that off as "bone powder")
    • -
    • Skeletons now lack internal organs, except for the runic mind which exists in their head - an analogue for the brain
    • -
    • Skeletons that drink milk will be regenerated at a moderate pace, have a small chance of mending bones, and will praise the great name of mr skeltal
    • -
    • Adds a reagent system for species reacting to specific reagents
    • -
    • Slime People can now select from all human hairstyles, and their "hair" will be tinted a shade of their body.
    • -
    • Increases the frequency of the cortical borer event.
    • -
    • People with borers cannot commit suicide - this applies to a controlling borer, too.
    • -
    • Borers can no longer overdose their hosts.
    • -
    • Borers can now inject Saline-Glucose, Spaceacillin, Hydrocodone, Mitocholide, Salbutamol, Capulettium+, and Charcoal. Styptic was removed, as it's pathetic at healing when directly injected. Salicyclic acid was removed too, as its functionality is duplicated by both hydrocodone and saline-glucose.
    • -
    • A mind trapped by a cortical borer can now understand things it could understand when normally in its body.
    • -
    • Changes chemistry's welding tank to a wall-mounted version, to increase the room available.
    • -
    • You can now gib butterflies and lizards with a knife
    • -
    • Ghosts can now follow mecha
    • -
    • You can now access an R&D console by emagging it - it did nothing before.
    • -
    • Walls will now properly smooth and show damage.
    • -
    • Fixes the dialog that occurs when the AI shuts off to actually do what it says it does
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes not being able to attach IEDs to beartraps
    • -
    • Can no longer spamclick someone to death using headslamming on a toilet/urimal
    • -
    • Toilet/urinal headslamming now plays a sound
    • -
    • Toilet headslamming damage reduced slightly
    • -
    • Can now fill open reagent containers in a toilet to receive "toilet water".
    • -
    • No more message spam when someone fills a container using a sink
    • -
    • Can now wash your face using a sink, which washes away lipstick and wakes you up slightly
    • -
    • Washing things will now use progress bars
    • -
    • Ensures consuming a single syndicate donk pocket won't get you addicted to meth
    • -
    • Kinetic Accelerators and E-bows automatically reload
    • -
    -

    Glorken updated:

    -
      -
    • Added a Knight Arena for Holodeck.
    • -
    • Added red and blue claymore sprites.
    • -
    • Changed overrided to overrode when emagging Holodeck computer.
    • -
    -

    KasparoVy updated:

    -
      -
    • Vox versions of the Officer SWAT sechailer + HOS SWAT sechailer + Warden SWAT sechailer.
    • -
    • Resprited versions of most Human masks to fit Unathi, Tajara and Vulpkanin.
    • -
    • Warden now gets their own version of the SWAT sechailer in their locker.
    • -
    • HOS now gets the appropriate version of the SWAT sechailer in their locker.
    • -
    • Repositioned smokeables now available for Vox, Unathi, Tajara and Vulpkanin.
    • -
    • Properly shades Vox bandana down-state sprites.
    • -
    • Readds Tajaran bald hairstyle.
    • -
    • Alternate style of non-Human breath mask (incl. surgical/sterile mask) down-state positioning.
    • -
    • Corrects all non-Human species' breath mask (incl. surgical/sterile mask) down-state icons to use the right position style.
    • -
    • Minor adjustments to Tajaran breath mask up-state sprites.
    • -
    -

    PPI updated:

    -
      -
    • Adds a reconnect button to the File menu in the client.
    • -
    • Adds head patting
    • -
    -

    Regen updated:

    -
      -
    • Powersink can now drain a lot more power before going boom
    • -
    • Buffed the powersinks drain rate
    • -
    • Buffed explosion from an overloaded powersink, try to find it instead of overloading the grid.
    • -
    • Admin log warning before the powersink explodes
    • -
    -

    Spacemanspark updated:

    -
      -
    • Miners can now utilize the power of mob capsules to take along their lazarus injected mining creatures!
    • -
    • Store your Pokemo- er, sorry, I mean mining mobs that you've captured in the lazarus capsule belt.
    • -
    -

    Tastyfish updated:

    -
      -
    • Species that don't breathe can kill themselves now!
    • -
    • Suicide messages are now catered to your species.
    • -
    • Shortened the default pill & patch name when using the ChemMaster.
    • -
    • The chaplain now has a service radio headset, as Space Jesus intended.
    • -
    -

    TheDZD updated:

    -
      -
    • When Ahelping, "Question" is now "Mentorhelp" and "Player Complaint" is now "Adminhelp."
    • -
    • Mentorhelps and PM replies from mentors appear in a bold aqua blue color.
    • -
    • Adminhelps and PM replies from admins appear in a bold bright red color.
    • -
    • PM replies from players appear in a dull/dark purple color.
    • -
    • Adds admin attack log to players being converted to cult.
    • -
    • Adds shadowling thrall jobbans.
    • -
    • Jobbanned players who are converted to shadowling thrall, revolutionary, or cultist will have the control of their body offered up to eligible ghosts.
    • -
    - -

    31 January 2016

    -

    Crazylemon64 updated:

    -
      -
    • Syndicate borgs can now interact with station machinery
    • -
    • People with slime people limbs can now *squish
    • -
    • Skrell's vulnerability to alcohol is checked on their liver, now - a liver transplant will let them take alcohol like a champ - lacking a liver will have the same effect as being a skrell, when drinking
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Adds in the Magic Eight Ball toy, found in Claw Game prize orbs.
    • -
    • Adds in the Magic Conch Shell, an admin-only shell of power.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Updates Summon Guns and Magic to include many of the new guns
    • -
    • Summon Guns/Magic can no longer be used during Ragin' Mages
    • -
    -

    Tastyfish updated:

    -
      -
    • The emergency shuttle status in the Status tab now has ETA/ETD/etc like before.
    • -
    • Code Gamma+ now has a 5 minute emergency shuttle call, like Red.
    • -
    -

    pinatacolada updated:

    -
      -
    • Adds NanoUI to the operating computer
    • -
    • Adds health announcing, critical and oxygen damage aural alerts to the computer, with a menu to selectively turn them on and off
    • -
    - -

    29 January 2016

    -

    Crazylemon updated:

    -
      -
    • The DNA scanner has now undergone a seminar to recognize fake identities; It will now scan the actual person's identity, rather than their disguise (read: wearing a mask with or without someone else's ID).
    • -
    • Matter eater now allows you to eat humans as if you were fat.
    • -
    • Eating mobs with an aggressive grab now generates attack logs.
    • -
    -

    Crazylemon64 updated:

    -
      -
    • For a short while, there was a clerical error where all AI communications equipment was replaced with bananas. This has now been fixed.
    • -
    • Ghosts can now see the contents of smartfridges and look at the drone console
    • -
    • Humans now only produce one message when shaken while SSD
    • -
    • The supermatter no longer will irradiate everyone, everywhere, when it explodes.
    • -
    • Writing on paper will now add hidden admin fingerprints, so that you can't forge mean notes in someone else's name.
    • -
    • Brains are no longer able to escape their brain by being a sorcerer.
    • -
    • Astral projecting with other runes on the same tile will now no longer prevent you from re-entering
    • -
    • Voxxy that is become ex-voxxy no longer carry voxxy appearance! yaya!
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Allows plants to be identified as enhanced*. Enhancing plants results from using reagents (like saltpetre) that affect the stats of a seed instead of using mutagens/machines. *May not meet standards for being classified as "organic produce". (This was already possible, just renames enhanced plants for easier differentiation)
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes mutadone not working with some genetic mutations
    • -
    • Fixes banana honk and silencer being alcoholic
    • -
    • Fixes Kahlua being non-alcoholic
    • -
    • Fixes polonium not metabolizing
    • -
    • Fixes being able to receive free unlimited boxes from the Merchandise store
    • -
    • Adds in wooden bucklers
    • -
    • Re-adds roman shield to the costume vendor
    • -
    • Buffs Riot shield damage from 8 to 10
    • -
    • Adds in a Skeleton race
    • -
    • Tweaks the skeletons colors to be more realistic and to blend in less with the floor
    • -
    • Adds in lichdom spell for the wizard
    • -
    • Adds in lesser summon guns spell for wizard
    • -
    • adds in Mjolnir and the singularity hammer as weapons the wizard can purchase
    • -
    • Wizard can purchase the charge spell from the spell book
    • -
    • Wizard can purchase a healing staff from the spell book
    • -
    • Tweaks and lowers spell costs of utility spells for wizard
    • -
    • Re-organizes the spellbook to be better divided into categories and have a better window size
    • -
    • Knock now opens+unlocks lockers
    • -
    • Magic Missile has a slightly longer cooldown and no longer deals damage, but has a lower cooldown is upgraded
    • -
    -

    KasparoVy updated:

    -
      -
    • Navy blue Centcom Officer's beret for use by the Blueshield.
    • -
    • Adds the new navy blue beret to the Blueshield's locker.
    • -
    • Gives the Blueshield's berets (black and navy blue) the exact same strip delay and armour as the Security Officer's beret.
    • -
    • Adds TG energy katana back and belt sprite.
    • -
    • Bo staff back sprite.
    • -
    • Adjusts energy katana sprites to make the weapon stand out a bit more from the regular katana.
    • -
    • Cutting open the toes of footwear so species with feet-claws can wear them.
    • -
    • Toeless jackboots.
    • -
    • Cleans up glovesnipping and lighting a match with a shoe.
    • -
    • Lighting a match with a shoe produces a more appropriate message, handled at the same standard as glove-snippingboot-cutting.
    • -
    -

    Tastyfish updated:

    -
      -
    • Cargonia now has its own section in the manifest.
    • -
    -

    TheDZD updated:

    -
      -
    • Due to budget cuts and reports of operatives accidentally firing enough bullets to reach a state of what our scientists refer to as "enough dakka," Syndicate High Command has decided to restore the Syndicate Strike Team arsenal to using standard-issue L6 SAW ammunition.
    • -
    - -

    24 January 2016

    -

    KasparoVy updated:

    -
      -
    • Fixes markings overlaying underwear.
    • -
    • Nude icon in underwear.dmi
    • -
    • Fixes Vox robes not using the correct on-mob sprites.
    • -
    • Fixes unreported bug where there was a slim chance during character preview icon generation that a character with Security Officer set to high would get rendered with either the wrong beret sprite or no beret sprite at all.
    • -
    • Fixes an issue where Sigholt's fluff beret wasn't using the correct sprites.
    • -
    -

    Tastyfish updated:

    -
      -
    • Passively power-consuming borg modules, such as the peacekeeper movement and shield module, won't spam the user infinitely if they're low on power anymore.
    • -
    - -

    23 January 2016

    -

    Fox McCloud updated:

    -
      -
    • Removes Vampire HUD
    • -
    • moves the Vampire blood counter to a more easy to see location
    • -
    • Adds in a Changeling chemical counter display
    • -
    • Adds in a Changeling sting counter display
    • -
    • Vampire total blood and usable blood will now appear under status
    • -
    • Changes vampire blood display to be similar to ling chemical counter
    • -
    • Fixes unnecessary toxin damage being dealt on severe bloodloss
    • -
    • Fixes human mobs not receiving proper random names
    • -
    • Adds in knight armor
    • -
    • Grants the chaplain a set of crusader knight armor
    • -
    • Adds in cult-resistant ERT paranormal space suit
    • -
    • Allows the Chaplain to convert his null rod into a holy sword with crusader knight armor
    • -
    • Chaplain's closet is now a secure closet
    • -
    • Adds in Assault Gear crate to cargo
    • -
    • Adds in military assault belt
    • -
    • Adds in spaceworthy swat suits
    • -
    • tweaks bandolier to hold 2 additional shotgun shells
    • -
    • bartender starts off with +2 additional shells
    • -
    • Reduces the cost of the space suit crate and doubles its contents
    • -
    • Refactors knives so their behavior is more universal
    • -
    • Fixes Hulk not properly being removed when your health drops below a threshold
    • -
    • Fixes flickering vision in a mining mech
    • -
    -

    Tastyfish updated:

    -
      -
    • Poly has taken a seminar on the latest trends in engine operations.
    • -
    • Player-controller parrots can now hear their headsets.
    • -
    -

    Tigerbat2000 updated:

    -
      -
    • The nuclear disk escaping on the shuttle no longer counts as a syndicate minor victory.
    • -
    • Cultists can once again actually greentext the escape objective.
    • -
    - -

    20 January 2016

    -

    DarkPyrolord updated:

    -
      -
    • Adds in hardsuit sprites for Vulpkanin
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Allowed cheap lighters and individual matches to be put into cigarette packages at the cost of cigarette space.
    • -
    • Matches can now be lit and put out by striking the match on your shoes. Good for if you lose that matchbox, or want to just feel cool.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes brute damage on weapons not knocking people down.
    • -
    • Tweaks implant behavior to be more consistent and unified.
    • -
    • Lowers the pAI cooldown from 60 seconds to 5 seconds.
    • -
    • Raw telecrystal can now be used to charge uplink implants.
    • -
    • Fixes being unable to holster the pulse pistol
    • -
    • Fixes being able to holster shotguns
    • -
    -

    KasparoVy updated:

    -
      -
    • Improved shading on all Vulpkanin hardsuit tails.
    • -
    • Vulpkanin hardsuit helmet respriting (colour tweaks).
    • -
    • Vulpkanin hardsuit helmets with proper flashlight-on sprites.
    • -
    -

    Tastyfish updated:

    -
      -
    • The ID computer Access Report printout now separates the access list with commas so it's actually readable.
    • -
    • The ID computer Access Report printout isn't blank if you don't have an authorization card in anymore.
    • -
    • In the supply ordering & shuttle consoles, one can now cancel an order at either the Reason or Amount input dialogs.
    • -
    • Table flipping uses correct sprites.
    • -
    -

    TheDZD updated:

    -
      -
    • Adds world.Topic() handling so that users are notified in-game when pull requests are opened, closed, or merged on the Github repo.
    • -
    - -

    18 January 2016

    -

    Crazylemon updated:

    -
      -
    • New classes of shapeshifters have been sighted around the NSS Cyberiad...
    • -
    • Wizards now can't teleport to other antag spawn points.
    • -
    • Removes an extruding pixel from the left-facing IPC glider monitor sprite.
    • -
    • Ragin' Mages now spawn every 7 minutes, instead of 5. Admins can further adjust this by modifying the 'delay_per_mage' variable.
    • -
    • Ragin' Mages are now made with 100% less in-use souls (Apprentices won't have their consciousness yoinked).
    • -
    • It takes half an hour for the REAL chaos of ragin' mages to start, for at least a semblance of normality.
    • -
    -

    Dave The Headcrab updated:

    -
      -
    • Adds the advanced energy revolver, toggles between taser and laser modes.
    • -
    • Removes the detective's revolver from the blueshield's locker.
    • -
    • Changes the taser the blueshield starts with into an advanced energy revolver.
    • -
    -

    Deanthelis updated:

    -
      -
    • Added the ability for the Magnetic Gripper to pick up and place light tiles.
    • -
    -

    Fethas updated:

    -
      -
    • Readds the hud icon showing up for master and servent
    • -
    • adds mindslave datum hud thingy based on TGs gang huds
    • -
    -

    Fox McCloud updated:

    -
      -
    • Fixes not being able to add/remove Weapon Permit from IDs.
    • -
    • Fixes the energy sword being invisible in-hand when turned on.
    • -
    • Fixes the telebaton being invisible in-hand when extended.
    • -
    • Fixes eye-stabbing not having an attack animation or hitsound.
    • -
    • Fixes some kitchen utensils playing the wrong hit-sound and playing twice in some cases.
    • -
    • Fixes the butcher cleaver sprite being backwards.
    • -
    • Fixes the telebaton sprite being missing from the side.
    • -
    • Fixes the meat cleaver being invisible in-hand.
    • -
    • Corrects some grammatical descriptive errors for the elite syndicate hardsuit.
    • -
    • completely overhauls implants to TG's standards.
    • -
    • Adds storage implant.
    • -
    • Adds microbomb and macrobomb implants.
    • -
    • Adds in support for removing implants directly into cases.
    • -
    • Removes Bay style explosive implants.
    • -
    • Removes compressed matter implants.
    • -
    • Tweaks the uplink to reflect removal of the old implants and inclusion of the new.
    • -
    • Fixes/cuts down on the lag caused by monkey cubes.
    • -
    -

    Jey updated:

    -
      -
    • Inflatable walls and door can now be deflated by altclicking them
    • -
    • Fixed lag from expanding multiple monkeycubes at once.
    • -
    -

    KasparoVy updated:

    -
      -
    • Adds blank icons with standardized timings for species tail wagging, used in icon generation.
    • -
    • Fixes tails overlapping arms/limbs + gloves, etc. when facing EAST or WEST.
    • -
    • Ensures tails will overlap stuff as normal only when facing NORTH so as to avoid unwanted interference with the base sprite.
    • -
    • Tails now appear in ID cards, overlays things correctly.
    • -
    • Tails now overlay and are overlaid by things correctly in preview icons.
    • -
    • Modifies the positioning of tail icon generation in the ID card preview icon generation file.
    • -
    • Modifies the positioning of tail icon generation in the player preferences preview icon generation file.
    • -
    • Breaks limb generation into its own layer, breaks tail generation into a second layer that can be overlaid by limbs.
    • -
    • If the user's species is flagged to have a tail that is overlapped, TAIL_LAYER will now overlay the NORTH direction sprite of a tail now, while TAIL_UNDERLIMBS_LAYER gets all remaining directions. Otherwise icons are generated in the traditional manner.
    • -
    • Adjusts the Unathi right arm east direction and animated tail sprites, recolouring a random pixel and fixing a floating tail respectively.
    • -
    • Adjusts position of tail layer such that tails' north direction sprites will overlay backpacks (more importantly, satchel straps).
    • -
    • Accommodates admin-overrides to the body_accessory species check by setting the default animation template to Vulpkanin.
    • -
    • Adjusts north-direction Unathi static tail sprite, now attaches to the body in the correct location.
    • -
    • Adds some TG underwear.
    • -
    • Adds an NV science goggles worn sprite.
    • -
    • Ports Bay/TG berets.
    • -
    • Adjusts beret sprite, recolours strange orange pixels.
    • -
    • Adjusts NV science goggles object icon. Removed strange border and centered it.
    • -
    • Ports Polaris' PRs 761 and 778, brings over Ragnie's awesome Ward-Takahashi prosthetics.
    • -
    -

    Kyep updated:

    -
      -
    • Changing level to gamma/delta/epsilon now displays a special gamma/delta/epsilon sprite on status monitors
    • -
    • Changing level to green/blue now clears the status monitors, so they no longer show higher alert levels after the level is changed
    • -
    -

    NTSAM updated:

    -
      -
    • Added a rainbow IPC screen.
    • -
    -

    PPI updated:

    -
      -
    • Modifies the effective time limit to activate the Nuclear Challenge as Nukeops from two minutes to seven minutes
    • -
    -

    Tastyfish updated:

    -
      -
    • The QM now actually has a QM stamp instead of a fake one, as well as an approved and denied stamp.
    • -
    • New area named 'Genetics Maintenance' solidifying/relabelling the confusing area between the morge and Mech Bay as being fully maintenance again, but working correctly and with proper doors.
    • -
    • Fixed a few maintenance door names to be in parity to the rest of the station.
    • -
    • Added the ability to print the records photo of a crew member from a security records console. Useful for Wanted notices!
    • -
    -

    Tigercat2000 updated:

    -
      -
    • You can no longer use the gibber for monkies.
    • -
    • Cleaned up gibber.dm styling.
    • -
    • The fire alarm now uses NanoUI, with color coded alert levels.
    • -
    • Upgraded NanoUI (again), fancy FontAwesome icons.
    • -
    • Didn't add any butts. Yet.
    • -
    - -

    13 January 2016

    -

    Fox McCloud updated:

    -
      -
    • Fixes Rezadone not clearing mutated organs.
    • -
    • Clone damage immunity removed from Slime People, Shadowlings, Golems, and Vox
    • -
    • Explosions will no longer destroy things underneath turfs until the turf is exposed.
    • -
    • fixes a runtime related to revolver spinning.
    • -
    • fixes server loading taking an abnormally long time.
    • -
    -

    Kyep updated:

    -
      -
    • Blob, vine and virus outbreaks are now more clearly labeled as such, to avoid people confusing them with each other
    • -
    -

    Tastyfish updated:

    -
      -
    • NT Rep fountain pens and magistrate gold pens can now write in 5 different colors. The IAA gets a cheap plastic equivalent.
    • -
    - -

    11 January 2016

    -

    CrAzYPiLoT updated:

    -
      -
    • Fixes the footsteps sounds to the fullest.
    • -
    -

    Crazylemon updated:

    -
      -
    • Bomb guardians now automatically notify their master when they've set something to boom, so there's less accidental friendly fire
    • -
    • Bomb guardians are only notified that their trap failed, if it ACTUALLY FAILED.
    • -
    • Bomb guardians now are more aware of what is primed to explode.
    • -
    • Bomb guardian summoners can now defuse their guardian's bombs without harm.
    • -
    • Brought RAGIN' MAGES back up to function.
    • -
    -

    Dave The Headcrab updated:

    -
      -
    • Added a new icon for the soy and cafe latte drinks. Icons courtesy of Full Of Skittles, resident overlord of art.
    • -
    -

    Fox McCloud updated:

    -
      -
    • Re-arranges the armory and changes its contents minorly.
    • -
    • Adds in rubbershot ammo boxes.
    • -
    • Fixes Mutadone incurring a massive cost on the server.
    • -
    • Positronic brains can no longer speak binary.
    • -
    • Positronic brains can be prevented from speaking (or allowed) by toggling their speaker on/off.
    • -
    • IPC's positronic brains start off toggled off.
    • -
    • Fixes the supermatter announcement causing massive amounts of server lag.
    • -
    • Adds in tradable telecrystals.
    • -
    - -

    08 January 2016

    -

    Crazylemon updated:

    -
      -
    • Fully enables a system to allow species to have unique procs and verbs that come and go with the species.
    • -
    • IPCs lose their change monitor verb when changing species now. Gone are the days of recalling a past IPC life to perform self-barbery! Oh, woe is me!
    • -
    • Sleepers and Body Scanners will now reliably work when rotated
    • -
    • SSD humans should be asleep more reliably now.
    • -
    -

    Dave The Headcrab updated:

    -
      -
    • Nerfs the damage the Detective's revolver does from 15 brute to 5 brute.
    • -
    • Adds a 300 round capacity buckshot magizine that fits into the L6 Saw.
    • -
    • Adds a 25 round capacity 40mm HE magizine that fits into the L6 Saw.
    • -
    • Adds the 'Devastator' L6 SAW, starts off loaded with the buckshot magizine.
    • -
    • Gives the SST the 'Devastator' L6 Saw, and one of each mag type in their bag.
    • -
    -

    FalseIncarnate updated:

    -
      -
    • Plants will now begin to die over time if their age exceeds 5 times their TRAIT_MATURATION value.
    • -
    • Weed growth chance per process in trays has been slightly increased (Previously: 5% chance if no seed, 1% otherwise;Now: 6% / 3%).
    • -
    • Pest growth in trays has been slightly buffed. (Previously: 3% chance to increase by 0.1; Now: 5% chance to increase by 0.5)
    • -
    -

    Fethas updated:

    -
      -
    • Due to Archmage Steve leaving the nya-cromantic stone near the microwave, the true power of the stone has been unleashed. Subjects of the stone are not only ressurected ... but resurrected as catgirls ... We fired steve.
    • -
    -

    Fox McCloud updated:

    -
      -
    • fixes a bug relating to some brute/burn damage being dealt to human mobs.
    • -
    • Adds in overloading APCs, causing them to arc electricity to mobs in range.
    • -
    • Makes Engineering related APCs overload proof.
    • -
    • Implements the timestop spell.
    • -
    • Implements new sepia slime reaction which halts time in an AoE.
    • -
    • sentience potions no longer can make slimes sentient.
    • -
    • Removes Hulk instant stun.
    • -
    • Hulk damage increased.
    • -
    • Hulk wears off at a lower health threshold.
    • -
    • Fixes strange reagent not working on simple animals.
    • -
    • Reduces the amount shock damage and bounces for the Tesla engine.
    • -
    • Fixes Syndicate Cyborg's LMG being invisible.
    • -
    • Fixes the uplink kit having implanters that were both nameless and looked as if they had been used.
    • -
    -

    KasparoVy updated:

    -
      -
    • Added the security gasmask, sexy mime mask, bandanas, balaclava, welding gas mask and wrestling masks for Vox. Added adjusted-state sprites for the Vox breath, medical, and surgical masks.
    • -
    • Removed a duplicate of the human balaclava sprite.
    • -
    • Modifies the Vox plague-doctor, fake moustache, sterile and medical mask sprites to fit the Vox anatomy and animates the Vox SWAT mask. Corrects the names of some Vox mask adjusted-state sprites.
    • -
    -

    Tastyfish updated:

    -
      -
    • Fixed the pronouns in a few verbs and the door to 'Interrogation Observervtion'.
    • -
    -

    Tigercat2000 updated:

    -
      -
    • Added 96x96 (3x) res option to icons menu
    • -
    - -

    06 January 2016

    -

    Certhic updated:

    -
      -
    • Corrected some air alarms so that atmos computer can access them
    • -
    • Bodyscanner now sees mechanical parts in internal organs
    • -
    -

    Crazylemon64 updated:

    -
      -
    • Sleeping simple animals should tick down sleeping as normal - deaf simple mobs are no longer a thing
    • -
    -

    Tastyfish updated:

    -
      -
    • Instruments now use NanoUI.
    • -
    • Corrected the blueshield mission briefing.
    • -
    - -

    03 January 2016

    -

    TheDZD updated:

    -
      -
    • Ports over changelog system from /tg/station.
    • -
    -
    - -GoonStation 13 Development Team -
    - Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
    - Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No
    -
    -
    -

    Creative Commons License
    Except where otherwise noted, Goon Station 13 is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 License.
    Rights are currently extended to SomethingAwful Goons only.

    -

    Some icons by Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 License.

    -
    - - + + + + Paradise Station Changelog + + + + + + + +
    + + + + +
    +
    Paradise Station
    + +

    +
    + + + + + +
    + Current Project Maintainers: -Click Here-
    + Currently Active GitHub contributor list: -Click Here-
    + Coders: ZomgPonies, DaveTheHeadcrab, tigercat2000, FalseIncarnate, AuroraBlade, Tastyfish, Crazylemon64, KasparoVy
    + Spriters: FullOfSkittles
    + Sounds:
    + Main Testers: Anyone who has submitted a bug to the issue tracker
    + Thanks to: Baystation 12, /tg/station, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original SpaceStation developers and Radithor for the title image.
    Also a thanks to anybody who has contributed who is not listed here :( Ask to be added here on irc.
    +
    Have a bug to report?
    Visit our Issue Tracker.
    + Please ensure that the bug has not already been reported and be as descriptive as possible about the circumstances under which the bug occurred. +
    + + +
    + +

    26 April 2020

    +

    Cazdon updated:

    +
      +
    • Admin Roles no longer appear on manifest.
    • +
    • Central Command PDA's no longer appear on the messenger list.
    • +
    • Potential Convertee's being unable to be converted.
    • +
    +

    Drakeven updated:

    +
      +
    • Fixed mislabeled traitor and mindslave special role.
    • +
    +

    Ionward updated:

    +
      +
    • Grey, Tajaran, Unathi, and Vulpkanin now properly have species specific fits for soft space suits.
    • +
    • Vox can now wear soft space suits, such as EVA (Clown and Mime included), NASA Void, and Syndicate suits.
    • +
    • Added Vox soft suit sprites.
    • +
    +

    JKnutson101 updated:

    +
      +
    • Combined the Rite of Tribute and Rite of Enlightenment into one Rite of Offering.
    • +
    • Sacrificing now properly puts victims that have at one point had CKeys into soul stones, or polls dead-chat to do so.
    • +
    +

    Kyep updated:

    +
      +
    • Tweaked Greater Hellhound, added more non-violent options and one unique combat spell.
    • +
    +

    SteelSlayer updated:

    +
      +
    • Fixes the "List SSDs and AFKs panel" showing everyone as the target of an assassinate objective
    • +
    • The global objectives list is now viewable in the MC Globals menu
    • +
    • Reverts some terrible changes that are causing some bugs with traitors
    • +
    • Fixes AIs with the combat module not being able to hack APCs
    • +
    +

    TDSSS updated:

    +
      +
    • duplicate mecha definitions
    • +
    • blobbernaut vision blur now clears as intended.
    • +
    • fixed a bug preventing ticket system from working under some circumstances.
    • +
    +

    VeteranKyl updated:

    +
      +
    • DNA Samplers now check if the target species has DNA.
    • +
    • Fixed the envenomed blob's spore toxin not causing harm.
    • +
    +

    craftxbox updated:

    +
      +
    • fixed colors not working without regex
    • +
    • fixed text panel not loading when an invalid regex is added
    • +
    • polyfilled string.prototype.includes
    • +
    +

    moxian updated:

    +
      +
    • being in a locker no longer interferes with tracking implant tracking
    • +
    • locator no longer locates tracking implants on other z levels.
    • +
    • fixed singulo being unable to expand when placed next to containment wall
    • +
    + +

    27 October 2019

    +

    AdamElTablawy updated:

    +
      +
    • Xenobiology can no longer produce hellhounds with gold slime cores.
    • +
    +

    AzuleUtama updated:

    +
      +
    • Vampire's shape shift ability and DNA scrambler item now clear flavour text on use.
    • +
    +

    Darkmight9 updated:

    +
      +
    • Adds a wide variety of craftable decorations! You can find them in the new 'Decorations' tab in the crafting menu.
    • +
    • tweaked the duct tape component so that you can now add it to items to make them naturally stick to walls.
    • +
    • added decorative sprites.
    • +
    +

    Fox McCloud updated:

    +
      +
    • windows are easier to break
    • +
    • Adds in the Rod of Asclepius, a healing item that carries an immense burden
    • +
    • Fixes Bubblegum spawning being ridiculously rare
    • +
    • Fixes planetary atmos not correctly happening
    • +
    • Fixes atmos pipe unwrenching
    • +
    • Survival pod medical vendors only have 2 pairs of splints instead of a wide array of medicines
    • +
    • Hivelord core, when used on someone, no longer fully revives them; instead it heals 25 burn, 25 brute, resets body temperature, removes all CC, cures all internal bleeding, and mends all fractures (slowdown bonus still stays
    • +
    • updates the close icon for storage to not be a trashy codersprite
    • +
    • Fixes excessive mob and tendril clumping on Lavaland
    • +
    • Fixes being able to exploit the destructive analyzer for unlimited materials
    • +
    • Fixes Hierophant arena atmos
    • +
    +

    Ionward updated:

    +
      +
    • fixed Battlemage armor having an unintended helmet light
    • +
    • added Vox versions of Battlemage, Paranormal, Inquisitor, Berserker, and Syndicate Elite Hardsuits.
    • +
    +

    SteelSlayer updated:

    +
      +
    • Fixes the RPED and bluespace RPED not displaying a list of parts in players chat when used on a machine
    • +
    +

    TDSSS updated:

    +
      +
    • yellow documents are no longer indestructible.
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • single quotes showing up weird in names and announcement titles
    • +
    +

    Terilia updated:

    +
      +
    • Headcrab Nests
    • +
    • Headcrabs can now eat dead simple_animal corpses to regain 10 hp.
    • +
    • Poison Headcrabs will not inject LSD anymore.
    • +
    • Headcrabs have more HP and some do more damage.
    • +
    • Headcrabs will not stop attacking people after they are unconscious.
    • +
    • Headcrab Nest DMI
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Admin attack log level of heirophant club updated
    • +
    +

    actioninja updated:

    +
      +
    • Nanoui interfaces in fancy mode now open more cleanly
    • +
    +

    craftxbox updated:

    +
      +
    • Vanilla JS Regex for chat highlighting
    • +
    • Removed jquery mark
    • +
    • quickfix to stop people using the scanner inside it
    • +
    +

    farie82 updated:

    +
      +
    • Cult whispering now uses your real name
    • +
    • Fixed the invisible blob zombies
    • +
    • A runtime in blob/factory/run_action
    • +
    + +

    13 October 2019

    +

    Darkmight9 updated:

    +
      +
    • Re-added the handheld defib sprites
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes wrench attacking telepads
    • +
    • performance improvements for xenobio stuff
    • +
    • LINDA is much more aggressive at distributing gas between turfs in an excited group
    • +
    +

    Kyep updated:

    +
      +
    • Removed admin-only "show duplicate discord links" verb.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Captains can access their display case again
    • +
    • Reverted autoban using legacy system causing issues
    • +
    +

    streather updated:

    +
      +
    • fixed a typo in the autolathe
    • +
    + +

    09 October 2019

    +

    Darkmight9 updated:

    +
      +
    • Gives the handheld defib a new sprite
    • +
    +

    Fox McCloud updated:

    +
      +
    • DNA vault requires 5 pico manipulators and 5 super capacitors instead of quadratic capacitors
    • +
    • Powers of the DNA vault adjusted
    • +
    • DNA vault no longer allows you to have unlimited genetics powers.
    • +
    • All previous powers removed with the exception of no breathing
    • +
    • New powers: breathable plasma immunity+virus immunity, heat immunity+burn reduction, speed increase, species armoring+pierce immunity, stun reduction, and action speed increase
    • +
    • Removes consoles screens; use plane old glass in place of them. Holy sheet, they were a pane.
    • +
    • Adds being able to make leather with the bio-generator
    • +
    • removed a lot of leather-related recipes from the bio-generator; these have been moved to leather crafting
    • +
    • can make hide mantles with leather
    • +
    • wearing pants while wearing an undershirt means your arms and chest are covered
    • +
    • Fixes AI swarmers not doing anything
    • +
    • swarmers can eat circuitboards and their own shells now
    • +
    • Fixed being able to eat soil
    • +
    • de-activated swarmer shells give 10,000 metal and 4,000 glass instead of 100 metal and 400 glass.
    • +
    • Fixes lavaland swarmers not being able to teleport people away
    • +
    • Swarmers can place lattice over lava
    • +
    • Floors no longer get dirty by walking on them
    • +
    • Zone selection tweaked; shouldn't notice anything different
    • +
    • melting research lockboxes no longer dumps the contents
    • +
    • Fixes reflective blobs using horrifying code that didn't reflect things *properly*
    • +
    • Fixes APCs not being hackable
    • +
    • Fixes explosions not properly interacting with storage items
    • +
    +

    Ionward updated:

    +
      +
    • Fixed a single pixel offset on Grey's Bags of Holding sprite.
    • +
    +

    JKnutson101 updated:

    +
      +
    • Shades can be stored in any Soul Stone.
    • +
    • Shades can once again be stored in Soul Stones.
    • +
    • Non-cultists and Non-wizards can no longer use most Soul Stones.
    • +
    • Cult Specters properly log as antags.
    • +
    • Cult Specters are properly removed from the cult on death.
    • +
    +

    KasparoVy updated:

    +
      +
    • Fixes an issue with the Tajaran striped tail's wagging animation by removing an extra frame.
    • +
    +

    PidgeyThePirate updated:

    +
      +
    • The abductor's silencer now actually silences radios for 10-20 seconds.
    • +
    +

    SteelSlayer and McRamon updated:

    +
      +
    • Added a new subtype of shade used exclusively by cultists to prevent chaplains metagaming with their shade sprites
    • +
    • Renamed path names for the altar and archives to be less confusing, and replaced all instances of the path names to reflect the change
    • +
    • Replaced nearly every sprite for reaper cult, including constructs, structures, airlocks and the reaper himself.
    • +
    • Removed the old reaper cult construct sprites
    • +
    +

    craftxbox updated:

    +
      +
    • cult teleport rune teleporting ai eye
    • +
    + +

    07 October 2019

    +

    AffectedArc07 updated:

    +
      +
    • SQL now properly disconnects at end round
    • +
    +

    Couls updated:

    +
      +
    • reviver implant now heals even when you're conscious
    • +
    +

    Darkmight9 updated:

    +
      +
    • Hair styles, body markings, clothes, and other character customization options are now alphabetized.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Most things are universally damageable
    • +
    • Acid melts things a bit differently now
    • +
    • Lava actually sets most things on fire.
    • +
    • Captain no longer has access to his display case by default
    • +
    • Xenos can break open vents
    • +
    • Fix syringe in-hand icon not updating
    • +
    • Fixes syringes not having materials
    • +
    • Lethal injection syringes should be a bit more...lethal
    • +
    • PDA health scans should be more in line with regular health analyzer scans
    • +
    • some blood type fixes, nothing noteworthy
    • +
    +

    Ionward updated:

    +
      +
    • fixed invisible Drask surgical masks
    • +
    • added Drask surgery cap icons
    • +
    +

    JKnutson101 updated:

    +
      +
    • Pylons heal robotic limbs.
    • +
    • Soul Shards fail when used on mobs that have never had a ckey.
    • +
    • Soul Stone Shards properly poll dead chat to be filled.
    • +
    • Incorrect icon path for reaper tome
    • +
    +

    Kyep updated:

    +
      +
    • Fixed the medkit spawning in the syndie depot being empty.
    • +
    +

    PidgeyThePirate updated:

    +
      +
    • Revived simple animals keep their ability to pull things and their density if they originally had it.
    • +
    • replaced the Lavaland winter dome ATV with a snowmobile.
    • +
    • The snowmobile key in the winterdome now accompanies an actual snowmobile instead of an incompatible vehicle.
    • +
    +

    SteelSlayer updated:

    +
      +
    • Added GPS coordinates under that status tab for cyborgs which have a GPS
    • +
    • You can no longer fire mining cyborg's KA with no cooldown
    • +
    • Bought items from the wizard spell book are first placed into any empty hands. If all hands are full, it places the item on the ground.
    • +
    • Cultists no longer get more than one summon objective
    • +
    • Mindslaves now show up in their own "Mindslaves" section in the check antagonists panel
    • +
    • Mindslaves will now get their objectives added to their notes and announced in their chat properly
    • +
    • Mindslaves will now have the red (A) in admin attack logs, which shows that the attacker is an antag
    • +
    +

    TDSSS updated:

    +
      +
    • fixed visual issues in beach gateway
    • +
    +

    farie82 updated:

    +
      +
    • Tickets can now be unassigned by staff members.
    • +
    • Toxic compensation now deals the right amount of toxic damage. Instead of just the last healed damage
    • +
    + +

    30 September 2019

    +

    Couls updated:

    +
      +
    • Renames slime organs to be more player friendly
    • +
    +

    PidgeyThePirate updated:

    +
      +
    • The Ripley now collects all the ore it unearths after drilling.
    • +
    +

    SteelSlayer updated:

    +
      +
    • Cultists will no longer get multiple summoning objectives
    • +
    +

    TheSardele updated:

    +
      +
    • MULEbots no longer cause any damage when running over SSDs.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • "Factual" changed to Actual in the explosion doppler array detector system
    • +
    + +

    29 September 2019

    +

    AzuleUtama updated:

    +
      +
    • The camera bug now lists all cameras in alphabetical order.
    • +
    +

    Couls updated:

    +
      +
    • species without bones no longer have ribs or a skull either
    • +
    • slime heart and fleshy masses no longer go invisible after being removed through surgery or being eaten or necrotizing
    • +
    +

    Evankhell561 updated:

    +
      +
    • replace high power cells with high power cell+
    • +
    +

    Fox McCloud updated:

    +
      +
    • can insert keys into vehicles instead of having to hold them in your hand (alt-click while riding a vehicle to remove the key); lava boat still requires holding the key in your hand
    • +
    • Fixes moving diagonally with vehicles making you super fast
    • +
    • Vehicles now factor in the configured human movement delay; this means all vehicles are slower than they previously were
    • +
    • fixes a bug with mobs on vehicles causing incorrect space transitions
    • +
    • ATV sprites updated
    • +
    • Slime speed potions can now apply to vehicles, which makes them faster
    • +
    +

    JKnutson101 updated:

    +
      +
    • Allows for robotic hands, feet, and groin to undergo customization surgery.
    • +
    +

    PidgeyThePirate updated:

    +
      +
    • Abductor surgery will now remove heart subtypes.
    • +
    • Capitalized abductor surgery names for consistency with the surgery UI.
    • +
    • changelings no longer go bald after reviving.
    • +
    + +

    27 September 2019

    +

    PidgeyThePirate updated:

    +
      +
    • Rebooting a drone no longer requires both engineering and robotics access.
    • +
    • fixed a rare glitch in which a guardian that is killed instantly (i.e by a wand of death) may draw its charge into null space.
    • +
    • bluespace anomalies no longer teleport ghosts when their event fires.
    • +
    +

    SteelSlayer updated:

    +
      +
    • Fixes round-start autotraitors not getting their objectives and uplink codes
    • +
    + +

    26 September 2019

    +

    AzuleUtama updated:

    +
      +
    • Improvised shotguns are now in the correct tab when trying to craft them.
    • +
    +

    Couls updated:

    +
      +
    • Slime lungs and heart
    • +
    • Slimes no longer take toxins damage from blood loss
    • +
    • Slimes no longer take brute damage in crit
    • +
    • Slimes now breathe
    • +
    • slimes now use new crit
    • +
    +

    Kyep updated:

    +
      +
    • Fixed NPC redsuited syndicates from being unable to move in space.
    • +
    • Fixed NPC bots thinking that they can path through airlocks which are welded shut. refactor: Refactors some safety checks so that its impossible for depot mobs to generate runtimes in rare cases (e.g: admins spawning them outside the depot for testing)
    • +
    +

    MrMagolor updated:

    +
      +
    • Cult pylons no longer delete unsimulated walls and turn them into floors.
    • +
    • Cult pylons now turn simulated walls into cult walls.
    • +
    +

    TDSSS updated:

    +
      +
    • added missing tools to one abductor ship
    • +
    +

    farie82 updated:

    +
      +
    • Morphs examine text now stays true to the humanoid target they choose.
    • +
    • Cult constructs now show their examine text when you're next to it. Instead of on top of it.
    • +
    + +

    24 September 2019

    +

    AzuleUtama updated:

    +
      +
    • Fixed misleading uplink description for chef's traitor knife.
    • +
    • Reorganises products in seed vendor.
    • +
    • Fixes Durathread mutating into more Durathread
    • +
    +

    Dave-TH updated:

    +
      +
    • Mob spawners will no longer sometimes send players to the void.
    • +
    • The ghosts inside possessed blades are now invincible and will not die to weird edge cases.
    • +
    +

    Evankhell561 updated:

    +
      +
    • mechs now start with a high-capacity power cell+
    • +
    +

    Fox McCloud updated:

    +
      +
    • Buckling has its own icon
    • +
    • Fixes Xenobio monkey shortcuts not working
    • +
    • Bodyscanners are similar to sleepers; interact with them by clicking on the scanner; there is no console anymore
    • +
    • Summon guns/magic is no longer free, but costs 2 spells points
    • +
    • Summon guns/magic makes 10% of the crew antags with the objective to collect guns/magical items and kill anyone who gets in their way
    • +
    • If a wizard (or admin) summons guns/magic, latejoiners to the round will also acquire summoned items
    • +
    • Wizard's hardsuit is now battlemage armor
    • +
    • Battlemage armor protects you from pressure of space (but not the cold), has no slowdown, and a moderate amount of armor, however, it has 16 shields to block incoming attacks
    • +
    • Can purchase additional charges for your battlemage armor for 1 spell point
    • +
    • Shielded hardsuits now show the shield on the mob
    • +
    • Abductors, Skeletons, Shadowlings, and Plasmamen never get hungry
    • +
    • Abductors, Skeleton, and Plasmamen can't taste anything
    • +
    • Wood Golems now have a diet and taste sensitivity much like Diona
    • +
    • Unathi are more sensitive to tastes
    • +
    • Adjusted the sensitivity of "sharp" and "dull" tastes a bit
    • +
    • Slimes are a simple mob subtype
    • +
    • using a bloodlust slime potion on a docile slime removes the docility
    • +
    • using a docility potion on a rabid slime calms them down
    • +
    • slime core removal surgery steps are now just scalpel->hemostat
    • +
    • Slimes have action buttons to feed on, evolve, or reproduce
    • +
    • Fixes beepsky arresting slimes (maybe it should be a feature....)
    • +
    • Fixes Seed Vault gene modder having limitations
    • +
    • Fixes not being able to extinguish some items
    • +
    +

    Ionward updated:

    +
      +
    • Fixed Tajaran fat sprites, they are no longer duplicates of their slim torso.
    • +
    • Fixed fat aqua jumpsuit only using one direction.
    • +
    • Fixed missing Lasagna icon.
    • +
    +

    Kyep updated:

    +
      +
    • The Hierophant club and warp cubes (lavaland loot) no longer allow you to teleport into or out of areas that are set to forbid teleports.
    • +
    • Fixed a small bug that caused coins named "syndicate coin" or "antag token" to both incorrectly appear as "valid coin".
    • +
    +

    Markolie updated:

    +
      +
    • Fixed naked equipment selection and reincarnation not working.
    • +
    +

    TDSSS updated:

    +
      +
    • all huds are the first option when ghosts cycle through huds
    • +
    • fixed brig door timers from announcing admin names when stopped via admin powers.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • You can now silence the current midi with a verb in the preferences tab, without affecting your prefrence to hear midis in the future.
    • +
    +

    datlo updated:

    +
      +
    • Fixed clown changelings not losing comic sans on transformation
    • +
    • Clowns can now lose the clumsy and comic genes through DNA manipulation (but not mutadone)
    • +
    + +

    22 September 2019

    +

    Evankhell561 updated:

    +
      +
    • Mech ID upload panels now come with [add all] and [delete all] options
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes corpses/lying down mobs blocking projectiles
    • +
    +

    MarsM0nd updated:

    +
      +
    • can safely pick up nettles again
    • +
    +

    SteelSlayer updated:

    +
      +
    • Traitor and mindslave status is handled in a datum instead of the mind
    • +
    • You can no longer use a mindslave implant on a person with no mind
    • +
    • Adds the ability for admins to de-mindslave somone through the traitor panel
    • +
    • De-traitoring malf AIs via the traitor panel removes all instances of their Law 0
    • +
    • De-traitoring malf AIs via the traitor panel removes their ability to still state laws over the syndicate channel
    • +
    • De-traitoring malf AIs via the traitor panel removes their ability to shunt to hacked APCs
    • +
    • Unemagging borgs via the traitor panel properly removes their syndicate laws and gives them the crewsimov lawset
    • +
    • Unemagging borgs via the traitor panel who did not have a module selected does not cause a runtime anymore
    • +
    +

    TDSSS updated:

    +
      +
    • Just slight gloves refactor, shouldn't impact anything in game.
    • +
    + +

    21 September 2019

    +

    AzuleUtama updated:

    +
      +
    • The Captain's rapier can now be assigned as a theft objective.
    • +
    • Slime extracts and plasma tanks have been removed as theft objectives.
    • +
    • Document trading no longer counts towards a traitor's total number of assigned objectives.
    • +
    • Fixes a grammar error with the ambulance and slightly misleading description with the combat gloves.
    • +
    • Headpat gloves now inherit their click speed from the North Star gloves and are no longer as fast as before.
    • +
    • Sarin gas grenades no longer purchasable for nuke ops. balance: Grenadier belt now contains a sarin gas grenade. balance: Tactical medkit's hypospray tweaked to contain chems better for dealing with newcrit. balance: C20 bundle increased in price to 18TC, contains an additional clip of ammo. balance: Medical bundle increased in price to 20TC, Donk LMG removed, replaced with medbeam gun and magboots.
    • +
    • Fixed some minor spelling/grammar errors with synthflesh patches and sarin gas grenades.
    • +
    • R&D Console no longer has a default design called 'Name' show up in the mining category.
    • +
    • Syndie and Binary keys now use their own sprites rather than the default ones.
    • +
    +

    Couls updated:

    +
      +
    • Romerol virus that requires two traitors to team up to purchase
    • +
    • zombies that have a slow but steady health regeneration and cannot be killed permanently outside of decapitations and removal of the tumor in the brain
    • +
    • blood no longer stacks on itself endlessly
    • +
    • fixes footprints stacking
    • +
    • removes zombie from the secondary language list
    • +
    • hotkey menu option in the dropdown works correctly now
    • +
    • configurable limit to amount of monkeys that can be spawned by monkey cubes
    • +
    • handle_death is passed the gibbed variable
    • +
    • spec_death replaced with handle_death in romerol
    • +
    • you no longer hit yourself with things you throw
    • +
    • missing arguments in some procs
    • +
    • some macros that were defined twice
    • +
    • recycled monkeys were not being subtracted from the monkey cap
    • +
    +

    Dave-TH updated:

    +
      +
    • Fixes some vending machines (namely miner nanomeds) from adding all of their product twice.
    • +
    • Magical weapons can now be properly dual-wielded.
    • +
    • Fixes the description of energy shields, which said they block things that they do not.
    • +
    • Crayon drawings can stack again.
    • +
    • Crayons can no longer draw on multiple tiles at the same time, sorry octo-artist!
    • +
    • Fixes the lack of cooldown on attacking light fixtures.
    • +
    • Examining an air analyzer now informs you about its lesser-known function!
    • +
    +

    Emanthealmighty updated:

    +
      +
    • Updated the netherworld creatures' sprites.
    • +
    +

    Fox McCloud updated:

    +
      +
    • refactored gloves of the North Star to be more adminbusy
    • +
    • Adds Gloves of Headpats to the pet vendor as a premium item
    • +
    • Refactors the very core and soul of SS13 and enhances the code that powers it
    • +
    • Bible fartgibbing is now a form of suicide
    • +
    • Fixes mice coming back to life
    • +
    • Fixes nurse spiders not wrapping things
    • +
    • Fixes spiders not spazzing out
    • +
    • Simple mobs will now attack everything in the vicinity instead of just specific object types
    • +
    • Gutlunches now eat internal organs
    • +
    • ranged guardians don't rapid fire anymore, but have a lower cooldown on attacks
    • +
    • Fixes some turf underlays not working
    • +
    • adds in a wooden hatechet and rake to the ashwalker base; replaces the regular bucket with a wooden one
    • +
    • Fixes some blank tastes
    • +
    • Fixes not being able to brew fruit wine
    • +
    • Fixes poor TG copy pasta code that caused hundreds of runtimes
    • +
    • Reduces round-start lag
    • +
    • Fixes certain PDA cartridges causing insane performance loss
    • +
    • Carp Migration event no longer deletes the carp when it ends; they will continue to stick around the station
    • +
    • Personal crafting now has subcategories
    • +
    • Finishing crafting an item puts it in your hands instead of on the floor
    • +
    • comments out romerol (much like zombies, it will rise again, don't worry!)
    • +
    • zombies are high and lower pressure immune in addition to immune to heat and tox damage
    • +
    • Ian now has persistence; if he's killed, he'll start over life as a puppy--if he lives to a very long old age, he'll get a unique sprite
    • +
    • Pugs will now yipe on death and can bark
    • +
    • Adds new dog mob; a generic black dog
    • +
    • Foxes are now a dog subtype
    • +
    • Can manually yelp as a dog
    • +
    • All dog subtypes can now chase their tail and be given pats and pets. They all can additionally eat (and taste!) food
    • +
    • Nar-Sie will absolutely not tolerate sacrificing doggos
    • +
    • Ripleys are slightly faster on station, but dramatically faster on Lavaland
    • +
    • Mech mining drings can no longer drill through floors; they also don't just drill once. After a short delay, they'll attempt to drill the target, repeatedly.
    • +
    • Mech mining drills no longer instantly knock out mobs; if the mob is dead and has over 200 brute, the drill will attempt to harvest or gib the mob; can also disembowel
    • +
    • Mech plasma gun has a lower cooldown
    • +
    • Mining scanners apply a much brighter and visible overlay; mining a turf will now instantly clear the overlay
    • +
    • Mining mech (the one that's a lavaland find) has a partially depleted cell; it'll also no longer have multiple mining tools on it
    • +
    • Fixes null animal type with regards to pugs
    • +
    • Legion body loot adjusted; may find rare alternative mining belt or primitive one; bone bracers also show up on Ashwalkers; mini pickaxe spawn also possible
    • +
    • Large legions can damage objects
    • +
    • Small legion skulls no longer block mob movement
    • +
    • Basilisks are now gold core spawnable
    • +
    • Gutlunches no longer produce adult version of themselves, but have babies that grow into gutlunches
    • +
    • Mining belts can now hold pillbottles and shovels
    • +
    • Goliath cloaks hold different items now; more inclined to what Ashwalkers would use and not miners
    • +
    • Swarmer megafauna now has its proper GPS
    • +
    • Can't kill mining fauna by overheating them
    • +
    • new sprite for the Hierophant
    • +
    • Refactored tendrils; they won't show up on health HUDs anymore
    • +
    • Fixes Tendrils not emitting light
    • +
    • Fixes tendrils not changing the terrain around them
    • +
    • Fixes being able to exploit vending machines by deconstructing then reconstructing them to get additional items. Get an additional restocking units from cargo you filthy dirty exploiters
    • +
    • All vending machines require only a single restocking unit to build
    • +
    • Clothing, NanoMed, Wallmed, Vendomat, EngiVend, NutriMax, Megaseed Servitor, Sustenance Vendor, Dinnerware Vendor, Cart Tech, Robco Toolmaker, soviet BODA, security tech, and modular PC vendors are all now makeable/restockable
    • +
    • Most vendors can be damaged by brute force (Nanomed, wallmed, and youtool are notable exceptions)
    • +
    • Most restocking units can be ordered from cargo
    • +
    • Removed snowflakey laptop vendor
    • +
    • Adds in new laptop+tablet vendor; don't expect it to have as much (ask science for upgrade parts!)
    • +
    • Sustenance vendor has a new set of contraband if prisoners can actually hack the thing
    • +
    • breaks up the clothing restocking unit cargo pack from a single pack into 4 separate packs, 15 points each
    • +
    • Fixes Megafauna spawning near the base
    • +
    • Fixes lava rivers not forming
    • +
    • Upped the labor mineral spawn rate
    • +
    • Removed the ability to find random code-locked crates when mining
    • +
    • Watcher Icewing blasts will briefly freeze you
    • +
    • Fixes too much detecting corgis
    • +
    • Tweaks a few reagents tastes
    • +
    • fixes being able to taste metaphorical salt
    • +
    • nutriment no longer restores blood
    • +
    • Nuke ops can no longer advanced syndie magboots
    • +
    • Fixes an inconsistency with chameleon kit pricing--it was only 2 TC, making the no slip syndicate shoes worthless; price is now 4 TC
    • +
    • operatives pay 2 TC more for the no slip syndicate shoes and the chameleon kit
    • +
    • Wizard hardsuits no longer come with magboots
    • +
    • Syndie magboots are nuke ops only
    • +
    • Can purchase no slip shoes from the uplink instead of a full chameleon kit
    • +
    • Operatives can purchase no slip syndicate shoes
    • +
    • No slip shoes can protect against atmos pushing
    • +
    • removed most round-start magboots with the exception of EVA, atmostechs, CE, and engineering hardsuit dispensers
    • +
    • Fixes carp not being a threat to the station due to killing themselves
    • +
    • Fixes being able to exploit simple mob AI so it kills itself in an atmos death blender
    • +
    • vent and scrubbers work far more efficiently and quickly now
    • +
    • Fixes wideband on scrubbers constantly resetting itself
    • +
    • Portable scrubbers far more effective
    • +
    • Flamethrowers far more effective
    • +
    • Nanofrost twice as expensive
    • +
    • regular syndicate borgs don't have magpulse by default
    • +
    • Atmos pushing completely refactored; it'll still push you frequently and push items around frequently, but it won't throw you. Depending on how many dense objects or turfs are around you to "grab onto" will determine how effective atmos is at pushing you around. Does not alter the speed at which LINDA runs.
    • +
    • Plasma glass shards do less damage when attacking, but slightly more when stepping on them
    • +
    • Spears made out of plasma glass do slightly more damage
    • +
    • Light replacer can now be used in-hand to attempt to reload empty lighting fixtures around you in addition to showing how many lights it has
    • +
    • Light replacer needs less shards to increment bulbs
    • +
    • Updates moonflower, sunflower, novaflower, and pineapple sprites
    • +
    • Adds in Garlic
    • +
    • Fixes a few issues with incorrect values from the wine PR
    • +
    • Can now grow and extract the reagents/traits of Lavaland flora
    • +
    • Slightly tweaks soybean oil production on soybeans
    • +
    • Adds amusing garlic suicide
    • +
    • Ash Drake reworked; it's much more powerful now and has a diverse set of attacks--its fire breath is more random, it moves faster, it can turn the ground into lava, and once it's lower on health, will seal you into an arena and make you play the "only one turf is safe; stand on it or suffer" mini-game
    • +
    • Bubblegum is now much more difficult; instead of just spraying blood at you and attempting to endlessly charge you (walking backwards essentially counters it), it's now faster, engages in zig-zag attacks, uses a hallucination multi-attack, and can rapidly melee attack you in range
    • +
    • Fixes megafauana endlessly attacking dead mobs
    • +
    • Blood drunk Colossus, and Ash Drake made to be more player friendly if they control the fauna
    • +
    • Adds in Space dragon; a very weak version of the Ash drake which can't swoop, but can still breathe fire--has a spell that whips you back with its tail, too (not currently used anywhere)
    • +
    • The real Roman shield and real Roman helmets in the Autodrobe have been replaced by fake, armorless, varieties
    • +
    • Hierophant has been updated--it'll be a bit tougher and will attempt to trap you if you run for it.
    • +
    • Heirophant is no longer a weird bird thing, but a massive, indecipherable piece of machinery that will make you dance to ITS tune
    • +
    • Hierophant club is weaker up front, but becomes stronger the lower health you are
    • +
    • Fixes tendrils spawning inside ruins
    • +
    • Fixes light replacers breaking/hitting lights
    • +
    • Fixes blood drunk buff not making you slow immune
    • +
    • Regenerative core will give you 1 minute of slow immunity on application
    • +
    • carp sprites now support a wider range of colors
    • +
    • Megacarp names randomized in addition to their stats
    • +
    • Adds new friendly life reaction (strange reagent + synthflesh + sugar + heat)
    • +
    • Life reaction amount of critters spawned varies with created volume
    • +
    • Can now spawn the xeno maid, lightgeists, and bees with slimes cores/life
    • +
    • can no longer spawn the Shamebrero penguin with slimes cores/life
    • +
    • Adds new EVIL crab; is a "hostile" slime core/life mob
    • +
    • simple Xenos are a bit more powerful
    • +
    • Butchering simple Xenos now leaves a Xeno hide; use it to make a Xeno costume
    • +
    • Fixes spriteless dog
    • +
    • Fixes being able to spawn Proc with slimes cores/life
    • +
    • Fixes Blooddrunk being a flying mob
    • +
    • can move dense objects around corners
    • +
    • Removes unused, highly buggy VR code
    • +
    • Completely transitions to Lavaland for all maps. The mining asteroid and it's related bits are removed
    • +
    • Vox reworked
    • +
    • Vox are no longer spaceproof
    • +
    • EMP's no longer wreck cortical stacks
    • +
    • Vox cortical stacks are their brains; there's no longer two separate organs for Vox brain+cortical stack
    • +
    • Vox are immune to decay and will not skeletonize
    • +
    • Vox internal organs will never accumulate germs or decay, even when they're outside a Vox's body
    • +
    • Vox external organs do not accumulate germs when attached to their body
    • +
    • Vox have silent footsteps
    • +
    • Vox can process BOTH organic and synthetic reagents
    • +
    • Diona no longer decay into skeletons
    • +
    • Can now pick the species you want to play as for lavaland ghost roles
    • +
    • Golems have been buffed.
    • +
    • Golems are faster, better protected against damage, and have limbs that cannot break or be dismembered.
    • +
    • Golems are no longer virus immune
    • +
    • Golems can now wear labcoats and boxing gloves
    • +
    • Fixes golems being able to be healed/injected on parts other than the chest
    • +
    • Having a robotic chest allow you to wear an ID, PDA, and belt without a jumpsuit. Having a robotic right leg allows you to use your right pocket without a jumpsuit; same for your left
    • +
    • stepping on glass tubes now shatters them; can trip you up if you aren't wearing shoes
    • +
    • Stepping on a D4 will deal between 1 and 4 damage to you if you aren't wearing shoes and trip you up
    • +
    • skeletons have built in pierce immunity
    • +
    +

    Ionward updated:

    +
      +
    • Greys, Unathi, Tajaran, and Vulpkanin now have sprites for Lavaland reward hardsuits (Wizard, Elite Syndicate, and Paranormals), Biosuits, Voidsuits, and Syndicate Soft suits.
    • +
    • Plasmamen Librarians now have visible helmets.
    • +
    • Atmos Hardsuits now have inhand sprites again.
    • +
    • Added new uniform and hat to the AutoDrobe, the Rhumba outfit.
    • +
    +

    KasparoVy updated:

    +
      +
    • Tajaran characters can now have the tiny & short tails (plus marking).
    • +
    • Adds a striped tail marking for Tajara derived from the sriped/wingler body accessory to allow more flexible colouration.
    • +
    • Renames Vulpkanin alt. tails for brevity and easier keyboard navigation.
    • +
    +

    Kyep updated:

    +
      +
    • Fixed bug that made the syndicate depot impossibly difficult.
    • +
    • Various improvements to syndi depot, such as use of plastitanium walls, and nerfs to some cheese strategies.
    • +
    • Ported TG's simple_human.dmi, a sprite file of humanoid sprites (including syndicates).
    • +
    • Added a few extra syndi sprites from FoS.
    • +
    • fixed an issue with keyboard input
    • +
    • Brig timers now display the job of brigged people. E.g. "Joe Schmoe (Chemist) was incarcerated" as opposed to just "Joe Schmoe was incarcerated".
    • +
    • Brig timers now notify a person's boss via PDA when they are incarcerated. E.g. if a chemist is temporarily brigged, the CMO is notified of the brigging via PDA.
    • +
    +

    Markolie updated:

    +
      +
    • Guardian communciation now longer shows up to players in the lobby.
    • +
    +

    Mocha-Not-Latte updated:

    +
      +
    • Fixes #12354
    • +
    +

    Shadow-Quill updated:

    +
      +
    • Fixed ATM withdrawals doubling.
    • +
    • Fixed Fore Port Solars' APC not charging.
    • +
    • Fixed a typo in admin gloves of rapidness.
    • +
    • Plasma cutters will no longer eat plasma if you try recharging a full gun.
    • +
    • Blobs now get a audio notification roundstart (like traitors do.)
    • +
    +

    SomeSortaSquid updated:

    +
      +
    • Karma purchases no longer loop infinitely, leading to repeated purchase prompts or "You do not have enough karma!" message after successful purchase.
    • +
    +

    SteelSlayer updated:

    +
      +
    • The AI and magistrate get bold text when the "louder command members" telecomms setting is on
    • +
    • Command members will get the first letter of their radio message auto capitalized when the "louder command members" telecomms setting is on
    • +
    • Malf AI's overload machine & override machine action button behavior is changed to a point and click style ability.
    • +
    • Added some new mouse pointer icons for the machine overload and machine override abilities
    • +
    • The "Show Player Panel" verb is now right click only
    • +
    • The "C.M.A. - Admin" verb is now right click only
    • +
    • The "C.M.A. - Self" verb is now right click only
    • +
    • The "Check Contents" verb is now right click only
    • +
    • The "Freeze" verb is now right click only
    • +
    • The "Freeze Mech" verb is now right click only
    • +
    • The "Jump to Turf" verb is now right click only
    • +
    • The "Update Mob Sprite" verb is now right click only
    • +
    • The "List SSDs" and "List AFKs" verbs have been combined into one verb named "List SSDs and AFKs"
    • +
    • The "Resolve All Open Mentor Tickets" verb has been moved inside the mentor ticket interface window
    • +
    • The "Resolve All Open Admin Tickets" verb has been moved inside the admin ticket interface window
    • +
    • Increases the width of the new "List SSDs and AFKs" window a bit
    • +
    • The gravitational catapult no longer pushes ghosts when used
    • +
    • Fixes a runtime preventing walls from being repaired properly
    • +
    • Adds the ability to repair and remove bullet holes from reinforced walls that have no structural damage
    • +
    +

    TDSSS updated:

    +
      +
    • local gps signals, visible only on the same z level
    • +
    • lavaland mob signals were made local, reducing gps clutter
    • +
    • Objective to abductors to not disrupt crew too much.
    • +
    • healing fountain lavaland ruin now correctly heals
    • +
    • lowered attack log level of self-harm
    • +
    • certain harmless chems and food have reduced attack log logging levels
    • +
    • the most grave of wrong tips
    • +
    • The uplink dart gun now comes with some syringes to use with it.
    • +
    +

    Terilia updated:

    +
      +
    • stat_attack from unconscious to dead
    • +
    • added new headcrabs (poison and fast)
    • +
    • added new headcrab sounds for the poison headcrab and the fast zombie
    • +
    +

    TheMadTrickster updated:

    +
      +
    • fixed wonky/bugged sprites for custom guitar and hair gel
    • +
    • new improved clean sprites for custom items
    • +
    • old messy sprites for custom items
    • +
    +

    TheSardele updated:

    +
      +
    • Changes the attack log setting required to have the blood-drunk miner buff actively log to all attack logs.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Headpat gloves added to arcade machine prizes
    • +
    • Minor ban evasion update
    • +
    • Autonote for manual bans removed
    • +
    • SSD players no longer drown in shallow water
    • +
    • Admins can now autoreply with common answers to common questions / issues.
    • +
    • Opening an adminhelp/mentorhelp ticket will play a sound
    • +
    • Adminhelp ticket information color changed from neon green to a more toned down green
    • +
    • Global admin midis will now silence lobby music for those who have midis enabled.
    • +
    • Adds "Man Up" to autoreply
    • +
    • Autoreponses now show up as the last admin response in tickets
    • +
    • Fixes an issue where autoresolve was appearing in mentorhelps to mentors
    • +
    • Resolve button on adminhelps and mentorhelps work again
    • +
    • Fixes reversed logic in autorespond confirmation alert
    • +
    • Removed custom admin event info that only admins could view due to confusion with the regular non-admin verb.
    • +
    +

    datlo updated:

    +
      +
    • Added the Banana Touch and Mime Malaise spells to the Wizard spellbook.
    • +
    • Station goal crates now come in engineering crates.
    • +
    • Replaced the red emergency toolbox in hermit ruin by a regular blue toolbox.
    • +
    +

    farie82 updated:

    +
      +
    • Hoodies now work like they do in TG. Less abuse of NO DROP, more better
    • +
    • Welding a tile away now gives a more useful message when doing so.
    • +
    • Admins now don't get spammed by hugs.
    • +
    +

    kazboo updated:

    +
      +
    • added a nice metalic alarm sound for when the nuclear self-destruct is activated on the station.
    • +
    • candle boxes on the station are now properly filled
    • +
    +

    variableundefined updated:

    +
      +
    • Multiple food now have their own tastes
    • +
    • Corgi and mice can now taste food
    • +
    • Hallucination causes you to taste strange things
    • +
    • Nutriments now carry over the tastes of food
    • +
    • A quick resolve button to adminhelp and mentorhelp message!
    • +
    • Config option to let gamemode ignore the number of required players.
    • +
    • Hit_reaction proc has been refactored.
    • +
    • Flamethrower and grenade detonation by shot is now logged.
    • +
    • Refactored wooden chair so placing them won't make you see normal metallic chair anymore.
    • +
    • Contribution guideline has been updated. No in game changes.
    • +
    • Github pull request template has been changed
    • +
    • Officer starter pack to cargo. For 30 cargo points you can equip an officer just like an officer closet! Backpack not included due to budget cut.
    • +
    +

    xProlithium updated:

    +
      +
    • Replaced link to CA (check antags) in adminhelps, tickets, and adminmoreinfo with a link to TP (traitor panel)
    • +
    • Altered CA to TP for prayers and adminpms.
    • +
    + +

    30 August 2019

    +

    AffectedArc07 updated:

    +
      +
    • Fixes the changelog
    • +
    +

    Arkatos updated:

    +
      +
    • Added new icon for Charge spell
    • +
    • Added new icon for No Clothes spell
    • +
    • Added new icon for Wizard spellbook
    • +
    • Added new animations to 10 single-use spellbooks
    • +
    • Added new sprite for Bottle of Tickles
    • +
    • Added refunding functionality to the Bottle of Ooze akin to the other summoning bottles. Click with the bottle in hand on a wizard spellbook to refund its cost and limit slot.
    • +
    • Fixed an issue where Bottle of Tickles did not properly refund
    • +
    • Fixed an issue with alpha layering on Bottle of Ooze sprite
    • +
    • Very slightly adjusted brightness of the Boo! ghost spell icon
    • +
    • Wizard spellbook was completely reorganized, and new appropriate categories were added, each category is sorted by price, and if price of the two or more spells is the same, they are sorted alphabetically
    • +
    • Polymorph can now turn a mob into Syndicate medical or saboteur modules
    • +
    • Mobs made via polymorph into borgs are now unbounded free borgs
    • +
    • Repulse spell cost decreased from 2 to 1
    • +
    • Lighting bolt spell cost decreased from 2 to 1
    • +
    • Slaughter/Laughter demons and Magical Morphs now always have their second fluff objective considered as complete no matter the circumstances
    • +
    • Laughter Demons very slightly buffed, they are still a bit weaker than Slaughter Demons
    • +
    • Improved descriptions and wording regarding Wizard spellbook and Wizard spells
    • +
    • Traitor AI now uses action buttons for its malfunction abilities
    • +
    +

    AzuleUtama updated:

    +
      +
    • Adds false-bottomed briefcase from VG.
    • +
    +

    Couls updated:

    +
      +
    • Rechargers can now be crafted from science using one capacitor and a recharger board tweak:Smaller machines like microwaves and cell chargers can now be placed on tables(Fax machines included) tweak:can screwdriver open rechargers and then apply a crowbar to deconstruct them
    • +
    • Blood spread now depends on volume of the blood, requires more drips of blood to create a pool
    • +
    • DUAL WIELDING
    • +
    • new chatsubsystem from TG!
    • +
    • Update issue templates to latest version and clean up the current template
    • +
    • mining shuttle warning message and delay before launching
    • +
    • cardboard boxes are no longer sonic speed
    • +
    • shuttle timers now get set properly
    • +
    +

    EmanTheAlmighty updated:

    +
      +
    • Blobbernauts can now be controlled by players through a prompt which appears when they are spawned by blobs.
    • +
    • Blobbernauts and blobs can now communicate with each other.
    • +
    • Blobbernauts now regenerate health overtime when standing on blob structures.
    • +
    • Blobbernauts will slowly lose health if they are not standing on blob structures while not at full health. balance: Blobbernauts have been nerfed, they now have less health, deal less damage and cannot break walls anymore. balance: Blob's "Produce Blobbernaut" ability has been made more expensive to use, now costing 60 resources instead of 20.
    • +
    +

    Emanthealmighty updated:

    +
      +
    • The poll to play as a blobbernaut now lasts 10 seconds from 15.
    • +
    • Blobbernauts no longer chase after people while players are being polled to play as one.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Plasmamen dramatically overhauled.
    • +
    • Plasmamen can be cloned without burning to death in the clonepod
    • +
    • Plasmamen no longer start with spacesuits
    • +
    • Plasmamen start off with jumpsuits that seal to protect against oxygen. This allows for you to customize their appearance more
    • +
    • Plasmamen helmets now allow you to see a Plasmaman's actual face; should be able to see their eye color and mouth color now
    • +
    • Plasmamen take 50% extra brute and burn
    • +
    • Plasmamen are immune to radiation
    • +
    • Plasmamen start out with a small tank that can fit on a belt or in a pocket; it should be enough to last an entire shift
    • +
    • Plasmaman helmets now have built in welding goggles
    • +
    • Plasmaman karma cost lowered from 100 to 45
    • +
    • Reworks Diona
    • +
    • Diona bleed (call it chlorophy; it's green)
    • +
    • Diona Breathe (plants do need to exchange gas after all)
    • +
    • Rad Immunity Removed
    • +
    • Diona regenerate 1 OXY, 1 BURN, 1 BRUTE, and 1 TOX if they are in a bright area; this effect does not kick in if they're in crit
    • +
    • Diona no longer have unbreakable bones (wood can crack ya know!)
    • +
    • Diona are no longer space proof
    • +
    • Diona are more vulnerable to fire and heat damage
    • +
    • Diona weakness to weedkiller dramatically nerfed
    • +
    • Diona now use Newcrit
    • +
    • Diona are no longer slow
    • +
    • Diona can wear spacesuits
    • +
    • Fixes stun absorbing not working
    • +
    • Fixes parallax insane setting not doing anything
    • +
    • Ores can be destroyed by devastating explosions
    • +
    • silver, gold, and diamond pickaxes do a bit more damage and mine faster than before
    • +
    • drills slightly slower, but diamond drills slightly faster
    • +
    • Spade is the same speed as a shovel
    • +
    • Hivelord stabilizer will now make a hivelord core/legion soul stabilize and be preserved, even if it was previously inert
    • +
    • can use a hivelord core in your active hand to apply it to yourself
    • +
    • soulstone in the abandoned locked crates can now be used by anyone
    • +
    • Adds firelemon seeds to the abandoned locked crates as potential loot
    • +
    • Hardsuits have an integrated helmet; you no longer have to attach helmets
    • +
    • Toggling up/down helmets is now done with an action button
    • +
    • can no longer attach magboots to a hardsuit
    • +
    • Hardsuit base melee armor increased from 10 to 30
    • +
    • Security and HoS hardsuit melee armor increased by 5
    • +
    • HoS hardsuit helmet armor matches his hardsuit
    • +
    • CE's hardsuit helmet armor for rads increased by 10 (should be fully rad proof now)
    • +
    • Elite syndicate suits can't be acided
    • +
    • Fixes stuns and weakens related to reagents
    • +
    • Fixes the displayed cost of Plasmamen
    • +
    • Adds jetpack hardsuit upgrades: get yours at mining for 2000 points
    • +
    • Removes mining carbon dioxide jetpack
    • +
    • Can no longer use jetpacks in your suit storage slot
    • +
    • Chief Engineer's hardsuit, Syndicate Hardsuit (normal and elite), and Shielded Syndicate Hardsuit all have built in jetpacks
    • +
    • Fixes random singularity releases from the grid check event
    • +
    • loadout costs for most things cut from 2 to 1
    • +
    • Adds fingerless gloves, eyepatch, prescription glasses, black shoes, brown shoes, white shoes, and ian's shirt to the loadout
    • +
    • moved hipster glasses from donator to general glasses
    • +
    • Adds in sandbags. Use them to deploy destructable barriers; miners start off with a few
    • +
    • Removes access based security barriers
    • +
    • Adds in security barrier grenade. When it goes off, it will deploy up to 3 barriers that will lock into place; should find 4 of these in the armory
    • +
    • can tear up bedsheet and gauze to get cloth--requires a sharp object
    • +
    • Fixes plasmamen atmos techs not getting their proper suit
    • +
    • Adds in a loom, craft one out of 10 wood
    • +
    • Adds in cotton and durathread cotton to botany to grow
    • +
    • Adds in a number of expanded items to create out of cloth, such as improvised gauze, beanies, and softcaps
    • +
    • Adds the ability to use personal crafting to make durathread jumpsuits, bandanas, armor, helmets, beanies and berets. Aside from the bandana, these all have minor armor on them
    • +
    • Adds a number of new items to personally craft, related to clothing: ability to make health, sec, diagnotic, and reagent sunglasses.
    • +
    • Can additionally craft cowboy boots, lizardskin cowboy boots, fannypacks, and a spooky ghost disguise
    • +
    • adds a whole range of beanies, find them in the clothing vendor or make them yourself
    • +
    • Updates the cowboy boots sprites
    • +
    • Unironically fixes about several thousand runtimes
    • +
    • Fixes jackets not keeping you warm
    • +
    • Chefs are now trained in the art of Close Quarters Cooking
    • +
    • Adds the Book of Babel as tendril loot
    • +
    • Adds Jacbo's Ladder as tendril loot
    • +
    • Fixes fungus, blood, and graffiti not showing up on a wall
    • +
    • Fixes the lavaland inquisitor and berserker hardsuits having incorrect armor and slowdown values
    • +
    • Fixes baseball bats throwing anchored things
    • +
    • Fixes blood drunk buff
    • +
    • Fixes using a crusher on a trophy to equip it causing you to drop the crusher
    • +
    • refactors lazarus capsules; no real behavioral change
    • +
    • Fixes being able to revive megafauna with strange reagent
    • +
    +

    Fox McCloud and FullOfSkittles updated:

    +
      +
    • Tweaks the gummy worm, gummy bear, jeallybean, toffee, and bacon sprites
    • +
    • Fixes telebacon not properly acting as...well, a bacon beacon
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added an Engine Picker, which uses new engine beacons.
    • +
    • Replaced the current two engine generators with one engine beacon.
    • +
    +

    Ionward updated:

    +
      +
    • Drask crewmembers now have properly fitting shoes.
    • +
    • Fixed some minor issues in Drasks uniforms
    • +
    • non-humans now have proper sprites for durathread goods
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds sprites for all Vox & Armalis earwear.
    • +
    • Adds sprites for Armalis default backpack, nitrogen tank (old-style back & new-style belt) & all breath mask variations.
    • +
    • You can now species-fit in-hand icons: Use a single .dmi file and suffix the icon states with _l or _r.
    • +
    • Fixes an issue preventing Vox Armalis from being rendered with the proper in-hand icons for their massive noise cannons.
    • +
    • Fixes an issue preventing the species-fitting of earwear.
    • +
    • Fixes an issue preventing Vox Armalis from wearing the 'Vox' breath mask.
    • +
    • Picking up uniforms no longer renders a default grey jumpsuit on Vox.
    • +
    • Resolves an issue causing shining eyes to be rendered darker than intended.
    • +
    • Resolves an issue preventing appearance features (hair, eyes, etc.) from rendering on disembodied heads.
    • +
    • Resolves an issue preventing Admin-revived decapitated bodies from having appearance features or ears.
    • +
    • Non-shining eyes render the proper colour again.
    • +
    +

    Kurgis updated:

    +
      +
    • Beepsky now bumps around on its wheels when patrolling for crime.
    • +
    +

    Markolie updated:

    +
      +
    • A new outfit manager has been added for admins (under debug). It lets them save and load custom outfits on their computer and use these to equip players.
    • +
    • Upon transforming players into humans or reincarnating them through the player panel, admins will now directly be able to select their equipment.
    • +
    • The select equipment verb now works on observers: it'll create a human with the given equipment under the ghost.
    • +
    • A "Copy Outfit" button has been added to the View Variables dropdown, which lets admins instantly copy an outfit.
    • +
    • Outfits now support accessories and internal boxes.
    • +
    • The separate option to equip ERT members has been removed. It's been integrated into their regular outfits.
    • +
    • Water coming from sinks and certain water effects is now 10C instead of body temperature.
    • +
    +

    Shadow-Quill updated:

    +
      +
    • [Meta] Added buckshot and slugs to armoury.
    • +
    • [Meta] Added surgical tools, robotic first aid kits, and a photocopier to Robotics.
    • +
    • [Meta] R&D doors now has proper access requirements.
    • +
    • [Meta] Added RCS and telepad to cargo.
    • +
    • [Meta] Disposals sheet stacker and conveyor belts now works properly.
    • +
    • [Meta] One-way airlocks added in Medbay/Brig.
    • +
    • [Meta] Disposals sheet stacker disposals chute leads directly to the mailroom.
    • +
    • AIs not being able to restore their own power if in an area with an APC.
    • +
    • Fixed being able to talk in OOC under certain circumstances if it's disabled.
    • +
    • Lockers can no longer move around anchored mobs.
    • +
    +

    SteelSlayer updated:

    +
      +
    • You can no longer spam dismantle a SMES terminal and get 10 cable for every progress bar
    • +
    • The game will properly remove 10 cable from your stack after building a SMES terminal, instead of removing 0
    • +
    • A cable adding sound gets played when you add wires to create a terminal for a SMES
    • +
    • Rapid pipe dispensers can now place disposal sorting pipes
    • +
    • When changing the sort location of a disposal sorting pipe, the name of the pipe now also changes to the desired destination
    • +
    • Added a destination tagger to the atmosheric technician locker
    • +
    • Added atmospherics access to Engi-Vend's and Engineering checkpoint airlocks
    • +
    • Removed some random grey pixels from disposal sorting junction pipe sprites, and certain normal disposal junction pipe sprites
    • +
    • IV bags are able to transfer their contents to other containers by clicking on them with the bag
    • +
    • Adds a handheld defibrillator to the paramedic EVA closet
    • +
    • You can insert magazines into L6 SAWs again
    • +
    • Removed one of the high capacity tanks in hydroponics
    • +
    • Added a disk compartmentalizer to hydroponics
    • +
    • Delaying round start actually delays round start again
    • +
    +

    Terilia updated:

    +
      +
    • added headcrabs
    • +
    • adjusted the path's for headslugs. They are not called headcrab anymore
    • +
    +

    TheSardele updated:

    +
      +
    • Removes the ability of obese people and those with matter eater to swallow others.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Fixed a bug where hotwiring solar panels would allow for the station to remain powered in the Grid Check power failure event.
    • +
    +

    datlo updated:

    +
      +
    • Added ashstorm immunity to titanium and plastitanium golems.
    • +
    • Added lava immunity to plastitanium golems.
    • +
    • Bananium golems now slowly waddle around.
    • +
    • Uranium golems now properly irradiate nearby mobs that arent rad immune.
    • +
    • Tranquillite golems now properly get their miming powers.
    • +
    • Added the Clown and Winter biodomes as possible lavaland ruins.
    • +
    • Update a changeling error message to be clearer.
    • +
    +

    farie82 updated:

    +
      +
    • Items with NODROP that are dropped now lose the flag if they didn't get created with it
    • +
    • Adds tip text to the examine text of the ambulance trolley about how to attach it
    • +
    • Adds tip text to the nuke when trying to use the NAD before deploying it
    • +
    • Adds tip text to the fire axe cabinet about how to lock/unlock it
    • +
    • Adds tip text to airlocks if they have a note on them about how to remove the note
    • +
    • Can't put the NAD in the nuke now when it has the NODROP flag
    • +
    • Locking a fire axe cabinet is less weird now. No odd 5 seconds sleep
    • +
    • Can't put a nodrop fire axe in fire axe cabinets now. Duping them
    • +
    • Implants like the IPC charging work again. They won't get deleted after first use
    • +
    +

    variableundefined updated:

    +
      +
    • A proc's name got changed. That's it
    • +
    + +

    23 August 2019

    +

    AffectedArc07, Keekenox, Floyd/Qustinnus updated:

    +
      +
    • P A R A L L A X (That fancy space thing)
    • +
    • Adds a new Parallax layer that resembles Lavaland (Lava Planet), it spawns on a random location near the station. You need your parallax on high to see it.
    • +
    +

    Arkatos updated:

    +
      +
    • Added colored pillbottles
    • +
    • Added an option to change color of the pillbottles to ChemMaster3000
    • +
    • Added new description to patch packs
    • +
    • Jump to Node ability now shows a location of each Blob node
    • +
    • Added SlimeHUD when playing as a slime. This means slimes will have their own unique health doll and pull icon.
    • +
    • Action buttons can now be dragged onto each other to swap places
    • +
    • Fixed a case where dragging locked action buttons could result in white tooltip over the screen
    • +
    +

    AzuleUtama updated:

    +
      +
    • The Traitor thermal glasses and chameleon security HUD now use the updated chameleon code. balance: Traitor thermal glasses will no longer cause eye damage when hit with EMP.
    • +
    +

    Citinited updated:

    +
      +
    • Removes the big pipe dispensers from atmospherics, you can still find them elsewhere.
    • +
    +

    Couls updated:

    +
      +
    • After many complaints about being stuck in medbay. NT has modified all the airlocks on the station to allow leaving certain departments without requiring an respective ID. This new modification is indicated by a white light near the airlocks in the direction of unrestricted access.
    • +
    • New unrestricted access can be built by NT engineers through modification of the airlock electronics.
    • +
    • hit effects!
    • +
    • hit effect sprites for lasers, bullet hole and dent decals for walls
    • +
    • mice now have a very low chance of chewing through wires, this kills them if the wire is powered
    • +
    • You can now homerun things thrown at you with a baseball bat!
    • +
    • new baseball hit noise, new baseball sprite
    • +
    • there are much less one-way airlocks on station
    • +
    +

    DoctorDrugs updated:

    +
      +
    • removed the ability to eat the divine vocal cords
    • +
    +

    EmanTheAlmighty updated:

    +
      +
    • The AI can now change its intent by clicking on the new on-screen button or pressing 4 to switch to help or harm.
    • +
    • The AI can now toggle airlock safeties instead of toggling door bolt lights by pressing middle mouse.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Majorly updates lavaland
    • +
    • Miner starting equipment altered. They now start with a kinetic accelerator
    • +
    • Miners start off with a mini pickaxe
    • +
    • Adds in the boxed implant kit, regular shelter capsule, and mining drone passthrough upgrade to the mining equipment vendor
    • +
    • re-ordered the equipment vendor, so things are grouped together more logically
    • +
    • Added a number of new kinetic accelerator upgrades acquirable through tendril chests
    • +
    • Mining bot now uses an actual kinetic accelerator as opposed to a "Look alike"; you can upgrade its internal gun with various kinetic accelerator modkits.
    • +
    • Sentient mining bot nerfed; you can no longer apply the armor or melee buff to them; offset by the fact you can upgrade their kinetic gun.
    • +
    • Indoor pressure mod removed from R&D and made into a miner traitor item
    • +
    • Resonators have an increased amount of fields and do more damage in low pressure. Additionally, if you place a field on a tile that already has a field, it'll cause it to detonate early
    • +
    • Plasmacutter no longer does increased damage in low pressure, Advanced plasma cutter does slightly more base damage but has a bit less range. Price has been cut at R&D
    • +
    • removed the AoE Mob+Turf upgrade for mining pods
    • +
    • Fixes ripleys being slow on lavaland
    • +
    • Fixes walking on lavaland sounding like walking on metal plating
    • +
    • Adds in kinetic crusher trophies
    • +
    • Kinetic crusher can be wielded/unwielded (but you can't attack with it unwielded)
    • +
    • Adds the HECK suit as Bubblegum loot
    • +
    • Adds the kinetic accelerator bounty mod as Tendril loot
    • +
    • Add fulton extract packs to the mining vendor; rescue precious valuable or dead miners!
    • +
    • Adds mini-fans to the mining, engineering, and security shuttles
    • +
    • Adds a number of primal recipes: rake (cultivator), wooden bucket, firebrand (long burning match), and bone bracers (armored arm protection that goes on your glove slot)
    • +
    • Can attach bayonets to C20rs, bolt action rifles, security auto-rifles, and kinetic accelerator; harm intent to stab with them
    • +
    • can craft ore boxes out of wood
    • +
    • Skull helmets are now proper helmets
    • +
    • Survival autoinjectors tweaked
    • +
    • Survival autoinjectors have 15 units of teporone in them
    • +
    • Survival autoinjectors have double the epinpehrine and weak omnizine instead of saline glucose.
    • +
    • lavaland extract altered; it no longer heals tox or oxy, and heals slightly less brute and burn, but has nearly halved the metabolization rate and has a less harsh overdose
    • +
    • Fixes airlocks spamming their open and close when you stand in them
    • +
    • Fixes overriden door timers not working
    • +
    +

    Fox McCloud and FullofSkittles updated:

    +
      +
    • Changes the Venus Human Flytrap sprite
    • +
    +

    Ionward updated:

    +
      +
    • Adjusted Greys uniforms and backpack sprites.
    • +
    • Added a bunch of Drask masks and glasses.
    • +
    • Added God Eye sprites for Greys, Drask, and Vox.
    • +
    +

    JKnutson101 updated:

    +
      +
    • Issue where Emergency NanoMed Vendors required Medical ID to Access.
    • +
    • Added the ability for cyborgs with zero battery to use the 'succumb' verb.
    • +
    +

    Markolie updated:

    +
      +
    • Players now have thirty seconds instead of just five seconds to select if they want to be somebody's butler through a die of fate roll.
    • +
    • The Netherworld portal is now properly destroyed upon being killed. In addition, its max health is now equal to its starting health.
    • +
    • The iron ore sprite that shows up when using the miner scanner no longer has a background, making it blend in better with the actual rock.
    • +
    • Tightening the bolts of a falsewall now works properly.
    • +
    • Deconstructing plating now requires it to be unfastened using a screwdriver first, in order to prevent it from being accidentally deconstructed with a welder.
    • +
    +

    Quantum-M updated:

    +
      +
    • Minor grammar edits to the text that tells you that your thirst is dealt with but no blood power is given. balance: Vampires are no longer able to drink get power from ckeyless humanoid monkeys, they will now need to hunt down actual characters with ckey to get power.
    • +
    +

    Shadow-Quill updated:

    +
      +
    • Mass drivers now need two rods/cable coil instead of three to construct.
    • +
    • The RD's office door can now be opened by the RD, instead of by just the Captain.
    • +
    • Science lockdown can now only be (de)activated by the RD, instead of any scientist.
    • +
    • Using a health analyzer in-hand will switch the verbosity.
    • +
    • You no longer have to unscrew a plating to repair it.
    • +
    • The shivering symptom in virology now properly chills people.
    • +
    +

    SteelSlayer updated:

    +
      +
    • Wizard rounds now end if all wizards and apprentices are either dead, inside cyborgs, or in MMIs
    • +
    • Re-enabled the wizard's hud. Wizards can now see their own antag icon along with seeing other wizard's and apprentice's icons
    • +
    • When a cult sacrifice target leaves the round via cryo, the game will reassign a new target for them
    • +
    • Added an alarm sound that plays for cultists when their sacrifice target leave the round via cryo
    • +
    • When a cult sacrifice target leaves the round via cryo, the game will update every cultist's notes to reflect the change
    • +
    • Adds a new verb named "Toggle Health Scan" to the ghost tab. While toggled on, ghosts can perform health scans on humanoids and cyborgs by left clicking on them
    • +
    +

    TDSSS updated:

    +
      +
    • syndicate fax machine to lavaland syndie base.
    • +
    • syndicate lavaland base self destruct now requires syndie access.
    • +
    • moved headsets in lavaland syndie base.
    • +
    • Gave the HoP fax long-ranged faxing capabilities.
    • +
    • midround event spawned xeno larva now need less time to grow up and evolve.
    • +
    • cult talisman got unique icons to tell them apart
    • +
    • mining hardsuits come with helmets now again
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Whether you join the ERT is no longer determined by how fast you click "yes" on the prompt.
    • +
    • Drag and drop support and 20 seconds to pick ERT role instead of 15
    • +
    • Fix extra newline after field and disable Github Flavored Markdown in papers (normal markdown still works)
    • +
    • autogenerated papers no longer appear as HTML code
    • +
    • message window links added to PM send receipt
    • +
    • Many shuttle flight directions fixed
    • +
    +

    TheSardele updated:

    +
      +
    • All-In-one Grinders can now be constructed and upgraded
    • +
    • All-In-one Grinders now produce more reagents when upgraded.
    • +
    • Icon for cybernetic eyes
    • +
    • Sleeping while drunk no longer makes you more drunk.
    • +
    +

    dovydas12345 updated:

    +
      +
    • Fixes being able to pick up chairs and stools when you have items in both hand or when you don't have hands.
    • +
    • Adds a ERT shuttle console which is accessible to ERT members
    • +
    +

    farie82 updated:

    +
      +
    • Rigging a crate now doesn't delete your coil stack anymore but instead uses 15 of it. Borgs can use it safely again
    • +
    +

    kazboo updated:

    +
      +
    • adjusts the hierophant blast layer to make for it to always be below the effect. this should be the case already due to mouse_opacity, though for some unknown reason, it just doesn't work sometimes, so this should fix it.
    • +
    + +

    12 August 2019

    +

    AffectedArc07 updated:

    +
      +
    • Panic Bunker
    • +
    +

    Allfd updated:

    +
      +
    • Panthers can now see in the dark.
    • +
    +

    Arkatos updated:

    +
      +
    • You can ctrl-click any action button to lock/unlock its position
    • +
    • All actions buttons now start with their position locked
    • +
    +

    Citinited updated:

    +
      +
    • Mappers have a new tool that creates a fully functional cycling airlock.
    • +
    +

    CornMyCob updated:

    +
      +
    • The cursed heart you get from necropolis chests is now the one that heals you.
    • +
    +

    Couls updated:

    +
      +
    • Diagonal movement
    • +
    • Input subsystem(numpad targetting, press numpad 8 multiple times to target eyes and mouth, numpad 6 or 4 to target arms and press them again to target hands and numpad 1 or 3 to target legs and press them again to target feet) taken from https://github.com/tgstation/tgstation/pull/32751
    • +
    • change confused status to have you move diagonally randomly in the direction you're headed if not too confused(now you can drunkenly walk down the hall)
    • +
    • clients are now children of datums like everything else in BYOND taken from https://github.com/tgstation/tgstation/pull/20394
    • +
    • AZERTY and numpad targetting preferences
    • +
    • Reworks the biohazard event to have a chance of giving a randomized advanced disease with 6 varying symptoms instead of a preset disease.
    • +
    • change how bone breakage is calculated
    • +
    • can now butcher koi for salmon meat
    • +
    • adds a line to alert people as to why they're not getting blood from the monkeys
    • +
    • The vampires are finally off their monkey diet, theycan now suck blood from players and humanized monkeys
    • +
    • Symptoms are now correctly generated for level 7 biohazards
    • +
    • Borgs can now cycle modules with X again
    • +
    • Ahelp message is less confusing
    • +
    • F2 (say) F3(ooc) F4(me) buttons have been restored tweak:when numpad targetting is off you can use numpad 1-4 to change intents tweak:pressing shift before any of the intent buttons doesn't change intents(for people with shift+1-4 macros) tweak:backspace now sets the focus to the chat bar
    • +
    • fixes the runtime caused by running keyloop for clients
    • +
    • Preferences not saving properly
    • +
    • issue with preload_rsc
    • +
    • Restore hotkey mode
    • +
    • Q no longer drops items as a cyborg on AZERTY mode
    • +
    • Automatically offload ore you're carrying to an orebox you're dragging
    • +
    • typing indicators show up again
    • +
    • TG waddle component, clowns can now optionally waddle, penguins always waddle. Ctrl Click clown shoes in hand to toggle waddling
    • +
    • Added invismin macro back to F9
    • +
    • stealthmin macro removed from F9
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Fixes a bug that would cause ghosts to teleport their bodies sometimes
    • +
    +

    Dave-TH updated:

    +
      +
    • The syndicate uplink is now complete with a new spooky background. Very neat!
    • +
    +

    DoctorDrugs updated:

    +
      +
    • Adds additional roundstart miner slots and the additional gear required for them to do their jobs
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes being able to sharpen toy double-bladed energy swords
    • +
    +

    IAmBigCoat updated:

    +
      +
    • Added explosion warnings to medbeams, because medbeams can cause explosions. DON'T CROSS THE BEAMS!
    • +
    +

    Ionward updated:

    +
      +
    • Fixed vox jester uniform not appearing correctly.
    • +
    • species specific fit underwear for greys
    • +
    +

    KasparoVy updated:

    +
      +
    • Re-adds the ability to see in the dark. Adds overlays for each level of darksight (>=8,7,6,5,4,3,<=2).
    • +
    +

    Kyep updated:

    +
      +
    • Round time (h:mm) and station security level (green/red/blue/etc) are now visible on our server hub entry.
    • +
    • Round time is now visible to all player-controlled mobs in their status panel (including simple animals).
    • +
    • Admins using the 'MOST' attack log setting no longer see player-v-NPC combat, or any attack logs generated in the admin room, admin testing area, thunderdome arena, or lavaland syndicate base. Prevents admins being spammed with attack logs.
    • +
    • Heads of department may now issue department-specific medals to members of their department.
    • +
    +

    Markolie updated:

    +
      +
    • Humans and mice that are secretly blobs now have an antagHUD icon.
    • +
    • All hivemind languages now display follow links to ghosts.
    • +
    • Announcements, whispers (with ghost ears) and cultist messages are no longer displayed in the lobby.
    • +
    • The sentience event no longer triggers a huge number of ghost polling messages.
    • +
    • When xenomorphs are damaged, their health HUD now updates properly.
    • +
    • Custom title for ghost notifications now work properly.
    • +
    • Fixed double admin commands in the grenade priming message.
    • +
    • Ghosts will now always see whispers/zero pressure speaking if they're on the screen with the mob speaking.
    • +
    • Ghosts with ghost sight enabled will no longer see emotes from clientless mobs.
    • +
    • The prison labor point system has been refactored so it works properly.
    • +
    • Plating can now be removed (exposing the baseturf) using a welder.
    • +
    • All remaining Lavaland ruins have been ported over from /tg/.
    • +
    • All chairs on shuttles have been replaced with brand new shuttle chairs.
    • +
    • Tribal splints have been added to the game, which can be crafted with two bones and one piece of sinew.
    • +
    • The Lavaland Syndicate base now has a defibrillator and mounted defibrillator. The animal hospital now has a mounted defibrillator.
    • +
    • The Ash Walker storage area now comes with an advanced medkit instead of a regular one and one set of medical splints. It also comes with aloe vera, comfrey and wheat seeds.
    • +
    • The water tank in the Ash Walker nest has been replaced with a puddle.
    • +
    • The items in vending machines on the beach ruin and animal hospital are now free.
    • +
    • Fixed an issue where slimes wouldn't take damage from water in space.
    • +
    • It is no longer possible to unanchor the surivval pod storage units.
    • +
    • Drinking from a beaker now only applies the effect of five units of the ingested chemical, instead of the entire volume of the beaker.
    • +
    • Resolved an issue where beaker attack logs were reversed.
    • +
    • Moving through portals very quickly no longer breaks movement.
    • +
    +

    Quantum-M updated:

    +
      +
    • New sprites for vampires being "hungry".
    • +
    • New sprite for vampire usable blood count.
    • +
    • New sprites for the safety muzzle.
    • +
    • Safety muzzle (aka the anti-bitting one) can no longer be resisted out of.
    • +
    • Vampires can now suck blood from monkey mobs (e.g. monkeys, stoks, etc.) for sustenance but do not get blood power points.
    • +
    • RnD is no longer able to print out any telescience boards.
    • +
    +

    SteelSlayer updated:

    +
      +
    • Gives vampire thralls an objective, which can be viewed in their notes
    • +
    • Increases the size of the enthralling message seen by newly created vampire thralls
    • +
    • Vampire thralls are now stunned briefly (about 3 seconds) upon being enthralled
    • +
    • The AI's robot control window now allows you to see and interact with available bots again
    • +
    +

    TDSSS updated:

    +
      +
    • cult teleport runes and similar powers now work on z levels 9-12
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Inputs sanitized
    • +
    • autocomplete input mishandling single quotes (you can teleport to Wizard's den now)
    • +
    • newlines not working in CC announcements
    • +
    • players not being able to send single quotes in ahelps or PMs
    • +
    • robots not being able to pick their name
    • +
    +

    TheSardele updated:

    +
      +
    • Lowers throwforce of drinking cartons from 15 to 0
    • +
    • Bees no longer inject venom when nuzzling
    • +
    • Sec pod pilots can now spawn with the loadout security armbands
    • +
    • It is no longer possible to raise zero to -infinity fingers using the *signal emote
    • +
    • Earmuffs now properly protect you from vampire screeches no matter what you are wearing on your other ear
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Reworded permanent bans to non-expiring bans.
    • +
    • Door remotes now add to admin-only hidden fingerprint list
    • +
    • Gave plastic surgery to line 364 of atoms.dm
    • +
    +

    and DominikPanic updated:

    +
      +
    • Limits IC notes
    • +
    +

    datlo updated:

    +
      +
    • Free Golems are now a lavaland ruin spawn instead of a space ruin spawn.
    • +
    • Free Golems must now purchase their shuttle board for 2000 mining points before being able to fly their shuttle.
    • +
    • Added a shuttle recall console at the golem lavaland spawn point so that golems can always recall the shuttle back to lavaland
    • +
    • The Free Golem Ship can now move to the Construction Site, the Derelict, or back to their Lavaland spawn.
    • +
    • The Free Golem Ship has been redesigned with an open floor plan, removing most of its interior walls for extra space.
    • +
    • Free Golems no longer get a free kinetic accelerator on their ship.
    • +
    • New crit species with below -100 health will be considered dead for hijack purposes, and will not interrupt a shuttle hijack attempt.
    • +
    • Fix some cases of traitors getting conflicting objectives, such as assassinating and protecting the same target.
    • +
    +

    farie82 updated:

    +
      +
    • Beepsky will now respect your disguise again. No more looking right through that gasmask
    • +
    • Medical and security HUDs now use the correct way to identify somebody. They will see the same as you do on your screen.
    • +
    • You will now get a job icon in the sec HUD when you use your PDA as ID. It'll use the PDA's assigned job.
    • +
    • Ticket takes now ask for confirmation if you want to take an already assigned ticket.
    • +
    • Blindfolds are now craftable from 3 cloth. For those vampire prisoners you want to keep in check
    • +
    • Empty beaker button from the PANDEMIC is now replaced with Empty and eject beaker
    • +
    • List AFK players is now a verb for admins to use
    • +
    • Adds the AFK auto cryo system. By default it won't affect players unless they activate it themselves by setting the preference in their game preferences tab.
    • +
    • The syndicate can't use meta warfare no more. Advanced pinpointers no longer crash the server
    • +
    +

    iantine updated:

    +
      +
    • Mouse suicide
    • +
    +

    improvedname updated:

    +
      +
    • adds lasagna
    • +
    +

    kazboo updated:

    +
      +
    • changed the display name shown to a player upon being frozen in a manner that only the admins ckey is displayed, not the character name along with it
    • +
    + +

    08 July 2019

    +

    Arkatos updated:

    +
      +
    • Clicking on a health doll icon will now check you for injuries
    • +
    • Rechargers now show their contents and charge status on close examine
    • +
    • Smartfridge will now try to put an item in your hands after vending, if able
    • +
    +

    AzuleUtama updated:

    +
      +
    • The cybernetic implant bundle can no longer be bought by traitors.
    • +
    +

    Citinited updated:

    +
      +
    • Alt-clicking the RPD now brings up a radial menu with rotate, flip, and delete modes accessible. The main interface remains unchanged.
    • +
    • Writing in blood can't be done while dead or incapacitated any more
    • +
    • You can't write stuff in blood at a distance any more
    • +
    +

    Couls updated:

    +
      +
    • lantern sprites
    • +
    • typo in msg
    • +
    +

    Improvedname updated:

    +
      +
    • Explorer suits now properly hide tails
    • +
    +

    JKnutson101 updated:

    +
      +
    • Fixed Construction Permits deleting themselves prematurely.
    • +
    +

    Kyep updated:

    +
      +
    • fixed a bug with biogenerator.
    • +
    +

    Markolie updated:

    +
      +
    • Ghosts can now see all PDA messages when enabled through a preference setting.
    • +
    • The Mask of Nar'Sie transformation buttons have been removed, as the mask was removed a long time ago.
    • +
    +

    Shadeykins updated:

    +
      +
    • Changed Quarantine, NT Default, Aggressive, and Corporate AI lawsets. balance: Reduced the ability for NT Default AI's to murder people just because.
    • +
    • Removed several redundancies in Aggressive lawset.
    • +
    • Fixed a few subject-verb disagreements (is -> are).
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • paper supports markdown as well as pencode
    • +
    • Autocomplete for ghost buttons
    • +
    • PMs window scrollable
    • +
    • Fix a bug where a player who reconnects is still shown as disconnected
    • +
    +

    datlo updated:

    +
      +
    • Fix an antag rolling exploit.
    • +
    + +

    30 June 2019

    +

    Crazylemon64 updated:

    +
      +
    • SDQL2 no longer allows a macro argument
    • +
    + +

    28 June 2019

    +

    AffectedArc07 updated:

    +
      +
    • SSticker
    • +
    • You can no longer force-start a round unless its fully initialised.
    • +
    • Tweaks some preference orders
    • +
    • Moved a global define
    • +
    +

    Akatos updated:

    +
      +
    • Smartfridges now visually show approximate number of items inside
    • +
    +

    Arkatos updated:

    +
      +
    • Ragin' Mages gamemode should now be playable without any major issue
    • +
    • Slaughter and Laughter Demons no longer have duplicit objective shown at the Round End
    • +
    • Laughter Demon is now properly called Laughter Demon instead of Slaughter Demon in the role polls
    • +
    • Improved wording and fixed mistakes in Wizard and Ragin' Mages gamemodes
    • +
    • Wizards are now properly polled in the Ragin' Mages gamemode
    • +
    • You can no longer buy Summon Ghosts spell in the Ragin' Mages gamemode
    • +
    • You can no longer buy Bind Soul spell in the Ragin' Mages gamemode
    • +
    • Deck of tarot cards renamed to Guardian Deck in the Wizard spellbook
    • +
    • Rituals and Challenges categories merged into one in the Wizard spellbook
    • +
    • Laughter Demon is now slightly weaker compared to the Slaughter Demon
    • +
    • Bottle of Ooze now creates a magical morph instead of a normal one. Magical morph is capable of casting smoke and forcewall spells.
    • +
    • Visible ghosts will now get a special description about their visibility
    • +
    • Removed Cursed Heart from the Wizard spellbook
    • +
    • Changeling verbs replaced with action buttons
    • +
    • Changeling ability descriptions updated
    • +
    • Added custom icons for changeling action buttons
    • +
    • Added movement animation for mice, chickens and killer tomatoes
    • +
    • Added inhand sprite for eggbox
    • +
    • Added inhand sprites for all types of soaps
    • +
    • Added inhand sprite for small parcel
    • +
    • Added inhand sprite for sechailer
    • +
    • Added inhand sprite for bag of holding
    • +
    • Added new system for outputting contents of smartfridges
    • +
    • Blob split consciousness ability now requires you to directly target a node you want to turn into another sentient overmind instead of selecting a nearest one
    • +
    • Fixed and improved some descriptions regarding Blob offspring
    • +
    • Fixed a case where ghosts had an extra ghost icon visible on them
    • +
    • Fixed a case where some ghosts were too bright
    • +
    • You are now unable to swap forms with another changeling
    • +
    • You can no longer hiss while muzzled
    • +
    • Upon purchasing Augmented Eyesight changeling ability, changeling immediately receives passive version of the ability
    • +
    • Changelings in the lesser form can now toggle Augmented Eyesight ability
    • +
    • Changelings are now removed properly via Traitor Panel
    • +
    • Changelings do not get their action buttons bugged when using Swap Forms ability now
    • +
    • Action buttons should update their cooldown statuses more reliably
    • +
    • Changelings should now correctly receive their action buttons
    • +
    • Changelings now do not steal action buttons from other changelings
    • +
    • Added new Boo! spell icon
    • +
    +

    Christasmurf updated:

    +
      +
    • Fixes a random pixel on the leather shoes
    • +
    +

    Citinited updated:

    +
      +
    • Boo affects APCs again
    • +
    • Boo no longer fully charges when you enter your corpse
    • +
    • The button to close radial menus is much more obvious and easily-clickable now
    • +
    • Destroying a disposals trunk should no longer occasionally delete things held inside it.
    • +
    • Fixes conveyor belts not moving items spawned via an autolathe. (And other possible behaviours when machines switch between speed and normal processes)
    • +
    • Ports liquid dispenser sprites from tgstation.
    • +
    +

    Couls updated:

    +
      +
    • Only names from the manifest will be used for syndicate code phrases
    • +
    • randomly generated people names from syndicate code phrases
    • +
    • Medical category to exosuit fabricator with implants and cybernetics
    • +
    • t-t-t-typo!
    • +
    • codephrase names no longer appear blank
    • +
    +

    EmanTheAlmighty updated:

    +
      +
    • Admin made cultists can now properly summon their Gods if the gamemode wasn't initially Cult.
    • +
    +

    Evankhell561 updated:

    +
      +
    • Portable Seed Extractor designon the protolathe.
    • +
    +

    Fethas updated:

    +
      +
    • Fixes an oversight from the lavaland port invovling Laz injectors and sentience typing that didn't carry over from tg.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Future proofs the coming Ticker subsystem
    • +
    • Removes the Process Scheduler
    • +
    +

    Improvedname updated:

    +
      +
    • Cargo miner starter kit crate will no longer include a ID
    • +
    +

    Kyep updated:

    +
      +
    • Ported XKeyScore from TG.
    • +
    • New system to securely link ingame/forum accounts
    • +
    • Removed old insecure 'link discord account' system
    • +
    • unanchored vending machines will no longer generate a runtime error when throwing products at people.
    • +
    • Disarming/grabbing a door with IDSCAN disabled no longer results in a can_admin_interact runtime error.
    • +
    • Terror Spiders no longer trigger their special attack when nuzzling someone on help intent.
    • +
    +

    Markolie updated:

    +
      +
    • Chameleon items now use the appropriate species icon.
    • +
    • Lighting now respects color blindness again.
    • +
    • pAI flashlights now work properly.
    • +
    • Rotatium can now be created properly.
    • +
    • Ghosts can now transition through space again. This is now done by clicking on the edge of space.
    • +
    • Added custom explorer gas mask sprites for Grey/Drask.
    • +
    • Added a lantern to the Hermit cave.
    • +
    • Added a bone setter, bone gel, FixOVein, sterile masks and sterile gloves to the Lavaland Syndicate base.
    • +
    • The pickaxes on the Lavaland labor camp have been replaced with safety variants. The flashlights have been replaced with lanterns.
    • +
    • Fixed many species missing sprites for explorer gas masks and jumpsuits. They now use the humans icons until we have custom sprites.
    • +
    • Resolved an issue with piping not working on the Lavaland mining bases.
    • +
    • Fixed all items being free in the mining vendor.
    • +
    • Fixed improper wiring to the turbine in the Lavaland Syndicate base.
    • +
    • Fixed the Lavaland Syndicate base oxygen sensor not working.
    • +
    • Moved the pipe dispenser in the Lavaland Syndicate base so it doesn't clip with tables.
    • +
    • Fixed the Lavaland Syndicate base incinerator doors not working.
    • +
    • Ash Walkers now once more have fine manipulation. Their lack of fine manipulation caused unintended side effects (such as them being unable to mine).
    • +
    • Ash Walkers (and other ghost spawner roles) can no longer be antagonist targets or become antagonists through the antagonist creation.
    • +
    • Fixed the Lavaland Syndicate base incinerator buttons not working.
    • +
    • Fixed the Syndicate communication agent spawning with a broken voice changer mask.
    • +
    • Fixed the Disk Compartmentalizer not having a sprite.
    • +
    • The Ancient Goliath now has a small chance of spawning instead of regular goliaths.
    • +
    • Survival capsules now have a NanoMed.
    • +
    • Water bottles now behave as glass containers.
    • +
    • The behaviour of glass reagent containers has changed. When used on non-mobs, contents will now only be spilled on harm intent. When used on mobs, on any intent aside from harm the contents will be fed to the mob like regular drinks. On harm intent it will still be spilled.
    • +
    • Hairless hide can now be made wet using most sources of water (minimum volume of 10), instead of just washing machines.
    • +
    • Added some additional offstation role checks to ensure ghost spawner roles don't become antagonists, are kidnap targets or are counted towards station goals.
    • +
    • Fixed some piping in the Lavaland Syndicate base incinerator and made sure the vault door starts locked.
    • +
    • Fixed the Lavaland swarmers getting stuck on propulsion.
    • +
    • Fix goliath tentacles sometimes being left behind.
    • +
    • The walls around the Lavaland Syndicate base turbine have been coated, to prevent them from starting a plasma fire in the base.
    • +
    • Syndicate agents can now access the air alarms on the Lavaland Syndicate base.
    • +
    • Air alarm control computers can no longer access the air alarms on the Lavaland Syndicate base.
    • +
    • Fixed the disk compartmentalizer/drying rack missing a sprite under certain circumstances.
    • +
    • Fixed the Lavaland Syndicate base triggering atmospherics alerts.
    • +
    • You can now properly place tiles on basalt.
    • +
    • An exploit with the sheet multiplier has been fixed.
    • +
    • Portals can now be activated by clicking on them with or without an object. Ghosts can now also click on them to be taken to their destination.
    • +
    • Portals now warn admins when they are used to teleport megafauna.
    • +
    • The singularity can now eat basalt and chasms on Lavaland. They get turned into lava.
    • +
    • AI swarmers will no longer get stuck on effects (such as blood).
    • +
    • Fixed the spectral blade turning all ghosts visible.
    • +
    • Fixed a runtime with assigning outfits to mindless mobs.
    • +
    • Fixed certain alarms triggering despite being outside of station contact and the Syndicate base still triggering fire alarms.
    • +
    • Fixed being unable to put the wormhole jaunter in the belt slot.
    • +
    • Fixed the disk compartmentalizer not accepting disks.
    • +
    • Gutlunches and Gubbucks will now reproduce properly.
    • +
    • The necropolis chest cult clothing drop no longer spawns with a cult hood as well, as that's part of the suit itself.
    • +
    • Goliath steaks can now be eaten properly.
    • +
    • Fixed a stray light on the beach ruin.
    • +
    • Lavaland ruins should no longer spawn on the Labor Camp.
    • +
    • Ancient goliaths will now properly randomly spawn tentacles.
    • +
    • The labor camp will now spawn properly with a processing console.
    • +
    • Water turfs in the beach ruin (and other water turfs that previously didn't do so) will now properly apply water to you.
    • +
    • Ash flora is now anchored.
    • +
    • Gutlunches will now eat properly.
    • +
    • The tesla can no longer travel through wormholes.
    • +
    • Fixed an issue with honkbot construction.
    • +
    +

    Markolie and Ionward updated:

    +
      +
    • Added Tajaran, Vulpkanin, Unathi and Vox sprites for the explorer gas mask (thanks to Ionward!)
    • +
    • Added custom species sprites for the explorer suits and hoods (thanks to Ionward!)
    • +
    • Added missing surgical tools and a pet vendor to the animal hospital.
    • +
    • Added a custom cigarette vendor to the beach biodome ruin.
    • +
    • Added an autolathe and RPD to the Lavaland Syndicate base. Also added a custom cigarette vendor and made the vendors not charge money.
    • +
    • Added tiny fans to the mining base and labor camp exist.
    • +
    • A separate jobban for ghost roles has been added.
    • +
    • The alternative sink now has directional sprites. This resolves an issue with shelters having sinks facing the wrong way.
    • +
    • Fixed the Syndicate sleepers on the Lavaland Syndicate base pointing the wrong way when a ghost role spawns in.
    • +
    • Fixed Lava being removed by the staff of lava not working. Also added a missing warning effect when the staff is turning regular turf into lava.
    • +
    • Fixed random bookcases not spawning books (hopefully).
    • +
    • Fixed surgical drapes not having a sprite.
    • +
    • Fixed being unable to modify the GPS tag of shelters.
    • +
    • Fixed the Lavaland swarmers not eating anything.
    • +
    • The ash drake swoop attack is no longer incredibly loud.
    • +
    • The Syndicate base self-destruct is now much more powerful and capable of destroying the entire base.
    • +
    • The flavor text of Ash Walkers and Syndicate operatives now clarifies what they can('t) do.
    • +
    • Ash walkers can no longer use machinery.
    • +
    +

    Ported by Markolie and CornMyCob. Developed by many /tg/ coders updated:

    +
      +
    • The mining asteroid has been replaced with Lavaland.
    • +
    +

    Shadeykins updated:

    +
      +
    • Fixes a paper exploit.
    • +
    • Fixes rogue pixels on breath masks/gas masks for Plasmamen.
    • +
    +

    TDSSS updated:

    +
      +
    • Vampire rejuv wakes you up if you're asleep now
    • +
    • Cling epinephrine wakes you up if you're asleep now
    • +
    • Sling glare popup no longer lists invalid targets for glaring
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Messages window (My PMs in OOC tab)
    • +
    • You no longer have to wait on others for ERT spawning
    • +
    • Admin jobs no longer announced
    • +
    +

    Terilia updated:

    +
      +
    • Added the Donksoft sniper into the Trader spawnpool.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Changed admin take ticket color from neon green to Asay pink
    • +
    • Manual bans now auto-note
    • +
    • Stops projectiles using the legacy system such as emitters from hurting shield blobs due to an exploit where it would always hit or go through.
    • +
    +

    craftxbox updated:

    +
      +
    • Highlight string uses regex
    • +
    • Removed jquery mark
    • +
    +

    datlo updated:

    +
      +
    • The Syndicate will no longer hire golems as agents.
    • +
    • Banana juice and Banana honk will now heal everyone with the Comic Sans mutation instead of checking for the clown job
    • +
    • Nothing will now check if the player has an active vow of silence instead of checking for the mime job
    • +
    • Ghosts will no longer get the wrong role offered when a nukie spawns a borg and will properly be informed whether they will spawn as a nuke ops or a syndi cyborg.
    • +
    +

    dovydas12345 updated:

    +
      +
    • Fixes cryopod removing ambulance, secway keys
    • +
    • Fixes cryopod recovering the invisible headpocket item
    • +
    +

    farie82 updated:

    +
      +
    • Can't use cuffs now while you have antidrop
    • +
    • can_equip now checks if you have the limbs required to equip something
    • +
    • Reverts the string highlighting done by regex
    • +
    +

    iantine updated:

    +
      +
    • Skrell *warble emote
    • +
    +

    uc_guy updated:

    +
      +
    • Theft objective locations hints now ignore the Centcomm Z level.
    • +
    • Adv. Pinpointer no longer targets items in Centcom Z level.
    • +
    • Fixed "Venus Human Traps" being invisible.
    • +
    + +

    10 May 2019

    +

    AffectedArc07 updated:

    +
      +
    • Removes an infinite loop in the code
    • +
    • Removes unused code
    • +
    • Captains display case now actually has captains thumbprint lock on it
    • +
    • Morgue updates happen slightly better now
    • +
    • Fixes a minor NTTC issue
    • +
    +

    Arkatos updated:

    +
      +
    • Patch Pack is now craftable with a cardboard, costs 2 cardboard sheets.
    • +
    • Examine tooltip delay increased slightly
    • +
    • Examine tooltips now work properly on items in storage
    • +
    • Full toolbelts now spawn with randomly a colored cable coil
    • +
    • Added inhand sprites for belts
    • +
    • Species name now shows in a species theme color on examine
    • +
    • Added 4 new plushies
    • +
    +

    Couls updated:

    +
      +
    • necromantic stone now forces the ghost back into the body as a skeleton
    • +
    • allow skeletons to give up their bodies and offer control to ghosts
    • +
    +

    Crazylemon and Fox McCloud updated:

    +
      +
    • Fixes toggles not properly saving
    • +
    +

    EvadableMoxie updated:

    +
      +
    • Added the Nanotrasen Hospital Vessel Asclepius, able to be deployed by admins.
    • +
    • Admin shuttle now requires ERT clearance instead of admin clearance.
    • +
    • Admin shuttle now has a navigation computer and tiny fans at the airlock.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes a few instances generating log spam relating to z-level tracking
    • +
    • Fixes weird behavior with ghosts being able to trigger a few things by crossing over them
    • +
    • Fixes drifting ghosts
    • +
    +

    Ionward updated:

    +
      +
    • Updated the cautery sprite!
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds a verb to eyewear you can use to adjust them so they appear above or below masks. Discover interesting combinations and enjoy a cool look.
    • +
    +

    Kyep updated:

    +
      +
    • Trying to latejoin a round with no open job slots now results in an informative error message, rather than broken-looking blank window.
    • +
    • Added new bonus loadout items for higher-tier patrons. Also gave admins access to patron items, and ensured that during custom events, you see the custom event announcement when you connect.
    • +
    • You can now identify when someone is using internals from a tank in their pocket, without having to remove the tank.
    • +
    • punching a windoor no longer generates a runtime error.
    • +
    • cryogenic_liquid/envenomed_filaments blobs no longer generate runtimes when their blob special attack hits mobs that do not process reagents
    • +
    • fixed $5+ donors not getting extra loadout points.
    • +
    +

    Markolie updated:

    +
      +
    • Ambient occlusion had been added to the game. This represents a shadowy effect on most objects. It can be turned off through the game preferences menu.
    • +
    • Our lighting system has been updated to /tg/'s latest version. Hopefully this means we'll have less lag later in the round.
    • +
    • Night vision has been modified. There are now three levels of night vision. Certain creatures that were previously able to toggle night vision can now switch between all levels. Thermals now give some night vision.
    • +
    • Mesons now no longer fully light up non-visible turfs. It uses slight darkness instead.
    • +
    • Syndicate operatives may now purchase a chameleon bundles (2TC), which allows them to disguise not just their jumpsuit, but all of their equipment. They can change individual clothing as well as the outfit as a whole.
    • +
    • When using a voice changer, NTTC will no longer default to an "Unknown" job: it'll still use the assignment on your card to prevent meta-gaming. Always combine a voice changer and a Syndicate ID.
    • +
    • Admins with advanced admin interaction toggled on can now interact with the small airlock buttons.
    • +
    • The steel_rain runtime fix has been re-applied.
    • +
    • The propulsion on the admin shuttles has been fixed. The shutters on the south side of the hospital shuttle now point the right way.
    • +
    • Nuclear Operative reinforcements now spawn with a properly counted agent designation.
    • +
    • Fixed an issue where a mob's sight wouldn't update properly in certain cases, such as being revived.
    • +
    • Resolved an issue where the lobby would be bright white when being sent back.
    • +
    • Resolved an issue where the ambient occlusion preference wouldn't update properly in the lobby.
    • +
    • Resolved an issue where clicking on a windoor would no longer prevent it from auto-closing.
    • +
    • When a nuclear operative chooses to play as the borg instead of operative using the cyborg teleporter, ghosts will now be informed of this in their acceptance message.
    • +
    • Resolved an issue where cameras couldn't take pictures of non-dynamic lighting areas, such as the holodeck or space.
    • +
    • Resolved an issue where mobs would appear above water.
    • +
    • Resolved an issue where radiation storms would make lighting invisible in space.
    • +
    • Simple mobs no longer retain their X-Ray upon being revived.
    • +
    • Applying brute/fire damage through the View Variables menu for non-humans has been fixed.
    • +
    • NTTC regex has been disabled due to an urgent security issue.
    • +
    +

    Mitchs98 updated:

    +
      +
    • You can now order a Pig Crate from Cargo for 25 points.
    • +
    +

    TDSSS updated:

    +
      +
    • typo on sst shuttle console
    • +
    • opening turret covers now stay on top of their turret.
    • +
    +

    Twinmold93 updated:

    +
      +
    • Adds Server Time to the Status Tab for Admins.
    • +
    +

    farie82 updated:

    +
      +
    • Transforming into another species will now retain the items correctly. Example clings will keep their armblades and they won't get stuck with a non existing armblade they can't put back
    • +
    • Devour and regurgitate use forcemove now. So no being buckled inside an alien
    • +
    +

    fludd12 updated:

    +
      +
    • Project Mind now has a corollary ability, Scan Mind. Now communication can be two-way!
    • +
    +

    variableundefined updated:

    +
      +
    • Simple animals actually use the new subsystem now
    • +
    • What was NPCAI is now renamed to NPCPool - Its the functional equivalent of what it is in tg
    • +
    • Simple animals actually run on subsystem instead of a process now.
    • +
    • idleNPCpool has been added reducing performance impact of hostile simple animals
    • +
    • NPCAI Process (That run both SNPC and SimpleAnimals) that was somehow left out by me
    • +
    • SNPC & assocaited NPCAI Subsystem
    • +
    • Some of space hotel's functions.
    • +
    • Bodysnatch gland.
    • +
    • process_ai has been deprecated
    • +
    + +

    02 May 2019

    +

    AffectedArc07 updated:

    +
      +
    • ssMapping
    • +
    • Gateway and space ruins are now loaded with ssMapping
    • +
    • Master Controller
    • +
    • Darkmode chat department colors match NTTC theming now
    • +
    • SSvotes
    • +
    • SSradio
    • +
    • SSevents
    • +
    • SSholiday
    • +
    • We no longer check if its Christmas every tick. Dont ask.
    • +
    • SSalarms
    • +
    +

    Arkatos updated:

    +
      +
    • Shadowlings now have a slightly bigger colored text when speaking in the Shadowling Hivemind
    • +
    • Replaced title2.ogg music with a higher quality version
    • +
    • Shield Blobs automatically spawned around Blob Cores now give no refund upon removing. No freebies.
    • +
    • Added new Wizard Spell - Summon Ghosts! This nefarious spell will make all ghosts visible to the living. Be careful though, as while they cannot harm you in any way, they might prove a bit.. annoying. Costs 0 points in the Wizard's spellbook.
    • +
    • Ghosts now orbit around their followed targets
    • +
    • Added new Shadowling Ability - Null Charge! This new ability allows Shadowling to completely drain an APC of it's power after a moderate delay. Shadowling must not be interrupted, or the whole process will fail.
    • +
    • Added custom icon for the Null Charge ability
    • +
    • Shadowling Drain Life ability removed
    • +
    • Added Observer HUD buttons for Jump to Mob, Orbit, Re-enter corpse, and Teleport
    • +
    • Added custom icons for Observer HUD buttons
    • +
    • Added Floorbot color variants. Different toolboxes will result in a differently colored Floorbots. One even might be a little stronger than others..
    • +
    • Added sprites of Floorbot color variants
    • +
    • Fixed incorrect amount of required floortiles for the Floorbot in the crafting tab
    • +
    • Added cancel button to Wizard teleportation scrolls
    • +
    • Added an option to grant Martial Arts via administrative Var menu
    • +
    • Toggling hardhat light on/off now correctly updates wearer's sprite
    • +
    • Added deathsound for Silicons
    • +
    • Dice will now roll when thrown
    • +
    • Added sound when adding or removing IDs from ID modification computers
    • +
    • Added cancel button to transfer amount from stack menu
    • +
    • Alt-click is a new shortcut to take a custom amount from stack
    • +
    • Added shortcuts for handling pumps, volume pumps, filters, and mixers. Ctrl-click these devices to turn them on/off and Alt-click them to set their output to maximum.
    • +
    • Added ability to rename pumps, volume pumps, filters and mixers with a pen.
    • +
    • Added sound for throwing bolas
    • +
    • Added hitsound for all types of bolas
    • +
    • Added AntagHUD to everyone at the round end
    • +
    • Circuit Boards now show their required components on examine
    • +
    • Revenants now have randomly generated flavor names
    • +
    • You can shift-click any action button to reset it's position. Alt-click on Hide Buttons will reset all action buttons to their default positions.
    • +
    • Pill Bottles are now printable in the Autolathe. You can find them in the Medical section, and each costs 80 metal and 20 glass to print.
    • +
    • Puts beakers in your hand upon eject from chemistry machines
    • +
    • Cardboard can now be made in the Biogenerator
    • +
    • You can now hotswap tanks in a canister or gas pump by clicking it with a new tank!
    • +
    • You can now also close a canister's valve and remove the tank inside it by alt-clicking it.
    • +
    • Added examine toolptips. Hover over any equipped or hold item for a little while and it will display the item description as a tooltip.
    • +
    • Ghost teleport verb will no locker flicker when used
    • +
    • Alt-click now opens and closes fire extinguisher cabinet
    • +
    • Fire extinguisher cabinet now properly updates it's sprite correctly when putting fire extinquisher inside the cabinet
    • +
    • Fire extinguisher no longer sprays when put into fire extinguisher cabinet with a safety off
    • +
    • Added sound for opening and closing fire extinguisher cabinet
    • +
    • Added new torch sprites
    • +
    • Torch light color is now orange instead of red
    • +
    • Torch sprite now correctly shows all inhand sprites
    • +
    • Blob Rally Spores power is now free to use
    • +
    • Blob mobs can no longer speak while being dead via Blob Broadcast
    • +
    • Blob structures now properly show working animation
    • +
    • Added new sprites for variants of Blob resource, factory and storage structures
    • +
    • Added inhand sprites for winter coats
    • +
    • Carps now spawn with a random color! There might even be some really rare ones..
    • +
    • Added carp color variants sprites
    • +
    +

    Arkatos and Paradise community: updated:

    +
      +
    • Added Tip of the round to a pre-game lobby
    • +
    • Added Show Custom Tip admin verb
    • +
    • Added Give Random Tip OOC verb
    • +
    +

    Citinited updated:

    +
      +
    • You can no longer turn transit turfs into foamed metal flooring.
    • +
    • Foamed metal floors have a sprite now.
    • +
    • Pipe dispensers (the big ones) now work again.
    • +
    • Cooldown on pipe dispensers reduced to 0.4 seconds, down from 1.5 seconds
    • +
    +

    CornMyCob updated:

    +
      +
    • The plasma cutter now cuts through multiple rock tiles.
    • +
    +

    CthulhuOnIce updated:

    +
      +
    • you can smell dead bodies, even if someone else shouldn't
    • +
    +

    Fethas updated:

    +
      +
    • Cluwne suits should no longer fall off cluwnes from being fat.
    • +
    +

    Fox McCloud updated:

    +
      +
    • CQC has been updated; a few combos are more powerful
    • +
    • cost increased to 13 TC
    • +
    • CQC is now nuke ops only
    • +
    • gloves of the north star restriction on CQC removed
    • +
    • CQC disarms will now take the item from your opponent
    • +
    • CQC blocks melee weapons and a couple of stun weapons and not everything now
    • +
    • Reagents will now adjust to the body temperature over time as opposed to all at once
    • +
    • Strange Reagent will work 25% of the time with TOUCH based reactions
    • +
    • Strange reagent will revive whether there's a ghost or not (can use SR on clientless mobs now, like monkies)
    • +
    • SR puts the occupant back in their body automatically
    • +
    • Cloners that eject their messes will now eject the unattached organs
    • +
    • the message for brain death will now properly and only occur when they have truly died from brain damage
    • +
    • Fixes being able to attain brain damage over 120
    • +
    • Updates nations. Updates nations so hard right into the void
    • +
    • Plasma fires should burn a bit faster now
    • +
    • Bleeding will now stop at the temperature at which cryoxadone heals
    • +
    • Fixes a few potential exploits with forcing chem, dust, and explosive implants activating with the deathgasp emote, prior to death
    • +
    • Tesla can't zap cameras and other disposal structures anymore
    • +
    • Simple mobs can now be shocked
    • +
    • Electrocution damage scales a bit more linearly up to its maximum potential instead of being heavily random
    • +
    • Fixes being able to shock yourself with TK, at range, on electrical equipment
    • +
    • simple mobs can now be shocked by the tesla and other sources
    • +
    • Fixes goats not attacking people
    • +
    • Goats will eat glowshrooms
    • +
    • Goats will eat full grown diona
    • +
    • Remapped toxins to be more compatible with the modern age
    • +
    • updates plasma and N2O sprites
    • +
    • Fixes not being able to look at a turf if it had plasma/N2O on it
    • +
    • cold turfs no longer become icy
    • +
    • Cryostylane makes turfs icy
    • +
    • Icy turfs are slippery; wear magboots to counteract the effect. Watch your head!
    • +
    • Fixes grammar of slipping on turfs; no more "you slipped on floor" or "you slipped on wet floor"
    • +
    • removes ponies
    • +
    • object and fast processing are now proper subsystems
    • +
    • Fixes multi-spawn blobs
    • +
    • Powersinks drain rate increased, but they also explode a bit sooner
    • +
    • Multitools display total power, load, and free power
    • +
    • Fix emitter sparks sparking at the location of emitters where biult as opposed to emitter current location
    • +
    +

    Ionward updated:

    +
      +
    • Added new mantles! Check the ClothesMate, or in department head's lockers.
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds striped normal-height socks.
    • +
    • Vox can now wear whatever undergarment they want.
    • +
    • Removes flesh from shredded Vox uniform sprites.
    • +
    • Armalis can no longer wear undergarments. They didn't fit, anyhow.
    • +
    • Underwear no can no longer lock up the character creator.
    • +
    +

    Kyep updated:

    +
      +
    • bans issued by admins via the Player Panel no longer incorrectly omit IP/etc information
    • +
    • admins issuing permanent bans are no longer presented with an "ip ban?" prompt, as all bans include IP/CID information now. This prompt was a legacy thing from back when the filesystem was used to store bans, and hasn't ever affected how DB-based bans were stored.
    • +
    • Added a config file option which allows SSD crew members to be moved to cryo after a defined amount of minutes.
    • +
    • Added a config file option which causes most people trying to attack/loot/interact with a SSD character to need to confirm they've read the rules before being able to do so.
    • +
    • Fixed an error message being inappropriately generated for admins when someone signs up as a pAI.
    • +
    • The ID computer now color-codes potential job transfer options, highlighting good choices for a job transfer in green, and bad ones in gray.
    • +
    • Taking a job transfer now gives you playtime based on your new job, instead of incorrectly still giving you playtime based on your old job.
    • +
    • Job transfers to karma jobs are now possible - if you have the job unlocked.
    • +
    • Attempting to bypass a job ban via a job transfer now generates a warning to all online admins.
    • +
    • Refactored and improved our entry on the server hub.
    • +
    • Fixed a runtime in job_exp.dm
    • +
    +

    Markolie updated:

    +
      +
    • Safes can now consist of more than two tumblers.
    • +
    • All safes now have three tumblers by default, instead of two.
    • +
    • The safe opening mechanism has changed slightly. This is described on the safe cracking UI.
    • +
    • The hardsuit equipment lockers on the Syndicate Nuclear Operative shuttle have been replaced with suit storage units. Suit storage units now have a separate slot for magboots.
    • +
    • Nuclear Operatives can now purchase reinforcements. These reinforcements cost 25 telecrystals each.
    • +
    • A number of new ammunition and weapon bundles have been added for Nuclear Operatives.
    • +
    • For every ten players on the server, the Nuclear Operatives now receive 2 extra telecrystals.
    • +
    • The Syndicate borg spawners have been separated into three separate spawners, one for each type of Syndicate cyborg. Their prices have been modified.
    • +
    • Saboteur borgs now spawn with thermals.
    • +
    • The Syndicate borg and exosuits have been moved to a new category, "Support and Mechanized Exosuits".
    • +
    • Existing bundles and telecrystal purchases have been moved to a new category, "Bundles and Telecrystals".
    • +
    • There are now more spawn points for nuclear operatives on their base. The number of operatives spawning has not been changed.
    • +
    • Spawning nuclear operatives through the traitor panel now causes their ID to be properly updated.
    • +
    • Shuttles no longer leave behind their propulsion.
    • +
    • AZERTY hotkey mode users can now switch between regular mode and hotkey mode properly using TAB again.
    • +
    • Jumpsuits are now removed by clicking instead of clicking and dragging.
    • +
    • Removed a useless message that would be sent to admins whenever a drone joins the round.
    • +
    • Fixed an issue where admins would receive a message whenever someone joined up as a pAI.
    • +
    +

    McDonald072 updated:

    +
      +
    • You can no longer examine or teleport things using clipboards
    • +
    +

    Quantum-M updated:

    +
      +
    • Two multicolor pens to the Internal Affairs Office
    • +
    +

    TDSSS updated:

    +
      +
    • nukies can buy plasma grenades again
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Moves AI admin log to the all preference
    • +
    +

    dovydas12345 updated:

    +
      +
    • Fixes normal cameras spooking non-chaplains even when they don't capture any ghosts
    • +
    +

    farie82 updated:

    +
      +
    • Makes puke less lag inducing
    • +
    • Puke can now appear on all kinds of turfs except spess
    • +
    • Ticket messages now have their corresponding span classes. Making them easier to notice
    • +
    • PM's now shouldn't go to the wrong client anymore when the target left.
    • +
    • Cure text for Shock and Cardiac failure are more clear now
    • +
    • Ducttape gags can now be removed properly without spawning an invisible one in your hands
    • +
    • Windoors now give the airlock assembly electronics once deconstructed
    • +
    • Can't place runes in space anymore
    • +
    • Admins can now use all mhelp related things again
    • +
    • Fixed the toggle mentor ticket messages text
    • +
    • Vampiric glaring is logged now
    • +
    • Doctor delight and orange juice now heal again
    • +
    • Fixes admin PM's. Bwoinks are back on the menu!
    • +
    • Organs will now prompt a update_stat. Meaning that IRCs and the like now get revived when possible when you put their battery and brain in
    • +
    • The typing limiter option should now work for all edge cases. Such as dying while talking and such
    • +
    • Borgs health status now updates properly when removing and adding parts
    • +
    • You won't try to fix destroyed components in borgs anymore. Which resulted to lost materials and no healing
    • +
    • Borg analysers will now properly show missing components and won't show their damage if missing
    • +
    • Self diagnostics for borgs now also shows missing parts and destroyed ones
    • +
    +

    iantine updated:

    +
      +
    • Adds Lumi's vox suit fluff
    • +
    +

    uc_guy updated:

    +
      +
    • Players in the lobby no longer see cult speak.
    • +
    + +

    08 April 2019

    +

    TDSSS updated:

    +
      +
    • Added missing vent in toxins mixing
    • +
    + +

    07 April 2019

    +

    Arkatos updated:

    +
      +
    • Guardians can no longer change action intents on their own
    • +
    • Fixes #10900 - Guardians can no longer attack their host while inside them
    • +
    • Explosive and Support Guardians now get precise cooldown shown (instead of just static estimate) before their bomb and beacon abitilites are ready to be used again, respectively
    • +
    • HARM action intent icon for Guardians updated
    • +
    • Dehydrated Space Carp TC cost changed from 3 to 2
    • +
    • Shadowling Glare ability reworked - The further Shadowling is from their glared target, the shorter stun their target gets. Stuns also have a delay before they kick in, based on the distance, however targets will be slowed and muted before stun takes effect. Targets on the tile just next to them are still stunned and muted for 10 seconds without any delay.
    • +
    • Added victory message to the End Round messages in the Shadowlings Rounds
    • +
    • Shadowling Destroy Engines ability reworked. You now need to sacrifice non-ally target to delay the emergency shuttle arrival by 10 minutes, and shuttle will be unable to be recalled. This ability can be used only once across ALL Shadowlings.
    • +
    • Descriptions now show with a mouse hover over action buttons
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes Russian revolvers triggering no matter where you clicked
    • +
    • Power gloves electric shocks can target anything now (still only damages mobs)
    • +
    • Power gloves electric arcs will bounce around (if it happens to target a mob though, it'll ground out and not bounce any more)
    • +
    • Power gloves cooldown lowered from 12 to 4
    • +
    • Power gloves heat up the turf they target
    • +
    • Using power gloves on disarm intent will weaken your target instead of dealing damage
    • +
    • CLF3, Phlogiston, and Fluorosulfuric acid all require greater volumes to achieve their upper damage limits
    • +
    • CLF3 and Phlogiston have lower minimum damage
    • +
    • Grey's treat water more closely to sulfuric acid (including passive damage while it's in them)
    • +
    • Grey's don't instantly purge all sulfuric acid from their system; it depletes at the normal rate, but doens't cause damage
    • +
    • Foam altered to be a bit more viable compared to smoke
    • +
    • Fixes being unable to view pill bottle inventory in some circumstances
    • +
    • Vending items from vending machines will try to put the item in your hands after vending
    • +
    • Vending machines with refill-canisters can be beaten apart and broken
    • +
    +

    Kyep updated:

    +
      +
    • Ghosting while alive, conscious, and a member of the crew will now result in your body being moved to cryo after 5 minutes, assuming your body isn't killed or restrained in any way in the meantime.
    • +
    • An AI that ghosts while alive gets a dismissable hint that they might consider using OOC -> Wipe Core instead.
    • +
    • Ghosting out of your body while you are alive, and an antag, will result in admins being informed, so that they may replace you as an antag if needed.
    • +
    • Empress of terror (admin-only mob) is no longer incorrectly prevented from laying brown spider eggs.
    • +
    • Admins are now able to spawn a queen of terror in a room without a vent. Previously, queens would not allow this. Now, this just results in an alert to admins (since its probably a mistake) and deactivates the mob AI (but leaves it available for player control).
    • +
    • If there are player controlled terror spiders, admins using check antags panel will now be able to see eggs/spiderlings currently growing on the station. These counters only count eggs/spiderlings on station, and ignore fake spiderlings.
    • +
    • Empress of terror's 'erase brood' ability no longer incorrectly causes mothers of terror to spawn spiderlings on death. sprite: Empress of terror now has its own sprite.
    • +
    • White spider infections have been nerfed a bit. They no longer provide passive healing or increase infection progress while their host/victim is in crit. Also, the first spiderling to emerge from an infection can no longer be a green. Finally, the eggs now self-delete after the third spiderling emerges, so even in the event they aren't treated with surgery, the host isn't left with confused movement forever.
    • +
    +

    Markolie updated:

    +
      +
    • Changing your hotkey mode now happens instantaneously and no longer lags.
    • +
    • An issue where the Hotkey Toggle button wasn't working has been fixed.
    • +
    +

    TDSSS updated:

    +
      +
    • upload consoles now tell you if you forgot to select an ai/borg before using an upload module.
    • +
    • trick revolver comes in a box, so you can tell what it is when getting it in a surplus crate.
    • +
    +

    farie82 updated:

    +
      +
    • Gives you the option to disable text popup spam. Aka if enabled you won't get popups after you pressed T and had a lagspike and you typed a sentence containing a lot of T's. Default is off
    • +
    • Now checks if OOC and LOOC are enabled before showing the popup
    • +
    • Adds a Mhelp ticket system
    • +
    • Take in the m/a-helps now actually takes the question
    • +
    • a/m-help followup responses using a-mhelp verb now get added to the last ticket like it should
    • +
    • Normal players can now see their open tickets using the My Admin/Mentor tickets verb
    • +
    + +

    06 April 2019

    +

    Fox McCloud updated:

    +
      +
    • Fixes people popping out of cloning taking tons of damage
    • +
    • Fixes Teslium recipe
    • +
    • Fixes some reagents not causing status updates
    • +
    +

    Twinmold updated:

    +
      +
    • No longer costs toner to send a fax to Central Command
    • +
    +

    dovydas12345 updated:

    +
      +
    • Fixed diamond statue names and description.
    • +
    +

    farie82 updated:

    +
      +
    • Sec huds work again. No longer does the perp need glasses to be set to arrest. Cool does not equal arrest now
    • +
    + +

    04 April 2019

    +

    Kyep updated:

    +
      +
    • Improved the interface for Syndicate Uplinks. They now clearly mark which items are hijack-only and which are not. If you attempt to purchase a hijack-only item without hijack, they will explain why you can't.
    • +
    • Atmos Gas Grenades (the uplink grenade kit) are now split into Knockout grenades (2 N2O grenades, 8 TC, available to all agents), and Plasma Fire grenades (2 plasma fire grenades, 12 TC, only available if you have hijack). This both makes knockout grenades more useful for normal traitors, and also prevents non-hijackers using a plasma fire grenade to cause massive casualties/damage.
    • +
    • Plasma Grenades and the Syndicate Bomb can no longer show up in surplus crates, or be discounted. This means while you can buy one if you intend to, you're not randomly encouraged to bomb your target.
    • +
    + +

    03 April 2019

    +

    Fox McCloud updated:

    +
      +
    • Dramatically improves human life performance (sorry, doesn't fix your actual crappy real life)
    • +
    • Blobspores will additionally zomify all players who have 200 damage or more
    • +
    • Holoparasites will additionally die once their host has 200 damage or more
    • +
    • Fixes blob zombies who infect players who have no head being invisible
    • +
    +

    farie82 updated:

    +
      +
    • Death nettle can be picked up again
    • +
    • Auto cloning now doesn't clone a person more than once.
    • +
    • A person in the cloning scanner won't be scanned if he's already being cloned
    • +
    + +

    02 April 2019

    +

    Alonefromhell & AffectedArc07 updated:

    +
      +
    • Fixed an edgecase compile error for spacehotel.dmm
    • +
    +

    Arkatos updated:

    +
      +
    • Added Medical Beamgun to a Syndicate Medical Cyborg
    • +
    • Appropriate antagonist sound theme now plays when an antagonist is selected via Traitor Panel
    • +
    • Cult sound theme now plays for a new cult converts
    • +
    • Traitor/Malfunction sound theme now plays for newly autotraitored crew/AI
    • +
    +

    AzuleUtama updated:

    +
      +
    • Cleaned up some outdated code left in uplinks.dm
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes some mobs not being able to hear sounds
    • +
    • Fixes the Master Controller not actually shutting down on round end
    • +
    • Adds space ants to the game; leave your food on tables or inside a container to avoid infestation!
    • +
    • Fixes bees not properly generating if they have a reagent in them
    • +
    • Can break bee boxes
    • +
    • Fixes bees breaking things they shouldn't
    • +
    • Fixes bees not properly injecting toxin if they lacked a reagent
    • +
    • purchased bee boxes are no longer wrenched down by default
    • +
    • Adds trick revolver to the syndicate uplink for the clown. Teach those pesky validhunters a lesson!
    • +
    • Adds the ability for admins to start a revolver only summon gun version; there's also a suicidal version that makes half the guns summoned real and the other half trick revolvers
    • +
    • stabilizing agent gets used up in reactions that utilize it
    • +
    • flashbangs spark when they initially go off
    • +
    • Fixes mech users being stunned by their own flashbangs
    • +
    • Fixes necromantic stone not working properly and other edge cases where you had O2 damage and could become O2 damage immune
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds Vox-fitted Tajaran veil sprites.
    • +
    • Removed stray pixel from Vox-fitted gasmask sprites.
    • +
    • Adjusts the Vox-fitted blindfold sprite.
    • +
    +

    Kyep updated:

    +
      +
    • Blob mobs can definitely no longer be spawned in xenobio.
    • +
    • Changed playtime requirements for command jobs. HoS/RD/CE/CMO/AI now require 5h played in their department to be playable. HoP/Captain now require 5h played as a member of the command staff.
    • +
    +

    Markolie updated:

    +
      +
    • Fixed some issues the compiler doesn't spot and some start up issues.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Start now confirmation is now a config option
    • +
    • Grid check event sound effect
    • +
    +

    farie82 updated:

    +
      +
    • Antidrop give edge case fixed
    • +
    • Can't give items to resting people now
    • +
    • put_in_hands now checks if you actually have hands
    • +
    • Wrapping lockers and crates now takes 1.5 seconds to do
    • +
    • Welding lockers now takes 1.5 seconds to do
    • +
    + +

    01 April 2019

    +

    Arkatos updated:

    +
      +
    • New Blob UI buttons for Storage Blob and Split consciousness abilities
    • +
    • New custom icons for Storage Blob and Split consciousness abilities
    • +
    • Added Node Requirement verb to the Blob. This verb, which is activated by default, enforces that resource and factory blob structures are built in a close proximity of the core/node in order to properly function. Players can disable it anytime in the Blob tab.
    • +
    • Remove Blob verb now has a new feature - partial refund for special Blob structures. When Blob Overmind removes special blob structure (such as a factory or node), it will receive 30% of the structure cost back as a refund.
    • +
    • Blob Overminds now show in Check Antagonists admin verb
    • +
    • Blob Mobs now use complementary colors of the Blob Overmind reagent as their own color
    • +
    • Removed Dark Matter from a list of possible Blob reagents
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes syndicate medborgs and regular medborgs not having handheld defibs
    • +
    • Fixes multi-tile airlocks breaking and not leaving behind an assembly
    • +
    • Updates the Timer SS
    • +
    • Roundstart ChemMasters are now constructable/deconstructable
    • +
    • Can upgrade ChemMasters. Larger beakers mean a larger reservoir
    • +
    • Mobs that are gibbed with strange reagent and GBS have a bit more of a dramatic flare to them with violent convulsions before exploding into tiny bits
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Modified alert sounds for Code Gamma and Code Epsilon.
    • +
    +

    dovydas12345 updated:

    +
      +
    • Fixes AI's toggle floor bolts ability
    • +
    +

    farie82 updated:

    +
      +
    • Bluespace golems no longer can crash the server
    • +
    • Spontaneous combustion now has a minimum stacksize of 1. No more getting wet from the fire virus
    • +
    + +

    30 March 2019

    +

    Fox McCloud updated:

    +
      +
    • Fixes a runtime involving decapitation
    • +
    • playing sounds performs better
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Removes SSD sleep bubbles from ghosts
    • +
    + +

    29 March 2019

    +

    Arkatos updated:

    +
      +
    • Fixes #11087 - Swarmers are now locked to their default action intent
    • +
    • Swarmers are now able to open airlocks and windoors (access restrictions still apply)
    • +
    • Added new Wizard item - Bottle of Ooze! This powerful item awakens all-consuming Morph, ready to eat everyone and everything on the station! Be careful though, as Morph diet also includes Wizards.. Costs 1 point in the spellbook.
    • +
    • Added custom icon for Bottle of Ooze
    • +
    • Morph introduction is now properly formatted
    • +
    • Added new Blob UI and icons, ported from /tg/station13
    • +
    • Added new *Blob Help* verb, designated to help out new players playing as Blob
    • +
    • Added descriptions for each Blob reagent
    • +
    • Added complementary colors for each Blob reagent
    • +
    • Blob marker now uses complementary color of Blob reagent as it's own color
    • +
    • Blob shortcuts updated. Blob shortcuts are now: Click = Expand Blob | CTRL Click = Create Shield Blob | Middle Mouse Click = Rally Spores | Alt Click = Remove Blob
    • +
    +

    Fox McCloud updated:

    +
      +
    • Crit has been dramatically overhauled. Treating patients now requires a broader range of medicine. Recommend checking out a guide for how to treat using the new system!
    • +
    • Medical vendors now have styptic and silver sulfadiazine, saline, atropine, mannitol, mutadone, calomel, diphenhydramine, oculine, insulin, morphine, and potassium iodide for helping treat new patients. Amount of Gauze, Advanced Trauma, and Burn packs has also been increased.
    • +
    • Adds new handheld defibs. Utilize these for treating patients with cardiac arrest. Note: these do not revive people from the dead!
    • +
    • Doctors lockers now have a handheld defib in addition to a regular defib.
    • +
    • Medical borgs now have a handheld defib
    • +
    • CPR dramatically buffed. Heavily lowers O2 damage and resets losebreath to 0
    • +
    • Cryoxadone tuned down a little
    • +
    • Health analyzer UI altered ever so slightly for cardiac arerest, so it's easier to find
    • +
    • Added bacon grease reagent to traitor poison bottles; induces immediate cardiac failure
    • +
    • Upgraded Robotic Hearts now attempt to correct both cardiac failure and cardiac arrest tweak; Upgraded Robotic Hearts now do not punish you quite as severely for receiving a shock while having one (EMPs will still destroy you though)
    • +
    • Corazone recipe removed
    • +
    • hotspot sprites updated; fire will also now appear over top of things, rather than underneath it
    • +
    • Roundstart chem dispensers are now construcable/deconstrucable and can be moved
    • +
    • Energy ratio for chem dispensers increased by x10 (how many reagents you can dispense before running out and how quickly it recharges is all the same, however)
    • +
    • Adds the ability to add a single unit of reagent in the chem dispenser
    • +
    • Adds the ability to isolate reagents in the chem dispenser
    • +
    • Portable chem dispenser removed (the circuit board for them now makes full dispensers)
    • +
    • Fixes some suicides dealing damage and gibbing you at the same time
    • +
    • Allows you to suicide with more object types. Currently the only new object type you can suicide with is the gibber
    • +
    +

    Kyep updated:

    +
      +
    • Blob mobs can no longer be spawned in xenobio.
    • +
    • Blob mobs spawned by blob cores can no longer have sentience potions used on them, which would allow whoever controls them to kill the blob with no countermeasure.
    • +
    +

    Mitchs98 updated:

    +
      +
    • Adds in Shrimp & Fish Skewers as well as Cheeseburgers. Shrimp Skewer(Grill): 4 Shrimp(uncooked) + 1 Metal Rod, Fish Skewer(Grill): 2 Salmon Meat + Metal Rod + 10u Flour, Cheese Burger(Microwave): Burger + Cheese Wedge.
    • +
    +

    farie82 updated:

    +
      +
    • Borgs can now only cuff people with two hands. Just like humanoids
    • +
    • You can cuff people with at least one hand now
    • +
    +

    ingles98 updated:

    +
      +
    • Plasma Golems will now report their suicide acts to the Admins.
    • +
    + +

    25 March 2019

    +

    Fox McCloud updated:

    +
      +
    • Fixes some reagent performance edges cases
    • +
    • Fixes chem smoke lagging under some circumstances
    • +
    • Fixes smoke not wanting to garbage collect
    • +
    • Fixes flares not returning a qdel hint
    • +
    • Fixes hotspots being slow to ignite turfs around them
    • +
    • Fixes LINDA not conducting temperature through things.
    • +
    +

    Mitchs98 updated:

    +
      +
    • Chitinous Mass is no longer weaponized lag if examined.
    • +
    +

    farie82 updated:

    +
      +
    • Diona nymphs are grabbable and punchable again
    • +
    + +

    24 March 2019

    +

    AffectedArc07 updated:

    +
      +
    • Preferences are now in alphabetical order
    • +
    +

    AzuleUtama updated:

    +
      +
    • Added Syndicate MMI for Roboticist Traitors, priced at 2TC. balance: Removed Syndicate MMI from the traitor surgery duffelbag. Price reduced to 2TC.
    • +
    +

    EmanTheAlmighty updated:

    +
      +
    • Can no longer offer Gateway Terror Spiders sentience potions. ( They literally exploded if you did, and that could have been used to effortlessly clear out hordes of them. )
    • +
    • Using the Shadowling ability "Hatch" as a monkey will change your HUD to be the human one.
    • +
    • It is now possible to put a collar on any animal that has gained sentience.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Pills maximum size increased from 50 to 100
    • +
    • Chem Master bottle size increased from 30 to 50
    • +
    • Pill bottles can now hold 50 pills instead of 14
    • +
    • Pill bottles can no longer hold patches
    • +
    • Adds Patch Boxes, which can hold patches, but not pills
    • +
    • Can now use a pill bottle or patch box on someone to apply a pill/patch from the bottle/box to a mob. Usual delays will still apply
    • +
    • Can down an entire pill bottle at once!
    • +
    • Cryostylane and pyrosium reactions now consume 2 of themselves when exposed to oxygen
    • +
    • fires, temperature, and hotspots can heat anything that contains reagents
    • +
    • Having hot/cold chemicals dumped on you or ingesting them will hurt you. Wear a mask or hat to protect from having someone dump the hot/cold things on you.
    • +
    • Chem Heater temperature adjustment tweaked; can no longer set temperature on empty containers.
    • +
    • Chem Heater generally heats faster, but cannot be upgraded
    • +
    • Chem Heater automatically stops around target temperature
    • +
    • Adjusts fire stacks and how they're applied with a few chems. Naplam, Phlogiston, fuel, thermite, and a few others have all received changes. Most direct fire damage removed.
    • +
    • Adds phlogiston dust; a safer, cooler burning Phlogiston.
    • +
    • Water and Firefighting foam will no longer automagically put out mob based fires; they'll reduce fire stacks (when fire stacks hit 0 they put the mob out)
    • +
    • cryostylane puts out mobs instantly
    • +
    • Heating fuel can set it off. Be careful when heating it now
    • +
    • Increased welding fuel tank size from 1000 to 4000 (wall mounted are still 1000)
    • +
    • Sorium and Dark matter now actually throw things
    • +
    • Thermite now gets applied to turfs. You'll have to heat the turf up to ignite it. Anything that can heat can now ignite thermite on walls
    • +
    • Adds fake hotspots. They don't do anything except set you on fire when you cross into them. Chemistry's pyrotechnics use these, for the most part; anything that causes a fireball that's chemistry related uses these
    • +
    • Sorium and Liquid dark matter now have visual effects
    • +
    • Fixes chem smoke being on the wrong layer.
    • +
    • Adds in unidentified tank filled with an unknown experimental gas in deep space. Find it and experiment!
    • +
    +

    Tails2091 updated:

    +
      +
    • New emotes to Cats and Corgis.
    • +
    • Change directories for some creature sounds to be in the creature sound folder.
    • +
    • Two bark sounds, a yelp, and a meow.
    • +
    +

    farie82 updated:

    +
      +
    • Holo firedoors now update atmos correctly after being destroyed
    • +
    • Inflatable walls/doors now update atmos correctly after being destroyed
    • +
    • Alien resin walls now update atmos correctly after being destroyed
    • +
    • Foamed metal walls now update atmos correctly after being destroyed
    • +
    • Pod doors (shouldn't ever happen) now update atmos correctly after being destroyed
    • +
    • Mining flaps now update atmos correctly after being destroyed
    • +
    + +

    23 March 2019

    +

    Arkatos updated:

    +
      +
    • Players who enable AntagHUD are now unable to join the round as swarmers
    • +
    • Adds a message explaining why Antag-banned players cannot join the round as cortical borer
    • +
    +

    Calecute updated:

    +
      +
    • South Prison camera now belongs to Prison camera network, thus showind in Prison camera monitor
    • +
    +

    Kyep updated:

    +
      +
    • Admins offering control of a mob with no real_name to ghosts will no longer cause a "Do you want to play as ?" popup. Instead, the ? will be replaced with a descriptive string, such as "the blobbernaut".
    • +
    +

    Tails2091 updated:

    +
      +
    • Lockboxes actually close when locked now.
    • +
    +

    farie82 updated:

    +
      +
    • When disarming a bomb from a guardian you now don't pickup an empty object.
    • +
    • no more organ: spam sorry admins
    • +
    + +

    22 March 2019

    +

    Arkatos updated:

    +
      +
    • Updated Tarot Deck description in Wizard's spellbook, credits to /tg/station13
    • +
    +

    Fox McCloud updated:

    +
      +
    • Smoke now has much better sprites and has a new area of denial behavior
    • +
    +

    Mitchs98 updated:

    +
      +
    • Fixed Dionae names so "Embrace of Starsong (as Embrace Of Starsong)" will no longer happen when renaming ID's at a ID Console.
    • +
    +

    Quantum-M updated:

    +
      +
    • Vox Cargo Crate - Contains two vox tanks and two vox masks. Costs 50 cargo points.
    • +
    • Plasmaman Cargo Crate - Contains a Orange plasmaman space suit and helmet, along with a breathing mask and a emergency plasmaman tank. Costs 75 cargo points and requires EVA access.
    • +
    + +

    20 March 2019

    +

    Dave-TH updated:

    +
      +
    • Krav Maga gloves can no longer steal the unstealable.
    • +
    +

    farie82 updated:

    +
      +
    • Fixed the middle mousebutton locking exploit
    • +
    + +

    17 March 2019

    +

    AffectedArc07 and Alonefromhell updated:

    +
      +
    • Cell management consoles: See the status of all brig cells without having to leave your office
    • +
    • New screen sprite for cell management console
    • +
    +

    Jazz23 updated:

    +
      +
    • Xenobio hotkeys, slime potion thing, remote slime scanner, monkey recycler linking.
    • +
    +

    Kyep updated:

    +
      +
    • It is no longer possible to crawl into a vent while you are simultaneously buckled to a chair or other solid object.
    • +
    +

    farie82 updated:

    +
      +
    • Adds a confirmation to the start now verb. Make it ansari proof
    • +
    • The invisible bumping into something should be fixed now
    • +
    • Fixes the atmos bug
    • +
    + +

    16 March 2019

    +

    Ty-Omaha and Ionward updated:

    +
      +
    • Carbon humans (people, not animals) who go SSD will now get ZZZ bubbles to indicate they are SSD
    • +
    + +

    15 March 2019

    +

    Arkatos updated:

    +
      +
    • Fixes #10987 - Guardians can now see the action intent they are on
    • +
    • Added custom action intent icons for Guardians
    • +
    +

    Couls updated:

    +
      +
    • Added a new line to the defib examine text
    • +
    + +

    14 March 2019

    +

    Couls updated:

    +
      +
    • tweaked shesi's fluff sprite
    • +
    +

    Quantum-M updated:

    +
      +
    • Changes the stamp sprites.
    • +
    • Add new sprites for the infernal and employment contracts.
    • +
    • Different organ sprites for each species
    • +
    • Different MMI sprites based on different species brains.
    • +
    + +

    13 March 2019

    +

    Couls updated:

    +
      +
    • universal translate no longer makes emotes over comms impossible
    • +
    • fixed a few typos with simple mobs
    • +
    + +

    12 March 2019

    +

    Arkatos updated:

    +
      +
    • Fixes #10261 - Pure Vampires in Traitor+Vampire gamemode will now properly show in AntagHUD
    • +
    • Fixes #9494 - Pure Changelings in Traitor+Changeling gamemode will now properly show in AntagHUD
    • +
    + +

    11 March 2019

    +

    Couls updated:

    +
      +
    • Display if karma gains are enabled or not on round start(instead of just disabled)
    • +
    • Fix wrong message when toggling karma
    • +
    +

    rb303 updated:

    +
      +
    • Fluff scarf for Rb303
    • +
    + +

    10 March 2019

    +

    AffectedArc07 updated:

    +
      +
    • You will now automatically be given admin rights if you connect to your local server
    • +
    • Mapmerge has been replaced with mapmerge2
    • +
    • Maps are now the TGM format. This means nothing for people who do not make map edits
    • +
    • Discord-related verbs are now under "Special Verbs" instead of "OOC"
    • +
    +

    Couls updated:

    +
      +
    • Toggle karma button in special verbs
    • +
    +

    Kyep updated:

    +
      +
    • Admins can now flag characters as having an event role, which makes them show up when admins look at the antag list, in admin attack logs, on antaghuds, and on the end-round score screen.
    • +
    +

    Tails2091 updated:

    +
      +
    • Added missing simple_animal emote help text.
    • +
    +

    TheMadTrickster updated:

    +
      +
    • added new fixed nice sprites
    • +
    • trashed old ugly buggy sprites
    • +
    + +

    08 March 2019

    +

    AzuleUtama updated:

    +
      +
    • Fixed nuke ops cybernetic bundles giving 6 implants rather than 5.
    • +
    • Fixed nuke ops cybernetic bundles being delivered in a box that was then delivered inside another box. balance: Nuke ops shotgun ammo bags and cybernetic bundles can no longer be discounted.
    • +
    +

    Dave-TH updated:

    +
      +
    • Medical smartfridges now accept IV bags.
    • +
    +

    Jazz23 updated:

    +
      +
    • Golems loose their shell when they switch species
    • +
    • Mousedrop applies slime speed/chill potions.
    • +
    + +

    07 March 2019

    +

    AzuleUtama updated:

    +
      +
    • Uplink items now use tooltips for their descriptions.
    • +
    • Uplink reformatted slightly.
    • +
    +

    Fox McCloud updated:

    +
      +
    • His Grace now allows you to toggle on/off binding to your hand
    • +
    • Activating his grace is now down by attempting to open it while it's in your hands
    • +
    • His Grace now removes slowed status, confusion, and resets shock stage if you're healthy
    • +
    • His Grace can now consume all mobs. Mobs consumed are permanently killed
    • +
    • His Grace will now neatly package up the inventory of people he consumes
    • +
    +

    Triiodine updated:

    +
      +
    • changes Neo-Russkiya Lang key to ?
    • +
    + +

    04 March 2019

    +

    AffectedArc07 updated:

    +
      +
    • Fluff item
    • +
    +

    Arkatos updated:

    +
      +
    • Fixes #10815 - Cloned cultists now retain their Commune ability
    • +
    +

    Fox McCloud updated:

    +
      +
    • Hopefully fixes weird stack issues. Maybe. Who knows. The World can burn.
    • +
    +

    Kyep updated:

    +
      +
    • Hardsuits that can already carry RCDs in their suit storage slot can now also carry RPDs in that slot.
    • +
    +

    Nicaragua1 updated:

    +
      +
    • Genewul Giftskee is less annoying
    • +
    • Fixed Griefsky acces and drop
    • +
    +

    Triiodine updated:

    +
      +
    • Neo-Russkiya Language
    • +
    +

    craftxbox updated:

    +
      +
    • open button is separated more from previous href
    • +
    +

    datlo updated:

    +
      +
    • Shuttle hijacking is no longer interrupted by people cuffed, straight jacketed, or locked inside a welded/locked locker or wall locker.
    • +
    • Updated hijack's objective description to reflect the change.
    • +
    + +

    03 March 2019

    +

    Fox McCloud updated:

    +
      +
    • Fixes genetic powers always activating when injected
    • +
    • Fixes Diona being able to be speedy and irradiate themselves with genetic powers
    • +
    + +

    02 March 2019

    +

    Dave-TH updated:

    +
      +
    • Wall-mounted defib frames. Swipe an appropriate card to lock the defib in place and use it to save lives!
    • +
    • IV bags have been refactored and may now accept any chemical. Play around with them a bit!
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes invisible stacks in hands
    • +
    • Fixes invisible bluespace crystals
    • +
    +

    Kyep updated:

    +
      +
    • Fixed cases of some genetics block SE injectors that are spawned at round start (such as the ones that can appear on the Sol Trade ship) not initializing properly, which would cause them to fail to work, and generate a runtime error. refactor: Did some minor refactoring to dna_injector.dm, fixing bad spacing.
    • +
    +

    Nicaragua1 updated:

    +
      +
    • Bots now drop their proper robotic arm
    • +
    • Honkbot drop is consistent with other bots
    • +
    +

    datlo updated:

    +
      +
    • Added navigation computers to the nuclear, SIT, SST, ERT, and vox shuttles. This computer lets you set a custom destination to jump to.
    • +
    • Most off-station shuttle consoles are now indestructible and impossible to deconstruct.
    • +
    • Added atmos blocking tiny fans and a security camera console to the ERT shuttle.
    • +
    +

    farie82 updated:

    +
      +
    • Can't use telepathy now when unconcious or dead
    • +
    + +

    26 February 2019

    +

    Fox McCloud updated:

    +
      +
    • Adds in stable mutagen; a DNA altering compound
    • +
    • Having the max allowable number of advanced viruses will no longer confer total and complete disease immunity to *all* future viruses infections
    • +
    • Maximum number of advanced viruses you can have in your system at once reduced from 3 to 1
    • +
    • Removed stimulant symptom
    • +
    • Removed weight gain and weight even symptoms
    • +
    • Removed Sensory Destruction symptom
    • +
    • Sensory Restoration renamed to Mind Restoration.
    • +
    • Mind restoration functions largely the same as Sensory restoration, with a few minor number changes that adjust it downward ever so slighty. It no longer heals toxin or eye damage
    • +
    • Vision Restoration renamed to a more appropriate "Sensory Restoration"
    • +
    • Capulettium is no longer a perma-stun as long as it's in your system; keeps your paralyzed for the same time as it did previously.
    • +
    • Fixes edge case mutagen behavior
    • +
    • Adds upgraded cybernetic heart to R&D
    • +
    • can now repair robotic organs, outside of the body, with nanopaste
    • +
    +

    Kyep updated:

    +
      +
    • Pink terror spiders are now called Queens after they evolve.
    • +
    • The terror spider major event now has a princess variant, and no longer has a mother variant.
    • +
    • White terror spider infestations are now less predictable, more spread out over time, and affected by nutrition and some chems, but also have worse consequences if left completely untreated for a long time.
    • +
    +

    PidgeyThePirate updated:

    +
      +
    • changed a whole bunch of strings to add a bit more flavor to most reagents in the game (most of these can be found in the spreadsheet).
    • +
    • resurrected the old "flavor_strength" value which appears fully functional in testing but has been entirely unused.
    • +
    +

    Ralta updated:

    +
      +
    • Ian can now wear a CentComm Officer Beret to become Blueshield Ian
    • +
    • Sprite added for Blueshield armor to corgi_back.dmi
    • +
    • beret_centcom_officer and beret_centcom_officer_navy copied to corgi_head.dmi spritesheet
    • +
    +

    UmeFuu updated:

    +
      +
    • New recipe for cookies and sugar cookies, new ingredients such as pastry dough, flat pastry dough, unbaked cookies and a new tool called circular cutter (Added to the dinnerware vendor). New chem mix to create a specific type of dough for cookies and pastries.
    • +
    • Removed old cookie/sugarcookie recipe
    • +
    • added reagents of the cookies (They now actually taste like sugar and chocolate): - sugar = 3 - hot_coco = 5 +Also adjusted the sugar cookies nutriment from 3 to 1, just like chocolate cookies (They're made of the same dough after all) Chocolate bar can now be cutted into pieces/chocolate pile
    • +
    • added cookie(pastry) dough, flat cookie(pastry) dough, unbaked cookies/choco and circular cutter sprites. (Disclaimer: The cookie dough and flat cookie dough are edits of the normal doughs, pretty obvious but credits to who sprited them. Same with the tray with the unbaked cookies)
    • +
    +

    datlo updated:

    +
      +
    • Added a "voice" option to the magic mirror, letting you toggle comic sans/wingdings/swedish/chav
    • +
    • Free Golem Ship's interior walls and floors are now fully simulated titanium walls/floors, so they can be deconstructed, built upon, etc. balance: Increased the cost of RND boards for free golems to 2000 mining points (from 1500)
    • +
    • Golems can no longer activate robotic brains or have their brain put into an MMI.
    • +
    • Replaced one welding fuel tank in the golem ship by a chem master 3000.
    • +
    +

    farie82 updated:

    +
      +
    • Beepsky now can't insta cuff you when you run away and get back close to him.
    • +
    + +

    24 February 2019

    +

    Fox McCloud updated:

    +
      +
    • Adds the compact syndicate sniper rifle to the uplink. A weaker, low capacity variant of the operative syndicate rifle
    • +
    • Fixes blindness mutation not making you blind
    • +
    +

    datlo updated:

    +
      +
    • Golems can no longer use telescience consoles.
    • +
    • Nuclear operatives can now choose to take over a cyborg when spawning one, with a ghost playing the nuclear operative.
    • +
    + +

    23 February 2019

    +

    datlo updated:

    +
      +
    • Golems can no longer be objective targets
    • +
    • Offstation antag/special roles such as the ERT, abductors, etc, can no longer be objectives targets
    • +
    • Nukies no longer retain flavor text from saved character
    • +
    • Antag clowns can now toggle their clumsiness off and on.
    • +
    + +

    19 February 2019

    +

    Citinited updated:

    +
      +
    • Using a multitool on a conveyor switch now switches between one and two directions without needing you to set it on a menu.
    • +
    + +

    17 February 2019

    +

    Arkatos updated:

    +
      +
    • Changed Aurora Caelus event ending title to actually reflect that event is ending
    • +
    +

    Nicaragua1 updated:

    +
      +
    • Name of secbots
    • +
    • Honkbot wasnt dropping oil when exploded
    • +
    + +

    16 February 2019

    +

    Alonefromhell & AffectedArc07 updated:

    +
      +
    • Tweaked the discord link alert text slightly.
    • +
    +

    Mitchs98 updated:

    +
      +
    • Bar Starter Kit to Cargo. 20 points for both Beer/Soda Boards and a package of glasses.
    • +
    • Beer and Soda Machines can now be wrenched to move them.
    • +
    • Beer and Soda Machines can now be constructed as well as upgraded to include a slightly wider range of drinks.
    • +
    • Properly named the Banana Honk to Banana Honk from Banana Mama.
    • +
    +

    Nicaragua1 updated:

    +
      +
    • Adds General Griefsky bot and a toy version!
    • +
    • Spin-sabre sound
    • +
    • Adds Griefsky sprites
    • +
    +

    Terilia updated:

    +
      +
    • Added the donksoft sniper rifle
    • +
    • special donksoft sniper foam darts & special foamforce sniper foam darts
    • +
    • Sniper Foam Boxes && Riot Sniper Foam Boxes.
    • +
    • creates an admin log, if a player is being hit by a Foam Dart which has been tinkered with.
    • +
    • fixes a small misalignment in the magazine sprite if a dart is loaded.
    • +
    +

    aleksix updated:

    +
      +
    • AI's "Wipe Core" now properly ghosts the player
    • +
    +

    farie82 updated:

    +
      +
    • Removes some of the chaplain special religion names
    • +
    + +

    15 February 2019

    +

    aleksix updated:

    +
      +
    • posibrains and robobrains don't vanish upon the controlling player's suicide
    • +
    + +

    14 February 2019

    +

    AzuleUtama updated:

    +
      +
    • Added Super Surplus Crates from TG. They contain 125TC worth of gear, but cost 40TC meaning you'll need to team up if you want one.
    • +
    • The Surplus chance value for various uplink items will now work when ordering a crate.
    • +
    +

    Citinited updated:

    +
      +
    • Adds jestosterone to the list of standard reagents, not sure if this has any in-game effect.
    • +
    +

    EmanTheAlmighty updated:

    +
      +
    • Sentience event now adds some damage to the affected mob.
    • +
    • Sentience event now adds health to the affected mob, rather than replacing the old value with another value.
    • +
    +

    Mitchs98 updated:

    +
      +
    • IV Drip crate can now be opened by general medical personnel, instead of only the CMO.
    • +
    +

    TDSSS updated:

    +
      +
    • NT rep and Magistrate lose access to the HOP office
    • +
    +

    aleksix updated:

    +
      +
    • made the lighter size consistent before and after first lighting.
    • +
    +

    datlo updated:

    +
      +
    • The Nuclear Authentification Disk can no longer be taken from the station by the ERT, Abductors, or Sol Traders.
    • +
    + +

    12 February 2019

    +

    Citinited updated:

    +
      +
    • Fixes some spelling mistakes in the NT soul ownership contract
    • +
    +

    Kyep updated:

    +
      +
    • Added pink (princess) T3 terror spider, better terror spiderling AI.
    • +
    • Tweaked green and mother terror spiders. All terror spider types now have their own variants of the standard spider web.
    • +
    +

    datlo updated:

    +
      +
    • Added Greey's fluff duffelbag
    • +
    • Staff and wand of door can now also open lockers.
    • +
    + +

    11 February 2019

    +

    AffectedArc07 updated:

    +
      +
    • Admins that linked their discord account that round no longer show up as "the adminkey" in adminwho.
    • +
    • Changelog button loads properly on darkmode now
    • +
    • Added an admin verb that allows admins to forcefully unlink discord accounts
    • +
    +

    Fox McCloud updated:

    +
      +
    • Cryotubes no longer passively heal patients without chems. Effectiveness at stabilizing critical patients increased
    • +
    • Sleepers no longer gain additional chemicals when upgraded. Selection of chemicals altered
    • +
    +

    Shadeykins updated:

    +
      +
    • Added Chav to roundstart character preferences.
    • +
    • Removed Epilepsy, Tourette's, and Can't speak properly from roundstart character preferences.
    • +
    +

    datlo updated:

    +
      +
    • Reworked golems to use the ghost spawner system. Craft a golem shell with adamantine then apply 10 sheets of minerals to finish it.
    • +
    • Added golem subtypes. Each material has pros and sometimes cons. Type depends on the material used during construction.
    • +
    • Golems are now more resistant to damage and are no longer slowed by the cold of space.
    • +
    • Golems now get golem-y names.
    • +
    • Fixed golem's stone face hiding their identity, showing them as unknown.
    • +
    • Added the Free Golems mob spawners and ship. Go do whatever.
    • +
    • Added a small asteroid on the telecomms zlevel.
    • +
    • Added Shesi's fluff winter coat
    • +
    • You can no longer use mob spawners (old station/golems) if you've forfeited your right to respawn.
    • +
    + +

    10 February 2019

    +

    Fox McCloud updated:

    +
      +
    • Allows you to switch strap sides on leather satchel
    • +
    +

    TDSSS updated:

    +
      +
    • New space ruin, the crashed wizard shuttle. Rumored to contain fabulous magical treasures.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Reviver implant does not heal when you sleep, only when you fall unconscious involuntarily
    • +
    + +

    09 February 2019

    +

    AffectedArc07 updated:

    +
      +
    • You can now link your discord account and BYOND account together
    • +
    • With the accounts linked, you can get roundstart notifications within discord!
    • +
    • Fixed roundstart message in discord so that people are notified instead of characters being replaced
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds Fox's fluff coat
    • +
    • Health HUDs now have a defib indicator showing if they can be revived with a defib or not
    • +
    • Defib "safe" time reduced from 5 minutes to 2 minutes
    • +
    • fixes a bug where sometimes revived individuals still appeared to be dead or severely damaged on health HUDs after being revived with a defib
    • +
    +

    MINIMAN10000 updated:

    +
      +
    • Configuration option for disabling subsystems
    • +
    +

    Quantum-M updated:

    +
      +
    • Headslug sprite looks more deader.
    • +
    +

    TDSSS updated:

    +
      +
    • Singularities can no longer be pushed
    • +
    +

    Triiodine updated:

    +
      +
    • ozewse fluff item
    • +
    + +

    08 February 2019

    +

    Alonefromhell updated:

    +
      +
    • Drones should die properly now.
    • +
    +

    Kyep updated:

    +
      +
    • Characters are no longer massively more/less likely to be chosen for head jobs, especially the Captain job, based on their character's age.
    • +
    +

    Shadeykins updated:

    +
      +
    • Food descriptions/casing.
    • +
    + +

    07 February 2019

    +

    Alonefromhell updated:

    +
      +
    • Pineapple Salad's fluff coat
    • +
    +

    Dovydas12345 updated:

    +
      +
    • Fixes cult shackles appearing on the ground when removed
    • +
    + +

    06 February 2019

    +

    DrunkDwarf updated:

    +
      +
    • Reduced the size of the Ward-Takahashi Alt IPC head to prevent pixels clipping when wearing human clothing.
    • +
    + +

    05 February 2019

    +

    Alonefromhell updated:

    +
      +
    • LDM and Sorium should no longer push/pull ghosts
    • +
    +

    Kyep updated:

    +
      +
    • fixed a "_logging.dm,85: Cannot execute null.simple info line()" runtime when xenobio slimes emoted.
    • +
    + +

    03 February 2019

    +

    Fox McCloud updated:

    +
      +
    • Fixes a few edge cases of being able to create immunity to a few diseases
    • +
    • Adds suspiciously Voxy outfit to the game
    • +
    • Lack of breathing will render you unable to speak
    • +
    +

    MINIMAN10000 updated:

    +
      +
    • Boom function now properly checks for fuel
    • +
    +

    Tayyyyyyy, TaukaUsanake updated:

    +
      +
    • pAI units now have access to a flashlight module, which can be obtained with 5 RAM points.
    • +
    + +

    02 February 2019

    +

    AzuleUtama updated:

    +
      +
    • Added Pack of C-4 for Traitors and Nuke ops. Comes with 5 C-4 charges for 4TC.
    • +
    +

    Kyep updated:

    +
      +
    • Made playtime numbers displayed to admins (in the playtime report) and players (in the 'check my playtime' verb) clearer in meaning.
    • +
    +

    MINIMAN10000 updated:

    +
      +
    • Mobs in help intent do not push mobs pulling a structure or the structure they are pulling
    • +
    • mobs standing on the same tile when being walked into on help intent.
    • +
    • structures pulled beyond 1 distance call stop_pulling
    • +
    • stop_pulling() now sets pulledby to null
    • +
    +

    Shadeykins updated:

    +
      +
    • Thunderdome volume.
    • +
    • Newscaster placement
    • +
    • Power alarm subtype (noalarm), vomit/blood
    • +
    +

    TDSSS updated:

    +
      +
    • Mob spawner menu buttons now work. This time it really works, I swear.
    • +
    +

    uc_guy updated:

    +
      +
    • Non-breathing mobs no longer cause an increase in germ level by not wearing a mask.
    • +
    + +

    01 February 2019

    +

    AffectedArc07 updated:

    +
      +
    • Disabled darkmode is now normal grey, not full white
    • +
    • Changelog button now respects darkmode and will update when clicked
    • +
    +

    Citinited updated:

    +
      +
    • Sexy clown suits now have the squeak component
    • +
    • You can now change the way your sexy clown mask looks
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Admin save feature in build mode will ignore mobs
    • +
    +

    datlo updated:

    +
      +
    • Wingdings now garbles sentences.
    • +
    • Clown and mime now have their ID properly updated to their new name after they rename roundstart
    • +
    • Added some ID photo outfits to some jobs missing it.
    • +
    • Agent ID photo editing refactored. The photo now looks the same as a real ID, with an outfit based on the job you've forged on the ID.
    • +
    • Agent ID should now be impossible to distinguish from a real ID by non-antagonists once properly forged.
    • +
    • You can now reset access or delete the agent ID's information without having to do both.
    • +
    + +

    31 January 2019

    +

    Darkmight9 updated:

    +
      +
    • Adds the Camera Flash. A flash disguised as a camera for use as a cheap stun against non-sec, blinding crowds for a get away, and stunning borgs for emaging. Has a charge based system to prevent burning out.
    • +
    • Did some changes to flash code allowing different flashes to not be overcharged if one wants to or play a different sound when used.
    • +
    +

    Kyep updated:

    +
      +
    • Fixed various door control buttons that did not work correctly (brig prison lockdown, admin room lockdown, terror spider away mission containment doors, etc). refactor: refactored door_control buttons to check the GLOB.airlocks list, rather than doing a range(huge_number) check.
    • +
    • Terror Spider movement speed settings are no longer ignored when under player control. Instead, movement speed has been unified for both AI and player controlled spiders. Under player control, reds will now be slower, and purples will be faster. Under AI control, all spiders will be slower, except reds, which will be faster.
    • +
    +

    alffd updated:

    +
      +
    • revert to SS13 bot standard.
    • +
    +

    datlo updated:

    +
      +
    • Fixed surgery bugging and sometimes not starting properly when you try to surgery on a table or roller bed.
    • +
    • Surgery can now be done on any type of bed, with penalties.
    • +
    • Help intent is now required to start surgery. Was already needed to do surgery steps.
    • +
    • Surgery early cautery has been refactored. It is still done by holding a cautery in your inactive hand, but can now be done using ghetto tools, which can fail.
    • +
    • Medical cyborgs now have a laser scalpel instead of scalpel and cautery. lt is slightly faster and more versatile than standard tools.
    • +
    • Medical cyborgs now have a medical gripper. You can help patients up with it.
    • +
    • Medical cyborg can now cauterize incisions early by using the laser scalpel.
    • +
    • Added two black suit jackets to the arrivals locker room vendor
    • +
    • Added the armored suit jacket to the Bond, Payday, and Professional syndicate bundles.
    • +
    • Replaced the X4 in the Payday bundles by a C4.
    • +
    • The professional syndicate bundle now gets thermal fake sunglasses instead of thermal fake mesons.
    • +
    • Replaced the toolbox in the professional syndicate bundle by a pair of combat gloves.
    • +
    • Wingdings mutation works again.
    • +
    + +

    30 January 2019

    +

    AffectedArc07 & Teri updated:

    +
      +
    • There is now a toggle-darkmode verb to switch darkmode on and off
    • +
    • Chat settings also has a dark mode
    • +
    • The icon for the server is now the paradise palm tree
    • +
    +

    Shadeykins updated:

    +
      +
    • New Russian statue
    • +
    • Moved some cables, swapped a vendor.
    • +
    • Fixed missing door button, some dupes, and unintended object behavior.
    • +
    +

    Terilia updated:

    +
      +
    • Added a notification about the chat reconnecting on toggling of the dark chat mode.
    • +
    + +

    29 January 2019

    +

    Alonefromhell and Mitchs98 and farie82 updated:

    +
      +
    • Cake cat is now makeable.
    • +
    +

    Kyep updated:

    +
      +
    • Player-controlled hellhounds will no longer activate their smoke attack when they touch people on help intent.
    • +
    • Greater hellhounds (a far more dangerous version of the hellhound) now have descriptions that make it clear they are not the same as the regular hellhounds people are used to seeing.
    • +
    +

    farie82 updated:

    +
      +
    • fixes the viruses symptom creation being bugged. No more bluespace symptom creation
    • +
    +

    v0idp updated:

    +
      +
    • Discord Bot Functionality
    • +
    + +

    28 January 2019

    +

    AzuleUtama updated:

    +
      +
    • Fixed Binary Key's description to give the correct code to use when communicating with the AI or borgs.
    • +
    +

    Ionward updated:

    +
      +
    • Ionward's fluff coat
    • +
    +

    Shadeykins updated:

    +
      +
    • New derelict station. New floortiles (brownfull, cautionfull, darkredgreen, darkredblue, darkredyellow) New trash subtype (spent ammo casings) New titanium walls subtype (nodecon) Minor/oblique lore references (USSP, TSF, Cult/Bluespace) Context/modified objects (custom descriptions, slogans, etc.)
    • +
    • Old derelict station, two suspicious toolboxes
    • +
    • Remap teleporter, DJ station
    • +
    • Clown shuttle missing adjacent wall tiles
    • +
    +

    datlo updated:

    +
      +
    • Abductors no longer start with your preset character's flavor text.
    • +
    • Abductor scientists now have their SE properly cleaned on spawn.
    • +
    + +

    27 January 2019

    +

    Citinited updated:

    +
      +
    • Fixes tape being unapplicable to headsets and the autopsy scanner
    • +
    • You can't tape intercoms any more
    • +
    • The chemist can now create a new clown-based reagent using banana juice, lube, blood, space drugs, and salt.
    • +
    • Jestosterone heals brute damage for clowns, triggers annoying side-effects in other crewmembers, and is toxic to mimes.
    • +
    +

    Kyep updated:

    +
      +
    • fixed a runtime in hear_say.dm
    • +
    • Fixed item_attack / attack_obj runtime.
    • +
    • Fixed runtime when double-clicking a stool in-hand.
    • +
    • Antag objectives (kill, debrain, etc) can no longer target people on unreachable zlevels, like the admin-only/centcom zlevel.
    • +
    • fixed incorrect definitions of some spells related to shapeshifting.
    • +
    • Admin JMP links now work even if you're already following someone/something.
    • +
    +

    Kyep and alonefromhell and Ty Omaha updated:

    +
      +
    • Whispers are now fully readable in admin log.
    • +
    +

    TDSSS updated:

    +
      +
    • ether in syndie medical borg's hypospray replaced with hydrocodone
    • +
    • syndicate medical borg's hypospray no longer incorrectly lists its content
    • +
    +

    datlo updated:

    +
      +
    • Syndicate medical cyborgs now get a portable full body analyzer, making them much more effective field surgeons.
    • +
    • Bat swarm can no longer be spawned by gold slime extracts or reality tears. Regular bats can still be spawned.
    • +
    + +

    26 January 2019

    +

    AzuleUtama updated:

    +
      +
    • C4 and X4 are now much better at destroying objects they are directly placed on.
    • +
    +

    Citinited updated:

    +
      +
    • Renames the "Bar" on the Centcomm level to "Bar Lounge".
    • +
    +

    Shadow-Quill updated:

    +
      +
    • The engineering outpost now has atmospheric blocking tinyfans in the mass drivers.
    • +
    • Changed the wall in the Kitchen/Botany vendor to a plating.
    • +
    +

    datlo updated:

    +
      +
    • Fixed bluespace bunny ears fluff item description
    • +
    • Chameleon flag reworked : Now cost 1 TC from 7, but starts without an explosive. It can be boobytrapped using any grenade or a syndicate minibomb.
    • +
    • Chameleon flag moved from "Explosives" to "Stealthy Tools" in the uplink.
    • +
    • Fixed description of syndicate flags on the suspicious supply depot.
    • +
    • Books now deal light damage on hit if you're not on help intent. Space law book deals extra damage.
    • +
    + +

    25 January 2019

    +

    Agameofscones updated:

    +
      +
    • Cheeky Crenando's Soviet Greatcoat Fluff item.
    • +
    +

    Aurorablade updated:

    +
      +
    • Pineapplesalad fluff item
    • +
    +

    AzuleUtama updated:

    +
      +
    • Damp rags no longer have a lid, and must remain inferior to other containers.
    • +
    +

    Jazz23 updated:

    +
      +
    • Surgical Arm Menu
    • +
    +

    Kyep updated:

    +
      +
    • Fixed a mapping error in the brig remap PR.
    • +
    +

    blinkdog updated:

    +
      +
    • Normalized some paths in the code tree
    • +
    +

    datlo updated:

    +
      +
    • Reduced the cost of plasteel bomb frame crafting to 3 plasteel sheets (from 10)
    • +
    • Added emergency oxygen grenades to atmospherics lockers and the cargo emergency equipment crate.
    • +
    +

    warior4356 updated:

    +
      +
    • Drills now properly stop when turned off.
    • +
    + +

    23 January 2019

    +

    AzuleUtama updated:

    +
      +
    • Various text and formatting changes to traitor items.
    • +
    +

    Dovydas12345 updated:

    +
      +
    • Fixes simple animals (mice, corgis, etc.) and silicons (borgs, drones) being able to grab decks of cards, paperbins, chairs, stools.
    • +
    • Fixes simple animals (mice, corgis, etc.) and silicons (borgs, drones) being able to split stacks of sheets.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes null crafting recipes
    • +
    +

    Ionward updated:

    +
      +
    • Updated some drink sprites!
    • +
    +

    datlo updated:

    +
      +
    • Added sprites for the SST hardsuit (Mostly black with dark red), sprited by Ionward
    • +
    • Mapped SST and SIT shuttles on deltastation map.
    • +
    +

    iantine updated:

    +
      +
    • Lumi's fluff mouse
    • +
    • Mice now use their rest sprite when resting
    • +
    + +

    22 January 2019

    +

    TDSSS updated:

    +
      +
    • Suit Storage Units to most places that held hardsuits.
    • +
    • Ugly hardsuits on racks
    • +
    • reworked engineering slightly, removed the pointless hardsuit holding room.
    • +
    +

    Terilia updated:

    +
      +
    • Added Cake Cat - allowing the chef to create a living small pet in his kitchen.
    • +
    • Fixed frosted donuts, as they were filled with "spinkles" and not "sprinkles"
    • +
    + +

    21 January 2019

    +

    AzuleUtama updated:

    +
      +
    • Backpacks will now give a rough indication as to how much space they have left when examining them.
    • +
    +

    Nicaragua1 updated:

    +
      +
    • added mining drone sprites
    • +
    • sound alert for vampire gamemode
    • +
    • clown bot
    • +
    • clown box (Its made stamping a piece of cardboard with a clown stamp)
    • +
    • "honkbot evil laugh"
    • +
    • clown bot and box sprites
    • +
    • honkbot sprites
    • +
    +

    Spartan6 updated:

    +
      +
    • Gives Sol Traders a baton and a cargo cap.
    • +
    +

    datlo updated:

    +
      +
    • RD, CMO, and CE greys will now properly get a translator implant if they need one.
    • +
    • Updated the Syndicate Strike team's gear and ready room. Syndicate commandos will now be wearing reinforced black elite syndicate hardsuits and pack more ammo and supplies.
    • +
    • Syndicate commandos no longer start with all access.
    • +
    • Fixed some issues and improved the usability of the SIT and SST shuttle blast doors. They can now be reliably used to lockdown your shuttle from NT would-be intruders, and can be opened from inside and outside.
    • +
    • Fix accidental revert of the Syndicate Forward Base area name
    • +
    + +

    20 January 2019

    +

    AzuleUtama updated:

    +
      +
    • Fixed bee briefcase going into a negative number of remaining bees when used with less than 5 left.
    • +
    +

    Shadow-Quill updated:

    +
      +
    • You will no longer smack body scanner consoles when you rotate them.
    • +
    +

    datlo updated:

    +
      +
    • Fixed deathgasp emote not being called on death
    • +
    • Fixed nukies no longer exploding on death
    • +
    + +

    19 January 2019

    +

    Alonefromhell updated:

    +
      +
    • Mulecloset killing machine has been fixed. Mulebots are no longer able to be put into closets.
    • +
    +

    Shadow-Quill updated:

    +
      +
    • Removed a description that gets overwritten, moved the current one to it's old location.
    • +
    + +

    18 January 2019

    +

    Alonefromhell updated:

    +
      +
    • Revenant and Statue vision mode fixed.
    • +
    +

    AzuleUtama updated:

    +
      +
    • Added Professional Syndicate Bundle
    • +
    • Added Soporific Sniper Rifle. balance: Syndicate Bundles rebalanced to be worth more TC on average.
    • +
    +

    Nicaragua1 updated:

    +
      +
    • clown and mime locker now have correct acces
    • +
    • Golgrubs now run away from mechas being piloted
    • +
    +

    Quantum-M updated:

    +
      +
    • Medical Head Mirror, two spawn in the white medical clothes closet.
    • +
    +

    datlo updated:

    +
      +
    • Syndicate will no longer force you to play with the shiny new saboteur borg and instead send you the assault borg you actually ordered
    • +
    + +

    17 January 2019

    +

    Eschess updated:

    +
      +
    • Jetpacks work properly when placed on suit slot
    • +
    + +

    16 January 2019

    +

    Shadow-Quill updated:

    +
      +
    • Fixed a typo for when spiderlings enter vents.
    • +
    +

    uc_guy updated:

    +
      +
    • The burial suit (needed for the devil game mode) now shows up properly.
    • +
    + +

    15 January 2019

    +

    Jazz23 updated:

    +
      +
    • Bluespace Closet
    • +
    • Bluespace closet animations/sprites
    • +
    +

    uc_guy updated:

    +
      +
    • Actually activates devil friends contract.
    • +
    • Adds employment cabinet and codex gigas.
    • +
    + +

    14 January 2019

    +

    Kyep updated:

    +
      +
    • Doubled playtime requirements for command/sec jobs.
    • +
    • Starts tracking playtime on a per-department basis as well. E.g: "X hours in the Sec department".
    • +
    • Fixes bug which can cause more than 2 traders to spawn during the Sol Trader event.
    • +
    • Further improved sol trader event in general.
    • +
    • Enabled sol trader event to happen late-round as a randomly chosen event. Can only happen if the alert level is below red.
    • +
    +

    Quantum-M updated:

    +
      +
    • Magistrate Locker to the code.
    • +
    • Magistrate version of the Nanotrasen Navy Suit.
    • +
    • Gives the Magistrate a new wig, called Justice wig.
    • +
    • Magistrate specific stamp.
    • +
    • Adds the NT Rep version of the Nanotrasen Navy Suit (which already existed) to the NT Rep locker.
    • +
    +

    datlo updated:

    +
      +
    • ED bots no longer arrests you just because you have no ID by default
    • +
    • Nuke ops now spawn with their pinpointer.
    • +
    + +

    13 January 2019

    +

    Aurorablade updated:

    +
      +
    • Fluff item for Asmerath. rscadd:Accordions now have inhands
    • +
    +

    Shadow-Quill updated:

    +
      +
    • Stopped emergency shield generators from magically unbolting themselves when they get turned off.
    • +
    +

    Superhats updated:

    +
      +
    • Vox, Drask, Diona and Grey can now choose the Neutral gender option.
    • +
    +

    datlo updated:

    +
      +
    • Nuclear operatives can now select the Saboteur module when picking a cyborg, a modified engineering module designed around stealth and sabotage.
    • +
    • Fixed an exploit allowing you to get free syndicate cyborgs.
    • +
    +

    lordPidey updated:

    +
      +
    • Infernal devils have been seen onboard our spacestations, offering great boons in exchange for your soul.
    • +
    • Employees are reminded that their soul already belongs to Nanotrasen. If you have sold your soul in error, a lawyer or head of personnel can help return your soul to Nanotrasen by hitting you with your employment contract.
    • +
    • Nanotrasen headquarters will be bluespacing employment contracts into the IA's office filing cabinet when a new arrival reaches the station. It is recommended that the lawyer create copies of some of these for safe keeping.
    • +
    • Due to the recent infernal incursions, the station library has been equipped with a Codex Gigas to help research infernal weaknesses. Please note that reading this book may have unintended side effects. Also note, you must spell the devil's name exactly, as there are countless demons with similar names.
    • +
    • When a devil dies, if the proper banishment ritual is not performed on it's remains, the devil will revive itself at the cost of some of it's power. The banishment ritual is described in the Codex Gigas.
    • +
    • When a demon gains enough souls, It's form will mutate to a more demonic looking form. The Arch-demon form is known to be on par with an ascended shadowling in power.
    • +
    • Added Devil agent gamemode, where multiple devils are each trying to buy more souls than the next in line.
    • +
    • If you've already sold your soul, you can sell it again to a different devil. You can even go back and forth for INFINITE POWER.
    • +
    + +

    12 January 2019

    +

    AzuleUtama updated:

    +
      +
    • Chef Excellence's Special Sauce uplink description updated to be more accurate.
    • +
    +

    Shadow-Quill updated:

    +
      +
    • Fixed the QMs PDA supply app not showing the correct cargo shuttle location.
    • +
    • Changed the capitalization of CentCom and Station in the supply PDA cartridge.
    • +
    +

    datlo updated:

    +
      +
    • Nuke ops, ERT, and ayyybductors will now properly lose disabilities on spawn.
    • +
    + +

    10 January 2019

    +

    Aurorablade updated:

    +
      +
    • Cap guns was checking for claiber type 'cap' when the ammo was set to caliber typer 'caps'. Fixed.
    • +
    + +

    09 January 2019

    +

    Dovydas12345 updated:

    +
      +
    • Fixed NT Rep and Blueshield office door buttons not having correct required access
    • +
    +

    DrunkDwarf updated:

    +
      +
    • Analyzers now show the amount of moles within pipes and tanks
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes glasses not properly masking eye-shine
    • +
    +

    datlo updated:

    +
      +
    • Added the Staff of Slipping to the wizard spellbook for 1 spell point, sprites by Mithrandalf.
    • +
    • Added the wizard clown outfit to the wizard vending machine.
    • +
    • Added the magic mirror to the wizard den, letting wizards swap to other species and change their appearance.
    • +
    • Added spare plasmaman suit, plasma tank, and vox internals to wizard robes racks for any wizard that wishes to change to these species.
    • +
    • Made the snack machine in wizard den free to use. (wizards don't take silly credits as currency)
    • +
    + +

    08 January 2019

    +

    Alonefromhell updated:

    +
      +
    • Added an "All" option to ghost hud vision.
    • +
    +

    AzuleUtama updated:

    +
      +
    • Renamed and reorganized the ammunition in the uplink to make it easier for Nuclear Operatives to find the right ammo for their gun.
    • +
    +

    datlo updated:

    +
      +
    • Fixed grey translator translating the entire server.
    • +
    • Fixed BSA size checks being reversed, causing the BSA to clip through walls or prevent construction.
    • +
    + +

    07 January 2019

    +

    Fox McCloud updated:

    +
      +
    • Fixes auto-injectors being free parapens
    • +
    + +

    06 January 2019

    +

    AffectedArc07 updated:

    +
      +
    • Emitter reflectors are a thing now
    • +
    +

    Alonefromhell updated:

    +
      +
    • Dark matter and Sorium blob attacks should no longer affect ghosts and cameras.
    • +
    • All heads now have a HUD implant according to their department.
    • +
    +

    AzuleUtama updated:

    +
      +
    • New cane shotgun assassination shells. These buckshot shells are coated with a mute toxin which will prevent anyone hit either calling for help or screaming in pain.
    • +
    • Old cane shotgun assassination darts.
    • +
    • Cane shotgun now uses its own internal magazine rather than copying the code for the improvised one. It also now starts with an assassination shell preloaded.
    • +
    +

    Citinited updated:

    +
      +
    • You can now build snowmen out of 10 snowballs, 2 logs, and a carrot.
    • +
    +

    Dovydas12345 updated:

    +
      +
    • Added office door buttons, which open the office doors, to CE, HoP, CMO, HoS, RD, BS, NT Rep offices.
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Christmas!
    • +
    +

    Mithrandalf updated:

    +
      +
    • Added toy handcuffs
    • +
    +

    TDSSS updated:

    +
      +
    • Variants of Suit Storage Units that are ID locked
    • +
    • SSUs can now be hacked. Old SSU maint panel menu removed.
    • +
    • IRC chassis now have titanium cost to produce on top of metal.
    • +
    +

    datlo updated:

    +
      +
    • Added new, different voice sets to Syndicate, Clown, Mime, and ERT/Dsquad mechs
    • +
    • Added voice modification kits to the exosuit fabricator, letting you swap a mech's onboard voice to another.
    • +
    • Added visual and audio warnings when your mech is running low on power
    • +
    • Added visual warning when your mech is locked by maintenance protocols
    • +
    • Capulettium fake death will now actually be convincing, fooling examine, medhud, and health analysers, but not body scanners.
    • +
    • Capulettium plus can now be used to manually fake your own death when you wish by resting, and wake up when you wish by toggling rest again.
    • +
    • Added fake death pill bottle to maintenance loot, contains 3 pills of capulettium plus.
    • +
    • Fixed a mech runtime when an empty mech used power.
    • +
    • Grey wingdings is now a disability, add it to your saved characters if you want to have them on.
    • +
    • Grey translator implant preference added. Translates speech to be comprehensible, the implant can be turned off and on at will.
    • +
    • Mutadone no longer removes genes that you have at round start, from your job, species, or disability you've picked in character creation.
    • +
    • Mutadone no longer removes powers gained from a completed DNA vault.
    • +
    • Removed syndicate uplink management consoles.
    • +
    • Nuclear ops now automatically get bonus TC from round start and war declaration split between their uplinks.
    • +
    • Nuke ops can now buy stacks of 50 TCs.
    • +
    • Added a regular internals box to the Honk Brand Infiltration Kit.
    • +
    • CC officers plasmamen now get an appropriate suit.
    • +
    • Updated admin-outfitted syndicates
    • +
    • Wizard forcewalls can now be walked through by the wizard summoning them.
    • +
    • Added a new spell to the wizard spellbook, "Greater Force Wall". Summons a larger wall than the regular one, but requires wizard robes.
    • +
    • Added one box of pill bottles to Scichem
    • +
    • Replaces one of the two crew monitor consoles in medical front desk by a medical record console.
    • +
    +

    improvedname updated:

    +
      +
    • Mindshield implant, is now shown by a green flashing outline of your job hud
    • +
    • Moves some huds around to make them not overlap
    • +
    • changes some icons
    • +
    • fixes two missing pixels on execute status
    • +
    +

    uc_guy updated:

    +
      +
    • Fixes active deswords being pocketable.
    • +
    + +

    31 December 2018

    +

    Aurorablade updated:

    +
      +
    • Fixes Slaughter demons not releaseing corpses on death.
    • +
    • Fixes tears in spacetime just kinda sitting there.
    • +
    +

    Citinited updated:

    +
      +
    • Air pumps will now switch off when the inserted tank is removed.
    • +
    +

    Shadow-Quill updated:

    +
      +
    • No longer get debug messages from Slaughter Demons dropping mobs on death
    • +
    • Removed a useless comment in chronosuit code.
    • +
    +

    datlo updated:

    +
      +
    • Mech flashbang, banana, and mousetrap launchers now properly throw the item at your target instead of dropping it at the mech's feet.
    • +
    • Fixed nuclear operatives burning/choking on spawn if your set character is a plasmaman/vox. (they get healed once the round is done setting up)
    • +
    +

    farie82 updated:

    +
      +
    • Changed the laser tag gun pathing in the code.
    • +
    • Removed the / from the encryptionkey object in code.
    • +
    • Fixes the runtime in admin tickets
    • +
    +

    uc_guy updated:

    +
      +
    • Fixed death alarms / cell timer / beepsky radios.
    • +
    + +

    30 December 2018

    +

    datlo updated:

    +
      +
    • Glowsticks now process fuel properly
    • +
    + +

    29 December 2018

    +

    Alonefromhell updated:

    +
      +
    • Glowsticks are now compatible with shadowlings.
    • +
    +

    Spartan updated:

    +
      +
    • Adds emergency glowsticks to emergency box. sound: Glowsticks and flares now make more relevant usage sounds.
    • +
    +

    farie82 updated:

    +
      +
    • at the end of a radiation storm the maint access doesn't get revoked if it was set to emergency before hand.
    • +
    + +

    28 December 2018

    +

    AzuleUtama updated:

    +
      +
    • "Grenades and Explosives" category added to the uplink. Anything classed as such in the uplink has been moved here for easier access.
    • +
    +

    Ionward updated:

    +
      +
    • missing drask crusader helm #10486
    • +
    +

    Kyep updated:

    +
      +
    • Added kangaroo, a new creature type that is initially passive, but can be dangerous if provoked.
    • +
    +

    Mitchs98 updated:

    +
      +
    • All movement / pull resistance has been moved over to tg's move resist system.
    • +
    • You now drop a pull by ctrl + clicking anywhere else on the screen, rather than the object/mob being pulled.
    • +
    • All atom movables now have move force and move resist, and pull force An atom can only pull another atom if its pull force is stronger than that atom's move resist.
    • +
    • Mobs with a higher move force than an atom's move resist will automatically try to force the atom out of its way. This might not always work, depending on how snowflakey code is.
    • +
    • As of right now, everything has a move force, pull force, and resist of 1000. Structures can be crushed with sufficiently big move_force.
    • +
    • Failing to move onto a tile will now still bump up your last move timer. However, successfully pushing something out of your way will result in you automatically moving into where it was. Makes moving much smoother.
    • +
    • Mobs that shouldn't be able to pull objects now use a better check to prevent it.
    • +
    +

    Spartan updated:

    +
      +
    • ERT Medics now spawn with a medical analyser upgrade.
    • +
    • Amber ERT now spawn with a flashlight.
    • +
    • Red Engineer ERT now have an Elite ERT Hardsuit.
    • +
    • Paranormal ERT now spawn with a seclite.
    • +
    • CE toolbelt renamed. grammar: Surgery Belt > surgery belt
    • +
    +

    TDSSS updated:

    +
      +
    • clumsy people are now properly bad at handcuffing
    • +
    • Holoparasites/Guardians using the say verb now use host communication
    • +
    +

    Tails2091 updated:

    +
      +
    • Mice can *squeak now.
    • +
    +

    datlo updated:

    +
      +
    • Added the ability for command to set emergency access on all station airlocks with the keycard authentification device. (ID swiper)
    • +
    • Added the Boots of Gripping to the wizard hardsuit, sprited by Ionward
    • +
    • Fixed a cast check missing plasmaman wiz suit, causing issues with spell icons for them
    • +
    +

    improvedname updated:

    +
      +
    • Syndi emergency box to nuclear opratives.
    • +
    • Moves the suicide pill to the emergency box
    • +
    • Adds a recipe for the toolbox to make it a suspicous toolbox
    • +
    +

    name here updated:

    +
      +
    • new hat in the autodrobe
    • +
    +

    uraniummeltdown updated:

    +
      +
    • RPDs should be available in hacked autolathes again
    • +
    +

    v0idp updated:

    +
      +
    • missiles shot from missile racks in mechs will no longer spin in air
    • +
    • banana cake and slice
    • +
    + +

    26 December 2018

    +

    Shadow-Quill updated:

    +
      +
    • Fixed being able to start multiple prayers using the prayer beads.
    • +
    +

    v0idp updated:

    +
      +
    • Syndicate officer will not show in card modification/identification consoles anymore
    • +
    + +

    25 December 2018

    +

    Ranged updated:

    +
      +
    • Mutadone removes dizziness immediately instead of taking 5 minutes
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Fixes "makes frantic gestures" invalid emote with mute people using spells
    • +
    +

    improvedname updated:

    +
      +
    • fixed a typo
    • +
    +

    v0idp updated:

    +
      +
    • no bork in swedish accent while muzzled anymore
    • +
    + +

    24 December 2018

    +

    Alffd updated:

    +
      +
    • Removed fart based mechanics.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Removes "name here" from PR template
    • +
    +

    datlo updated:

    +
      +
    • Added the grenadier belt for nukies, ported from tg, containing a LOT of various grenades to throw at people.
    • +
    • Added the gluon grenade (Freeze floors and irradiate) and the frag grenade.
    • +
    • Added Toxins tech to RND. Can only be improved by testing explosives in the toxins lab, and unlocks various atmospherics tanks and items in the protolathe.
    • +
    • Added the Bluespace Rapid Pipe Dispenser, allowing you to place pipes at a distance. Built in the protolathe after improving Toxins and Bluespace tech. Sprite made by Ionward.
    • +
    • Welding Gas Mask now requires toxins tech.
    • +
    • Syndicate Officer job now available for admins, along with a brand new office connecting to the SIT, SST, and nuke ops ready room.
    • +
    • Remapped SIT and SST starting areas to be next to nuke ops starting area. Added sleepers and a couple of other QOL stuff in their ready rooms
    • +
    • Added a holding cell to the SIT starting area
    • +
    • Added a teleporter available to SIT and SST if admin enables it, can go to and from the z2 area.
    • +
    • Added an armory SST can get if admin enables it. 2 bulldogs, 2 SMG, 1 sniper, 1 medigun, 1 rocket launcher and assorted ammo.
    • +
    • Added 3 dark gygaxes, tools, and welding fuel to the SST mechbay room (admin access required)
    • +
    • Added a new subtype of mech rechargers for CC zlevel that will always recharge an attached mech even without power/recharger monitor
    • +
    • Added SIT shuttle transit area
    • +
    +

    v0idp updated:

    +
      +
    • Syndicate Officer won't show in nt recruitment anymore
    • +
    + +

    19 December 2018

    +

    Citinited updated:

    +
      +
    • Fixes a bug preventing snow machine crates from being orderable at roundstart. Ho ho ho!
    • +
    +

    uc_guy updated:

    +
      +
    • Fixed anomalies being disabled by random radio traffic.
    • +
    + +

    18 December 2018

    +

    Citinited updated:

    +
      +
    • Adds the snow machine. Fill it up with water, turn it on, and watch it create a winter wonderland all on its own! For best results set your room's air alarm to the lowest value it can go to.
    • +
    • The snow machine is orderable from cargo during Christmas time.
    • +
    • You can use a shovel to clear away generated snow. Scrooge.
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Christmas!
    • +
    +

    Ionward updated:

    +
      +
    • updated santa hat sprite, use hat to toggle beard
    • +
    +

    Tails2091 updated:

    +
      +
    • Fixes vent crawl vision sticking around for simple_animals.
    • +
    +

    datlo updated:

    +
      +
    • Added a global cap on printing papers.
    • +
    + +

    17 December 2018

    +

    MarsM0nd updated:

    +
      +
    • Restores mech radial menu functionality.
    • +
    + +

    15 December 2018

    +

    MarsM0nd updated:

    +
      +
    • radial menu now works for normally implanted implants
    • +
    +

    datlo updated:

    +
      +
    • Added sprites to specie specific boxes made by shazbot
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Me button added to chatbar
    • +
    + +

    13 December 2018

    +

    Breenland updated:

    +
      +
    • Adds drask ability to have auto-accent.
    • +
    +

    Edefff updated:

    +
      +
    • increase rollie smoketime to accommodate new chem volume
    • +
    +

    Kyep updated:

    +
      +
    • Tweaked the syndicate depot to fix various bugs and unintended design things, as well as make some changes to improve fun value.
    • +
    • Computer and machine frames are no longer invincible, and can now be destroyed by hostile NPCs.
    • +
    +

    McDonald072 updated:

    +
      +
    • Fixed being unable to cast lightning with the action button.
    • +
    +

    Mitchs98 updated:

    +
      +
    • Add's Makiroll's! Larger sliceable variants of sushi that yield four rolls of sushi in the same time that it previously took for one. You can also eat the Makiroll itself for 4x the nutriment/protein of a regular roll of sushi. Requires the Sushi Mat to craft.
    • +
    • Add's the Sushi Mat. 3 start in the chef's vendor. New ones craftable with 5 wood and 5 cable coil.
    • +
    +

    Shadow-Quill updated:

    +
      +
    • Makes people who are miming/mute give a visible indicator of their communion.
    • +
    +

    Tails2091 updated:

    +
      +
    • trimmed 300ms delay from smash.ogg
    • +
    +

    datlo updated:

    +
      +
    • Removed access requirement on emagged fax machines
    • +
    + +

    12 December 2018

    +

    Kyep updated:

    +
      +
    • Fixed a few things that should not be possible with pAIs and AIs.
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Read only sec hud for IAA and blueshield
    • +
    +

    name here updated:

    +
      +
    • Fixed Bulldog and C20 having their ammo alarms only go off once per gun.
    • +
    + +

    11 December 2018

    +

    Alonefromhell updated:

    +
      +
    • Miniature energy gun now has an action icon for it's light toggle(like flashlight).
    • +
    +

    Azule Utama updated:

    +
      +
    • Syndicate Uplink now uses expandable and collapsible categories. General layout of the uplink has also been changed to work alongside this.
    • +
    +

    Birdtalon updated:

    +
      +
    • Species specific starting boxes.
    • +
    +

    Citinited updated:

    +
      +
    • Fixes a runtime caused by AIs watching dance machines
    • +
    • You can now tape much more than just paper!
    • +
    • You can now order a crate full of sticky tape
    • +
    • Maximum amount in a tape roll is now 25 (up from 10).
    • +
    • Fixes some issues and runtimes in floorcluwne code.
    • +
    • Admins will now be informed of a new floorcluwne's chosen target if one is provided via the event.
    • +
    • There's a button next to secure storage's blast doors now.
    • +
    +

    Darkmight9 updated:

    +
      +
    • Added overheal to nanopaste
    • +
    +

    Ionward updated:

    +
      +
    • fixed slight spriting errors
    • +
    • added some more grey headwear
    • +
    +

    Kyep updated:

    +
      +
    • Fixed runtime related to chaplains.
    • +
    • Player-controlled giant spiders will no longer unintentionally poison anyone they nuzzle on help intent. They can still poison people they bite.
    • +
    • Altered the warning you get when you try to put one bag of holding inside another, so it is absolutely clear what this does, and there is no chance someone can do so by accident.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Arm implants use radial menues where suitable
    • +
    • Item actions can have icons different from the icon of the item
    • +
    +

    MrKicker updated:

    +
      +
    • Sorting of call list for holopads
    • +
    +

    Shadow-Quill updated:

    +
      +
    • Makes the chem-master update it's icon on power change, as well as showing the correct sprite after being loaded in.
    • +
    • Changed Oldstation Air Alarms/APCs to no longer give warnings to the main station.
    • +
    +

    TDSSS updated:

    +
      +
    • ghost spawn menu jump and spawn buttons now work.
    • +
    +

    Tails2091 updated:

    +
      +
    • Fixed typo for Schrodinger's cat.
    • +
    +

    datlo updated:

    +
      +
    • Display case burglar alarm no longer triggered if there's no power to equipment
    • +
    +

    gangelwaefre updated:

    +
      +
    • Aesthetic changes to Lumi's custom sprites
    • +
    + +

    10 December 2018

    +

    Farie82 updated:

    +
      +
    • Can't become 1 pixel big anymore due to genetics
    • +
    + +

    06 December 2018

    +

    Shadow-Quill updated:

    +
      +
    • Fixed protocol spelling in the Photon Projector description.
    • +
    +

    TDSSS updated:

    +
      +
    • Reverted holopad sorting to make holopads work again.
    • +
    + +

    01 December 2018

    +

    Kyep updated:

    +
      +
    • Fixed a couple of bugs with the special event pets triggered by admin bless command.
    • +
    +

    TDSSS updated:

    +
      +
    • Ancient Station asteroids now contain minerals and can be mined.
    • +
    +

    datlo updated:

    +
      +
    • Added 3 carrot seed packets to perma.
    • +
    + +

    30 November 2018

    +

    Azule Utama updated:

    +
      +
    • Fixed an ORM exploit which would let you smelt invalid stacks of alloys.
    • +
    +

    TDSSS updated:

    +
      +
    • Removed ballgag and assless chaps
    • +
    + +

    29 November 2018

    +

    Kyep updated:

    +
      +
    • Updated chaplains. They now spawn with their nullrod in their hand, and their soulstone in their locker. They now have the ability to bless other players. The more players they bless, the more likely admins are to answer their prayers. There are no longer any atheist chaplains. The chaplain items that reference atheism have been tweaked accordingly, e.g the atheist fedora is now the binary fedora. A few other items have also been tweaked. Paranormal ERT members now count as holy, like the chaplain, and red/gamma paranormal ERTs get a more powerful version of the nullrod, so they have a reason to use a weapon other than their gun.
    • +
    +

    TDSSS updated:

    +
      +
    • No more making infinite meat and crashing the server with gibbers
    • +
    + +

    28 November 2018

    +

    Kyep and FoS updated:

    +
      +
    • Updated hellhound with new sprites by FoS, slightly better AI, and more fixes/tweaks.
    • +
    +

    MrKicker updated:

    +
      +
    • Sort callable holopads by name
    • +
    +

    tigercat2000 updated:

    +
      +
    • You can now speak in multiple languages in the same message! This works for all forms of speech, including radios. Minus megaphones because fuck em.
    • +
    • Some mild formatting errors and inconsistencies that have historically been present within mob speech.
    • +
    • Holopads behaving a bit weirdly with how they interact with the typical say system
    • +
    + +

    27 November 2018

    +

    Azule Utama updated:

    +
      +
    • Power beacon made purchasable again in Nuke Ops uplinks.
    • +
    +

    Dovydas12345 updated:

    +
      +
    • Fixes being able to attach IV drips when incapacitated
    • +
    +

    Farie82 updated:

    +
      +
    • You can now actually make the rescue jaws
    • +
    + +

    26 November 2018

    +

    Citinited updated:

    +
      +
    • Adds the rubbish bin in front of the kitchen again
    • +
    +

    TDSSS updated:

    +
      +
    • Medbay secondary storage is now accessible to everyone with medbay access, hardsuits were put behind a windoor with CMO access to keep them at the same level of accessability.
    • +
    • Added and removed some items from medbay secondary storage.
    • +
    • Medical storage and secondary storage were renamed to be more accurate.
    • +
    +

    datlo updated:

    +
      +
    • Updated description of finger gun to point out you can holster the gun manually by using it in hand.
    • +
    • Fixed a bug where you couldn't learn finger gun if you already knew fake finger gun.
    • +
    • Power beacon cost reduced to 10 TC, and is now hijack-exclusive.
    • +
    • Guillotines can now be deconstructed with a welder.
    • +
    + +

    25 November 2018

    +

    Azule Utama updated:

    +
      +
    • Job-specific gear can no longer be discounted.
    • +
    • Discounted items now get an alternate log entry stating the item's new price.
    • +
    +

    KasparoVy updated:

    +
      +
    • Fixes Unathi Snout 2 not using the correct sprite.
    • +
    • Fixes Unathi Points Head not using the correct sprite.
    • +
    • Fixes Unathi Sharp Tiger Head and Face not using the correct sprite.
    • +
    • Fixes Unathi Tiger Head and Face not using the correct sprite.
    • +
    • Removes Unathi Sharp Points Head and enables Unathi Points Head marking for use on all Unathi head types.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Coins will now always show a side on being spawned.
    • +
    +

    Reagent Scanner Changes updated:

    +
      +
    • Removed Mass Spectrometer and Advanced Mass Spectrometer
    • +
    • Reagent Scanner and Advanced Reagent Scanners can now identify blood types
    • +
    +

    datlo updated:

    +
      +
    • Added the Advanced Mimery Series to Syndicate Mime uplink.
    • +
    • Added a fake Finger Gun manual to the arcade prize machine.
    • +
    • Changed the look of the teleporter hallway from maintenance to dirty hallway.
    • +
    + +

    24 November 2018

    +

    Azule Utama updated:

    +
      +
    • Added uplink discounts. Traitor and Nuclear Operative uplinks now have a discounted gear section! 3 random items will be chosen to be 50% off (rounded down), 25% if they usually cost 20 or more TC. You can only buy a discounted item once per uplink. Ported from TG.
    • +
    +

    Eschess updated:

    +
      +
    • hardsuit helmets now unlink from the hardsuits upon being detached
    • +
    • syndicate hardsuit helmet combat mode can no longer be toggled on hand
    • +
    • fixes non-syndicate hardsuit helmet attaching/detaching runtimes
    • +
    +

    TDSSS updated:

    +
      +
    • Space ruin/gateway hardsuits now should all come with helmets
    • +
    • Telecom setup in wizard gateway can now be completed with the present stock parts.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Added reflective blobs, these blobs have a high chance to deflect energy projectiles while being vulnerable to ballistics and brute damage. Reflective blobs can be obtained by upgrading a shield blob.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Fancier Transpara-corner Nano take 2.
    • +
    • Nano's build-watching works on 512 again.
    • +
    • Nano scrolling issues with the power monitor (they existed before I touched this goddamnit I swear!!!)
    • +
    • Rewrote Nano's buildscripts and upgraded all the dependencies (again)
    • +
    + +

    23 November 2018

    +

    Azule Utama updated:

    +
      +
    • Additional check added to damage falloff code, will only delete bullets that reach 0 damage if they actually have a falloff value.
    • +
    +

    Kyep updated:

    +
      +
    • Dead mice no longer squeak.
    • +
    • Ghosts walking over living mice no longer makes them squeak.
    • +
    +

    TDSSS updated:

    +
      +
    • no more runtime spam each time a simple mob is attacked
    • +
    +

    datlo updated:

    +
      +
    • Replaced "illegal" and "weapon" in strange objects name
    • +
    + +

    22 November 2018

    +

    AlAtEX updated:

    +
      +
    • re-adds sprites for boxes that disappeared
    • +
    +

    AlAtEx updated:

    +
      +
    • Added a new medkit for IPCs
    • +
    • added a purple medkit
    • +
    • Added a repair kit box to start with for IPC's
    • +
    • Re-added the crowbar and extended tank to miner's boxes
    • +
    • added three new box images
    • +
    +

    Azule Utama updated:

    +
      +
    • Made laser tag guns work again.
    • +
    • Syndicate Cigarettes added to maintenance loot.
    • +
    +

    Eschess updated:

    +
      +
    • Adds ui button to toggle hardsuit helmet
    • +
    • syndicate hardsuit combat mode is activated only by the helmet button
    • +
    +

    Kyep updated:

    +
      +
    • Added hellhound, a dangerous new monster.
    • +
    +

    datlo updated:

    +
      +
    • Added the CQC manual to nuke ops and traitor uplinks, letting them remember some of the basics of CQC.
    • +
    + +

    21 November 2018

    +

    MrKicker updated:

    +
      +
    • Added generated sound files to sound/vox_fem , then added references to them in vox_sounds.dm
    • +
    + +

    20 November 2018

    +

    AffectedArc07 updated:

    +
      +
    • NTTC now has multiple job tag styles
    • +
    • NTTC now has option to make job tags colored
    • +
    • NTTC now has option to make nametags colored
    • +
    • NTTC now has options to make command members louder (bold)
    • +
    • The NTTC window title is no longer NTSL.
    • +
    +

    Azule Utama updated:

    +
      +
    • Fixed chameleon suit having two invalid options.
    • +
    +

    TDSSS updated:

    +
      +
    • Silencers now have a tech origin, give research levels when deconstructed
    • +
    • Moved gun attachments to their own folder, code-wise.
    • +
    +

    name here updated:

    +
      +
    • Fixed a runtime in a syndieteam radio.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Nano scrolling is 95% less buggy
    • +
    • NanoUI's Fancy Mode now less broken as hell remove: 512 support for Nano dev tools
    • +
    + +

    19 November 2018

    +

    Birdtalon updated:

    +
      +
    • Fixes a runtime in safe.dm
    • +
    +

    Citinited updated:

    +
      +
    • Alt-clicking a jumpsuit removes accessories from it
    • +
    • Removing an accessory now shows a small message
    • +
    +

    KasparoVy updated:

    +
      +
    • Brings the logging of plasma statue ignition up to the same spec at as welder tank explosions.
    • +
    • You can no longer ignite plasma statues with disablers.
    • +
    +

    Kyep updated:

    +
      +
    • Tweaked many of the special admin outfits. This means centcom officers are less likely to be seen wielding illegal syndicate gear, and subtle flaws with many other outfits (such as pirates lacking radio, singulo knights lacking a backpack, several outfits not showing up on secHUDs correctly, etc etc etc) have been addressed.
    • +
    • Added several new admin options for fax responses, blessings, and smiting.
    • +
    +

    Quantum-M updated:

    +
      +
    • Sleeping carp uplink description now points out that it is unable to be learned by vampires or changelings.
    • +
    • Holoparasite kit uplink description now points out that it doesn't work on vampires or changelings.
    • +
    • Attempting to learn sleeping carp as a changeling or vampire gives you a red warning message.
    • +
    • You can now refund the sleeping carp scroll to the uplink.
    • +
    +

    TDSSS updated:

    +
      +
    • A warning if slings are very close to ascension, so the crew can potentially still stop them
    • +
    +

    craftxbox updated:

    +
      +
    • add observer/incapacitated check for all sec/medhud actions
    • +
    +

    datlo updated:

    +
      +
    • Added antag alert sounds that play at roundstart for most major antagonists, ported from TG.
    • +
    + +

    17 November 2018

    +

    uc_guy updated:

    +
      +
    • Syndicate borgs are no longer pseudonymous on syndie radio.
    • +
    + +

    16 November 2018

    +

    Azule Utama updated:

    +
      +
    • Changed falloff damage to be usable on any desired projectile rather than just shotgun pellets. balance: X-ray lasers now use 100 charge per shot (previously 50). balance: X-ray laser guns now have falloff damage. The longer the laser is in the air, the lower its damage becomes.
    • +
    • Slight addition to X-ray laser's description.
    • +
    +

    Certhic updated:

    +
      +
    • Replaces radio freq magic numbers with constants
    • +
    +

    Farie82 updated:

    +
      +
    • Borgs can't get perma stunned anymore by goliaths and slings and such
    • +
    +

    Fethas updated:

    +
      +
    • The floors are not safe! HONK!
    • +
    +

    Jazz23 updated:

    +
      +
    • Added flasher buttons in perma brig as well as windoors in botany, the wardens office, and cargo. Also added blast doors to transit tube.
    • +
    • HoP's flasher button not working, CE's secure shutter button and transit tube lockdown button not working.
    • +
    +

    Kyep updated:

    +
      +
    • The admin verb to list SSD players now highlights players who are another player's antag target. Additionally it lets you despawn players whose body is already in cryo.
    • +
    • Fixed a bug which caused banning to fail in rare situations.
    • +
    +

    Mitchs98 updated:

    +
      +
    • You can no longer rip the hood part of a hoodie off of someone's head.
    • +
    • Bee Costume and Monk Robe icons now show up properly in your inventory.
    • +
    +

    Triiodine updated:

    +
      +
    • Hotfixes taser projectiles being borked due to X-Ray re-work.
    • +
    +

    tigercat2000 updated:

    +
      +
    • SPEEEEEEEED to the asset cache, making preloaded UI assets transfer much faster.
    • +
    • NTTC deserializing works again
    • +
    • NTTC regex works again
    • +
    • NTTC no longer spams admins
    • +
    • NTSL2 no more, it is officially NTTC
    • +
    • NanoUI's fancy mode is hot shit again!
    • +
    • NanoUI's fancy mode is no longer broken as hell!
    • +
    • 512 support for Nano dev tools
    • +
    + +

    15 November 2018

    +

    Azule Utama updated:

    +
      +
    • Fixed an exploit which allowed cultists to curse the shuttle more than twice. Steve can only take so much punishment ya know...
    • +
    +

    Certhic updated:

    +
      +
    • The scrollbar of NanoUI now looks more Nano-ish
    • +
    • The title bar of NanoUI now sticks while scrolling
    • +
    • changed the mouse hover behavior on the fancy NanoUI buttons
    • +
    +

    Dave-TH updated:

    +
      +
    • Internal bleeding is now represented by coughing (And occasionally vomiting) blood! Nifty!
    • +
    +

    uc_guy updated:

    +
      +
    • Fixed the passive effects of prayer beads and prayer bread.
    • +
    + +

    14 November 2018

    +

    KasparoVy updated:

    +
      +
    • Vulpkanin Earfluff can be selected in facial hair again.
    • +
    • Vulpine Fluff and Earfluff head accessories and facial hair now have correct icon states.
    • +
    +

    uc_guy updated:

    +
      +
    • Borgs no longer have infinite roller beds.
    • +
    + +

    13 November 2018

    +

    Birdtalon updated:

    +
      +
    • Fixes playtime self checker.
    • +
    +

    Certhic updated:

    +
      +
    • fixed a cigs runtime error
    • +
    +

    TDSSS updated:

    +
      +
    • Ancient station's lockdown is now lifted correctly.
    • +
    • Ancient station RD console can now be used.
    • +
    +

    craftxbox updated:

    +
      +
    • use mob voice instead of mob name for radios broadcasting signals.
    • +
    +

    datlo updated:

    +
      +
    • Prevent wizards from casting rod form inside the wizard den.
    • +
    + +

    12 November 2018

    +

    Azule Utama updated:

    +
      +
    • Fixed text errors in the descriptions for Booger cocktails and Feral cat grenades.
    • +
    +

    Birdtalon updated:

    +
      +
    • Verb to check your own playtime.
    • +
    +

    CornMyCob updated:

    +
      +
    • You can now unwrench and move the library machines/computers, chem master, chem heater, washing machine, pandemic and PDA painter
    • +
    +

    Farie82 updated:

    +
      +
    • Added the pressure damage reduction to mining bots. No more killing machines called mining bots.
    • +
    +

    variableundefined updated:

    +
      +
    • AI can now select the alien screen display
    • +
    • Nearly every single sprite accessories (species customization option) has been separated and refactored. Report missing hairstyle / screen / horns / frills / tails etc.
    • +
    • Desolate's peacekeeper fluff cyborg sprite is now his service sprite.
    • +
    + +

    11 November 2018

    +

    Azule Utama updated:

    +
      +
    • Borgs can no longer stunbaton into infinity. Their batons will now deactivate if they have no power left after hitting someone and cannot be turned back on until they recharge.
    • +
    +

    Eschess updated:

    +
      +
    • large cardboard boxes now show their size when examining
    • +
    • fulltile plasma glass windows now have armor
    • +
    • rised plastitanium windows integrity
    • +
    +

    Farie82 updated:

    +
      +
    • You can now hurt mining bots with welders on any attempt other than help
    • +
    • Can put suits and such back into the suit storage units
    • +
    • Fixed the tank/magboots storage part being called Breathmask storage, lazy copy pasta
    • +
    +

    Squirgenheimer updated:

    +
      +
    • Hatched alien larvas will default to being created on the turf of the mob instead of the mob's location, unless specifically allowed (like closets and spacepods)
    • +
    +

    tigercat2000 updated:

    +
      +
    • Ears are now an organ, which can be damaged, removed, and inserted!
    • +
    • Human icon code should perform massively better.
    • +
    + +

    10 November 2018

    +

    Citinited updated:

    +
      +
    • Prevents an infinite metal exploit using the autolathe.
    • +
    • Minimum returnable metal of ammunition boxes has been lowered from 2000 to 500.
    • +
    +

    Dovydas12345 updated:

    +
      +
    • Fixes being unable to slice certain food grown by hydroponics (pineapple, watermelon etc.)
    • +
    +

    Shazbot updated:

    +
      +
    • Some fancy new box sprites, props to Shazbot for the sprites
    • +
    • Old cuff box is gone
    • +
    +

    TDSSS updated:

    +
      +
    • Quarantine is now its own lawset.
    • +
    + +

    09 November 2018

    +

    Alonefromhell updated:

    +
      +
    • Most sheets held in hand should now display either a metal or reinforced glass icon where appropriate.
    • +
    • Holopad should no longer automatically revert to default sprite.
    • +
    +

    Azule Utama updated:

    +
      +
    • Small change to cursed heart's spellbook description.
    • +
    +

    AzuleUtama updated:

    +
      +
    • RCD now gives visible messages when building without enough ammo or on an invalid tile.
    • +
    +

    Citinited updated:

    +
      +
    • Fixes ghosts being able to make conveyors drain more power than they should.
    • +
    +

    Dave-TH updated:

    +
      +
    • Space levels is named now.
    • +
    +

    Mitchs98 updated:

    +
      +
    • Chemical implants now work and can be properly filled via beaker or syringe. Reagents inside can also be syringed out.
    • +
    +

    Warior4356 updated:

    +
      +
    • Thermal Drill, Diamond Tipped Thermal Drill, Safe Codes Paper, Safe Internals, Gives Captain Floor Safe, Gives Captain Safe Codes, Safe-cracking Kit
    • +
    • Removed Captain's Digital Safe
    • +
    • Changes safe contents
    • +
    • Added a safe drilling sound
    • +
    • Added drill and safe intenral sprites made by Shazbot194
    • +
    + +

    08 November 2018

    +

    Citinited updated:

    +
      +
    • Conveyors use less power now
    • +
    +

    Eschess updated:

    +
      +
    • fixes the NOR, NAND and XOR logical gates
    • +
    • reinforced plasma glass windows give you reinforced plasma glass sheets now
    • +
    • fulltile reinforced plasma glass windows now have armor
    • +
    +

    Farie82 updated:

    +
      +
    • Mining bots now function as expected when giving them a health upgrade. No more repairing without healing
    • +
    +

    Fel updated:

    +
      +
    • You can now craft wooden barrels with 30 pieces of wood! They can hold up to 300u of reagents.
    • +
    • Putting hydroponics-grown plants into the barrel lets you ferment them for alcohol! Some give bar drinks, while others simply give plain fruit wine.
    • +
    • Reagent containers like bottle & glass should be more consistent now.
    • +
    +

    Spartan updated:

    +
      +
    • Plastic bags and wet floor signs can now spawn in maint.
    • +
    • Plastic bags are now supplied to your syndicate uplink. Apply directly to head.
    • +
    +

    Wario4356 updated:

    +
      +
    • Mecha can now drill other mecha
    • +
    +

    Warior4356 updated:

    +
      +
    • Mecha drills now tell you when they can't drill
    • +
    +

    datlo updated:

    +
      +
    • Added the Toxins Payload Casing to crafting recipes, a new method of activating tank transfer valve bombs.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Mecha now use action buttons instead of ugly verbs.
    • +
    • Mecha weapons can now be selected through a radial menu brought up by Ctrl Clicking on the Mecha while you are piloting it.
    • +
    • Tooltips now appear on radial menu buttons when you hover over them. Seriously, why wasn't this a thing in the first place?
    • +
    • Action button icons are now located in their own file.
    • +
    • Captain and HoS can be nearsighted again.
    • +
    +

    variableundefined updated:

    +
      +
    • Baycard, including tarot cards to loadout
    • +
    • Baycard to prize machine
    • +
    • All non-syndicate card deck on map has been replaced with bay card.
    • +
    + +

    07 November 2018

    +

    Spartan updated:

    +
      +
    • Bluespace Crystals no longer use the entire stack when used on self to teleport.
    • +
    +

    Squirgenheimer updated:

    +
      +
    • toggling off global antag candidacy will disable you from being selected by the Create Antagonist verb.
    • +
    +

    TDSSS updated:

    +
      +
    • added mulebot control to captain's PDA again.
    • +
    +

    name here updated:

    +
      +
    • objective lists are now sorted for admins.
    • +
    +

    uc_guy updated:

    +
      +
    • IPCs and slimes now have an effect on the floor when bleeding.
    • +
    + +

    06 November 2018

    +

    R1f73r updated:

    +
      +
    • Added a death text to headslugs when they die
    • +
    +

    Squirgenheimer updated:

    +
      +
    • blob and autotraitor game modes will now check for Global Antag Candidacy when picking new antagonists after round start
    • +
    • Global Antag Candidacy button will now show up after round start
    • +
    +

    TDSSS updated:

    +
      +
    • Can no longer attempt to build tranquilite walls (and delete the wall in the process)
    • +
    +

    TatsumakiMagi updated:

    +
      +
    • target icon updates when lit by user
    • +
    +

    Triiodine updated:

    +
      +
    • Airlock sensors & vent system to west mining outpost (Safety first!)
    • +
    • Disposals inlet now directly goes to cargo _delivery_ (not conveyor)
    • +
    • More spawns for science nerds in accordance to highpop.
    • +
    • All conflicting C_tags, dispatch cops or AI should freely use all cameras now.
    • +
    • [delta] APC to virology mainroom
    • +
    • [delta] All unsimulated turfs are now simulated.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Fixes spacing in admin deletion logs
    • +
    +

    datlo updated:

    +
      +
    • Added syndicate themed internals to traitor spacesuit and hardsuit.
    • +
    + +

    05 November 2018

    +

    AzuleUtama updated:

    +
      +
    • Added Traitor's toolbelt
    • +
    • Replaced Military belt with Traitor's toolbelt in the uplink.
    • +
    • Price of new belt lowered to 2TC
    • +
    • Replaced Military belt with Traitor's toolbelt in maintenance loot.
    • +
    +

    Regen updated:

    +
      +
    • The tentacle changeling power now generates admin logs.
    • +
    +

    TatsumakiMagi updated:

    +
      +
    • Fixes adjacency and standing checks for cutouts
    • +
    + +

    04 November 2018

    +

    AffectedArc07 updated:

    +
      +
    • Makes status display font crispy. mmmmmmmmmmmmm
    • +
    +

    Citinited updated:

    +
      +
    • Fixes a bug in machines when switching between speedy and normal processing speeds.
    • +
    +

    Dave-TH updated:

    +
      +
    • Adds the access tuner, a syndicate device for interfacing with airlocks. Try it out!
    • +
    +

    Farie82 updated:

    +
      +
    • Clings now appear dead on medical huds when using regenerative stasis
    • +
    +

    R1f73r updated:

    +
      +
    • Admin Character names will no longer appear in adminhelps
    • +
    +

    TDSSS updated:

    +
      +
    • Allow , in names, Kidan of the world, rejoice
    • +
    • Made kidan random name generation less shitty
    • +
    +

    Triiodine updated:

    +
      +
    • ghost role sprites with a palette more depressed than the playerbase
    • +
    • medical doc spawn to ghost station
    • +
    • Xydonus's second fluff item
    • +
    + +

    03 November 2018

    +

    Certhic updated:

    +
      +
    • Added diona nymph action buttons
    • +
    • Added diona nymph resist alert when they're merged
    • +
    • Diona nymph can now initiate merge with the gestalt
    • +
    • Diona nymph can now leave their gestalt by resisting
    • +
    • Diona nymph can no longer attack its gestalt
    • +
    +

    Farie82 updated:

    +
      +
    • Security comments now work again. Sec hud arrests will now function as intended.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes exploit involving materials and the recycler
    • +
    +

    Jazz23 updated:

    +
      +
    • A method of uploading coordinates to perma teleporter circuit board.
    • +
    +

    variableundefined updated:

    +
      +
    • Tigercat2000 & variableundefined (Ansari) to the maintainer list.
    • +
    + +

    02 November 2018

    +

    Purpose updated:

    +
      +
    • After over 100 years in cryosleep, a few cryocells are starting to open... AncientStation ghost roles are now available.
    • +
    • Adds a ghost role menu, available under the Ghost menu
    • +
    • Adds an all-access Air Alarm for mappers to utilise.
    • +
    • Adds glowsticks. Currently only available in AncientStation.
    • +
    +

    variableundefined updated:

    +
      +
    • Attack log to stun gloves
    • +
    + +

    01 November 2018

    +

    Citinited updated:

    +
      +
    • A disposal nullspace bug.
    • +
    +

    Farie82 updated:

    +
      +
    • Repairing a mech now says you're doing it to the others balance: Mechs now take time to repair. No more spam repairing
    • +
    • Random news feed now does not contain random code.
    • +
    +

    Mitchs98 updated:

    +
      +
    • Lowers the spam you receive from entering a warm or cold pool. You will no longer receive 'The water is quite warm.' nearly every few seconds.
    • +
    • Headslugs no longer teleport out of closed lockers upon bursting.
    • +
    +

    Warior4356 updated:

    +
      +
    • Ghosts can no longer re-enter a drone that has been shut down.
    • +
    + +

    31 October 2018

    +

    Arkatos updated:

    +
      +
    • Fixes Rewriter drink description typo.
    • +
    +

    Jountax updated:

    +
      +
    • Renamed Ice Peppers to Chilly Peppers.
    • +
    +

    TatsumakiMagi updated:

    +
      +
    • fixed merch shop, arcade shop and the give command working from a distance
    • +
    + +

    30 October 2018

    +

    Dave-TH updated:

    +
      +
    • Adding a paper to a paper bundle no longer automatically opens the bundle.
    • +
    +

    Farie82 updated:

    +
      +
    • Items dropped in a space pod are now under the seat. No more magical dropping out of the pod
    • +
    • Cargo can now buy oil tanks.
    • +
    +

    Warior4356 updated:

    +
      +
    • Megaphone now handle speech impediments properly
    • +
    • Swiping an ID through a drone no longer causes a runtime and correctly shuts it down
    • +
    • Silicons are now able to open a door linked to a button regardless of proximity
    • +
    +

    uc_guy updated:

    +
      +
    • You can no longer table people through walls/doors/shutters.
    • +
    +

    warior4356 updated:

    +
      +
    • fixed the holosign in surgery1
    • +
    + +

    29 October 2018

    +

    Farie82 updated:

    +
      +
    • Round start time is now variable. Defaults to 240 if not filled in
    • +
    +

    Mitchs98 updated:

    +
      +
    • Re-Adds a Guest Pass terminal to Medbay front desk.
    • +
    +

    Squirgenheimer updated:

    +
      +
    • regular mining satchels will now only hold 10 slots of ore stacks instead of 50
    • +
    • Deleting mechs no longer causes a runtime
    • +
    • Mech speech bubbles should now follow the mech.
    • +
    +

    gatchapod updated:

    +
      +
    • Fixed airlocks electrocuting people remotely through open UI
    • +
    + +

    28 October 2018

    +

    Dovydas12345 updated:

    +
      +
    • Fixed being able to pull when incapacitated
    • +
    • Fixes catching two handed items with one hand.
    • +
    +

    Fox McCloud updated:

    +
      +
    • changes the oil can sprite
    • +
    • Colorful Reagent changes your blood color
    • +
    +

    Mitchs98 updated:

    +
      +
    • Adds the Security Jacket to the standard sec gear lockers, an alternative to the standard armor vest that covers more area but protects less. Style matters.
    • +
    +

    Normalyman updated:

    +
      +
    • Fixed being able to open containers via dragging, while being incapacitated.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Pulling fixed
    • +
    • Better way of fixing hostile mobs not attacking
    • +
    • Hostile mobs attack again instead of nuzzle
    • +
    +

    uc_guy updated:

    +
      +
    • Fixes shadowling game mode delaying the game ticker
    • +
    + +

    27 October 2018

    +

    AffectedArc07 updated:

    +
      +
    • Removed catgirls, be gone foul beasts
    • +
    +

    Alonefromhell updated:

    +
      +
    • Runtime in species.dm, 620 fixed
    • +
    • Stable LDM and Sorium creates their vortexes properly now.
    • +
    • Inject chems into all your favorite types of smokeables, TODAY!
    • +
    • Backend: Added dummy vortex reagents to prevent further runtimes.
    • +
    +

    Certhic updated:

    +
      +
    • fixed wrenched down unconnected pipes being invisible
    • +
    • fixes invisible diona observers
    • +
    • Fixes simple animals attacking while they were on help intent.
    • +
    +

    Farie82 updated:

    +
      +
    • Dusting a mob now dusts everything he holds and has equiped
    • +
    • fixes animals activating the paperfolding proc. No more runtimes there
    • +
    • One less piano runtime
    • +
    • fixes the runtime in the AI code. You now get messages if you lose power and stuf.
    • +
    • Fixes the runtime in Landmarks
    • +
    +

    TDSSS updated:

    +
      +
    • HoP's door remote has access to his office doors + supply doors now
    • +
    +

    tigercat2000 updated:

    +
      +
    • Pretty radial menu for the RCD!
    • +
    • SSoverlays human mobs
    • +
    • Catgirls!
    • +
    • /tg/'s catgirl refugees
    • +
    • Ears are now organs
    • +
    • The suffering of thousands of displaced kittens
    • +
    +

    uc_guy updated:

    +
      +
    • Fixed roller beds not going to their "down" position.
    • +
    • You can now tell if a borg has suicided by examining them
    • +
    + +

    26 October 2018

    +

    Mitchs98 updated:

    +
      +
    • Unary vents, scrubbers, passive vents, connectors, air injectors, and pipe caps now orientate as intended when using Orientate Automatically with an RPD.
    • +
    • Fixes #8036, Door controls not respecting range for pod doors.
    • +
    • Now when holding a flag it won't be stabbing into your characters face. Burning a flag also won't magically change its orientation.
    • +
    +

    dovydas12345 updated:

    +
      +
    • Fixes ghosts being able to unflip flipped tables.
    • +
    +

    uc_guy updated:

    +
      +
    • Syndicate communication channel is now pseudonymous.
    • +
    + +

    25 October 2018

    +

    Aurorablade updated:

    +
      +
    • welders will now fix external IPC leaking. My Bad.
    • +
    +

    Birdtalon updated:

    +
      +
    • User responses not being appended to admin tickets
    • +
    +

    Dave-TH updated:

    +
      +
    • Adds surgical trays! You can drag these cool tables around and the items placed on them come along for the ride! Nifty!
    • +
    +

    Farie82 updated:

    +
      +
    • Objectives now get fully removed when removing them admin style. Removing the assassinate cryo message if you were de antagged.
    • +
    +

    tigercat2000 updated:

    +
      +
    • PiP Hud Elements
    • +
    • AI PiP Multicam - Enabled by admins
    • +
    • Calling /New( with excess arguments is now properly directed to /Initialize(
    • +
    + +

    24 October 2018

    +

    Alonefromhell updated:

    +
      +
    • Mind check in pre_quip added, to prevent runtime.
    • +
    +

    Birdtalon updated:

    +
      +
    • Backend cleanup of assembly.dm and proximity.dm
    • +
    +

    Certhic updated:

    +
      +
    • Runtime error in CureIfHasDisability
    • +
    • Borg health is now updated after being repaired
    • +
    +

    Farie82 updated:

    +
      +
    • Tablets now spawn correctly. No more buying (seemingly) broken tablets
    • +
    +

    Fethas updated:

    +
      +
    • Ipcs bleed oil. Bleeding can be patched by welders and organ mainp surgery(if you have to heal an ipc via surgery we may as well take that out too).
    • +
    • Kidan biolum slightly brighter. tweak:Vox now become confused and unintellible(..more) on cort stack damage.
    • +
    +

    Warior4356 updated:

    +
      +
    • Safe tumbler 2 no longer makes I am open noise when turning tumbler 1.
    • +
    +

    dovydas12345 updated:

    +
      +
    • Added data disk to misc designs.
    • +
    +

    variableundefined updated:

    +
      +
    • Using reagent dispenser like fuel and water tank no longer give you an attack cooldown / animation.
    • +
    • Tracking for shadowling win rate. Improved parsability for other win/loss round type's win rate.
    • +
    + +

    23 October 2018

    +

    Alonefromhell updated:

    +
      +
    • You should now be able to put all your favorite chems in food again.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Reagents now GC slightly better
    • +
    + +

    22 October 2018

    +

    Dave-TH updated:

    +
      +
    • Fancy tables now properly smooth.
    • +
    +

    MrStonedOne updated:

    +
      +
    • Fixes a cause of lag in the Timer subsystem
    • +
    +

    Purpose updated:

    +
      +
    • Removes unused code in Nuclear gamemode.
    • +
    • Removes some empty icon files.
    • +
    • Fixes a typo in an SDQL parse warning.
    • +
    • Code improvement with timers in Revolution gamemode.
    • +
    +

    name here updated:

    +
      +
    • The autopsy scanner now works even when it does not know the weapon and/or the time of death.
    • +
    • Unused weapon chance code
    • +
    +

    uc_guy updated:

    +
      +
    • Removed logging ambiguity for uplink purchases.
    • +
    +

    variableundefined updated:

    +
      +
    • Component refactor from tg made by ninjanomnom has been ported over. Report unexpected issue (with autolathe / ORM)
    • +
    + +

    21 October 2018

    +

    Alonefromhell updated:

    +
      +
    • Fixed some formatting issues in post_equip.
    • +
    +

    Ansari updated:

    +
      +
    • Oculine processing should be less expensive now.
    • +
    +

    Desolate updated:

    +
      +
    • Refactors some reagent lists into global list
    • +
    +

    Farie82 updated:

    +
      +
    • Cyborgs can now refill welding tools and fire extinguishers using the recharging station
    • +
    • Oculine now updates the blindness status correctly
    • +
    • Added the Viral Injector. A virologist specific traitor item that acts like a sleepy pen but can transfer viruses. It's disguised as a functional pipette.
    • +
    +

    Purpose updated:

    +
      +
    • Moves Icon Smoothing to a Subsystem.
    • +
    • Atom code will no longer track a list atoms, for literally zero reason.
    • +
    • Fixes grammatical error in the suit storage unit
    • +
    +

    Shazbot194 updated:

    +
      +
    • all north facing in hand icons for flags.
    • +
    +

    Squirgenheimer updated:

    +
      +
    • Explosive holoparasite booby traps will now behave better, such as correctly triggering on mobs
    • +
    +

    Triiodine updated:

    +
      +
    • Skrell & Tajaran sechardsuit to paracode palette, from Bay12 palette.
    • +
    • TG & BS12 sec-hardsuits in all dmis
    • +
    +

    Warior4356 updated:

    +
      +
    • Final UI update was missed in Safe Refactor PR
    • +
    +

    name here updated:

    +
      +
    • Holodeck plating sprite is now back to the old one.
    • +
    +

    tigercat2000 updated:

    +
      +
    • We're going 512 boisssssssssssssss
    • +
    +

    variableundefined updated:

    +
      +
    • Improves the List free slots admin verb to show useful information.
    • +
    • Cyborg hypospray's attack log message should no longer be reversed.
    • +
    • How containers work is now standardized in the back-end. There might be unexpected or odd bugs with containers and reagent transfer, please report them.
    • +
    • Minor refactor of revenant code.
    • +
    • Some relative path & commented out code has been cleared up in code. Report unexpected issues.
    • +
    + +

    20 October 2018

    +

    Birdtalon updated:

    +
      +
    • Spacepods explosions are significantly reduced.
    • +
    +

    Dapocalypse updated:

    +
      +
    • Adds password protected files to modular computer.
    • +
    +

    Farie82 updated:

    +
      +
    • Guardian injectors now tell in their examination text if they are spend or not.
    • +
    • Added feedback on the RCD airlock access topic.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Updates the Garbage SS so it's less likely to induce lag
    • +
    +

    Purpose updated:

    +
      +
    • Suit storage units now contain magboots for relevant roles.
    • +
    • Adds the captains jetpack to his suit storage unit, so it is now stealable again on Delta.
    • +
    • Aluminum & Aluminium properly standardized.
    • +
    +

    craftxbox updated:

    +
      +
    • added check to make sure person downloading pAI isnt dead.
    • +
    +

    uc_guy updated:

    +
      +
    • It is no longer possible to duplicate uvents.
    • +
    +

    variableundefined updated:

    +
      +
    • Plating's icon is back to the old one once again.
    • +
    + +

    19 October 2018

    +

    Fox McCloud updated:

    +
      +
    • Fixes round-start sparks being stuck in maintenance
    • +
    +

    Purpose updated:

    +
      +
    • Fixed an issue with Space Vine mutations
    • +
    +

    SpaceManiac updated:

    +
      +
    • The body zone selector now indicates which body part you are about to select when hovered over.
    • +
    +

    TDSSS updated:

    +
      +
    • New exosuit equipment: The rescue jaws for the Odysseus lets it open doors, firelocks and even force powered doors. It can also be added to firefighter ripleys.
    • +
    +

    Triiodine updated:

    +
      +
    • new DNA Sampler Sprite
    • +
    +

    Warior4356 updated:

    +
      +
    • Added nanoui for safe. Added minor quality of life to safe.
    • +
    • Removed old UI from safe
    • +
    • Safe now is only Right - Left - Right. Safe is 0-99 rather than 0-71.
    • +
    • Added safe dial for it's nanoui.
    • +
    + +

    18 October 2018

    +

    IrkallaEpsilon updated:

    +
      +
    • Feral Cat grenades are now listed as job specific items.
    • +
    +

    Shazbot updated:

    +
      +
    • Shazbot's custom cyborg sprites.
    • +
    +

    Squirgenheimer updated:

    +
      +
    • Ghosting from cryopods with an inventory open should no longer cause a runtime
    • +
    +

    Triiodine updated:

    +
      +
    • disposals pipes sprite offsets & stray pixels.
    • +
    • id_decal icons
    • +
    • arcade id_decals using mind batterer sprite. (That's just silly.)
    • +
    + +

    17 October 2018

    +

    Alonefromhell updated:

    +
      +
    • Added a Nanotrasen Navy Uniform to the blueshields locker
    • +
    +

    Crazylemon updated:

    +
      +
    • Buildmode is now compatible with 511 clients.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Floodlights will now shut off if lacking a power cell.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes the Timer SS timing out when it shouldn't
    • +
    • Fixes reagent overdose runtimes
    • +
    +

    TDSSS updated:

    +
      +
    • Examining a borg tells you what module it has loaded
    • +
    +

    datlo updated:

    +
      +
    • Added the Honk Brand Infiltration Kit to Nuke Ops.
    • +
    + +

    16 October 2018

    +

    FalseIncarnate updated:

    +
      +
    • Corpse spawners (such as those on the Wild West away mission) now properly spawn corpses at roundstart that don't remain standing.
    • +
    + +

    15 October 2018

    +

    FreeStylaLT updated:

    +
      +
    • Crunchy sounds when bones are broken
    • +
    +

    Squirgenheimer updated:

    +
      +
    • Changelings will now wake up after using Regenerative Stasis.
    • +
    +

    TDSSS updated:

    +
      +
    • The maximal length of a name that won't be rejected as a 'bad name' has been raised.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Fixes stunbaton runtime (Stun() being called on a turf)
    • +
    • Borers with their "Dominate" window already open can no longer run across the map and successfully cast the spell on those people, they must be within 7 tiles (default view range)
    • +
    • Borers can no longer spam open the "Dominate" spell
    • +
    • Borers with their "Dominate" target window already open can no longer successfully target someone if they are dead
    • +
    • Borers no longer "slither up and probe people's ear canal" if they select the target of an "infect host" spell after they die
    • +
    +

    uc_guy updated:

    +
      +
    • You can no longer roll around when dead.
    • +
    + +

    14 October 2018

    +

    Purpose updated:

    +
      +
    • Makes it so that Screwdrivers & Wirecutters are no longer invisible in the map editor.
    • +
    • Fixes a gibbing runtime
    • +
    +

    taac updated:

    +
      +
    • added cryo cell description
    • +
    +

    uc_guy updated:

    +
      +
    • fixed runtime in IsBanned.dm
    • +
    +

    variableundefined updated:

    +
      +
    • Stacks are split by CtrlShiftClick instead of AltClick now.
    • +
    • A runtime that occurs with paper bundle being created with one or less paper.
    • +
    + +

    13 October 2018

    +

    Birdtalon updated:

    +
      +
    • Chem master now will show its de-powered state properly.
    • +
    +

    DarkPyrolord updated:

    +
      +
    • Changed attack log level for reagent forcefeeding from FEW to MOST
    • +
    +

    FlimFlamm updated:

    +
      +
    • Tweaked formatting of Newscaster stories
    • +
    • Fixes images displaying improperly on Newscaster stories
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Boxing logs moved to the ALL preference
    • +
    +

    alex-gh updated:

    +
      +
    • Species damage modifiers now only affect damage, not healing.
    • +
    • Races that took more damage from certain damage types no longer heal from that damage type faster. For example: Drask no longer heal from burn at double rate; Grey, Vox no longer heal from brute at increased rate (Note: IPC healing with welders/wires is not affected).
    • +
    • Kidan no longer heal from brute at a reduced rate.
    • +
    +

    uc_guy updated:

    +
      +
    • You can no longer get an infection and die during abductor surgery.
    • +
    • Voice analyzers no longer activate on noise.
    • +
    + +

    12 October 2018

    +

    Alonefromhell updated:

    +
      +
    • META - Cargo shuttle blast doors now reacts to the right button.
    • +
    • META - Cargo shuttle airlocks now bolt properly.
    • +
    • META - Cargo shuttle flaps are now airtight. All hail Cargonia.
    • +
    +

    Birdtalon updated:

    +
      +
    • Gamma ERT Paranormal gets their null rod.
    • +
    • Moves check_and_add() to reagents holder
    • +
    +

    DesolateG updated:

    +
      +
    • Refactors global var lists to use the global subsystem.
    • +
    +

    Farie82 updated:

    +
      +
    • Added the on_give proc for items. Was needed for the fixes
    • +
    • Giving two handed items like the DIY chainsaw and potted plants now works correctly
    • +
    • The DIY chainsaw, doomslayer chainsaw and the potted plants now do damage when given to somebody else and when picked up while the chainsaw was on.
    • +
    +

    Purpose updated:

    +
      +
    • Cyberiad's grimy tiles are now actually dirty and cleanable.
    • +
    • Delta's grimy tiles are now actually dirty and cleanable.
    • +
    • Ironsand is now visible in the Map Maker.
    • +
    • Away missions updated with the appropriate dirt/grime so that it is now cleanable.
    • +
    • Fixes stool's unique suicide message.
    • +
    • Fixes rollerbeds no longer going through plastic flaps.
    • +
    +

    TDSSS updated:

    +
      +
    • Removed Skrell discrimination, allows ! character in IDs (agent IDs or made via ID computer)
    • +
    +

    variableundefined updated:

    +
      +
    • Ore now represented by stack that holds up to 50 items. Should reduce lag with ORM greatly.
    • +
    • Satchel can only carry ten items instead of 50 items. You should end up carrying more ore in total however
    • +
    • Fire acting on ore means they would be refined with 50% efficiency.
    • +
    • Stack merges automatically if dropped on the floor, or a new stack is created. This doesn't happens on your body.
    • +
    • They also merge if you drag them over eachother.
    • +
    • Alt-click split a stack
    • +
    • You can throw sand into people's eyes! Pocket sand!
    • +
    • Phazon take 5 bluespace crystal to construct now instead of 1. remove: Transfer prompt when you click on a stack of the same type with a stack
    • +
    + +

    11 October 2018

    +

    Citinited updated:

    +
      +
    • Fixes an oversight in autopsy report drawer's description.
    • +
    +

    Farie82 updated:

    +
      +
    • NPC's now initialise correctly. Removing a lot of runtime errors.
    • +
    +

    Kyep updated:

    +
      +
    • Fixed the admin ERT panel not working correctly if the admin using it was playing as a carbon mob.
    • +
    +

    Stork Industries updated:

    +
      +
    • Fixes "Arachno-Man's" boots
    • +
    +

    Triiodine updated:

    +
      +
    • SLOT_MASK from necklaces.
    • +
    • thatdanguy23's fluff item
    • +
    + +

    10 October 2018

    +

    Alonefromhell updated:

    +
      +
    • You should no longer be able to relight a burned match by using a shoe.
    • +
    +

    Birdtalon updated:

    +
      +
    • Small runtime in tickets.dm
    • +
    • Mulebot teleportation exploit.
    • +
    • Iron sand icons now render correctly.
    • +
    +

    Citinited updated:

    +
      +
    • Emagging a locker will keep the original description instead of telling you it was emagged twice.
    • +
    • Examining airlocks displays the proper icon now
    • +
    • Holopads don't work when unanchored any more.
    • +
    +

    Purpose updated:

    +
      +
    • Fixes a few broken tiles in maintenance, by breaking those tiles properly.
    • +
    +

    Purpose & AndrewMontagne updated:

    +
      +
    • New grimy dirt sprites.
    • +
    • Dirty tiles now get dirtier if neighbouring tiles are also dirty.
    • +
    +

    Triiodine updated:

    +
      +
    • new sprites for cup-chicken soup, icecups, weight loss shakes.
    • +
    • cup to can of chicken soup.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Fixes PAIs
    • +
    • Ambulances work again
    • +
    +

    Warior4356 updated:

    +
      +
    • added Grey sprite for psysuit, made by dumbdumb
    • +
    +

    tigercat2000 updated:

    +
      +
    • Hovering over an inventory slot now shows an indicator for if that item can go in that slot or not. Pretty!
    • +
    • SSOverlays has been added, but not implemented!
    • +
    + +

    09 October 2018

    +

    Alonefromhell updated:

    +
      +
    • Edited the attack text of the teleport armor.
    • +
    +

    Birdtalon , LPSpartan, Shazbot, Memager updated:

    +
      +
    • Portable Body Analyzer for ERT
    • +
    • Muilti Lens Immolation gun for gamma ERT
    • +
    • PDW-9 sidearm for ERT
    • +
    • T4 Thermite Charge for Gamma ERT security
    • +
    • Sprites for gamma ERT suits
    • +
    • Red ERT loadouts
    • +
    • Gamma ERT loadouts
    • +
    +

    Citinited updated:

    +
      +
    • Conveyor belts have received a facelift!
    • +
    • Rotating a belt with a wrench now nicely rotates the belt for you
    • +
    • Click a lever with a lever to link their IDs. Click a belt with a lever to link that belt to that lever.
    • +
    • Deconstructing a syndicate console will no longer ruin it forever.
    • +
    +

    DesolateG updated:

    +
      +
    • Refactors the timer subsystems and bugfixes
    • +
    +

    Purpose updated:

    +
      +
    • Code improvements on mouse_opacity
    • +
    • Plating shadow faux 3d now works properly.
    • +
    +

    Purpose & AndrewMontagne updated:

    +
      +
    • Adds tile smoothing to plating. Plating should now be a bit more of a 3d look...
    • +
    +

    Purpose & Birdtalon updated:

    +
      +
    • Takes Runtime out of the oven.
    • +
    +

    Squirgenheimer updated:

    +
      +
    • fixed a potential runtime in the sentient animal event
    • +
    +

    Triiodine updated:

    +
      +
    • Tidied up nuclear shuttle's mini-medbay to better utilize the space provided.
    • +
    • Full Body-Scanner, surgery set, replacement limbs, bloodpacks to the nuclear shuttle's mini-medbay.
    • +
    • One of the nuclear shuttle's sleepers.
    • +
    +

    uc_guy updated:

    +
      +
    • Legless human mobs no longer scream non-stop when buckled into a chair.
    • +
    +

    variableundefined updated:

    +
      +
    • Poolcontroller performance are improved dramatically. Expect slightly reduced CPU use on beach gateway map
    • +
    • Poolcontroller will no longer work properly if you directly var-edit someone's location to inside a body of water and a decal's (However if the mob move right after it will still work)
    • +
    + +

    08 October 2018

    +

    Ansari, Birdtalon updated:

    +
      +
    • Updates resting procs, fixes getting people up from help intent.
    • +
    +

    Birdtalon updated:

    +
      +
    • Conservation of damage mechanic for set species
    • +
    • Changeling transform conserves damage when transforming to a different species.
    • +
    +

    Crazylemon updated:

    +
      +
    • Fixes AIs being unable to examine due to a runtime.
    • +
    • Fixes nearsighted glasses behavior being inverted (seeing worse with glasses).
    • +
    • Mining mobs now update their sprites on death.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Updates for damage on HUD elements are now instant for cyborgs and humans.
    • +
    • When dead, you can now see your surroundings with ghost vision and examine things around you.
    • +
    +

    Farie82 updated:

    +
      +
    • PANDEMIC can print a virus release form now. Viromancers REJOICE!
    • +
    +

    Purpose updated:

    +
      +
    • Adds the missing turfs under windows & doors on Mech Transport Space ruin.
    • +
    • Fixes improper turf in the shuttle crashed into one of the space ruins.
    • +
    • Fixing improper decals & missing turfs in the Space Bar space ruin, and some tiny fixes.
    • +
    • GasTheLizard Space Ruin now uses Decals properly.
    • +
    • MoonOutpost19 Away Mission now uses Decals properly.
    • +
    • Evil Santa Away Mission now uses Decals properly.
    • +
    • Fixes the corpse spawners in Space Battle Away Mission.
    • +
    • Space Battle Away Mission now uses Decals properly.
    • +
    • Prettier Donate/Karma buttons!
    • +
    • Adds new stair sprites.
    • +
    • Blackmarket Backpackers now uses Decals properly.
    • +
    • OneHalf Space Ruin now uses Decals properly.
    • +
    • CentComm Away Mission now uses Decals properly.
    • +
    • Cyberiad Z2 now uses Decals properly.
    • +
    • Space Hotel Away Mission now uses Decals properly.
    • +
    • Terror Spiders Away Mission now uses Decals properly.
    • +
    • Adds plasma window spawners for mappers.
    • +
    • Thrown stunbatons & improvised batons have a low chance to stun.
    • +
    • You can now alt click breath masks to pull them up & down.
    • +
    • You can no longer erroneously pull down a vox mask.
    • +
    • TravisCI now checks all space ruins & away missions for integration.
    • +
    +

    Triiodine updated:

    +
      +
    • Rsik's fluff katana ~~modkit~~
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Replaces Security's bomb suit with their cooler Security version
    • +
    • Fixes runtime in world.dm;127
    • +
    +

    tigercat2000 updated:

    +
      +
    • Made mind.dm 1/1000 less awful.
    • +
    +

    variableundefined updated:

    +
      +
    • NPCpool (SNPC) is now a subsystem.
    • +
    • NPCAI (For simple mob) is now a subsystem.
    • +
    • Customising SNPC no longer results in screaming death and a naked person.
    • +
    • Logging added to RD teleport gun, some projectile are always logged
    • +
    • EMPulse & Explosion can optionally log a cause for administrative purpose
    • +
    • Backend Attack logs now display coordinates of attacker & defender for forensic reconstruction.
    • +
    • Grill shock cooldown is 1 second instead.
    • +
    + +

    07 October 2018

    +

    Birdtalon updated:

    +
      +
    • Ammo boxes now return materials proportional to their contents when recycling, nullifying infinite ammo exploit.
    • +
    +

    Farie82 updated:

    +
      +
    • Fixing a disability now fixes the gene related to it if needed. No more free gene stability from blindness and such
    • +
    • fixed bluespace disposal bins
    • +
    • instant recall doesn't fuck up disposals
    • +
    • meteor shots now deconstruct the disposals unit, removing weird behaviour
    • +
    +

    Purpose updated:

    +
      +
    • Winged chairs now get placed back down correctly as winged chairs.
    • +
    • CyberiadAI Discord Bot now announces which station is being used.
    • +
    • Less things will refer to the NSS Cyberiad when not actually ON the NSS Cyberiad.
    • +
    • Decals now Initialize()
    • +
    +

    SkeletalElite updated:

    +
      +
    • Fixed grammar in meat spike's name
    • +
    • Chaos Holoparasite's abilities actually work
    • +
    +

    datlo updated:

    +
      +
    • Changelings with wingdings now permanently switch to regular speech after transforming
    • +
    +

    variableundefined updated:

    +
      +
    • All sharp items can cut sliceables like cheesewheel now.
    • +
    • Putting items inside sliceables is done by alt-click now.
    • +
    + +

    06 October 2018

    +

    Alonefromhell updated:

    +
      +
    • META - Cryogenics now has a Cellcharger.
    • +
    +

    Purpose updated:

    +
      +
    • Delta - Adds a Paramedic's Office.
    • +
    • Latejoining autotraitors should now have their uplinks again.
    • +
    • You can now pick up most chairs and beat colleagues with them. Careful too many whacks and they'll break.
    • +
    • Adds new bar stools.
    • +
    • Delta - Removes extra door in arrivals.
    • +
    +

    Squirgenheimer updated:

    +
      +
    • Victims of changeling swap forms and wizard mindswap can now re-enter their corpses
    • +
    + +

    04 October 2018

    +

    Alonefromhell updated:

    +
      +
    • Sensory Restoration should now work with Ocular Restoration.
    • +
    +

    Farie82 updated:

    +
      +
    • borgs can now heal their patients while there is a surgery going on.
    • +
    +

    Purpose updated:

    +
      +
    • Boxstation: Fixed a number of turf/decal/overlay issues
    • +
    • Boxstation: The poster in medbay maintenance now displays properly...
    • +
    • Boxstation: Xenobio slime cameras should no longer be able to see into maintenance.
    • +
    • Boxstation: Adds missing firelock to vacant office.
    • +
    • Boxstation: Moves Medbay AIR Alarms around to more functional locations.
    • +
    • Boxstation: Fixes 'fake grass' in the kitchen area.
    • +
    • Boxstation: Fixed several issues were Radiation Storm events could bleed into maintanence.
    • +
    • Boxstation: ALL catwalks should now be able to see space through the holes.
    • +
    • Delta - Adds fuel depo to the hanger.
    • +
    • Delta - Adds the Nullrod & Shard to the Chaplain's back office.
    • +
    • Delta - Fixes the invisible wardrobe in the dorms.
    • +
    • Delta - Adds a few art vendors across the station.
    • +
    • Delta - Adds the buttons to the Perma Airlock.
    • +
    • Delta - Doctors now have access to the patients rooms. Oops.
    • +
    • Delta - Adds the Coroner's spawn point in the morgue.
    • +
    • Delta - Increases blood packs in medbay, by random blood spawners.
    • +
    • Delta - Fixes the exit button of Medbay.
    • +
    • Delta - Increases the size of the atmos space loop.
    • +
    • Delta - No longer can maintenance fire lasers at the Supermatter....
    • +
    • Delta - Added some wiring to make it easier to emitter the SM.
    • +
    • Delta - Extends the wiring out of solars airlocks in atmos solars.
    • +
    • Delta - Atmos now have access to Atmos solars.
    • +
    • Delta - Adds an additional atmos void suit.
    • +
    • Delta - Adds two additional engineering void suits, but into secure storage.
    • +
    • Delta - Fixes the missing airlock cycling on an atmos airlock.
    • +
    • Delta - Adds the missing multi-tool to atmospherics.
    • +
    • Delta - Fixed Mixed Air & Gas Mix computers access to the tanks & sensors.
    • +
    • Delta - Can now cross parts of the transit tube.
    • +
    • Delta - Garbage disposal is now functional.
    • +
    • Delta - Disposals no longer fires trash into the atmos office.
    • +
    • Delta - Atmos techs now have access to the jetpacks in EVA.
    • +
    • Damaged plating when fixed, now loses the aesthetic damage too.
    • +
    • Yellow closets now use the correct icons.
    • +
    + +

    03 October 2018

    +

    Farie82 updated:

    +
      +
    • Your hands won't become the surgeons hands anymore in surgery
    • +
    +

    Fethas updated:

    +
      +
    • Cryostorage ghost role spawners for ruin/mapping/adminbus. Also refactors corpse landmark code.
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Remapped Medbay Lobby.
    • +
    • Moved the cell charger from Cryo to the break room.
    • +
    • Added a cell to Medbay's break room.
    • +
    + +

    02 October 2018

    +

    Birdtalon updated:

    +
      +
    • Small formatting fix in soulstone.dm
    • +
    +

    Kurgis updated:

    +
      +
    • The chief engineer jumpsuit no longer appears as a green suit when held in-hand.
    • +
    • Added a new in-hand sprite for the chief engineer jumpsuit from Polaris.
    • +
    +

    Purpose updated:

    +
      +
    • Delta Station, codenamed Kerberos has been acquired by Nanotrasen.
    • +
    • Wizard Academy now uses decals
    • +
    • Wizard Academy misplaced wires fixed
    • +
    +

    Tails2091 updated:

    +
      +
    • Claw Game is now a bit easier to use. Slower speeds, still receive prize when interrupted, and auto-close.
    • +
    • Claw Game has correct window size, centered buttons, general code cleanup.
    • +
    +

    name here updated:

    +
      +
    • Remove canvas and easel from Deltastation
    • +
    +

    tigercat2000 updated:

    +
      +
    • Chat no longer horribly breaks at the first high-ascii character.
    • +
    + +

    01 October 2018

    +

    Aurorablade updated:

    +
      +
    • adjusts to Arachno-Man suit fluff.
    • +
    +

    Birdtalon updated:

    +
      +
    • Admin ticket subsystem - migrates existing global datum.
    • +
    +

    Dapocalypse updated:

    +
      +
    • Added a grille cooldown to prevent alt-click spam someone on a grille to instantly husk people.
    • +
    +

    Farie82 updated:

    +
      +
    • Not being able to place chutes over tiles with multiple pipes.
    • +
    +

    Purpose updated:

    +
      +
    • CPU Performance in get_area proc
    • +
    • Excavates a few relics from area code.
    • +
    • Metastation - Escape Shuttle windows are now breakable again.
    • +
    • Metastation - Medbay camera no longer floating in mid-air.
    • +
    • Metastation - Adds the missing component analyzer to Robotics.
    • +
    • Metastation - Fixes the wiring issues in Medbay.
    • +
    • Metastation - Fixes the wiring issues in Virology.
    • +
    • Metastation - Fixes the lack of fungus on the map, placing it near water sources in maintenance.
    • +
    • Metastation - Fixes area definition, so that admins can now send people to cryo.
    • +
    • Metastation - Fixes bizarre map corruption from the Arcade PR which turned Coroners into a bit of an arcade....
    • +
    • Metastation - Law office's shutters now grant privacy properly.
    • +
    • Metastation - Fixes the lack of inflatables & pipe painter in Atmospherics
    • +
    • Metastation - Adds a second atmos locker, as one is lower than number of atmos slots available....
    • +
    • Metastation - Properly marks airless tiles by the hanger as airless.
    • +
    • Metastation - Hooks up Security's Camera Computer to the station's cameras...
    • +
    • Metastation - Fixes the floating fire alarm in Security.
    • +
    • Metastation - Fixes the detective's lack of Evidence Storage access...
    • +
    • Metastation - Captain, IAA and NT Rep's fax machines are hooked up properly. Bloody IT department...
    • +
    • Metastation - Security cannister attachment is now attached to the pipe grid.
    • +
    • Metastation - Bots now correctly patrol the station again.
    • +
    • Metastation - Updates the turfs & decals to use the correct decals.
    • +
    +

    Purpose & AndrewMontagne updated:

    +
      +
    • Tiles now retain the styling when damaged.
    • +
    • Tile damage now uses decals, and can be mapped easier.
    • +
    +

    TDSSS updated:

    +
      +
    • RnD server control console's data management now works, allowing for deletion of research levels and known techs.
    • +
    • fixed minor typos.
    • +
    • bluespace polycrystals can now correctly be broken down while floating in space.
    • +
    +

    variableundefined updated:

    +
      +
    • Nano Mob Hunter ported to StonedMC. Report unexpected issues.
    • +
    • Shuttle has been ported over to the StonedMC Subsystem.
    • +
    + +

    30 September 2018

    +

    Crazylemon updated:

    +
      +
    • Corrects a comment in the code regarding IPC damage.
    • +
    +

    Purpose updated:

    +
      +
    • Fixes various message format overflows.
    • +
    +

    Shazbot updated:

    +
      +
    • You can now remove KA mods from borgs.
    • +
    +

    TDSSS updated:

    +
      +
    • Plasma statues and walls are no longer ignited by laser tag guns or practice lasers.
    • +
    • Crowbars can no longer make pool water invisible.
    • +
    +

    datlo updated:

    +
      +
    • Made the poison pen available to traitor librarians
    • +
    +

    variableundefined updated:

    +
      +
    • One click antagonist giving antag to people in restricted job.
    • +
    + +

    29 September 2018

    +

    Dapocalypse updated:

    +
      +
    • Removes extra penlight given to plasmemes.
    • +
    +

    DarkPyrolord updated:

    +
      +
    • Pyro's fluff item
    • +
    +

    Kyep updated:

    +
      +
    • Fixed several bugs with blob, including lateround blobs not generating biohazard alerts, blobs missing out on early resources they should have, and a bug with blob storage being broken that prevented blobs getting any resources.
    • +
    +

    NoWolfie updated:

    +
      +
    • New Pyr'kus cult floor and wall sprite.
    • +
    +

    Triiodine updated:

    +
      +
    • Nukies spawning with cybernetic organs/limbs
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Removes canvases due to everybody crashing from them.
    • +
    +

    farie82 updated:

    +
      +
    • Headbutting the airlock is more consistent.
    • +
    • refactored the airlock code.
    • +
    • Using multitools and such on a door with a note now doesn't remove the note. Only grabbing with an empty hand now.
    • +
    + +

    28 September 2018

    +

    DarkPyrolord updated:

    +
      +
    • Fixes a ten year old atmos bug, fix will cause toxins bombs and plasma fires to be a little less lethal
    • +
    • Readds modkit sprites to items.dm to fix invis fluff item modkits.
    • +
    +

    Farie82 updated:

    +
      +
    • No more broken tile due to getting shot out of disposals.
    • +
    • Point blank shots not hitting the correct person. When multiple people are on the same tile.
    • +
    +

    Kyep updated:

    +
      +
    • The wild west away mission no longer offers hijack traitor status as a potential reward.
    • +
    • Deconstructing/reconstructing the space pod fab no longer turns it into a mech fab. No more mechanics building surprise mechs.
    • +
    • The spacepod fab circuit is now buildable in R&D.
    • +
    • Spacepod fabs now require mechanic access to use, like the mechanic R&D console does.
    • +
    +

    Purpose updated:

    +
      +
    • Mappers can now have Floodlights round-start enabled.
    • +
    +

    Tails2091 updated:

    +
      +
    • Refactored Hallucinations to match contribution guide standards a bit more.
    • +
    +

    Triiodine updated:

    +
      +
    • Fixes jade lipstick being lime.
    • +
    • Adds lime lipstick.
    • +
    • New storage implant icon
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Ambulances now have sirens!
    • +
    • Shadowlings no longer are able to target simple animals (mice)
    • +
    +

    farie82 updated:

    +
      +
    • fixed cling transformed humanoids looking rather pale.
    • +
    • Fixed emagged camera consoles not opening the tabs
    • +
    +

    uc_guy updated:

    +
      +
    • Vox auto equip the nitrogen tank when spawning if possible.
    • +
    • Nitrogen tanks no longer overwrite job items.
    • +
    +

    variableundefined updated:

    +
      +
    • Benjaminfallout's fluff item.
    • +
    • Qdel log is now re-added to the garbage subsystem to enable coders to investigate sources of hard delete.
    • +
    • When you remove a light tube while lying down, the light tube disappear. This no longer happens.
    • +
    • Latejoin AI no longer spawn in naked at arrival shuttles.
    • +
    • Not spawning in with your memory of bank account at roundstart...
    • +
    + +

    27 September 2018

    +

    Anasari updated:

    +
      +
    • You can now deconstruct a fire extinguisher cabinet to yield a single piece of metal. You can construct them for five pieces of metal, with extinguisher included. (Using metal construction menu)
    • +
    +

    Birdtalon updated:

    +
      +
    • Borg modules now add item action buttons if present.
    • +
    • Beepsky responds to attacking him with disarm intent.
    • +
    +

    CornMyCob updated:

    +
      +
    • Adds in a prompt for becoming a headslug.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Adds a fluff item for ELO
    • +
    +

    DesolateG updated:

    +
      +
    • Added a check to whispering adverbs to prevent double adverbs while whispering.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds mixing bowls, which allow you to cook multiple recipes at the same time! The dinnerware vendor comes pre-stocked with 10!
    • +
    • Adds 2 mixing bowls to the Food Crate from cargo should you need additional. This is the same crate that includes the extra bottle of enzymes.
    • +
    • Burned messes now scale their carbon and "????" content with both physical ingredients and directly inserted reagents while burning in the cooking machines.
    • +
    • Upgraded cooking machines now attempt to evenly distribute reagents from ingredients across all produced results, rather than just the original.
    • +
    +

    Farie82 updated:

    +
      +
    • You can remove notes from an airlock now with the grab intent using an empty hand.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes 128x128 menu location
    • +
    +

    Kyep updated:

    +
      +
    • Refactored shieldgen.dm, fixed a bug which could cause shieldgens to behave improperly under some rare conditions.
    • +
    +

    Purpose updated:

    +
      +
    • CPU Performance tweaks in the Bananaium floor honks & squeaks
    • +
    • Capitalisation correction in automated chef npcs
    • +
    • CPU Performance tweaks in the Xeno Hunter tackles
    • +
    • CPU Performance tweaks in Malf AI
    • +
    • NT Formal clothing now updates to the station names correctly.
    • +
    • Fixes typos in NT Formal clothing
    • +
    • Minimap is now updated
    • +
    • Holopads now use the correct amount of power.
    • +
    • CPU Performance tweaks in the Pipe Dispenser
    • +
    • Blobs now delete light fixtures correctly.
    • +
    • use_power variable is more clearly defined as non-boolean via defines.
    • +
    +

    TDSSS updated:

    +
      +
    • Atmospherics external airlocks can now be controlled by borgs and AIs
    • +
    +

    Triiodine updated:

    +
      +
    • righthand fork sprite being oriented wrong.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Fixes vending machine bank account security. You can now use them with a bank account security level above zero.
    • +
    • Fixes a bunch of \ tags
    • +
    +

    alex-gh updated:

    +
      +
    • Drask no longer take damage from cryokinesis
    • +
    • Cryokinesis deals less damage, but lowers the body temperature a lot more.
    • +
    • Autopsy scanner now prints all times in human readable format.
    • +
    +

    datlo updated:

    +
      +
    • Added the wizard spell Greater Knock, letting them remove all access restrictions on the Cyberiad and master door opening.
    • +
    +

    variableundefined updated:

    +
      +
    • drop_location & AllowDrop() has been ported over from tg. Report unexpected issues with dropping items.
    • +
    • When you late join, extra items you can't equip / hold spawn on the ground instead of in the lobby screen. Including vox medkit etc.
    • +
    • Plasmaman no longer get double the firepower when spawning in as Captain, BS, or sec roles.
    • +
    • Non-human's DNA (Except for IPC, of course) should show up properly in the DNA modifier now.
    • +
    + +

    25 September 2018

    +

    Birdtalon updated:

    +
      +
    • Secure console UI (security records) appears bigger by default.
    • +
    • One-click-antag now respects game-mode's protected jobs.
    • +
    +

    Fox McCloud updated:

    +
      +
    • adds support for 128x128 skin interface pixel size for 4K monitors
    • +
    +

    Purpose updated:

    +
      +
    • Space is now visible under corner pieces of the Intact Empty Ship ruin.
    • +
    + +

    24 September 2018

    +

    Triiodine, Desolate, updated:

    +
      +
    • Things without blood bleeding red when rolled over by a mulebot.
    • +
    + +

    19 September 2018

    +

    Birdtalon updated:

    +
      +
    • Screwdrivers now open fire alarms instead of wirecutters.
    • +
    + +

    18 September 2018

    +

    Birdtalon updated:

    +
      +
    • Laser tag ED-209 bots get the correct names upon construction.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • adds a missing italics tag to nano/templates/song.tmpl
    • +
    + +

    16 September 2018

    +

    Shazbot updated:

    +
      +
    • Adds in the ability to have multiple custom screens.
    • +
    • Adds in Lumi's custom faces.
    • +
    +

    dandykong updated:

    +
      +
    • Internal manipulation surgeries can now be performed on mouths after the head is augmented.
    • +
    +

    variableundefined updated:

    +
      +
    • Contribution.md now properly state that changelog is mandated for all PR.
    • +
    + +

    14 September 2018

    +

    Ty-Omaha updated:

    +
      +
    • Fixes logic with obscure proc adjust_bodytemperature
    • +
    + +

    11 September 2018

    +

    Aurorablade updated:

    +
      +
    • Adds a missing var to cult comms logging.
    • +
    +

    alex-gh updated:

    +
      +
    • It is now possible to heal robotic limbs and IPCs through View Variables
    • +
    +

    variableundefined updated:

    +
      +
    • pAI can no longer use name with special characters that cause their chat messages to disappear.
    • +
    + +

    09 September 2018

    +

    AffectedArc07 updated:

    +
      +
    • You can no longer gib everyone on the server by forcing admins to call verbs with NTSL
    • +
    +

    Agameofscones updated:

    +
      +
    • removes the equip region for the mask slot on holobadge-cords
    • +
    • changes implementation of https://github.com/ParadiseSS13/Paradise/pull/9471 to be smarter and more long term.
    • +
    +

    Kyep updated:

    +
      +
    • Fixed bad spawn points in the Wizard Academy away mission.
    • +
    • The two welding goggles that went missing from the table in atmos have been returned.
    • +
    +

    SkeletalElite updated:

    +
      +
    • The paper in the holoparasite kit now describes both of the Chaos holoparasite's modes
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Nightmare writhing now properly works
    • +
    • Fixes the wire under the door in med maint that led to a wall
    • +
    • Virology now has a hologram
    • +
    +

    nicetoolbox updated:

    +
      +
    • Prevent instant rev victory in rev gamemode
    • +
    • Cryo now heals all your mutated limbs
    • +
    +

    uc_guy updated:

    +
      +
    • Ghosts can no longer eject IDs from fax machines and ID computers.
    • +
    • Fixed exploit that allowed exiled mobs to return to the station
    • +
    +

    variableundefined updated:

    +
      +
    • One-click antag vampire showing up as a changeling on antag HUD.
    • +
    • Claw game should give you token for payment by card properly again.
    • +
    • Mime forcewall now properly last for 30 seconds instead of 10.
    • +
    • The cancel button actually work properly when editing memory now.
    • +
    • A wallet now shows a green card decal by default if there's a card inside.
    • +
    + +

    05 September 2018

    +

    IrkallaEpsilon updated:

    +
      +
    • Adds an attack cooldown on mirrors for all mobs. Yes simple mobs and Xenomorph larvaes included
    • +
    +

    variableundefined updated:

    +
      +
    • Economy code has been slightly refactored. Report issues.
    • +
    • EFTPOS no longer has a name.
    • +
    • All date on transaction log should be in long form like "1 January, 2500 22:00:00".
    • +
    • Negative number is represented by parentheses in transaction log, positive without (Opposite of before).
    • +
    • There's a higher chance of winning $10 in the slot machine now.
    • +
    + +

    04 September 2018

    +

    Flatty updated:

    +
      +
    • Additional icon scaling settings
    • +
    +

    FreeStylaLT updated:

    +
      +
    • New Kidan sprites and accessories
    • +
    +

    IrkallaEpsilon updated:

    +
      +
    • Atmos Grenades wont appear in Surplus anymore due to them virtually being unuseable due to OOC reasons in almost any case.
    • +
    +

    Kyep updated:

    +
      +
    • The power grid in the black market packers away mission has been fixed, and it is no longer possible to effectively skip the entire mission using a crowbar.
    • +
    • Lateround blobs now start off as an infected mouse. By moving around/ventcrawling as a mouse, they can find themselves a good nesting area before they turn into a blob core.
    • +
    • Meth (and ultra-lube, its equivalent for synthetics) now grant less of a speed bonus.
    • +
    +

    Shazbot updated:

    +
      +
    • Now you can actually make xeno borgs.
    • +
    +

    TDSSS updated:

    +
      +
    • Medbelts can now hold hyposprays.
    • +
    +

    Tails2091 updated:

    +
      +
    • Double welding a closet no longer removes welding tool. format: Changed 0 1 booleans to TRUE FALSE.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Secure fridges can be properly emagged
    • +
    • Secure fridges can now be EMP'd to override their access requirements
    • +
    +

    datlo updated:

    +
      +
    • Megaphone now uses the user's speech font (Wingdings/comic sans)
    • +
    +

    nicetoolbox updated:

    +
      +
    • Fixes Plasmamen wizards not counting as fully garbed
    • +
    +

    variableundefined updated:

    +
      +
    • Analyzer are now consistently spelled Analyzer instead of Analyser.
    • +
    • Hivelord remains send the proper feedback about its preservation method to database.
    • +
    • IPC no longer displays their UI / SE in console. Same goes for other invalid subjects. You also can't save their UI / SE anymore.
    • +
    + +

    31 August 2018

    +

    variableundefined updated:

    +
      +
    • Being incapacitated when changing IPC monitor now show a message properly.
    • +
    • Borg & AI say actually work properly now. They no longer become whisper.
    • +
    + +

    30 August 2018

    +

    Alffd updated:

    +
      +
    • Fix emote check of can_speak() to only return if the emote produces sound.
    • +
    +

    Kyep updated:

    +
      +
    • Fixed depot armory shield key not being properly randomized.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Decreases sechailer shitcode
    • +
    + +

    29 August 2018

    +

    Agameofscones updated:

    +
      +
    • Removes stray pixel in RD sechud.
    • +
    +

    Flatty updated:

    +
      +
    • You can now put items on people and take them off while you're riding that sweet, sweet wheelchair.
    • +
    +

    Kyep updated:

    +
      +
    • Fixed various bugs with spider structures (webs, cocoons, etc), such as them not triggering attack animations, not respecting melee cooldowns, being invulnerable to simple_animals and aliens, etc.
    • +
    +

    Superhats updated:

    +
      +
    • Adds Meson and Diagnostic HUD implants.
    • +
    • ERT equipment has been reviewed by Nanotrasen and changed to more appropriately assist the station when called.
    • +
    • Amber Janitor ERT Armor sprite now works.
    • +
    • Field Surgery Belt added for Code Amber Medical ERT
    • +
    +

    Triiodine (Agameofscones) updated:

    +
      +
    • Removed original paramedic EVA sprites
    • +
    • Replaced paramedic EVA sprites with medical hardsuit inspired set.
    • +
    • Added species variants _(Which did not exist before hand)_ to Unathi, Tajaran, Drask, Skrells, & Vulpkanins.
    • +
    • Added the same armor values the basic EVA suit gets (bio 100, rad 20), this puts the paramedic suit in standard with other NT soft suits. edit: Fixed a typo in the santasuit comment, because why not.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • NT Rep stamp no longer stamps as Central Command, they have their own stamp now.
    • +
    +

    variableundefined updated:

    +
      +
    • Cutting wires shouldn't cause a runtime error anymore.
    • +
    • You cannot bola people without at least two legs (on them) anymore.
    • +
    + +

    28 August 2018

    +

    Alffd updated:

    +
      +
    • Fixes emote code to preform mute checking in the same manner as say code.
    • +
    • Adds a new type of muzzle that will shock its wearer when pulsed by an assembly.
    • +
    • Adds a new type of voice trigger assembly that is activated by audible emotes.
    • +
    +

    Birdtalon updated:

    +
      +
    • Fixes torn down posters dropping hypothetical poster when their wall is deconstructed.
    • +
    +

    Flatty updated:

    +
      +
    • IPCs can also change their screen color in addition to the image now
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Harm intent attack animations are red instead of white
    • +
    +

    taukausanake updated:

    +
      +
    • Corrects formatting for the abductor objective messages
    • +
    +

    variableundefined updated:

    +
      +
    • Logging for prayer.
    • +
    • Silicons no longer broadcast their radio message to everyone in hearing range (Only those next to them). Yes, that's a bug, not a feature.
    • +
    + +

    26 August 2018

    +

    Agameofscones updated:

    +
      +
    • Mr. Chang vendor sprite (icon_state: chang).
    • +
    • Three new Mr. Chang vendor slogans.
    • +
    + +

    23 August 2018

    +

    Aurorablade updated:

    +
      +
    • Changes to air Subsystem to make it load faster taken from TG by SpaceManiac.
    • +
    • Attemps to cap dogs you can cough up to 10..then you cough up a plush fox. Totally normal.
    • +
    +

    Birdtalon updated:

    +
      +
    • Fixes unexpected item deletion upon changing species.
    • +
    +

    Kyep updated:

    +
      +
    • Fixed a few bugs (notably, grid check event raising alert level) in the depot.
    • +
    • Fixed hand_tele, bluespace tomatoes, etc not respecting the tele_proof flag of areas.
    • +
    +

    alex-gh updated:

    +
      +
    • Changeling fleshmend no longer overfills their blood.
    • +
    +

    variableundefined updated:

    +
      +
    • Admin logging for kinetic accelerator.
    • +
    • Implantcase no longer disappears when dropped or placed in bag.
    • +
    • Logging to borer infestation.
    • +
    • A runtime with admin ticket.
    • +
    • Defibrillator paddles snap away if you walk away from the defibrillator.
    • +
    • Fixes the discard action not displaying who discarded a card from a hand of card
    • +
    • Fixes deck of card not being removed properly from your pocket when you drag it over your sprite.
    • +
    + +

    18 August 2018

    +

    Crazylemon64 updated:

    +
      +
    • makes AA's map fix not annihilate every map PR in existence
    • +
    + +

    16 August 2018

    +

    AffectedArc07 updated:

    +
      +
    • Half the scrubbers actually work now
    • +
    +

    Birdtalon updated:

    +
      +
    • All obj/machinery is now below obj layer.
    • +
    • Prevents creation of 0u pills with Chem Master
    • +
    + +

    15 August 2018

    +

    tlc2013 updated:

    +
      +
    • The AutoDrobe now carries a Transylvanian Coat, imported straight from /vg/station for all your Dracula-cosplaying needs. Much like the false Wizard robes, it does nothing for the actual antagonist.
    • +
    +

    variableundefined updated:

    +
      +
    • Banangarang's medical fluff cyborg's hair colour inconsistency.
    • +
    • Comfrey now actually works for healing brute damage.
    • +
    + +

    09 August 2018

    +

    variableundefined updated:

    +
      +
    • banangarang's maid bot fluff sprites
    • +
    + +

    07 August 2018

    +

    Anasari updated:

    +
      +
    • Polaris card system partially ported. Credits to Jedr for the hand of card item_action sprites.
    • +
    +

    Kyep updated:

    +
      +
    • Simple_animal mobs now get a HUD button that lets them switch between HELP and HARM intents.
    • +
    • Replaced the Syndicate Supply Depot with a new version, rebuilt from scratch, that is much more challenging/interesting.
    • +
    • It is no longer possible to walk straight through decoy AI cores as if they were not there.
    • +
    • Syndicate grenade launcher turrets now actually launch grenades.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Unathi can now tailwhip when they are supposed to be able to.
    • +
    • Tail whipping gets logged.
    • +
    + +

    06 August 2018

    +

    AffectedArc07 updated:

    +
      +
    • Barber no longer spawns with an extra pair of shoes in his bag
    • +
    +

    Tails2091 updated:

    +
      +
    • Fixed Therapy Dolls not working.
    • +
    • Made Prize Machine & Merch Sore readable.
    • +
    • Fixed capitalizations and typos in both lists.
    • +
    + +

    05 August 2018

    +

    Crazylemon64 updated:

    +
      +
    • Space ruins can no longer trap you upon border transition
    • +
    • There are now several levels of space ruins
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in medical hyposprays
    • +
    + +

    03 August 2018

    +

    Fox McCloud updated:

    +
      +
    • IPC Change monitor is now an action button
    • +
    • Slime Color change is now an action button
    • +
    • Fixes staff of change leaving behind unknowns
    • +
    • Fixes Shadowlings not having shock resistant and thermal vision
    • +
    • Fixes staff of change gibbing people
    • +
    +

    Shazbot updated:

    +
      +
    • Adds in the ability to unsaw sawn off riot shotguns. Change: Changes the riot shotgun icon.
    • +
    + +

    02 August 2018

    +

    variableundefined updated:

    +
      +
    • Nightmares now works. Sleep well.
    • +
    • Megaphone actually logs in say log now.
    • +
    + +

    01 August 2018

    +

    Citinited updated:

    +
      +
    • Heaters and freezers now have min and max buttons
    • +
    +

    CornMyCob updated:

    +
      +
    • The description for miniature energy guns is now accurate
    • +
    • The third person text of someone reinforcing an airlock is now accurate
    • +
    +

    Tails2091 updated:

    +
      +
    • Karma refund now uses switch statement.
    • +
    +

    datlo updated:

    +
      +
    • Updated syndicate hardsuit description.
    • +
    + +

    31 July 2018

    +

    Tails2091 updated:

    +
      +
    • Claw Game Prize Ball now drops more than one ticket like it should.
    • +
    +

    variableundefined updated:

    +
      +
    • fix a runtime error with bluespace projector
    • +
    + +

    30 July 2018

    +

    Tails2091 updated:

    +
      +
    • Changed wannabe for loop to a real for loop.
    • +
    + +

    28 July 2018

    +

    KasparoVy updated:

    +
      +
    • You can now safely augment the heads of pointy-snooted Unathi, although your mileage may vary.
    • +
    + +

    27 July 2018

    +

    AffectedArc07 updated:

    +
      +
    • You can no longer use embeds in NTSL
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Space hotel is back in business
    • +
    • Non-hotel SNPCs work again
    • +
    +

    Fox McCloud updated:

    +
      +
    • Extract posibrains should have the correct names now
    • +
    • Abductors can now purchase a mind device to speak into crewmembers minds or give directives to abductees
    • +
    • Abductors now have their own versions of the FixOVein, Bonesetter, and Bonegel. Credit to Triiodine for the sprites
    • +
    • Adds a new electric shock and chemical gland for abductors
    • +
    • viral gland generates random viruses and egg laying gland eggs now have random reagents in them
    • +
    +

    variableundefined updated:

    +
      +
    • Cyborg Analyzer no longer rounds off the damage number it displays.
    • +
    + +

    25 July 2018

    +

    variableundefined updated:

    +
      +
    • Fixes runtime error from medical kit change
    • +
    + +

    24 July 2018

    +

    Kyep updated:

    +
      +
    • Number of roundstart atmos suits in atmos increased from 2 to 4.
    • +
    + +

    22 July 2018

    +

    Fox McCloud updated:

    +
      +
    • Fixes monkeys not having their own HUD
    • +
    • Fixes monkey to human transformations missing their HUD
    • +
    • Fixes changing species unequipping items
    • +
    • Fixes organs not being rejuvinated properly by mitocholide
    • +
    • Fixes shadowlings not being forced to hatch
    • +
    • Having a robotic head will allow you to use buzz, ping, beep, and the likes
    • +
    • Claw sharpening now works
    • +
    • Abductors have their own headset instead of a syndicate one
    • +
    • Can put monkeys in the gibber
    • +
    • gibbing some species will now generate different types of hides (monkeys give monkey hides, unathi give lizard hides, the likes)
    • +
    • fixes Vox name generation based on the wrong syllables
    • +
    • consolidates diona name lists; you'll no longer be asked to rename your Diona when you start the shift
    • +
    • botany grown diona can no longer rename themselves (as is consistent with ghost roles)
    • +
    • Fixes DNA scrambler so it gives a proper randomized species name
    • +
    • Fixed an edge case were Vox would have a permanent nitrogen alert
    • +
    • Fixes operatives being bald most of the time
    • +
    • Adds beesplosion chemical reaction
    • +
    +

    and taukausanake updated:

    +
      +
    • Swarmers can no longer destroy active clone pods.
    • +
    + +

    17 July 2018

    +

    Citinited updated:

    +
      +
    • volume pumps can be dispensed by the RPD again
    • +
    +

    datlo updated:

    +
      +
    • Provided abductors with an infection free surgery table.
    • +
    + +

    16 July 2018

    +

    Citinited updated:

    +
      +
    • RPD behaviour has been slightly tweaked - for example you can now rotate / flip / delete individual pipes by clicking on them without affecting other pipes on that tile.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes hand labelers not being able to label storage objects
    • +
    • Cameras can now be destroyed with weapons that have a force of 12 or greater
    • +
    • Cameras have 2 wires as opposed to 6; camera focus and power wires still remain
    • +
    • You can use hand labelers on reagent containers now
    • +
    + +

    14 July 2018

    +

    Anasari updated:

    +
      +
    • Assuming there is heal left, bandages and ointments used on limbs now heal both the limb and the hand / foot. Bandages and ointments used on the torso now heal head, arms, and lower body. The one on lower body heals the legs too.
    • +
    +

    Aurorablade updated:

    +
      +
    • Adds Spess Koi and related event.
    • +
    +

    Citinited updated:

    +
      +
    • The tachyon-doppler array now has a logging interface, and can print off stored explosive logs. Brag to your friends about your bomb-making skills!
    • +
    +

    Fox McCloud updated:

    +
      +
    • Robotic brains have their own unique sprite and full flavortext's now
    • +
    • Fixed a bug where IRC's would have IPC names
    • +
    + +

    11 July 2018

    +

    Alffd updated:

    +
      +
    • Updates SM engine to modern standards
    • +
    • Ports SM monitoring system from Bay and TG
    • +
    • Adds station wide radiation alarm when crystal/shard goes critical
    • +
    • Tesla zapping
    • +
    +

    Citinited updated:

    +
      +
    • Fortune cookies now drop random fortunes if cooked with a blank piece of paper.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds constructable Integrated Robotic Chassis
    • +
    • Adds surgery to customize existing robotic limb appearances
    • +
    • Positronic brains renamed to robotic brains
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added a Harmonica to Perma Brig
    • +
    +

    datlo updated:

    +
      +
    • Replaced instances of "Human" in ion laws by "Crew".
    • +
    • Fixed the ability of Service Borgs to spawn items on floors. Dosh!
    • +
    + +

    10 July 2018

    +

    Fox McCloud updated:

    +
      +
    • Can no longer take assisted organs at round-start (mechanical organs are still a go, but renamed to cybernetic organs)
    • +
    • Can now start the round with cybernetic lungs, liver, and kidneys
    • +
    • Can produce cybernetic eyes at R&D and mechfabs
    • +
    • Cybernetic internal organs no longer take reduced damage (this does not apply to augments)
    • +
    • Cybernetic internal organs can be rendered inoperable (this does not apply to augments)
    • +
    • Fixes mitocholide/oculine healing damage on cybernetic organs
    • +
    • Fixes being able to restart a dead heart in your hands or with a defib
    • +
    + +

    09 July 2018

    +

    Fox McCloud updated:

    +
      +
    • Enabled augmentation of the head
    • +
    • Adds cybernetic heart, lungs, liver, and kidneys to R&D and Robotics; also adds cybernetic upgraded lungs
    • +
    • Heads are no longer vital organs, but brains still are
    • +
    + +

    07 July 2018

    +

    Fox McCloud updated:

    +
      +
    • Stechkin pistols in maintenance no longer spawn with a broken magazine
    • +
    +

    Kyep updated:

    +
      +
    • Removed PDA chatrooms. NTNet Relay Chatrooms, part of modular computers, still exist.
    • +
    + +

    06 July 2018

    +

    Fox McCloud updated:

    +
      +
    • removes explosive lances
    • +
    +

    datlo updated:

    +
      +
    • Replaced duplicate labor shuttle console on the bridge by a mining shuttle console.
    • +
    + +

    04 July 2018

    +

    Citinited updated:

    +
      +
    • Spelling error in agent IDs
    • +
    + +

    03 July 2018

    +

    MINIMAN10000 updated:

    +
      +
    • Restrained spacepod passanger can now exit pending a 2 minute wait time without moving.
    • +
    + +

    02 July 2018

    +

    Citinited updated:

    +
      +
    • Canisters obey melee cooldown now
    • +
    +

    Crazylemon64 updated:

    +
      +
    • All MMI variants can now install an "MMI radio upgrade" in order to acquire radio capability when outside of any other chassis. It can be installed either directly on the MMI, or through an opened cyborg chassis. This radio can later be removed if desired by using a screwdriver on the MMI.
    • +
    • MMIs can now pull up the direct interface of the radio instead of a single-toggle verb
    • +
    • MMI radio control is now done via action button instead of via verb
    • +
    • The radio MMI no longer exists as a distinct item
    • +
    + +

    01 July 2018

    +

    Anasari updated:

    +
      +
    • Shuttle can be called at 30:00 instead of 25:00 during War Ops.
    • +
    +

    Citinited updated:

    +
      +
    • The chef can now process spaghetti into macaroni, and can make several derivative foodstuffs.
    • +
    +

    datlo updated:

    +
      +
    • Syndicate clowns can now purchase Clown Magboots. Keep honking through slips and atmos!
    • +
    +

    monster860 updated:

    +
      +
    • Adds the mining podbay (again)
    • +
    + +

    30 June 2018

    +

    Citinited updated:

    +
      +
    • Adds the conveyor belt placer and bluespace conveyor belt placer, allowing you to much more easily create conveyor belts. The former can be gotten at any autolathe, the latter must be researched first.
    • +
    • Use a conveyor belt lever on aforementioned item to link all belts inside the placer with that lever.
    • +
    + +

    27 June 2018

    +

    MINIMAN10000 updated:

    +
      +
    • Containment emitters
    • +
    • deferred processing of SMES
    • +
    + +

    26 June 2018

    +

    Alffd updated:

    +
      +
    • Additional logic to atmos throwing.
    • +
    + +

    23 June 2018

    +

    matt81093 updated:

    +
      +
    • death squid hitbox position
    • +
    + +

    19 June 2018

    +

    Anasari updated:

    +
      +
    • Gloves of the north star is now categorized under highly visible and dangerous weapon instead of pointless badassery. (Because it's actually good)
    • +
    +

    Fox McCloud updated:

    +
      +
    • Can cast spells on CentComm z-level during ragin' mages
    • +
    +

    MINIMAN10000 updated:

    +
      +
    • Cardboard drop counts
    • +
    + +

    17 June 2018

    +

    Fox McCloud updated:

    +
      +
    • Fixes wizards not spawning with their clothes and backpack
    • +
    • It no longer snows on away missions
    • +
    +

    variableundefined updated:

    +
      +
    • Nuclear challenge time limit now depends on round start time.
    • +
    + +

    13 June 2018

    +

    Aurorablade updated:

    +
      +
    • Fluff for Panzerskull
    • +
    +

    Fox McCloud updated:

    +
      +
    • Medibots now actually talk, like beepsky
    • +
    • Adds Plastic surgery; fix someone's face or give them a new identity!
    • +
    • Having more than 50 cloneloss will render you "Unknown"
    • +
    • head disfigurement requires you to have more than 50 combined brute and burn damage, rather than tracking it separately
    • +
    • Fixes Cryoxadone and Rezadone not fixing disfigurement, Fixes fluorosulfuric acid not causing disfigurement at proper thresholds
    • +
    • Fixes syndicate medibot not being constructable from tactical medkits
    • +
    • Syndicate medibot and the mysterious medibot are better at treating brute and burn damage
    • +
    • Radiation event reworked; graphics updated--effects may be a bit more deadly
    • +
    • Buffed DIY chainsaws damage slightly
    • +
    • You now flip about when you spin with a double e-sword
    • +
    • Adds surgical augment to R&D
    • +
    • Tools on surgical augment are slightly faster at surgery
    • +
    • Wishgranter grants "Avatar of the Wishgranter" instead of making you a superhero
    • +
    • Toxin damage is stealthier and will no longer cause stinging spam message
    • +
    +

    Kyep updated:

    +
      +
    • Additional job slots are now available at 80+ server population.
    • +
    +

    MINIMAN10000 updated:

    +
      +
    • Airlock electronics lock
    • +
    • Airlock electronics close button
    • +
    +

    Piccione updated:

    +
      +
    • Added Magboots to the Paramedic's EVA gear closet
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Shadowling dethrall has been shortened to scalpel, hemostat, retractor, shine light, cautery
    • +
    + +

    11 June 2018

    +

    FalseIncarnate updated:

    +
      +
    • Food on utensils now properly inherits the name of the source dish.
    • +
    • Joined Souls rune can now properly can summon restrained targets with 3+ invokers.
    • +
    + +

    09 June 2018

    +

    Fox McCloud updated:

    +
      +
    • Fixes holobarrier icons being missing
    • +
    + +

    08 June 2018

    +

    Alffd updated:

    +
      +
    • Adds an automated emergency var on air alarms for mappers
    • +
    +

    Anasari updated:

    +
      +
    • Fixes admin log for spray displaying (0,0,0) all the time.
    • +
    +

    Desolate updated:

    +
      +
    • ED-209 code corrected to work properly. Floorbot code corrected to work properly.
    • +
    +

    and Dumbdumb updated:

    +
      +
    • Unathi and Vox Sec Hardsuit update
    • +
    + +

    05 June 2018

    +

    Kyep updated:

    +
      +
    • The Terror Spider away mission now has spiders colonizing the west side of the map. Only the gateway room is safe.
    • +
    + +

    04 June 2018

    +

    Fox McCloud updated:

    +
      +
    • Hulk mutation no longer works at range (ie: punching/breaking windows/walls at range)
    • +
    • You must be on harm intent to damage things if you have hulk
    • +
    • Having hulk allows you to punch and damage just about anything
    • +
    +

    uraniummeltdown updated:

    +
      +
    • You can smelt titanium and glass together to form titanium glass for building shuttle windows
    • +
    • You can smelt titanium, plasma and glass together to form plastitanium glass for building plastitanium windows
    • +
    • Fulltile windows now smooth, windows crack as they get damaged and can be repaired with help intent welder
    • +
    • Windows have deconstruction hints and show whether they can be rotated or not
    • +
    • Plasma glass no longer gets auto-colored
    • +
    • RCDs can deconstruct airlocks again, they have no force now though
    • +
    • Wielded fireaxe does a lot of damage to windows and grilles instead of just deleting them
    • +
    • Glass stacks now use stack recipes instead of a custom menu
    • +
    + +

    31 May 2018

    +

    FalseIncarnate updated:

    +
      +
    • The singulo no longer feeds on attention.
    • +
    + +

    26 May 2018

    +

    Birdtalon updated:

    +
      +
    • Holoparasite guide updated to include newer models. Small tooltip added for charger models.
    • +
    • laser tag gun projectiles now play appropriate sound when striking.
    • +
    +

    Citinited updated:

    +
      +
    • Hopefully fixes all issues with disposals sending you to nullspace.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes not being able to propel yourself through space by farting if you possessed both superfart and toxic farts
    • +
    +

    Kyep and Bxil updated:

    +
      +
    • Prevents everyone and their mother from seeing through closed poddoors.
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Most things will now use the correct pronouns.
    • +
    • Newscasters properly check for feed channel creation and wanted issue creation
    • +
    • ERT should deploy properly without admins now.
    • +
    + +

    19 May 2018

    +

    Aurorablade updated:

    +
      +
    • Vet Coat Fluff item.
    • +
    • Spacepod mod kit now uses kit blueprints and not KITE blueprints (spelling error).
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds gloves of the North Star; get them on the uplink for 8 TC
    • +
    • Unarmed attacks now have their own icons, as does disarming.
    • +
    • Various mobs have their own custom icon attacks
    • +
    • Monkies now bite!
    • +
    + +

    18 May 2018

    +

    Fox McCloud updated:

    +
      +
    • Removes engineering and police tape
    • +
    • Adds security, atmospheric, and engineering holoprojectors
    • +
    +

    tigercat2000 updated:

    +
      +
    • You can now lock a facing direction with shift+middle mouse button, or lock your direction towards an object by clicking on it with shift + ctrl + middle mouse button.
    • +
    + +

    15 May 2018

    +

    Tayyyyyyy updated:

    +
      +
    • Pun pun is back!
    • +
    + +

    11 May 2018

    +

    Kyep updated:

    +
      +
    • It is no longer possible to create an infinite number of monkeys from the same monkey cube.
    • +
    + +

    09 May 2018

    +

    RyanSmake updated:

    +
      +
    • You can now jump on fax machines without the UI lying to you.
    • +
    + +

    07 May 2018

    +

    qwertyquerty updated:

    +
      +
    • The window title is custom now!
    • +
    + +

    06 May 2018

    +

    Kyep updated:

    +
      +
    • DeathSquad is now better equipped, and prompts eligible ghosts with a "Do you want to play as DeathSquad?" when called.
    • +
    • DeathSquad members (except team leaders) can now choose to spawn as either an organic DS member, or a DS borg.
    • +
    + +

    05 May 2018

    +

    Tayyyyyyy updated:

    +
      +
    • ERT members will have their proper name and appearance when cloned
    • +
    + +

    04 May 2018

    +

    RyanSmake updated:

    +
      +
    • You will now log in to the proper account you input to the ATM instead of the one associated with you.
    • +
    • Now ATMs will reconnect after a power outage.
    • +
    + +

    02 May 2018

    +

    CrazyLemon and Fox McCloud updated:

    +
      +
    • Fixes reagent smoke
    • +
    + +

    01 May 2018

    +

    Alffd updated:

    +
      +
    • Tell clients to rejoin after shutdown, before killing the server.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Removed programmable unloader circuit
    • +
    • Bomb testing range can now be utilized multiple times without worry of the bomb bouncing off and returning back to you
    • +
    + +

    30 April 2018

    +

    Fox McCloud updated:

    +
      +
    • Adds Guillotines: make them with plasteel, wood, and cable coil. Execute your comdom head of staff TODAY
    • +
    • Clapping now actually plays a clapping sound
    • +
    • Adds Blast cannon
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Medbay treatment center now has a wider entrance
    • +
    • Virology hallway is now publically accessible from Surgery waiting room, entrance is now double-doors.
    • +
    + +

    28 April 2018

    +

    MINIMAN10000 updated:

    +
      +
    • Developer express start
    • +
    + +

    26 April 2018

    +

    Fox McCloud updated:

    +
      +
    • Destroys uplink metagaming: Adds in F.R.A.M.E. cartridge
    • +
    • using raw telecrystal on an active uplink or yourself will use the entire stack at once
    • +
    • can purchase 5 and 20 unit TC bundles from the uplink
    • +
    • Removes radio icons when speaking over radio
    • +
    • Fixes cargo recycler never recycling items on its own
    • +
    • Fixes mech fabricator using an all white UI
    • +
    • Can upload alien alloy design to the ORM
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • You only need to click once to clean a floor
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Slimes can be injected with plasma reagent and epinephrine to control mutation chance. Plasma increases mutation chance 5% per 5u to a max of 50%, epinephrine decreases by 5% per 5u to a minimum of 0%
    • +
    • Slimes can change their face using new emotes
    • +
    • Slimes can steal nutrition from other slimes when attacking them
    • +
    • Slime docility potion no longer makes a simple animal slime, instead makes the target docile and never hungry
    • +
    + +

    25 April 2018

    +

    Fox McCloud updated:

    +
      +
    • Can make water bottles and caution signs out of plastic sheets
    • +
    • Increased cargo plastic sheet count to 50 and reduced cost to 10
    • +
    • Adds a recipe for making plastic sheets: oil, acid, and ash
    • +
    • Can now make a designs on the circuit imprinter that use metal and other exotic materials
    • +
    • Removed the acid cost from most circuit recipes
    • +
    • bluespace material requirement on a few parts: bluespace stock parts, phazon parts, bags of holding, and the likes all now require bluespace lattice.
    • +
    • Fixes invisible plushies and getting fluff item plushies
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • You can't see admin character names in PMs
    • +
    +

    Xhuis updated:

    +
      +
    • The Nanotrasen Meteorology Division has identified the aurora caelus in your sector. If you are lucky, you may get a chance to witness it with your own eyes.
    • +
    + +

    24 April 2018

    +

    Kluys updated:

    +
      +
    • Cleanblots not cleaning /obj/effect/decal/cleanable/trail_holder (blood trails)
    • +
    + +

    17 April 2018

    +

    Citinited updated:

    +
      +
    • Kitchen machinery no longer looks as if it is falling apart.
    • +
    +

    MINIMAN10000 updated:

    +
      +
    • Adds NOBLUDGEON to door_remote so the remote always triggers
    • +
    • Cable coils now allow you to transfer a part of the stack
    • +
    • Stack handling from cable.dm is removed as stack.dm already handles it
    • +
    • Changed cable coil message
    • +
    • The ability to change the color of cables
    • +
    • cableColor now follows the new cable_color format
    • +
    + +

    14 April 2018

    +

    Anticept updated:

    +
      +
    • Changed defib timer from 3 minutes to 5 minutes
    • +
    +

    MarsM0nd updated:

    +
      +
    • Single man up now looks and sounds the same as the global man up for that person.
    • +
    + +

    11 April 2018

    +

    KasparoVy updated:

    +
      +
    • Removes the job-restriction on the purely cosmetic Tajaran veils while those wth integrated HUDs remain unchanged.
    • +
    + +

    08 April 2018

    +

    Kyep updated:

    +
      +
    • Terror Spiders now have a new type in their roster (brown) and see the health status of humanoids (since some of their abilities depend on that status). The Terror Spider away mission has also been adjusted to smooth out areas of no challenge (safe spaces) as well as areas of nigh-impossible challenge (dozens of spiders stacking up together in the final room).
    • +
    + +

    07 April 2018

    +

    Alffd updated:

    +
      +
    • portable (stationary) scrubbers now remove 1/4th as much air per tick at maximum.
    • +
    +

    Birdtalon updated:

    +
      +
    • Nanocalcium can no longer be synthesised by bees or Odysseus
    • +
    • Silicons now have their diagnostic HUD removed correctly.
    • +
    • Defibs no longer give endless paddles.
    • +
    • Ether re-balanced into a more effective anaesthetic for surgery.
    • +
    • Atmos techs have access to tech storage and inner engineering tool room.
    • +
    +

    Citinited updated:

    +
      +
    • You can't play russian roulette without a head
    • +
    • using a russian revolver on another human will now hit them with the revolver instead of failing to play russian roulette with them.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Deletion of human mobs now properly deletes equipment balance: Hotel guards now dust on death balance: Hotel guards no longer drop equipment when stunned balance: Hotel guards now are able to use the tasers they hold
    • +
    +

    Dyhr updated:

    +
      +
    • Agent ID's now provide some presets for valid occupations.
    • +
    +

    Kyep updated:

    +
      +
    • SIT shuttle can no longer dock in scimaint.
    • +
    • Crew demotions and terminations now generate an automatic message to admins. All job changes are also logged.
    • +
    • Modular computers now support toggling priority on/off for jobs. The button for doing this in both normal and modular computers is now marked 'Pri', instead of the old '*'.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Admins can make a fax machine recive the faxes Centcomm or the Syndicate does get.
    • +
    • Stops "Unknown" department to send to from coming up when a fax machine gets spawned.
    • +
    • Allows adding of departments to send to over a proc-call.
    • +
    +

    Spacemanspark updated:

    +
      +
    • Mining drones now have movement sprites.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Drones will no longer shatter glass tables
    • +
    • All small mobs can bump open public access doors
    • +
    + +

    06 April 2018

    +

    Fox McCloud updated:

    +
      +
    • Fixes medical cyborgs having one less stack than they should have they recharge
    • +
    • Fixes inconsistency in the medical stacks amounts (they should all be 6)
    • +
    + +

    05 April 2018

    +

    uraniummeltdown updated:

    +
      +
    • Aliens can pull facehuggers out of eggs again
    • +
    + +

    03 April 2018

    +

    & Deathride58 & Tigercat2000 updated:

    +
      +
    • Station time is now randomized [if enabled in game_options configuration].
    • +
    • A separate round time has been added to status panel. This will start at 00:00:00.
    • +
    • Night shift lighting [if enabled in the same configuration] will activate between station time 7:30 PM and 7:30 AM. This will dim all lights affected, but they will still have the same range.
    • +
    • APCs now have an option to set night lighting mode on or off, regardless of time.
    • +
    + +

    02 April 2018

    +

    Desolate updated:

    +
      +
    • New Cricket Borg module selection.
    • +
    +

    EldritchSigma updated:

    +
      +
    • Mech mounted Disablers are now printable with consistency.
    • +
    +

    Fethas updated:

    +
      +
    • Viruses Lycancoughy, Adv. Pierrots throat and Kingstons added.
    • +
    +

    IK3I updated:

    +
      +
    • You can now opt out of the syndicate recruitment semminar prior to boarding the station.
    • +
    +

    Kyep updated:

    +
      +
    • Syndifox and Syndicat can now do melee damage. Paperwork (cargo sloth pet) no longer can.
    • +
    • Syndifox and Syndicat are no longer controllable by players by default.
    • +
    • Poly (parrot in Engineering) now knows more phrases.
    • +
    +

    Shazbot updated:

    +
      +
    • Adds E-pistol crates to the cargo manifest Change: changes the HoP's E-gun to an E-pistol
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Borg power warning is on a 2 second cooldown
    • +
    + +

    01 April 2018

    +

    Tayyyyyyy, LP Spartan updated:

    +
      +
    • Once you up to red, it takes 5 minutes before the shuttle transit time is reduced to 5 minutes.
    • +
    + +

    30 March 2018

    +

    matt81093 updated:

    +
      +
    • fish duplication when pulling out multiple fish at once
    • +
    + +

    28 March 2018

    +

    Birdtalon updated:

    +
      +
    • Enforces size limits for placing items inside slicable food
    • +
    +

    Fox McCloud updated:

    +
      +
    • Nano UI will update a bit faster
    • +
    +

    MarsM0nd updated:

    +
      +
    • Record printouts now automatically get labled with the name of the person.
    • +
    + +

    25 March 2018

    +

    Alffd updated:

    +
      +
    • Logic checks to lessen death from flying objects due to atmospheric breaches.
    • +
    • Removes atmospheric stunning while thrown.
    • +
    + +

    24 March 2018

    +

    matt81093 updated:

    +
      +
    • Borgs no longer keep their special vision when reset with the reset module
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Deconstructing default RCD airlocks should work now
    • +
    + +

    22 March 2018

    +

    uraniummeltdown updated:

    +
      +
    • Airlocks now have security levels. Secure airlocks cannot be hacked straightaway. Vault doors and highsecurity airlocks have some security by default. You can make an airlock secure by applying metal and plasteel to it while the panel is open
    • +
    • As a slime, you can drag yourself onto a target to feed
    • +
    • Doors, tables and table frames can be destroyed by hitting them. Airlocks can be repaired by a welder on help intent.
    • +
    • You can butcher with any sharp item on harm intent
    • +
    • Grilles are stronger
    • +
    • Vault door assemblies cost 8 plasteel up from 6
    • +
    • Xenomorphs can open non-locked non-welded airlocks after some time
    • +
    • Firelocks can be welded open again, firelock [de]construction uses crowbar instead of welder
    • +
    + +

    21 March 2018

    +

    MarsM0nd updated:

    +
      +
    • Xray machines now have xray vision, and check contents of an item, instead of just the item.
    • +
    + +

    20 March 2018

    +

    MarsM0nd updated:

    +
      +
    • Stops a mug from being invisible
    • +
    + +

    19 March 2018

    +

    Birdtalon updated:

    +
      +
    • re-adds the inline "take" shortcut for adminhelps
    • +
    +

    Birdtalon, LPSpartan, Shazbot updated:

    +
      +
    • Nanocalcium - bone repair reagent. Adds bone repair kit to syndicate uplink containing Nanocalcium autoinjector.
    • +
    +

    Fethas updated:

    +
      +
    • Vulpkanin, Hunger drain increased slightly. rscadd:Diona now have hair by skittles.
    • +
    • Bedsheets can contribute to dream messages.
    • +
    • sometimes dreams will be nightmares.
    • +
    • Moves dream/nightmare strings to txt files. rscadd:sleeping has a small change to heal brute/fire. but you need a bed..and a bed sheet to be effective.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes Vulpkanin hunger drain rate being absurd
    • +
    +

    IK3I updated:

    +
      +
    • Comically sized mugs are slightly less comically sized
    • +
    • Lord Singuloth's wrath can no longer be bypassed by baking your input device.
    • +
    +

    Shazbot updated:

    +
      +
    • Adds an ammo counter to the icon and the in hand icon for the M90-gl
    • +
    • Lowers the price of the .357 for nukies
    • +
    + +

    16 March 2018

    +

    MarsM0nd updated:

    +
      +
    • You can now fix broken message monitors
    • +
    + +

    13 March 2018

    +

    Citinited updated:

    +
      +
    • Restricts RPD usage to certain station-side turfs.
    • +
    +

    Piccione updated:

    +
      +
    • Added marijuana cigarette packets to the Psych's locker.
    • +
    • Changed the taste message of a few food items
    • +
    + +

    12 March 2018

    +

    Fethas updated:

    +
      +
    • Full of skittles borg fluff
    • +
    + +

    08 March 2018

    +

    shazbot updated:

    +
      +
    • Fixes up Desolate's name on his other items.
    • +
    + +

    06 March 2018

    +

    Regen updated:

    +
      +
    • Removes the purple hair flower pin from loadout and general player access, because this is a fluff item.
    • +
    + +

    04 March 2018

    +

    Funce updated:

    +
      +
    • APC Interface lock UI works for silicons.
    • +
    + +

    03 March 2018

    +

    Birdtalon updated:

    +
      +
    • A few more items in the Psyche locker.
    • +
    +

    Citinited updated:

    +
      +
    • IPCs can now lose russian roulette without going to nullspace
    • +
    +

    DarkPyrolord updated:

    +
      +
    • Sliceable food items are no longer hammerspace capable
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds colored, departmental, and novelty mugs to the hot drinks machine and loadout menu under "Mugs".
    • +
    • Adds Head of Staff coffee mugs to their respective lockers.
    • +
    • Adds support for inserting items into vendors and having the vendor interact with said item when vending items.
    • +
    • Adds the ability to insert containers into the hot drink machine, filling the container with your purchase.
    • +
    +

    Fethas updated:

    +
      +
    • The booze o' mat now has wine..bags.
    • +
    +

    KasparoVy updated:

    +
      +
    • The eyes of humanoids who have XRAY vision mutation, sufficiently high darkview, synthetic eyes or eye implants now appear to shine in the dark.
    • +
    • Adds a way to 'cut' one icon's pixels out of another by using the get_icon_difference() proc.
    • +
    • get_location_accessible() now checks the appropriate flags when determining the accessibility of eyes.
    • +
    +

    Serket updated:

    +
      +
    • Death Wand can kill slimes and hopefully everything
    • +
    • Wizards can no longer mind-swap borgs
    • +
    • ERT Specops Office now comes with extra privacy (borgs can't open the ERT mech room, etc.)
    • +
    • Removed snow from Mr Chang's
    • +
    • Fixed a dethralling error causing message typos
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • AIs can view info of their synced borgs in the status panel
    • +
    + +

    26 February 2018

    +

    Birdtalon updated:

    +
      +
    • Removes printing photos on security consoles.
    • +
    + +

    21 February 2018

    +

    uraniummeltdown updated:

    +
      +
    • Added titanium and plastitanium. Mine the asteroid for titanium, make plastitanium by smelting together titanium and plasma
    • +
    • You can build shuttle floors and walls with titanium and plastitanium. Can also make shuttle airlocks by applying titanium to a non-mineral airlock
    • +
    • Shuttle windows have explosion resistance now
    • +
    • A few RnD recipes require titanium now
    • +
    + +

    20 February 2018

    +

    Alffd updated:

    +
      +
    • Reduce all atmospheric stuns by 80%
    • +
    • Cap the maximum atmospheric stun time to 4 seconds
    • +
    +

    Anasari updated:

    +
      +
    • Add paperplane. Alt-click or use a verb on a piece of paper in your hand to make them.
    • +
    +

    Birdtalon updated:

    +
      +
    • adds [time] tag for paperwork
    • +
    +

    Citinited updated:

    +
      +
    • You can now roll up flags.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in a Dance Machine
    • +
    • IEDs now have a blast radius again
    • +
    • Slap crafting of IEDs is gone; use personal crafting instead
    • +
    +

    HugoLuman updated:

    +
      +
    • coughing and sneezing sounds for the Drask
    • +
    +

    MarcellusPye updated:

    +
      +
    • Grays can now drink sulphuric acid without being burnt
    • +
    +

    Shazbot updated:

    +
      +
    • Fixes Patch's patch
    • +
    +

    Tayyyyyyy, bryanayalalugo updated:

    +
      +
    • News reporters can now add titles to their stories!
    • +
    + +

    05 February 2018

    +

    IK3I updated:

    +
      +
    • Next gen dining is now available at your local autolathe!
    • +
    +

    MarsM0nd updated:

    +
      +
    • Pod lock busters can now unlock pods
    • +
    • Pods can only be locked with a locking system installed.
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Energy swords, energy daggers, energy cutlasses, and energy axes emit light. Toy versions do not.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Multitile airlock opening/closing animation is no longer glitchy and paper/photos don't float in the air when opening/closing them
    • +
    + +

    02 February 2018

    +

    Fethas updated:

    +
      +
    • TG Port, ais now have an advanced diagnostic hud that lets them see the path a bot is taking.
    • +
    • Bots get access for 60 seconds to all doors to get to thier locations. rscadd:Pai controlled bots will get a notification they are being called. rscadd:all living mobs now can have a med hud.
    • +
    + +

    01 February 2018

    +

    Squirgenheimer updated:

    +
      +
    • Using the 'tear reality' rune as cult should now be punished when the invokers do not have the god summoning objective
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Players job banned from syndicate can no longer play emagged drones
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Examining an airlock assembly gives construction hints and shows what pen name is set. Mineral airlocks can have glass added to them.
    • +
    • Added public and external maintenance airlock assemblies to metal recipes
    • +
    • Maintenance, standard and external airlocks now have glass versions. Multi-tile airlock has a solid version.
    • +
    • Added more airlocks to RCD
    • +
    • You can attach paper and photos to airlocks, wirecutters to remove them
    • +
    • Airlocks open faster
    • +
    • Vault and high-security airlocks are made with 6 plasteel up from 4
    • +
    • Plasteel should have the correct amount of materials in it now
    • +
    + +

    29 January 2018

    +

    Fox McCloud updated:

    +
      +
    • Slime blueprints can now make an area compatible with Xenobio consoles, regardless of the name of the new area
    • +
    +

    MarcellusPye updated:

    +
      +
    • Changes the ghost preferences section of game preferences to display the currently active option instead of the inactive option.
    • +
    + +

    27 January 2018

    +

    IK3I updated:

    +
      +
    • Saving a chat log no longer hangs you.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Client FPS setting should save properly now
    • +
    + +

    26 January 2018

    +

    tigercat2000 updated:

    +
      +
    • Insta-movement works marginally better
    • +
    +

    uraniummeltdown updated:

    +
      +
    • You can now change your client FPS in Game Preferences
    • +
    + +

    24 January 2018

    +

    IK3I updated:

    +
      +
    • Cancel means Cancel on admeme console reports!
    • +
    • When eldritch gods, demons, handsy aliens, and incarnations of darkness tell you it's time to go, you go
    • +
    • Comms Console will tell you when the shuttle can't be recalled
    • +
    • Admemes can now designate whether a shuttle they call is recallable
    • +
    • Admemes can exercise their power to recall any shuttle, even in defiance of spooky ghosts!
    • +
    +

    Kyep updated:

    +
      +
    • Added config option to limit the amount of time shadowlings can remain unhatched before they start getting pushed to hatch.
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Energy beams of all types emit light.
    • +
    • Flashbangs emit a burst of light when detonated
    • +
    + +

    21 January 2018

    +

    KasparoVy updated:

    +
      +
    • Avoids wanton bloodshed by revising logic that checks for blood already in the splat zone.
    • +
    • Adds a helper proc with which you can get a list of all atoms of a type at a given location.
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Due to increasing amounts of spaghetti code in the cryptographic sequencer, emagging maintenance drones cripples their table pathfinding and removes their ability to pathfind under people's legs. Also, Nanotrasen has patched its drones to remove the hidden diamond drill module and rewritten its drone control code so that drones that don't call home and verify their programming after a certain amount of time are destroyed automatically.
    • +
    + +

    20 January 2018

    +

    uraniummeltdown updated:

    +
      +
    • Fixed issues with ethereal jaunt directions, wraith jaunt no longer shows the wizard effects
    • +
    • Guardians phasing in/out will properly show a little animation
    • +
    • The petting heart animation is smoother
    • +
    + +

    19 January 2018

    +

    Citinited updated:

    +
      +
    • Using a syndicate balloon while it's in your hand allows you to play with it.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Wooden holodeck table sprites show up properly
    • +
    • Table construction has been changed a bit, apply stack items (carpet, metal, glass, wood) to table frames to build tables instead of using table parts.
    • +
    • Slightly increased the health of racks and tables with low health
    • +
    • Holodeck tables will now smooth with one another
    • +
    • Holodeck tables and racks can be interacted with in more ways
    • +
    + +

    13 January 2018

    +

    Citinited updated:

    +
      +
    • The ocean and the pool are no longer colder than outer space.
    • +
    • Water now cools or heats you gradually, not all at once.
    • +
    +

    Kyep updated:

    +
      +
    • Refactored Paranormal/Janitor dress code, and Cyborg ERT spawn code.
    • +
    • Signing up for ERT, then going AFK, such that your AFKness prevents you and/or others spawning as ERT within a reasonable (2 minute) period of time, now generates a warning to online admins.
    • +
    + +

    11 January 2018

    +

    Bxil updated:

    +
      +
    • Economy accounts now use the correct date.
    • +
    +

    Citinited updated:

    +
      +
    • Jaunters work again.
    • +
    +

    Jountax updated:

    +
      +
    • Fancy shoes no longer cost one's entire loadout.
    • +
    • Sugarcane added to the MegaSeed Servitor. No more garden raids!
    • +
    +

    Kyep updated:

    +
      +
    • Department management (aka: demotion) consoles only worked for their respective head of staff. Captains, CC characters, etc could not use them.
    • +
    • Fixed two brown wooden doors in wizard academy away mission which had space turfs under them, leading to nasty results with fastmos.
    • +
    • Added deathsquid.
    • +
    • Further modified construction site layout, fixing various issues and making it easier to test new engine setups there.
    • +
    +

    Tayyyyyyy, FPK updated:

    +
      +
    • The more dark view you have, the more eye damage you take from flashing. Darkness amplifies this effect.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Freezers and other atmos machines will drop frame and parts correctly again
    • +
    + +

    07 January 2018

    +

    Kyep updated:

    +
      +
    • All mineral floor tiles no longer incorrectly show up as abductor flooring.
    • +
    + +

    05 January 2018

    +

    Kyep updated:

    +
      +
    • Improved wild west away mission. Fixes issues such as lack of magboots, and 'projectile gun's appearing. Adds some flavor items (syndie soap in shower, medkits in storage). Also adds syndie comms device which alters the mission depending on how it is used.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Construct shells have a new sprite
    • +
    + +

    04 January 2018

    +

    Anasari updated:

    +
      +
    • A lot of underused nuke op items made cheaper.
    • +
    • Syndicate hardsuit removed from nuke op because you already got one free.
    • +
    • Tactical medkit give you four synthflesh patch, no more stetho or lethal syringe.
    • +
    • RSG added to nuke op uplink. Dart gun no longer available.
    • +
    + +

    31 December 2017

    +

    Alffd updated:

    +
      +
    • Wire panels are now effected by the colorblindness disability
    • +
    • Wire panel color changes now support RGB hex values
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes arm implants being immune to EMPs.
    • +
    +

    FreeStylaLT updated:

    +
      +
    • A dedicated toxic pill sprite, Cyanide and Toxin pills now use it by default.
    • +
    +

    KasparoVy updated:

    +
      +
    • Blood splattered by projectiles hitting a mob now land one tile away in the direction of the splatter graphic. Blood splattered on walls/windows/etc. can be cleaned off with soap.
    • +
    • Xeno-blood splatter is now the appropriate colour.
    • +
    +

    Kyep updated:

    +
      +
    • IAAs now require 10h of playtime, instead of 5h, to unlock. The IAA job's alt title is now "Human Resources Agent" instead of "Lawyer" or "Public Defender". IAAs now start with basic access to all departments (sci/med/cargo/eng), so that they can more easily conduct investigations. Overall, their role has been clarified, to be explicitly on the side of NT, not simply that of defendants. Further, they're empowered to, and expected to, actually conduct investigations, and generally be better at their jobs.
    • +
    • The mech bay next to Robotics now has a robotic storage unit (cryopod for cyborgs).
    • +
    • The Construction Site (partially finished space station east of eng outpost) has been revamped. With basic power/atmos networks in place, it should now be much more viable to repair it during a round.
    • +
    • Added shutters to specops office next to ERT spawn. This prevents borgs remotely activating the admin-only buttons in that office.
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Crew pinpointers no longer lose signal when the target enters something like a sleeper or a mech
    • +
    +

    Vivalas updated:

    +
      +
    • It is now possible to directly inject spaceacillin into organs during surgery, and it only uses 5u to completely cleanse the organ,
    • +
    + +

    27 December 2017

    +

    Tayyyyyyy updated:

    +
      +
    • Repeated lines are now combined in the chat window. This can be disabled in chat window preferences.
    • +
    • Paramedic, Blueshield, and Medivends get crew pinpointers
    • +
    + +

    23 December 2017

    +

    Fethas updated:

    +
      +
    • Borers can no longer be possesed by ghosts using an antag hud.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Having a master, as a spider means you actually get a message who is your master now
    • +
    +

    Purpose2 updated:

    +
      +
    • Cartographers dispatched. NanoUI Minimap is now updated.
    • +
    +

    Santa's Lawyer updated:

    +
      +
    • Removed riot dart toys from under Christmas trees.
    • +
    + +

    21 December 2017

    +

    FalseIncarnate updated:

    +
      +
    • Adds fans under the doors at the North Pole.
    • +
    +

    Purpose2 updated:

    +
      +
    • You may no longer use strikethroughs/italics in OOC. This was causing backend server problems due to how shoddily BYOND is coded, and cannot be safely added right now.
    • +
    + +

    19 December 2017

    +

    Santa Claus updated:

    +
      +
    • Christmas cheer!
    • +
    • Grinch
    • +
    • missing emergency nitrogen / plasma tanks
    • +
    + +

    15 December 2017

    +

    uraniummeltdown updated:

    +
      +
    • Plants no longer take twice as many cycles to age
    • +
    + +

    05 December 2017

    +

    Kyep updated:

    +
      +
    • Removed peacekeeper borgs.
    • +
    + +

    04 December 2017

    +

    Tayyyyyyy updated:

    +
      +
    • IPCs no longer vomit next to rotting bodies
    • +
    +

    Terillia updated:

    +
      +
    • Fixes the litch Hat and Sandals
    • +
    + +

    02 December 2017

    +

    uraniummeltdown updated:

    +
      +
    • You can now create vault door assemblies with 4 plasteel sheets
    • +
    • Science airlocks have been added to metal recipes and the RCD
    • +
    • Airtight and Maintenance Hatch added to the RCD
    • +
    • Highsecurity airlock assemblies are built with 4 plasteel instead of 4 metal
    • +
    • All doors and doorlike things (firelock, airlock, windoor, blast door, shutters, spacepod door) run off the Environment Power Channel
    • +
    • Emagged airlocks have a different description on examining
    • +
    • Screwdrivering an airlock now displays a message. No more guessing if the panel is open or not.
    • +
    • Cult airlocks will keep their old name on being converted.
    • +
    + +

    01 December 2017

    +

    Fox McCloud updated:

    +
      +
    • Lungs are now responsible for breathing instead of a mob; mix and match lungs however you like!
    • +
    • Ripping out someone's lungs or them necrotizing will make a person suffocate; it will no longer kill them instantly
    • +
    • Drask no longer heal burn damage from breathing cold air (brute is still healed)
    • +
    • Lungs no longer rupture in low pressure
    • +
    • Not having lungs means you can't talk
    • +
    • remove the discrete internals button on the HUD; use the tank action button!
    • +
    • Fixes slimes dying by themselves
    • +
    + +

    30 November 2017

    +

    ExitGame updated:

    +
      +
    • vox quill rustle emote
    • +
    • species check
    • +
    +

    Fox McCloud updated:

    +
      +
    • shotgun pellets deal less damage the further they travel
    • +
    + +

    28 November 2017

    +

    Kyep updated:

    +
      +
    • It is no longer possible for Service borgs using the Rapid Service Fabricator to end up with negative energy.
    • +
    + +

    27 November 2017

    +

    uraniummeltdown updated:

    +
      +
    • Composting plants/pills into hydroponics trays transfers all reagents
    • +
    + +

    26 November 2017

    +

    FalseIncarnate updated:

    +
      +
    • The Syndicate has determined that subtle and stealthy items don't benefit from obvious names, and thus have rebranded their contortionist jumpsuit to something less eye-catching.
    • +
    • The Syndicate decided to be less stingy than Nanotrasen and made the contortionist jumpsuit out of flame resistant materials. You may burn, but the jumpsuit won't!
    • +
    +

    Fethas updated:

    +
      +
    • Penguins, Penguins in shambreos and Albino penguins are a thing.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes being able to recall Abductor-called shuttles
    • +
    • Fixes slime transformation potion not making you a real slime
    • +
    • Polymorph slimes are now random color
    • +
    +

    Jountax updated:

    +
      +
    • Can now add laceup shoes to your loadout.
    • +
    +

    Kyep updated:

    +
      +
    • Service borgs are now able to dispense a variety of fruit juices, as well as coffee and tea. Additionally, they can use a health scanner on crew, and the poisoned beer they get from being emagged is much more deadly. They can also create snackfood using their Rapid Service Fabricator.
    • +
    • When an admin creates a classified message manually, and selects 'no' to the 'notify crew' option, the incoming message will be announced via command radio, instead of a priority announcement that the whole crew sees.
    • +
    • ERT borgs can now speak on ERT radio, even after choosing a module.
    • +
    • ERT borgs are now always named as such, may only take modules that would be useful in an emergency, and always have their emagged modules unlocked. They also have an 80% chance to resist emagging their cover lock, so you will need to stun them with a flash before trying to emag them.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Logs usage of stun talismans.
    • +
    • Stops rigsuits from shocking over distance.
    • +
    • Let's malfunction count down while not being actively worn, to avoid permanetly breaking it.
    • +
    • Allows boots to be worn under rigsuit boots.
    • +
    • Wirenames for the rigsuit wires if you can see them.
    • +
    • Rigsuits only slow you down when deployed, potentially less if active.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Gambling machines now payout again.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Particle effects pass over tables and grilles
    • +
    • Nanofrost smoke fading out actually works now
    • +
    • All smokes now fade out
    • +
    • Nanofrost smoke can now also weld scrubbers
    • +
    + +

    22 November 2017

    +

    Fox McCloud updated:

    +
      +
    • "Pick Up" from right clicking obeying the same rules as regularly clicking on it
    • +
    + +

    19 November 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes cult shuttle curse from being used more than twice and from extending shuttle call duration once nar-sie has been called/slaughter demons have been called.
    • +
    + +

    18 November 2017

    +

    MarsM0nd updated:

    +
      +
    • A (possibly non-existant) officer's beret does no longer incorrectly hide hair.
    • +
    + +

    13 November 2017

    +

    Alffd updated:

    +
      +
    • Fixes muzzles not preventing vampire biting unless the target was wearing the muzzle.
    • +
    • Makes throwing the ambulance with atmospherics almost impossible.
    • +
    +

    VexingRaven updated:

    +
      +
    • Fixes the message that appears when a mob being force-fed a snack finishes eating that snack.
    • +
    + +

    12 November 2017

    +

    Kyep updated:

    +
      +
    • It is now much harder for Command/HoS to get away with illegal executions. Admins are far more likely to notice people being set to execute, more detailed explanations of executions must be sent to CC, and admins are more able to intervene when an execution is obviously illegal.
    • +
    + +

    11 November 2017

    +

    FalseIncarnate updated:

    +
      +
    • Full windows are now 100% stronger than before, so you don't have to pick strength over security.
    • +
    • Full windows now take longer to deconstruct so they offer slightly better security against break-ins. Toolspeed does apply.
    • +
    • Full and directional windows can be built on grilles now, and you can even pick the direction! Technically both a tweak and an addition...
    • +
    + +

    10 November 2017

    +

    Allfd updated:

    +
      +
    • A new Anti-Bite muzzle has been added to the SecVendor. This muzzle can be locked through the strip panel and will prevent a vampire from feeding.
    • +
    • Holy water now causes vampires to vomit blood, before vomiting the water. After this holywater behaves as normal.
    • +
    +

    Anasari updated:

    +
      +
    • 79 hairstyles ported from Polaris.
    • +
    + +

    05 November 2017

    +

    Fethas updated:

    +
      +
    • changes the my tickets from a verb..to a prock. To quote lemons: F.
    • +
    +

    KasparoVy updated:

    +
      +
    • The Barber's dye bottle now works again.
    • +
    • The Barber's dye bottle can now colour alternate (facial) hair themes where applicable.
    • +
    + +

    04 November 2017

    +

    FalseIncarnate updated:

    +
      +
    • MANDATORY FUN! Arcades added to both stations!
    • +
    • Bottler units have been spotted on board both stations!
    • +
    • Arcade carpet tiles added to the prize counter for 150 tickets (credit to Goonstation for the turf icon).
    • +
    • Cyberiad bathrooms should have 100% fewer floating showers (behind curtains).
    • +
    • Showers have been fitted with mist-reducing showerheads. They should no longer generate infinite mist if rapidly toggled.
    • +
    • Cyberiad chemistry has had the extra APC removed. Now they only have one as standard.
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Medbay has been remapped
    • +
    • New Maint areas have been added south of Medbay.
    • +
    + +

    01 November 2017

    +

    FreeStylaLT updated:

    +
      +
    • Medbay has been remapped
    • +
    • New Maint areas have been added south of Medbay.
    • +
    +

    Kyep updated:

    +
      +
    • Freedom Operative suits no longer revert to a normal red syndi suit icon when you use their 'toggle hardsuit mode' option.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Stops holograms from attempting to appear when they just disappeared because the AI became unable to keep it up.
    • +
    + +

    30 October 2017

    +

    NewSta updated:

    +
      +
    • There is now a "GitHub" button.
    • +
    • Modified the height of the "Donate" button to make it equal to that of other buttons.
    • +
    • The distance between the info and wiki buttons is now 30 px. All other buttons now have a 5px distance between them.
    • +
    • Fixed a typo in the wiki window.
    • +
    + +

    29 October 2017

    +

    Alffd updated:

    +
      +
    • Ion Rifles are no longer pistols
    • +
    + +

    28 October 2017

    +

    Anasari updated:

    +
      +
    • Some underappreciated traitor items had been made cheaper.
    • +
    +

    Kyep updated:

    +
      +
    • Vamp jaunt/shadowstep no longer works on z2.
    • +
    • Ghosts with sec hud enabled can now see mindshield, tracker and chem implants, as well as wanted status.
    • +
    +

    Landerlow updated:

    +
      +
    • Adds Sake to a hacked booze dispenser's menu.
    • +
    +

    Squirgenheimer updated:

    +
      +
    • Fixed a typo causing the inability to create the large energy crossbow in the protolathe.
    • +
    + +

    27 October 2017

    +

    Birdtalon updated:

    +
      +
    • Birdtickets: Adminhelp Ticketing System
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Silver Slime Core reactions can only summon forth drinks that actually contain a drink. Begone thirst!
    • +
    • Removes some "unsafe" chemicals from lists of potential chemicals for inclusion in things like random pills or bottles, added one to replace them.
    • +
    • Removes adminordrazine and nanites from vent clog, replaces nanites with syndicate_nanites.
    • +
    + +

    26 October 2017

    +

    Anasari updated:

    +
      +
    • Change some brain damage phrases. Add a lot of new one.
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Moves Ambulance's key to Paramedic's EVA locker from his clothing locker
    • +
    • Removed an unnecessary EVA helmet from Paramedic's EVA locker
    • +
    +

    Kyep updated:

    +
      +
    • Soviets (including Soviet Tourists, a non-antag filler role) no longer get all-access to the Cyberiad when they visit.
    • +
    • Freedom Operatives are now a support outfit that admins can equip players as.
    • +
    +

    TDSSS updated:

    +
      +
    • Added a shortcut to talk on ERT channel, namely ':$', bringing it in line with other channels.
    • +
    + +

    25 October 2017

    +

    Anasari updated:

    +
      +
    • Flavour text description in character setup now consistent with rules.
    • +
    • Grenade reagent are also logged when they are primed
    • +
    • TC from war op increased by 2 per player above 50.
    • +
    +

    Kyep updated:

    +
      +
    • ERTs now support janitor, paranormal, and cyborg ERT units, as well as specific slot configurations.
    • +
    • Heads of staff who are editing another admin's permissions in the admin panel can now toggle several permissions for a person without re-finding them in the list. Hitting 'cancel' at any point drops out of the loop. It also notifies admins whether they're toggling a permission on, or off.
    • +
    • ERT spawn area now shows ERT request reasons, and admins can enable the use of a teleporter or grav catapult without mechs.
    • +
    + +

    22 October 2017

    +

    Crazylemon64 updated:

    +
      +
    • Suiciding crewmembers are no longer capable of being cloned.
    • +
    +

    Fethas updated:

    +
      +
    • makes a better proc for doing spins (IE Ian chasing tail, etc) then was previous.
    • +
    +

    McCloud and Alffd updated:

    +
      +
    • Merge all LINDA and atmos machine functions into the air controller subprocess.
    • +
    • Air alarms in scrubbing mode will shut off when alarm enters danger state. If this occurs simultaneously with a max2 temperature alarm panic siphon will automatically activate.
    • +
    • High air pressure differences will throw objects and knock over station species.
    • +
    • Add magpulse to syndicate and death squad borgs.
    • +
    • Change all volume pumps to regular pumps in atmospherics to accommodate new LINDA speeds.
    • +
    • Change LINDA interval from 2 seconds to 400 milliseconds.
    • +
    • Removed unused control from flamethrower.
    • +
    • Set flamethrower release equal to fuel used.
    • +
    • Increased Reinforced Wall HP from 200 to 600.
    • +
    • Buff aliens against space wind.
    • +
    • Buff Terror Spiders against space wind.
    • +
    • Buff some blobmobs aginst space wind.
    • +
    • Frost requires heat to remove.
    • +
    + +

    15 October 2017

    +

    Citinited updated:

    +
      +
    • Clipboards now have more functionality. You can now stamp them, attach paper bundles to them, write on any contained paper by clicking on the paper's name using a pen, add pens directly to them, and rearrange what piece of paper is on top!
    • +
    • Full-sized plasma windows are fire-resistant, and full-sized reinforced windows are fully fireproof.
    • +
    • You can now remove facehuggers from corgis. Corgis that have been glomped by multiple facehuggers will now work as you'd expect them to.
    • +
    • Radiation mines no longer change the DNA of species that don't have it.
    • +
    • Firedoors and other doors will no longer close when a shuttle docks. Open firelocks can no longer be welded. Welded firelocks should no longer open under any circumstances.
    • +
    • Open airlocks no longer spark when you throw something conductive through them.
    • +
    +

    Fethas updated:

    +
      +
    • Many things use sleeping. Surgry pain fail fix.
    • +
    +

    Imsxz updated:

    +
      +
    • Ballistic mech weapons now all use the ammo system
    • +
    +

    Kyep updated:

    +
      +
    • Changing someone's sec status now prompts for a reason. The change, and the (optional) reason for it, is written to that person's sec record, and to the server logs. This applies to changes made by sec HUDs, and by records computers.
    • +
    • Magistrate/Captain/HoS/Warden can now use a sec records computer to set a person to "Execute" status. This status cannot be unset by HUDs, and broadcasts a notification to all online admins when it is set. It is intended to replace the "fax CC" requirement for executions. Persons with this status show up with a white 'X' as their sec hud icon.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Shadowlings are extinguished after hatching, allowing Plasmamen Shadowlings to not burn to death.
    • +
    • Shadowlings now passively heal eye damage, eye blurriness
    • +
    +

    Vivalas updated:

    +
      +
    • Splints now pop off after 2000 steps, or when taking a lot of damage to that limb. Getting surgery for those broken limbs might be a good idea now.
    • +
    + +

    14 October 2017

    +

    Anasari updated:

    +
      +
    • Explosive lance doesn't embed anymore.
    • +
    +

    Fethas updated:

    +
      +
    • ARMBANDS! REPRESENT! SEE THE LOADOUT!
    • +
    +

    Kyep updated:

    +
      +
    • HoPs/Captains opening/closing job slots is now announced to admins. No more HoPs opening 30 clown slots without admins noticing.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Gives a choice whether to mangle black gloves, or to completely cut of the fingertips
    • +
    + +

    11 October 2017

    +

    Anasari updated:

    +
      +
    • Slot machine no longer earn money on average. Bet changed to 100.
    • +
    • All items can be used to smash windows instead of only those defined as weapons. (e.g. including guitar & flashlight)
    • +
    • Mulebot with pAI cannot knock people down anymore.
    • +
    +

    Birdtalon updated:

    +
      +
    • Terror spiders now respect antagHUD respawn restrictions.
    • +
    +

    Kyep updated:

    +
      +
    • mindslaving an antagbanned player now offers control of their mob to ghosts.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Can now place garbage in garbage cans without standing on top of them.
    • +
    +

    scrubmcnoob updated:

    +
      +
    • Cult must use teleport tailsman in active hands.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • New PACMAN portable generator sprites
    • +
    + +

    10 October 2017

    +

    Birdtalon updated:

    +
      +
    • Bees with no reagent will now work.
    • +
    + +

    07 October 2017

    +

    Birdtalon updated:

    +
      +
    • User interface tweaks to Brig timers.
    • +
    • Seconds converted to minutes and seconds in Brig radio and security console printouts.
    • +
    • Bees can no longer reproduce un-synthable reagents.
    • +
    +

    imsxz updated:

    +
      +
    • Aliens now always spawn as a pair when their infestation event begins.
    • +
    +

    scrubmcnoob updated:

    +
      +
    • Abductors can no longer use megaphones.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Adds new sprites to the unused and used eldritch whetstones. Sprites by Fury McFlurry.
    • +
    • Air tanks now have their own sprite, no longer looking like oxygen tanks
    • +
    • 10mm alt magazines have their own sprites
    • +
    + +

    06 October 2017

    +

    Birdtalon updated:

    +
      +
    • Bottler doesn't break after one use.
    • +
    + +

    05 October 2017

    +

    Birdtalon updated:

    +
      +
    • Re-adds missing light switch to robotics.
    • +
    + +

    02 October 2017

    +

    Imsxz updated:

    +
      +
    • Rapid re-hatch no longer kills shadowlings.
    • +
    • Vampires can no longer enthrall chaplains
    • +
    + +

    30 September 2017

    +

    Jovaniph updated:

    +
      +
    • Coroner now has their own locker in the morgue.
    • +
    +

    Landerlow updated:

    +
      +
    • Adds hydrocodone to the Cyborg Hypospray
    • +
    + +

    29 September 2017

    +

    Citinited updated:

    +
      +
    • Telescreens and entertainment consoles now have 'off' and 'broken' sprites.
    • +
    • Wooden TVs, engineering camera consoles, mining camera consoles, telescreens, and entertainment consoles now have their own circuit boards and can be reconstructed!
    • +
    • Using a multitool on a telescreen or entertainment monitor will now allow you to reposition it.
    • +
    +

    imsxz updated:

    +
      +
    • Subtle messages no longer begin with "old"
    • +
    + +

    28 September 2017

    +

    MarsM0nd updated:

    +
      +
    • Stops the electrified arm from combat and stunbaton implant from runtiming.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Changelings have a new power, Biodegrade, for 2 evolution points. For 30 chemicals you can vomit acid onto restraints, welded/locked lockers and spider cocoons to escape them.
    • +
    • Hivemind Link for changelings has been readded, it was removed in error
    • +
    + +

    05 September 2017

    +

    Kyep updated:

    +
      +
    • Adds alternative military shuttle, NT Navy troop transport.
    • +
    + +

    04 September 2017

    +

    Kyep updated:

    +
      +
    • Admins under the effects of 'invisimin' no longer show up on sec huds, medical huds, etc.
    • +
    + +

    03 September 2017

    +

    Birdtalon updated:

    +
      +
    • Flip emote has a small chance of a failure and 100% chance of embarrassing yourself.
    • +
    +

    Citinited updated:

    +
      +
    • You can now deconstruct the indestructible stool in the old bar's back room.
    • +
    • Security and bar maintenance airlocks are now decoupled.
    • +
    • The air vent at the fore of AI satellite now starts turned on.
    • +
    • Engineering equipment now only has one air vent, not three.
    • +
    • Added a missing bit of plating underneath the engineering shuttle's window.
    • +
    • Added a missing scrubbers pipe in Central Primary.
    • +
    • The camera and light fixture in the prisoner transfer centre are now wall-mounted instead of being attached to the blast doors.
    • +
    • Adds the Flaming Moe cocktail.
    • +
    • Shot glasses can now be set alight using something hot.
    • +
    + +

    02 September 2017

    +

    Landerlow updated:

    +
      +
    • Adds a recipe to create enzymes to cook with.
    • +
    + +

    01 September 2017

    +

    Birdtalon updated:

    +
      +
    • Fixed small bug with wall lockers not respecting distance.
    • +
    + +

    28 August 2017

    +

    Birdtalon updated:

    +
      +
    • Replaces civilian door remote in the Head of Personnel locker with a brand new remote with additional access to better suit the Head of Personnel's responsibilities.
    • +
    • Nanotrasen Mining Bots are no longer safe from EMPs.
    • +
    • Syndicate bee-case sound now only plays locally when opened.
    • +
    • You can open wall lockers with control click.
    • +
    +

    Birdtalon & Hylocereus updated:

    +
      +
    • Adds pineapples which can be grown in hydroponics, juiced or sliced and made into hawaiian pizza.
    • +
    • Adds hawaiian pizza to the pizza crate.
    • +
    +

    Fethas updated:

    +
      +
    • The cultist dagger has had its special removed, it still cuases small bleed and retains its embed chance.
    • +
    • Prayers now dsiplay the diety set by chaplains (if any) to admins in prayers, or eldergod if a cultist. Prayers are purple for normies, Red for cultist and blue for chaplains
    • +
    +

    Fox McCloud updated:

    +
      +
    • IPCs can now be dissected by adbudctors
    • +
    +

    Fox Mccloud updated:

    +
      +
    • Adds an accordian, glockenspiel, harmonica, recorder, saxaphone, trombone, xylophone, bikehorn, and piano synthesizer
    • +
    • pick up a big band supply pack of instruments at cargo for 50 supply points
    • +
    +

    Jovaniph updated:

    +
      +
    • Holodeck Energy Swords sound was change to simulate being attacked by a real energy sword.
    • +
    +

    Landerlow updated:

    +
      +
    • Adds six additional roundstart disabilities to choose from
    • +
    +

    matt81093 updated:

    +
      +
    • robot analyzer to medical module cyborgs for IPC diagnosing
    • +
    + +

    24 August 2017

    +

    Birdtalon updated:

    +
      +
    • Cultist structures can now be destroyed using melee and or projectiles
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes Diona, Plasmamen, and other races having internal bleeding
    • +
    + +

    16 August 2017

    +

    Citinited updated:

    +
      +
    • Adds the plasmaman flag; credit to Shadeykins for the original sprite! Buy it at the merch store and show your superiority over other, less flammable, species!
    • +
    • All flags should now have in-hand sprites.
    • +
    • Burning a flag while it is in your hand will now update your mob's sprite.
    • +
    • Fixes another issue with disposals sending things to nullspace.
    • +
    +

    Fethas updated:

    +
      +
    • Swarmers can now deconstruct simply by clicking, ctrl click to teleport.
    • +
    • you can now deactivate depowered swarmers with a screwdriver.
    • +
    • Swarmers can now consume swarmer shells for a refund.
    • +
    • swarmer lights are cyan.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Cluwning is far more difficult to remove
    • +
    • Cluwne mask cannot be melted with acid
    • +
    • Cluwne suit has no sensors
    • +
    +

    Kyep updated:

    +
      +
    • Admins now have a 'List SSDs' verb to list SSD players, and the ability to move them to cryo.
    • +
    + +

    15 August 2017

    +

    Birdtalon updated:

    +
      +
    • Medbots can now inject from their internal beakers.
    • +
    • Swarmers can no longer kill the AI with direct attacks.
    • +
    • Simple animal melee damage now has a sanity check for AI core.
    • +
    + +

    14 August 2017

    +

    AndrewMontagne updated:

    +
      +
    • Modular computers now print fields correctly.
    • +
    • Files on modular computers no longer vanish shortly after editing.
    • +
    • Modular computers printers now make printing noises.
    • +
    • You can no longer try and buy a tablet with a printer.
    • +
    • Cloning a file now works.
    • +
    +

    Birdtalon updated:

    +
      +
    • Spiderbots can now pass tables, making their Hide worthwhile.
    • +
    • Fixes interactions with cargo crates.
    • +
    +

    Citinited updated:

    +
      +
    • Nanotrasen's legal department clamped down on video cameras being misappropriated by crew, and as such cameras are now unable to broadcast from beyond the gateway.
    • +
    +

    Fethas updated:

    +
      +
    • Dethaws some IPC surgery issues.
    • +
    +

    taukausanake updated:

    +
      +
    • Adds an Atmospherics duffel bag that is yellow and blue
    • +
    • Adds sub-department colors to medical duffel bags and purple to Science duffel bags
    • +
    • Captain's lefthand west sprite corrected
    • +
    + +

    10 August 2017

    +

    KasparoVy updated:

    +
      +
    • Blood trails are now the same colour as the blood pools they came from when viewed by colour blind or noir shades wearing humanoids.
    • +
    + +

    09 August 2017

    +

    Purpose2 updated:

    +
      +
    • Adds a cycling airlock on the new mining mini outpost.
    • +
    • Re-adds the cycling airlock on mining outpost.
    • +
    • Fixes the broken atmos piping on mining outpost.
    • +
    • Fixes a lack of lighting on mining outpost.
    • +
    + +

    06 August 2017

    +

    Birdtalon updated:

    +
      +
    • Small wording change to syndicate collaborator greetings.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Botany nerfed; will need ambrosia gaia earth's blood to make a tray self-sustaining
    • +
    • Gene machine now requires heavy upgrading to make use of transferring high quality genes from one plant to another
    • +
    • Starthistle can now be grown
    • +
    • Adds in red and regular onions; slice them for onion rings; cook them for even more delicious onion rings
    • +
    +

    Kyep updated:

    +
      +
    • Playing as a smite/bless hunter, or syndie infiltration team member, now requires that you be traitor-eligible. IE: have enough playtime, and the preference enabled.
    • +
    +

    Purpose2 updated:

    +
      +
    • BoxStation: Adds a garbage receptacle by the kitchen. Don't forget to bus your plates.
    • +
    • BoxStation: Fixes an inappropriate access restriction on one part of an airlock, and ensures the buttons are visible.
    • +
    • BoxStation: Changes the now erroneous Science Shuttle Console on the bridge to a Labor Camp Shuttle Console.
    • +
    • Adds screwdrivers to Medical by the cell chargers for recharging the defibs.
    • +
    + +

    05 August 2017

    +

    Purpose2 updated:

    +
      +
    • Karma message will now point you in the right direction again.
    • +
    + +

    03 August 2017

    +

    Fox McCloud updated:

    +
      +
    • Internal organs can take damage again, brain damage can be fixed again, and you now take the proper damage from external sources to limbs, IPCs surviving EMPs, and robo limbs never malfunctioning
    • +
    + +

    02 August 2017

    +

    Fox McCloud updated:

    +
      +
    • removed a stasis book from the medical break room
    • +
    + +

    31 July 2017

    +

    Birdtalon updated:

    +
      +
    • Protolathe stock part printing no longer takes a lifetime.
    • +
    + +

    30 July 2017

    +

    FreeStylaLT updated:

    +
      +
    • Fixed erroneous pipes on z5
    • +
    +

    Kyep updated:

    +
      +
    • Evil-minded players can no longer use the Gateway's Mother of Terror spider to create an infestation on-station.
    • +
    + +

    29 July 2017

    +

    Fox McCloud updated:

    +
      +
    • Dead hearts now induce a heart attack
    • +
    • Fixed concentrated initro never metabolizing
    • +
    +

    FreeStylaLT updated:

    +
      +
    • replaces generic Mining z-level with Meta's
    • +
    +

    Purpose2 updated:

    +
      +
    • MetaStation: Adds the missing kitchen windows
    • +
    • MetaStation: Nerfs the Top Hat equivalent of the Sword in the Stone.
    • +
    • MetaStation: Adds a Pet Supply vendor, chefs now make sushi again!
    • +
    + +

    27 July 2017

    +

    Birdtalon updated:

    +
      +
    • Protolathe speed now increases when upgraded with manipulators.
    • +
    + +

    26 July 2017

    +

    Citinited updated:

    +
      +
    • The autopsy drawer's description makes more sense.
    • +
    + +

    25 July 2017

    +

    Birdtalon updated:

    +
      +
    • Reduces the volume of the electric guitars
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Antagonists will no longer get the objective to steal slime extracts and plasma tanks.
    • +
    • The Captain has a swanky high-tech jetpack now. Antagonists will try to steal this one instead of *any* jetpack.
    • +
    +

    Fox McCloud updated:

    +
      +
    • You can now point while voluntarily lying down
    • +
    • shotgun darts and syringe darts no longer react their reagents on hit (they will still transfer reagents)
    • +
    • removes cryostasis bag
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Removed sci outpost and dock from Metastation and Cyberiad
    • +
    • Added a Mining Outpost to the northernmost point of the Asteroid.
    • +
    +

    Kluys, Kyep & DarkLordpyro updated:

    +
      +
    • Emagged drones are now readily identifiable, as their lights turn red.
    • +
    +

    Kyep updated:

    +
      +
    • Eating as Ian (and other player-controlled corgis) is now rate-limited.
    • +
    • Reagents placed in shotgun shells will now react. It is no longer possible to make explosive shotgun darts by using regular darts like cryobeakers.
    • +
    • Admins' Smite command has been upgraded. No longer limited to Dark Priests, it can now send over a dozen different entities in search of its target, from the comic, like Greytiders, Tunnel Clowns, Masked Killers and Mime Assasins, to the serious, such as Syndicates, Soviets, Dark Lords and more. All come with a dust implant. These same characters can also be sent to protect specific crew members, so they aren't predictable.
    • +
    • The 'reaper' admin outfit now has a working briefcase.
    • +
    • Use of the 'Bless' command to bestow powers no longer causes genetic damage.
    • +
    +

    imsxz updated:

    +
      +
    • makes HONK rifle selfcharge
    • +
    +

    owenowen212 updated:

    +
      +
    • Adds the clownish language to honk squad members.
    • +
    + +

    24 July 2017

    +

    FlattestGuitar updated:

    +
      +
    • Adds a taste system! Drink or eat stuff to find out what it tastes like!
    • +
    +

    Kyep updated:

    +
      +
    • it is no longer possible to use a sentience potion to convert space pirates in the beach away mission to your side. Nor is this possible with other sentient NPCs, such as syndies or russians.
    • +
    + +

    23 July 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes cloners causing infections in clonees
    • +
    + +

    22 July 2017

    +

    Crazylemon64 updated:

    +
      +
    • Slipping now outputs a visible message instead of a personal one
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes IPCs and Diona being immune to weapon knockdown
    • +
    +

    Kyep updated:

    +
      +
    • Terror Spider away mission is now harder to cheese.
    • +
    • Loading a different character while in the lobby will now update the character name listed on the lobby screen. Same when you rename an existing character.
    • +
    • Blood decals are no longer movable. This means LINDA cannot move them, spiders cannot wrap them, etc.
    • +
    + +

    21 July 2017

    +

    Purpose2 updated:

    +
      +
    • MetaStation: Adds a brand new Medbay!
    • +
    • MetaStation: Adds the dogbeds to the CMO/HoS office
    • +
    • MetaStation: Adds Sergeant Araneus back to the HoS's office. HoS beware.
    • +
    • MetaStation: Adds a processing area to the brig.
    • +
    • MetaStation: Adds the Gamma Armory.
    • +
    • MetaStation: Adds two additional brig cells
    • +
    • MetaStation: Adds a morgue slab to the Brig Phys office
    • +
    • MetaStation: Morgue has a swanky new office, directly connected to Cloning.
    • +
    • MetaStation: Robotics gets gloves and masks.
    • +
    • MetaStation: Adds shutters to R&D and Genetics.
    • +
    • MetaStation: Adds a Paramedic's office.
    • +
    • MetaStation: Adds a fully function containment grid.
    • +
    • MetaStation: Moves Monitor Encryption key to the RD's office again
    • +
    • MetaStation: Dorms have glass doors and fewer tinted windows
    • +
    • Metastation: Engine Containment now has Blast Doors instead of Shutters.
    • +
    • Metastation: Execution chamber blast doors are no longer see-through.
    • +
    • Metastation: Only the appropriate plastic flaps should be see-through.
    • +
    • MetaStation: Botany is no longer all-access
    • +
    • MetaStation: Science gets access to the Science outpost again... for now...
    • +
    • MetaStation: Fixes camera network monitors
    • +
    • MetaStation: Church shutters block vision again
    • +
    • MetaStation: Adds the missing Armory shutter button.
    • +
    • MetaStation: Removes tinted windows from R&D & Genetics
    • +
    + +

    20 July 2017

    +

    Purpose2 updated:

    +
      +
    • Stops vampires spawning in the church.
    • +
    + +

    19 July 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes dismembering and some damage transfers (when limb damage is maxed out) being inconsistent
    • +
    • can no longer dismember groins
    • +
    • Cleans up human examine code to be better laid out and more consistent; minor grammatical changes and some fixes; consistency should be retained for species that lack a pulse. Soul departure now properly checks for if the person can re-enter their corpse or not. Also resolves issues with FAKE DEATH examination.
    • +
    • Adds in gunshot blood splattering
    • +
    + +

    18 July 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes blood volume being able to exceed 560
    • +
    +

    Purpose2 updated:

    +
      +
    • The Arrival's Trader Dock now cycles properly.
    • +
    + +

    16 July 2017

    +

    Ataman updated:

    +
      +
    • Fixed diona nymphs needing oxygen and getting cold.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Cable laying by clicking the cable you want to join to works now
    • +
    +

    KasparoVy updated:

    +
      +
    • Fixes a bug with Vampire Shapeshift where you didn't get a name appropriate to your species and clarifies the ability description.
    • +
    • Fixes a bug with DNA scramblers whereby you wouldn't get a name appropriate to your species.
    • +
    + +

    15 July 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes blood oddities with vampires
    • +
    +

    Kyep updated:

    +
      +
    • Mechs firing missiles no longer cause the missiles to drop at their feet, as if frozen in midair.
    • +
    +

    imsxz updated:

    +
      +
    • Edits the syndicate soft suit helmet's description to match the suit's.
    • +
    + +

    13 July 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes blood volume and type not showing up properly on health analyzer
    • +
    • Fixes exotic blood names being incorrect
    • +
    • fix examining/checking yourself/others for bleeding/bandaging
    • +
    • Everything that involves bandaging now properly uses the new blood system
    • +
    • Fixes species exotic blood being injected into a mob not increasing their blood volume (slimes rejoice)
    • +
    • Fixed faked deaths still allowing for bleeding
    • +
    • Fixes IV drips not transferring over the proper amount of blood
    • +
    • Embedded objects will cause additional bleeding
    • +
    • Adds in heparin, a drug that can cause bleeding
    • +
    • medical stacks can be used multiple times on the same limb
    • +
    • Blood depletes in the body a lot faster now, due to blood refactor changes
    • +
    +

    Shazbot-coding, Driker-Sprites updated:

    +
      +
    • Gives the clown their own jug
    • +
    + +

    12 July 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixed advanced scanners showing hidden viruses
    • +
    • Fixed changeling panacea curing beneficial viruses
    • +
    • removed blood decal infections
    • +
    • some diseases now bypasse species virus immunity (kuru, TB, and appendicitis)
    • +
    + +

    11 July 2017

    +

    Fethas and tigercat updated:

    +
      +
    • blood trails
    • +
    • blood is now eaiser to decrease/increase .
    • +
    • revamps about every method of adding blood to something, floors, walls, doors, PEOPLE.
    • +
    + +

    10 July 2017

    +

    AffectedArc07 updated:

    +
      +
    • APC frames now have the correct texture
    • +
    +

    Birdtalon updated:

    +
      +
    • Pool contractors have been back to school and can now spell "safety" on the controller correctly.
    • +
    • Minor change to blob description to address grammar issue.
    • +
    +

    Citinited updated:

    +
      +
    • Superfart once again works ass intended.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Radiation poisoning no longer permastuns, but deals burn damage now and has increased mutation chances
    • +
    • adds in electric guitars
    • +
    • can now craft violins and electric guitars
    • +
    • purchase electric guitars at the cargo store
    • +
    • service borgs now have an electric guitar, too
    • +
    • lowered the price of instruments, at cargo store, to 500
    • +
    • Fixed violins not having an in-hand icon
    • +
    + +

    08 July 2017

    +

    Citinited updated:

    +
      +
    • Rainbow and mime crayons will now change colour as intended.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Advanced mop slightly slower at cleaning and holds less reagents, but now regenerates water if turned on
    • +
    • Blood (on the floor) that has viruses in it will now properly infect you, if you get near
    • +
    +

    Kyep updated:

    +
      +
    • It is no longer possible to prioritize a job with no open slots, or close any job slots for a job that is already prioritized, as either of these actions could lead to a situation where a job is prioritized without people being able to join as it.
    • +
    + +

    05 July 2017

    +

    Purpose2 updated:

    +
      +
    • Anomalies will once again drop cores.
    • +
    + +

    04 July 2017

    +

    Birdtalon updated:

    +
      +
    • Traitor medical chemists can now access syndicate poison bottles.
    • +
    +

    Citinited updated:

    +
      +
    • AIs and cyborgs can now toggle liquid dispensers by ctrl-clicking them, and can make them dispense foam by alt-clicking.
    • +
    +

    Citinited & LightFire53 updated:

    +
      +
    • Adds the plasmaman coroner suit, the plasmaman geneticist suit, and the plasmaman virologist suit. Spooky purple skeletons everywhere rejoice!
    • +
    +

    Fethas updated:

    +
      +
    • Adds medical gowns to medical wardrobes.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Syndicate bombs now have visible timers for observers
    • +
    • Syndicate bombs tick more often
    • +
    • Syndnicate bombs can be deconstructed into plasteel if it is fully defused and has no bomb core
    • +
    • Can make Cryo, Pyro, and time released chemical grenades at R&D
    • +
    • Can make syndicate chemical bombs utilizing crafting
    • +
    • love just got more powerful; it now prevents a mob from being on anything other than help intent
    • +
    • IPCs can now process the love reagent
    • +
    • Adds in radio jammers to the traitor uplink
    • +
    • Adds in breathing tube augment to R&D
    • +
    • Adds in arm toolset augment to R&D
    • +
    • IPC cell charging device is now inside their right arm, as opposed to chest
    • +
    • IPC cell charging device can now be produced in mech fabricators
    • +
    +

    Ionward updated:

    +
      +
    • Greys now have properly fitting sprites for most head clothing items!
    • +
    +

    Kyep updated:

    +
      +
    • Gimmick Teams are now more configurable.
    • +
    +

    Vivalas updated:

    +
      +
    • "Tweaks" SecHUDs to only display criminal status of people if their face is uncovered or they have no ID.
    • +
    + +

    03 July 2017

    +

    Fethas updated:

    +
      +
    • fixes issue with hand teleporter not working in active hands
    • +
    +

    fludd12 updated:

    +
      +
    • Greys are now PROPERLY immune to sulfuric acid.
    • +
    • Greys don't pretend to touch their heads when they don't manage to anymore.
    • +
    + +

    01 July 2017

    +

    Fox McCloud updated:

    +
      +
    • Re-enables object embedding system; embedding objects now cause more damage than before
    • +
    • Adds in throwing stars kit to the traitor uplink
    • +
    • bullets no longer leave shrapnel
    • +
    + +

    30 June 2017

    +

    fludd12 updated:

    +
      +
    • Greys treat Sulfuric Acid as if it were water. They also treat water as if it were sulfuric acid.
    • +
    • Grey language is now Z-level wide, but requires you to be able to put a finger to your temple. (Requires at least one hand not disabled and not stunned.)
    • +
    • Remote Talk is buffed to have a range of two screens, and has some minor formatting changes!
    • +
    • Remote Talk no longer lets you magically know the true name of whoever you speak with.
    • +
    + +

    29 June 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes limbs being an open wound after augmentation
    • +
    +

    Kluys updated:

    +
      +
    • Bob ross painting in the captains office called "calming painting". +Also changes around the entertainment monitor and light switch to accomodate.
    • +
    • Clown painting was named "\improper mech painting"
    • +
    + +

    28 June 2017

    +

    Fox McCloud updated:

    +
      +
    • Fix's IPC head customization
    • +
    +

    Purpose2 and Re-Opened by Fethas updated:

    +
      +
    • Rare Sentience event, the mice now want coffee!
    • +
    + +

    27 June 2017

    +

    Alexshreds updated:

    +
      +
    • EMPs now disable radios for a period of time
    • +
    +

    Citinited updated:

    +
      +
    • Adds the Rapid Pipe Dispenser (RPD). All Atmospherics Technician lockers and the Chief Engineer's locker get one each.
    • +
    +

    Code Fethas and Sprites Phantasmicdream updated:

    +
      +
    • Fancy Victorian Clothes
    • +
    +

    FlattestGuitar updated:

    +
      +
    • defibs work even if you don't target the chest
    • +
    • Chaplain's soul stone is now opt-in.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Can now augment all non-head limbs with surgery
    • +
    • Can select the company design of a limb by using a robot part in your hands
    • +
    +

    Kyep updated:

    +
      +
    • Gamma ship now looks like a real supply pod/ship, doesn't encourage wizards/vampires to hide in it, and has been updated with a wall-mounted charger and smarter layout.
    • +
    • Fixed a bug causing gamma armory mech recharger to be unusable after gamma alert was declared.
    • +
    • Admins may now spawn 'Gimmick' teams, including Janitorial ERT, Paranormal ERT, and more. Any admin outfit, any mission, spawned anywhere.
    • +
    • Paranormal ERT outfit now exists. It acts like a red security ERT, except with focus on fighting paranormal threats.
    • +
    • Janitorial ERT now gets ERT headset, not centcom headset. Also, they now get a survival box, and a flashlight.
    • +
    • New 'department' shuttle now has more public-access seating.
    • +
    +

    ProperPants updated:

    +
      +
    • Plasmaman virologists now spawn with a medical plasmasuit instead of an assistant one.
    • +
    +

    Purpose2 updated:

    +
      +
    • Water coolers have been fitted with better bolts, enabling them to be loosened and moved.
    • +
    • Antag barbers scissors now have the same name as regular scissors.
    • +
    • AIs door open link is now [O] rather than [OPEN].
    • +
    • The Syndicate once more recognises the Coroner as a member of the medical team for purposes for uplink items.
    • +
    • The chef may now tap into the Syndicate's poison networks for use in his dishes.
    • +
    • The chef's supply crate now comes with another rolling pin. Stop misplacing these.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Karma returned to the Special Verbs tab
    • +
    + +

    26 June 2017

    +

    Crazylemon64 updated:

    +
      +
    • TK can now manipulate adjacent tiles. Use throw mode to override this if you want to move an object a single tile.
    • +
    • TK can now remotely manipulate item stacks.
    • +
    • TK can now remotely operate an RCD
    • +
    • TK now behaves more consistently regarding interacting with various objects remotely
    • +
    +

    Kyep updated:

    +
      +
    • ID card consoles can now be used to prioritize any on-station job, including head jobs and karma jobs.
    • +
    • Playing as a drone now requires 10h of playtime.
    • +
    • Admin-ghosts can now interact with (ie: activate) the drone fab without having to spawn in as engineer to do so.
    • +
    • Prioritized jobs now lose their priority status once all their slots are filled. In the event someone with a formerly prioritized job cryos, the HoP may want to re-prioritize the job.
    • +
    +

    Purpose2 updated:

    +
      +
    • Coroners are more battlehardened, and thus don't throw up around dead bodies anymore.
    • +
    + +

    25 June 2017

    +

    Kyep updated:

    +
      +
    • Trial admins no longer see a permissions error when opening player panel.
    • +
    + +

    24 June 2017

    +

    Allfd updated:

    +
      +
    • Ported growl and howl sounds from Goon
    • +
    • Added growl and howl emotes to Vulpkanin
    • +
    +

    Kyep updated:

    +
      +
    • Activating a dust implant no longer causes NODROP items to drop.
    • +
    +

    Purpose2 updated:

    +
      +
    • The *slap emote now has a cooldown like all other noise making emotes.
    • +
    +

    SamHPurp updated:

    +
      +
    • The Coroner will respect the CMO's Authoritah.
    • +
    + +

    23 June 2017

    +

    Kyep updated:

    +
      +
    • Smite/Bless commands are now restricted to Game Admins. (admins with R_EVENT)
    • +
    • Admins can now access telecomms while ghosted.
    • +
    +

    Vivalas updated:

    +
      +
    • Buckling mobs to beds now displays them correctly.
    • +
    + +

    22 June 2017

    +

    Crazylemon64 updated:

    +
      +
    • Cloners now malfunction if the original comes back to life
    • +
    +

    Purpose2 updated:

    +
      +
    • RCDs can no longer construct multiple airlocks on a single tile
    • +
    + +

    21 June 2017

    +

    tigercat2000 updated:

    +
      +
    • Changelings are now tentacle monsters. Give them a schoolgirl outfit.
    • +
    + +

    20 June 2017

    +

    Purpose2 updated:

    +
      +
    • Fixes Fluorine's non-functionality in plants.
    • +
    + +

    19 June 2017

    +

    Fox McCloud updated:

    +
      +
    • Diona nutrition bar should no longer flicker constantly
    • +
    + +

    18 June 2017

    +

    Citinited updated:

    +
      +
    • Using a screwdriver on a camera console will now deconstruct it instead of opening the camera window.
    • +
    + +

    16 June 2017

    +

    Alffd updated:

    +
      +
    • Makes kittens visible when resting
    • +
    +

    Fethas updated:

    +
      +
    • Public Wiggler Tail
    • +
    • Chaplains have some new clothes in thier locker.
    • +
    +

    Fox McCloud updated:

    +
      +
    • tweaked Revenant and slaughter demon movement speed
    • +
    • Spiderbots have been slowed down to human levels
    • +
    • Spiderbots melee attack consistently deals 2 damage, deals burn, and plays a sparks sound
    • +
    • Spiderbots no longer have a built in camera
    • +
    • Spiderbots now have 40 health (previously 10)
    • +
    • Attacking a spiderbot more consistent with other simple mobs
    • +
    • Healing a spiderbot with a welder now plays a sound and incurs a cooldown
    • +
    • Spiderbots can no longer carry items
    • +
    • Emagging a spiderbot makes it loyal to the person who emagged it. Additionally, it gains 20 extra health, its shocks will do 15 damage, and will explode on death
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Changed Araneus' spawn location so he wouldn't break tables at round-start anymore
    • +
    +

    Kyep updated:

    +
      +
    • HoPs can now set jobs as 'priority'. Priority jobs are highlighted on the latejoin screen. This allows HoPs to proactively broadcast that they need more people to fill those jobs - and reduces the chance of critical crew shortages.
    • +
    +

    Purpose2 updated:

    +
      +
    • Soylen Viridians are now correctly Soylent Viridians. Nanotrasen will still not confirm rumours of the contents of these nor Soylent Greens however.
    • +
    • Nanotrasen is now more consistent with brand management.
    • +
    • An array of typos, grammatical tweaks and other pedantic fixes.
    • +
    • Adds a jobs board to the Newscaster. See what roles are available before seeing the HoP!
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Autopsy Scanners will now print out Coroner Reports when a pen is used on them
    • +
    +

    alexkar598 updated:

    +
      +
    • Rename Spagetti to Spaghetti
    • +
    + +

    13 June 2017

    +

    KasparoVy updated:

    +
      +
    • Moves a hidden emergency locker to where it is visible.
    • +
    +

    Vivalas updated:

    +
      +
    • Brig timers will now update the records of those who are imprisoned in their cell, as long as their name is entered correctly.
    • +
    • Sentences and arresting officers are announced over the security channel by brig timers, as well as the names of those who end timers manually.
    • +
    + +

    10 June 2017

    +

    Alffd updated:

    +
      +
    • Ports Incoming5643's persistence features for Runtime from TG
    • +
    • Ports additional cat NPC emotes from TG
    • +
    +

    Citinited updated:

    +
      +
    • Disconnecting before the shuttle leaves after having spent karma will no longer prompt you to spend karma.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds Highlander Style, granted to the wielder of Highlander Claymores. This martial art allows you to deflect ranged attacks from the weapons of COWARDS. FOR THE HONOR OF THE HIGHLANDERS!
    • +
    • Highlander now equips combatants with a Highlander claymore instead of a normal claymore. FIGHT ON BROTHERS!
    • +
    + +

    09 June 2017

    +

    Alexshreds updated:

    +
      +
    • Taking mhelps no longer gives mhelping players your IC name
    • +
    +

    FlattyPatty updated:

    +
      +
    • Added forensics gloves for the Detective.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Paramedic door is no longer diamond
    • +
    • Fixes the backwards health analyzer sprite
    • +
    • Remove adrenaline and freedom implants from R&D
    • +
    • Added chem and tracking implants to R&D
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds some sanity checking to the RCS.
    • +
    • The cargo shuttle no longer permits RCS telepads.
    • +
    +

    Kyep updated:

    +
      +
    • glowshrooms are now destroyable with two hits from a wirecutter.
    • +
    • New 'department' shuttle, which can be sent by CC instead of the regular evac shuttle.
    • +
    • The gods have grown tired of prayers requesting freebies, and developed some new curses with which to smite those who would treat them like miracle vending machines.
    • +
    +

    alexkar598 updated:

    +
      +
    • Surgury holosign switch has correct icon at roundstart
    • +
    +

    tigercat2000 updated:

    +
      +
    • You can now zoom in with the Set View Range option in your Preferences tab!
    • +
    + +

    08 June 2017

    +

    Alexshreds updated:

    +
      +
    • Hyphema and Ocular Restoration are now possible to evolve from viruses
    • +
    + +

    07 June 2017

    +

    Fethas updated:

    +
      +
    • adds cardboard cutouts..now you can trick the station into thinkings it shadowlings!
    • +
    +

    tigercat2000 updated:

    +
      +
    • Luxury versions of the bluespace shelter capsule! Currently not obtainable.
    • +
    • Black Carpet can now be crafted using a stack of carpet and a crayon.
    • +
    • Black fancy tables can now be crafted using Black Carpet.
    • +
    • Shower curtains can now be recoloured with crayons, unscrewed from the floor, disassembled with wire cutters, and reassembled using cloth, plastic, and a metal rod.
    • +
    + +

    06 June 2017

    +

    DarkPyrolord updated:

    +
      +
    • Plasmamen should be able to become vampires on normal vampire rounds.
    • +
    +

    Fox McCloud updated:

    +
      +
    • adjust the mech tesla, immolator, and disabler techs to bring it in line with the tech refactor
    • +
    +

    Kyep updated:

    +
      +
    • Instagib lasers now work against non-carbon mobs, such as animals and borgs.
    • +
    +

    imsxz updated:

    +
      +
    • Sergeant Araneus now spawns at full HP.
    • +
    + +

    04 June 2017

    +

    Crazylemon64 updated:

    +
      +
    • Clone's hearts now start operational
    • +
    • EMP'd clone pods can now be emptied again
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Cell 6 is now connected to the atmos system properly.
    • +
    + +

    03 June 2017

    +

    FlattestGuitar updated:

    +
      +
    • PACMAN boards and pico manipulators now have proper research levels
    • +
    + +

    01 June 2017

    +

    Alexshreds updated:

    +
      +
    • Ian's hardsuit is no longer invisible
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Gamma armory no longer affected by brig events.
    • +
    • Outer armory windoor access has been lowered to Security Officer+, instead of Warden+.
    • +
    • Removed a redundant door in the brig's main hallway.
    • +
    • Removed a redundant fire alarm, placed it elsewhere in the north hallway.
    • +
    +

    Kyep updated:

    +
      +
    • ERTs no longer start penniless, unable to afford even basic food, or coffee.
    • +
    +

    Purpose2 updated:

    +
      +
    • Adds a build-time on Tables & Racks.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Upgrading the Exosuit Fabricator and Protolathe with the right parts will lower item costs
    • +
    • Added an item to Cargo that RnD can use
    • +
    • Tweaks the tech levels for many items and the required tech levels for their designs. This is to make RnD more of a station-wide effort.
    • +
    • RnD tech level skipping skips 1 level further
    • +
    • The Destructive Analyzer will only prompt the user if tech levels will not be increased.
    • +
    • The Experimentor can no longer raise tech levels of items. It can however discover the tech levels of strange objects.
    • +
    • Removes the Autolathe from the RnD Room.
    • +
    • Removed the Forensic Scanner from RnD. Cargo can order a Forensics crate now.
    • +
    + +

    31 May 2017

    +

    FalseIncarnate updated:

    +
      +
    • Shrimp and electric eels properly lay their own eggs again if they have a suitable partner.
    • +
    +

    Xantholne updated:

    +
      +
    • Virologists actually spawn with their skirt
    • +
    • Coroner now can finally spawn with some Medical loadout clothes.
    • +
    • Medical Doctors will stop spawning with Chemist/Virologist Skirts
    • +
    • CMOs won't spawn with a virologist skirt anymore.
    • +
    • Virologists and Chemists wont spawn with a Medical Doctor skirt anymore.
    • +
    + +

    30 May 2017

    +

    Fruerlund updated:

    +
      +
    • You can now take out pens by CTRL Clicking PDAs
    • +
    + +

    29 May 2017

    +

    Jovaniph updated:

    +
      +
    • Two welding goggles on in the atmos room
    • +
    +

    Purpose2 updated:

    +
      +
    • Increases the size of Megaphones.
    • +
    • Headset encryption keys are now 'small' items.
    • +
    +

    Tayyyyyyy, FlattestGuitar updated:

    +
      +
    • A targeting mode-esque message and sound when you point at something with a gun in your active hand
    • +
    + +

    28 May 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes various mobs moving around faster than intended
    • +
    + +

    27 May 2017

    +

    Crazylemon64 updated:

    +
      +
    • Cloning now can be halted at any point, but ejecting too early may result in clones with missing body parts.
    • +
    • Slime people now no longer spontaneously die
    • +
    + +

    26 May 2017

    +

    FlattyPatty updated:

    +
      +
    • Removes gateway hotel xeno embryo for the crew's safety.
    • +
    + +

    25 May 2017

    +

    FalseIncarnate updated:

    +
      +
    • Matter Eater now requires your mouth be uncovered before you can eat matter.
    • +
    +

    Fethas updated:

    +
      +
    • PLASMAMAN ATMOS SUITS ARE NOW THE SAME AS REGULAR ATMOS SUITS FLAG WISE! AND SO IS THE CE SUIT
    • +
    +

    Kyep updated:

    +
      +
    • Fixed some mapping bugs on Centcom, e.g: shuttle medbay no longer has black walls.
    • +
    +

    Purpose2 updated:

    +
      +
    • Metastation - Adds the Paramedic's cart and locker.
    • +
    • Metastation - Adds a backup set of paramedic keys in the CMO's office.
    • +
    • Metastation - Engine no longer hotwired.
    • +
    • Metastation - Turbine doors now function properly.
    • +
    • Metastation - Toxin Mixing's Controller is now accessible.
    • +
    • Metastation - Moved Containment out a single tile, to fix irregularities with Singularity setups.
    • +
    • Metastation - Reduced redundant redundancies in the Atmos/Wiring.
    • +
    • Metastation - removed blob spawn that was only a few tiles from Cryostorage....
    • +
    • Drones can now grip Tracker Electronics & Vending Refills
    • +
    +

    Tayyyyyyy, PhantasmicDream updated:

    +
      +
    • Skrell can put a pocket sized item in their head tentacles, which can be dislodged via stunning, stripping, or death
    • +
    • Skrell can no longer have their tentacles shaved off
    • +
    • Minor grammar fix for putting stuff that's too big into containers
    • +
    + +

    24 May 2017

    +

    Kyep updated:

    +
      +
    • Every head of staff now has a Department Management Console in their office. This is a very limited version of the ID console that they can use to demote people out of their departments, or move people between jobs in their department. These consoles cannot be used to hire anyone, or to accept cross-department transfers.
    • +
    + +

    23 May 2017

    +

    Fethas updated:

    +
      +
    • Lockets and necklaces to the loadout. Lockets can hold paper and photos
    • +
    • Fethas fluff item
    • +
    +

    Purpose2 updated:

    +
      +
    • Adds functionality for the Atmos/Engineering Minimap to update to the right station.
    • +
    + +

    22 May 2017

    +

    DarkPyrolord updated:

    +
      +
    • Rubber pellets should no longer embed.
    • +
    • Bananas fired from the staff of the honkmother should no longer embed, or be called bullets.
    • +
    +

    Kyep updated:

    +
      +
    • Adds mech-mounted variants of the existing tesla, immolator, and x-ray laser guns, with the same material and tech requirements. Admin-only Seraph mech also gets better weapons.
    • +
    + +

    21 May 2017

    +

    KasparoVy updated:

    +
      +
    • Fixes a bug where only the fat roundstart disability could be selected.
    • +
    + +

    20 May 2017

    +

    FlattestGuitar updated:

    +
      +
    • Adds a jobban-checking verb to the OOC tab.
    • +
    +

    KasparoVy updated:

    +
      +
    • You can now set your character's auto-accent at character creation. The verb still exists in the OOC tab.
    • +
    +

    Kyep updated:

    +
      +
    • Antag roles now have playtime requirements.
    • +
    +

    Kyep: updated:

    +
      +
    • Updated CC map.
    • +
    +

    Xantholne updated:

    +
      +
    • The Coroner now has an actual job icon.
    • +
    + +

    19 May 2017

    +

    IK3I updated:

    +
      +
    • Empath stops telling you how much it hurts to not be human
    • +
    +

    MarsM0nd updated:

    +
      +
    • NanoUI map now shows the up-to-date map.
    • +
    +

    Purpose2 updated:

    +
      +
    • Coroner no longer alt title for MD
    • +
    • Adds Coroner job as its own job.
    • +
    • Adds a swanky new office for the Coroner.
    • +
    + +

    18 May 2017

    +

    FreeStylaLT updated:

    +
      +
    • Added a Newscaster to Brig Toilet.
    • +
    +

    Purpose2 updated:

    +
      +
    • Adds a subtle chat-window reminder for karma on Shuttle departure. Disable/enable via preferences tab.
    • +
    • Removes the ugly round-end karma popup.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Deaf people cannot hear tape recordings anymore
    • +
    + +

    17 May 2017

    +

    Fethas updated:

    +
      +
    • MORE GREY SPRITES!
    • +
    +

    FlattestGuitar updated:

    +
      +
    • You can now silence shoes just by using some duct tape on them! Shoe rags no longer exist.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Neuro-toxin bar drink weakens after 13 cycles as opposed to instantly
    • +
    +

    Purpose2 updated:

    +
      +
    • Makes the new posters actually spawnable.
    • +
    • Fixes far more spelling errors than there ever should have been on the posters.
    • +
    +

    Travelling Merchant updated:

    +
      +
    • Adds a hiss emote for Unathi.
    • +
    + +

    16 May 2017

    +

    FlattestGuitar updated:

    +
      +
    • Brig lockers now have radios and prisoner IDs. As per SOP!
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Fixed broken disposals in brig.
    • +
    • Returned missing Sergeant Araneus to HoS office.
    • +
    • Fixed missing floor tiles in the execution hallway in Brig.
    • +
    • Remapped the entire Brig.
    • +
    +

    Kyep updated:

    +
      +
    • changed security officer job slots from 5 to 7.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • You can now resist out of straightjackets
    • +
    • Straightjacketed people can be handcuffed
    • +
    + +

    15 May 2017

    +

    TullyBurnalot updated:

    +
      +
    • Disposal Bin Light now works with thrown items
    • +
    • Fixes typos with cowboy items
    • +
    + +

    13 May 2017

    +

    Fethas updated:

    +
      +
    • fixes a redundent add_cultist proc so cult memorize objectives works on new converts.
    • +
    • fixes an istype with IS_GAMEMODE_CULT
    • +
    • Narsie now will sometimes make a door a cult door..i thought i had that in the first time.
    • +
    • runed metal can now be only used on cult girders.
    • +
    +

    KasparoVy updated:

    +
      +
    • Fixes a sprite issue with the Unathi Dorsal Frill's webbing.
    • +
    + +

    12 May 2017

    +

    Fethas updated:

    +
      +
    • Makes thrall examine use MASKCOVERMOUTH and HIDEFACE flags
    • +
    • fixes hudsunglass goof with vox.
    • +
    +

    Xantholne updated:

    +
      +
    • Changes name from dark brown to brown for the default cowboy boots
    • +
    • Gives a hint that the cowboy shirts are meant to be clipped on to your uniform
    • +
    + +

    11 May 2017

    +

    Fethas updated:

    +
      +
    • Greybarber suit sprite.
    • +
    • Removes sec access from the paramedic
    • +
    +

    Fox McCloud updated:

    +
      +
    • can no longer make lethal medical patches with droppers
    • +
    • dripping reagents on someone with a dropper now incurs a 3 second delay like syringes
    • +
    + +

    09 May 2017

    +

    Fethas updated:

    +
      +
    • a ton of grey clothing sprites.
    • +
    + +

    08 May 2017

    +

    Purpose2 updated:

    +
      +
    • Adds a wire to the modular console on the bridge, fixing the Power Grid program.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Examine a reinforced wall for deconstruction and repair hints.
    • +
    + +

    07 May 2017

    +

    GunDOSMk1 updated:

    +
      +
    • Adds Unathi cobra hood
    • +
    +

    Purpose2 updated:

    +
      +
    • Fixes the broken wiring re-electrifying the bridge window.
    • +
    • Adds the missing scrubber in Genetics holding pen
    • +
    +

    Twinmold updated:

    +
      +
    • No longer able to put grabs into kitchen equipment (deep-fried grab).
    • +
    • No longer able to put grabs inside of display cases.
    • +
    + +

    06 May 2017

    +

    Allfd updated:

    +
      +
    • Thrown mobs will not step on broken glass while being thrown.
    • +
    +

    Fethas updated:

    +
      +
    • Fixes sacreficed your target not triggering the next objective.
    • +
    • YOU CAN NOW ONLY CONVERT HUMANS NOT MICE!
    • +
    • bloodspill tiles changed from base 100 (plus random number based on players) to 70.
    • +
    • Adds Tajaran veils as a loadout options
    • +
    • Racial loadout tab
    • +
    +

    LightFire69 updated:

    +
      +
    • Added a pretty plasmaman suit
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Removed Robocop, Paladin, NT Default as roundstart lawsets.
    • +
    + +

    05 May 2017

    +

    Fethas updated:

    +
      +
    • Magistrate, IAA, and BS will now spawn with the correct color dpet satchal and duffel
    • +
    + +

    01 May 2017

    +

    Fethas updated:

    +
      +
    • There will now be an visual indicator to annouce that an incomming shuttle is about yo wreck you.
    • +
    + +

    30 April 2017

    +

    scrubmcnoob updated:

    +
      +
    • Combat Shotguns now more expensive in cargo.
    • +
    • Shotgun ammo_boxes are now named and sprited as speedloaders that can speedload into a shotgun. Normal shotgun ammo boxes are just storage items for shells.
    • +
    • Adds in shotgun ammos readily available to be ordered from cargo in bulk and allows the ordering of Riot shotguns.
    • +
    • Adds in a Dragonsbreathe shotgun ammo box.
    • +
    • Tranq darts now have a sprite.
    • +
    + +

    29 April 2017

    +

    FalseIncarnate updated:

    +
      +
    • Popcorn jellybeans require jellybeans to make.
    • +
    • Gum is no longer invisible, but is still very chewy.
    • +
    +

    Phantasmic Dream Art, Fethas PR updated:

    +
      +
    • Updates the shadowling sprite. Sprite by Dreamy
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Examine a girder for (de)construction hints
    • +
    • Projectiles have a chance to pass through some girders
    • +
    • You can construct rough iron (false) walls with rods, wood (false) walls with wooden planks on a girder
    • +
    • Screwdriver a displaced girder to deconstruct it
    • +
    • Increased displaced girder health, decreased reinforced and cult girder health
    • +
    • False wall construction is no longer instant
    • +
    • Girder (de)construction messages should read better
    • +
    + +

    28 April 2017

    +

    Alffd updated:

    +
      +
    • Adds Paperwork the sloth to cargo.
    • +
    + +

    27 April 2017

    +

    Kyep updated:

    +
      +
    • Changed "suggested client version" from 510 to 511.
    • +
    + +

    26 April 2017

    +

    FalseIncarnate updated:

    +
      +
    • Glowshrooms (and their subtypes) can be mass-cleared by scythes just like vines.
    • +
    +

    pinatacolada updated:

    +
      +
    • dirty surgery environments get you nasty infections
    • +
    • ghetto surgery internal organ disinfection with alcohol
    • +
    • dead limb revival surgery step
    • +
    + +

    25 April 2017

    +

    Flattest updated:

    +
      +
    • Animated progress bars!
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Runed girders have a clearer and bigger icon
    • +
    • Girder subtypes are properly named, "reinforced girder" and not "reinforced"
    • +
    • Summoned cult walls do not drop a girder or runed metal to prevent runed metal farming
    • +
    • Cult walls no longer have blood or human remains in them
    • +
    • Harvesters can smash more things and can summon cult walls and floors
    • +
    • Fixed not being able to make a cult wall with runed metal + runed girder
    • +
    • Runed girders will need to be deconstructed with a welder (or plasma cutter or jackhammer) instead of a wrench. Cultists can hit them with their tomes to instantly demolish them.
    • +
    + +

    24 April 2017

    +

    Flattest updated:

    +
      +
    • Sleepers spit out their victims when deconstructed now.
    • +
    + +

    23 April 2017

    +

    Citinited updated:

    +
      +
    • You can now fully insulate reinforced floors using a sheet of plasteel.
    • +
    • Certain floors in the turbine, incinerator, and toxins are now thermally insulated.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Reverts Norgad's east maintenance overhaul
    • +
    +

    IK3I updated:

    +
      +
    • flipping aliums now have a cooldown
    • +
    • Aliums have some more sounds to play with
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • You can no longer use space pod verbs when restrained, dead, or otherwise incapacitated.
    • +
    + +

    21 April 2017

    +

    Anticept updated:

    +
      +
    • Alternate Job Preference now defaults to "Return to Lobby if Preferences Unavailable". Only affects new players.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Tesla can now damage blobs
    • +
    • Tesla causes machinery to overload and explode when zapping it
    • +
    • Tesla dissipates energy more slowly and is easier to charge up (making it more deadly when released)
    • +
    • Tesla will now dust mobs it bumps into
    • +
    • Tesla coils now have wires that can be pulsed to generate a tesla zap
    • +
    +

    Lady-Luck updated:

    +
      +
    • Makes several balance adjustments to existing syndicate bundles, generally making them more worthwhile.
    • +
    • Adds an Allies Cocktail object for the Bond bundle.
    • +
    • Adds the 'gadgets' syndicate bundle.
    • +
    • Removes the 'lordsingulo' and 'murder' syndicate bundles.
    • +
    +

    Spacemanspark updated:

    +
      +
    • Permits hoodies to carry flashlights.
    • +
    +

    Twinmold93 updated:

    +
      +
    • Adds attack options for deep fryers, grills, and ovens. Those breaking into the kitchen beware.
    • +
    +

    alexkar598 updated:

    +
      +
    • you can now click on things underwater
    • +
    +

    monster860 updated:

    +
      +
    • Adds an in-game way of viewing poll results
    • +
    • The player poll window automatically pops up if there is an active poll you haven't voted on.
    • +
    • Adds an browser popup for creating new polls
    • +
    • Your account needs to be at least 30 days old in order to vote on polls
    • +
    + +

    19 April 2017

    +

    IK3I updated:

    +
      +
    • Chaplain now spawns with his bible
    • +
    +

    Xantholne updated:

    +
      +
    • You now correctly spawn with the CMO Skirt if selected in loadout menu
    • +
    + +

    17 April 2017

    +

    KasparoVy updated:

    +
      +
    • The God-emperor of Mankind diskette's UI works again.
    • +
    • DNA UI injectors will now immediately update a person's eye colour.
    • +
    +

    Krausus updated:

    +
      +
    • You can no longer squeeze non-match objects into matchboxes.
    • +
    + +

    16 April 2017

    +

    FalseIncarnate updated:

    +
      +
    • Potential collaborators for traitors now are informed they are potentially a collaborator for a potential increase in them potentially helping the traitors potentially do potentially bad things. Potentially.
    • +
    • Potential collaborators are given a single code word and response set so they can discretely find out that their best friend is a filthy traitor.
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds secondary (facial) hair colours to the genome (UI). There are 6 new blocks.
    • +
    • Characters with secondary (facial) hair colours won't find they've turned black after cloning anymore.
    • +
    +

    Kyep updated:

    +
      +
    • Plasma dust no longer creates plasma gas on objects or turfs during reactions.
    • +
    +

    Twinmold93 updated:

    +
      +
    • Missing sprite for pod pilot Drask now added.
    • +
    +

    Xantholne updated:

    +
      +
    • Adds Medical Beret available via loadout menu
    • +
    +

    ZomgPonies updated:

    +
      +
    • Fixes Superhero ID cards
    • +
    • Fixes Griffin missing his Freedom Implant
    • +
    • Fixes ElectroNegmatic's Ability not working at all.
    • +
    • Changes LightnIan's ability into a non-damaging stun lasting 2 ticks, with the amount of people affected depending on how long you hold the power in for.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • You can now create heat-proof glass airlocks by using a sheet of reinforced glass on the assembly during construction. Regular glass airlocks just require a sheet of glass.
    • +
    + +

    11 April 2017

    +

    FalseIncarnate updated:

    +
      +
    • Damage done to the shuttle engines by a shadowling's "Extend Shuttle" ability now prevent the shuttle from being recalled to CentComm.
    • +
    + +

    09 April 2017

    +

    Fox McCloud updated:

    +
      +
    • abductor glands now act as actual hearts; removing them induces heart failure
    • +
    • plasma gland no longer gibs you, but makes you vomit plasma instead
    • +
    • bodysnatcher gland no longer gibs you, but will deal brute damage instead
    • +
    • bloody gland will now drain blood instead of dealing brute damage
    • +
    • species change gland will now change your species until the gland is removed
    • +
    • adjusted the origin tech on a few gland
    • +
    • heart attacks will once again paralyse you and do slightly more brute damage
    • +
    • body snatch clones look more like their originator
    • +
    • Abductors can no longer use guns (minus their own alien energy gun)
    • +
    • Sending someone with an abductor teleport via the console will stun them for 3 cycles (doesn't apply with the advanced camera console)
    • +
    • Abductors can now purchase additional abductor vests
    • +
    • Abductors can lock/unlock vests
    • +
    • Purchasing supplies from the abductor console will no longer increase the amount of experiments you must do
    • +
    • Wonderprods will not induce sleep in those who are stunned OR sleeping
    • +
    • altered the origin tech of abductor tools
    • +
    • Can make abductor surgery tables from regular tables by adding silver sheets to an abductor table frame
    • +
    • Added a bunch more abductee objectives
    • +
    • abductors no long scream like girls
    • +
    • High capacity cells have 10,000 charge instead of 15,000
    • +
    • Mech equipment power costs minorly adjusted
    • +
    • APCs charge a bit faster
    • +
    • EMPs less effective against pods and mechs
    • +
    • Fixes not being able to recharge modular laptops/tablets
    • +
    +

    Purpose2 updated:

    +
      +
    • Welders must now been fueled and active to cut lattices.
    • +
    + +

    06 April 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes autopsy report printing; print reports by clicking the device itself
    • +
    +

    davipatury updated:

    +
      +
    • Rapid Cable Layer now have an autolathe design.
    • +
    + +

    05 April 2017

    +

    KasparoVy updated:

    +
      +
    • Adds a Tajaran facial hair style.
    • +
    • Adds a few new frill styles for Unathi.
    • +
    • Adds some new horn styles for Unathi.
    • +
    • Adds a couple new facial hair styles for Vulpkanin.
    • +
    • Adds a few new hair styles for Vulpkanin.
    • +
    • Updates Vulpkanin Adhara & Kajam hairstyles.
    • +
    +

    Purpose2 updated:

    +
      +
    • Can now take photos of the Blueprints to count as a completed objective.
    • +
    • Cryostorage console now stores the Null Rod & all variations.
    • +
    • Mime mech is now 'Reticence' as it should be
    • +
    • Fixes missing cult's Berserker Robe sprite.
    • +
    • Cryostorage console no longer stores hundreds of bomber jackets, and now stores hardsuits
    • +
    • Cryostorage console now catches and stores most unique objective items.
    • +
    • Corrects some typos and grammar.
    • +
    • You can now light cigarettes with Wands of Fireball, at the cost of your eyebrows.
    • +
    +

    Twinmold93 updated:

    +
      +
    • Buying poison pen will actually give you the poison pen now.
    • +
    + +

    04 April 2017

    +

    FalseIncarnate updated:

    +
      +
    • Adds FullofSkittles's custom pAI sprites. Thanks FoS!
    • +
    • Custom sprites for cyborgs, AI, AI holograms, and pAI units no longer are restricted to a single name. Get your money's worth by using that borg sprite regardless of your version number!
    • +
    + +

    03 April 2017

    +

    Kyep updated:

    +
      +
    • Ghosts manifested by cultists are no longer invincible, and an exploit allowing them to be made permanent has been fixed.
    • +
    + +

    02 April 2017

    +

    KasparoVy updated:

    +
      +
    • Nuclear Operatives/ERT Members/Abductors will no longer spawn in with genetic quirks.
    • +
    • Thrown objects that cross a tile with non-full windows will no longer hit the window even if it isn't visually obstructing the path.
    • +
    • Shooting guns (i.e. tasers) in the above circumstances means that the taser shots won't be blocked by windows that aren't visually obstructing the path.
    • +
    +

    Kyep updated:

    +
      +
    • Adjusted Black Market Packers away mission. It now has some danger to it (carp), some more interesting stuff to find (syndi lab) and a challenge (fix the ship powergrid).
    • +
    • Slight adjustment to word lists based on our rules.
    • +
    • Removed thunderdome armor from centcom away mission.
    • +
    • Cultists now get a new sacrifice target when the current one cryos.
    • +
    + +

    31 March 2017

    +

    Krausus updated:

    +
      +
    • Blobs are no longer nearly guaranteed to immediately tear themselves apart upon spawning.
    • +
    +

    Kyep updated:

    +
      +
    • Access to jobs is now based solely on Playtime, NOT days since BYOND account was registered.
    • +
    + +

    30 March 2017

    +

    Crazylemon64 updated:

    +
      +
    • Cult shifter should work now
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Strange Reagent only deals clone damage on a successful revival.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Non-designated drinks now mix their colors from the reagents within them
    • +
    • Autopsies can now be performed without needing to cut someone open
    • +
    • Adds modular receiver to the maintenance loot system
    • +
    • Receivers can now be produced in hacked autolathes; no longer available in R&D protolathes.
    • +
    • removes the random "scary" sounds that play when walking about
    • +
    +

    KasparoVy updated:

    +
      +
    • You can now slam drinks/bottles/flasks by click-dragging them onto yourself while it's in your active hand.
    • +
    +

    Kyep updated:

    +
      +
    • The moonoutpost19 away mission should now be finishable, and more enjoyable to attempt.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Emagging a closed firelock does not permanently break it anymore, only opens it.
    • +
    • Emagged windoors should be able to be screwdriver+crowbar'd again.
    • +
    • Powered grilles now have a chance to zap you when you throw an object at them.
    • +
    + +

    29 March 2017

    +

    Purpose2 updated:

    +
      +
    • 'Roundstart malfunctioning' cameras now appropriately have their wires cut.
    • +
    • AI core camera can no longer be a 'roundstart malfunctioning' camera on both Box & Meta Stations.
    • +
    + +

    28 March 2017

    +

    KasparoVy updated:

    +
      +
    • Skrell can now choose undergarments (undershirts, underpants, socks) at character creation and dressers.
    • +
    • Vox are now 20% less resilient to brute damage due to their light, porous and flexible skeletons.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Quick-replacing non-wooden tiles will only work with a crowbar in inactive hand instead of any item
    • +
    + +

    27 March 2017

    +

    Crazylemon64 updated:

    +
      +
    • Away mission power works now.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes some stacks not wanting to stack with similar stacks (such as space cash)
    • +
    +

    KasparoVy updated:

    +
      +
    • Skrell have been greyscaled and darkened. You can now colour your Skrell characters as you please.
    • +
    • Kidan can now select from multiple different antennae head-accessory styles.
    • +
    • Kidan male/female bodies now have differences, namely mandible/torso structure.
    • +
    • Skrell flesh is now blue (like their blood), though you'll only ever see this under certain circumstances if they're dismembered.
    • +
    +

    Kyep updated:

    +
      +
    • The invisible floors in the engineering area of the UO45 away mission are no longer invisible. Previously, you had to crowbar up a seemingly invisible floor to make a wire appear.
    • +
    • Fixed several Terror Spider bugs. Including the notorious 'spiders can get stuck in vents' bug, the 'spiders ignore mechs' bug, and the 'prince is cheesable' bug.
    • +
    • Adjusted White & Empress spider abilities - webs spun by white spiders are now infectious.
    • +
    +

    Purpose2 updated:

    +
      +
    • Adds the Psychiatrist's bed/sofa for 5 metal.
    • +
    • Wooden chairs broken by animals no longer drop metal.
    • +
    • Abductors no longer have Syndicate ties.
    • +
    • Fixes material loss on some chair/bed/stool deconstruction types.
    • +
    • IPCs can no longer be DNA Scrambled.
    • +
    • Health analysers clunk again when upgraded
    • +
    • Resolves further grammatical/typo issues.
    • +
    + +

    26 March 2017

    +

    FalseIncarnate updated:

    +
      +
    • Re-adds the telescopic scythe, the pinnacle of covert reaping technologies. Currently admin-spawn only, for use in the most dire of harvest times.
    • +
    • Scythes (normal and telescopic) should once again clear swathes through all but the hardiest of vines when in proper reaping configurations, and heavily damage those they don't outright destroy.
    • +
    • Ankle-high piles of dirt will no longer prevent you from stepping over them.
    • +
    +

    KasparoVy updated:

    +
      +
    • You can no longer climb through interdimensional rifts into cryopods.
    • +
    • Revenants can see properly in the dark again.
    • +
    +

    Kyep updated:

    +
      +
    • Adjusted Beach awaymission so it now includes deadly (but rewarding) pirate area.
    • +
    • Adjusted the centcom away mission to make it viable.
    • +
    • Deleted 'listening post' away mission.
    • +
    +

    Purpose2 updated:

    +
      +
    • QoL: Newly built APCs come unlocked.
    • +
    • QoL: Chief Engineer's locker has more building permits.
    • +
    • Assorted grammatical fixes.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Splints will display the proper sentence when applying them
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Metastation: Fixed Gateway airlock access and Command Hallway vendor areas, virology smartfridge is correctly stocked, mass drivers now have tiny fans, Sec spacepod keys work on the Sec pod, Airlocks should have the correct icon, Firelocks/Windoors/Shutters should be layered correctly, Shutters should be facing the right direction
    • +
    • Drone fabricator consoles search for a fabricator in the same area instead of 3x3 range.
    • +
    + +

    25 March 2017

    +

    Crazylemon64 updated:

    +
      +
    • All pens are now certified crayon-wax free!
    • +
    +

    Kyep updated:

    +
      +
    • Pipes in the Wizard Academy have been banished back under the carpet, where they belong.
    • +
    + +

    24 March 2017

    +

    KasparoVy updated:

    +
      +
    • Red wire-cutters and red crowbars now appear correctly in-hands again. imgadd: The medical wrench and all the brass tools (screwdriver, crowbar, wrench, wire-cutters, welder) now have in-hand sprites of their own.
    • +
    • Adds TG's inhand icons for screwdrivers, crowbars, wrenches, wire-cutters and welders.
    • +
    • Slime People can wear underwear, undershirts and socks.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • IV Drips are no longer dense objects, you can walk over them.
    • +
    • You can change gold and silver tiles into fancy versions by using them in hand.
    • +
    + +

    23 March 2017

    +

    FalseIncarnate updated:

    +
      +
    • Fish breeding has been tweaked to support fish refusing to cross-breed and improved egg chances with same-species parents.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Floors are now fully properly cleaned with mops and soap
    • +
    • Adds in emergency welding tool, fork, trays, drinking glasses, shot glasses, shakers, butcher cleavers, and riot darts to the autolathe
    • +
    • Adds all basic stock parts to the autolathe
    • +
    • re-arranges the autolathe menu to be more logical
    • +
    • light bulbs no longer require metal to produce
    • +
    • Incision management system can now cauterize
    • +
    +

    KasparoVy updated:

    +
      +
    • Unathi Security, Medical, Engineering and Syndicate side-facing hardsuit sprites have undergone weight reduction.
    • +
    +

    Kyep updated:

    +
      +
    • Chaplain's armor is no longer riot-grade. In addition, their nullrods do less damage.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Conveyor switches can now set to left-only direction toggling.
    • +
    +

    Norgad updated:

    +
      +
    • Maintenance areas near arrivals, science, and the bar have been revamped.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Station lighting has less lighting power, this is not noticeable apart from maint and 1 bulb rooms being a bit darker.
    • +
    • Tweaked the potency scaling for glowshroom/glowberry light; high-potency plants no longer light up a huge area, but are slightly brighter.
    • +
    • Added Shadowshrooms as a glowshroom mutation. They do exactly what you'd expect.
    • +
    + +

    22 March 2017

    +

    Crazylemon64 updated:

    +
      +
    • Rod form is now at half speed, and has a warning sound.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • When a person's limb is dying, it will no longer notify the whole server of the ordeal
    • +
    • Welding tools no longer tell you about their span classes
    • +
    +

    KasparoVy updated:

    +
      +
    • Deconstructing beds now yields the same amount of metal as was used to make the bed.
    • +
    • The PA console will no longer appear as though it is fully constructed at the start of the round.
    • +
    • Ore Redemption Machines no longer eat IDs when deconstructed.
    • +
    • Ore Redemption Machines and Mining Equipment Vendors now spit out whatever IDs were in them when they lose power.
    • +
    +

    Krausus updated:

    +
      +
    • Personal crafting is now usable again for those with an Internet Explorer version below 11.
    • +
    + +

    21 March 2017

    +

    Crazylemon64 updated:

    +
      +
    • Strange reagent now has a volume floor requirement to activate, induces clone damage, and may cause further trouble...
    • +
    +

    KasparoVy updated:

    +
      +
    • No-one escapes nuclear hellfire.
    • +
    • Secure fridges/freezers are now lead-lined and have thus become nuke resistant.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Baseball bats added to the game, are craftable from 5 wood planks.
    • +
    • Baseball burgers can be made with a baseball bat and a bun, either microwaved or table-crafted.
    • +
    + +

    20 March 2017

    +

    Jovaniph updated:

    +
      +
    • Tajaran EVA Suit Sprites
    • +
    +

    KasparoVy updated:

    +
      +
    • Gloves can be snipped again.
    • +
    +

    Purpose2 updated:

    +
      +
    • Fixes assorted wording / capitalisation / grammatical problems.
    • +
    • Fixes the exploit to produce infinite cable coil from airlocks.
    • +
    +

    Tayyyyyyy updated:

    +
      +
    • Added GPS devices to pod pilot and mechanic's offices
    • +
    + +

    19 March 2017

    +

    Jovaniph updated:

    +
      +
    • Voxes can now wear soft caps.
    • +
    +

    Krausus updated:

    +
      +
    • Pest spray bottles are no longer invisible.
    • +
    +

    Kyep updated:

    +
      +
    • Wood doors in wild west map no longer constantly open/close
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Shipping errors can sometimes cause the supply shuttle to receive an extra crate when ordering supplies.
    • +
    • Added dog beds! Can be made with 10 wood planks and deconstructed with a wrench. Ian's Bed added to Cyberiad and Metastation.
    • +
    + +

    18 March 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes abductor surgeries
    • +
    +

    Jovaniph updated:

    +
      +
    • Unathi EVA suits
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Shades now have directional sprites.
    • +
    • Attacking with glass shards now hurts your hand if not wearing gloves. Does not affect robotic hands though.
    • +
    + +

    16 March 2017

    +

    FlattestGeetar updated:

    +
      +
    • Workboots are now in the loadout system.
    • +
    • Ports winter boots from /tg/
    • +
    +

    Jovaniph updated:

    +
      +
    • New sounds to Firelocks and Airlock External
    • +
    • Door closing sound to Airlocks - from yogstation
    • +
    +

    Markolie updated:

    +
      +
    • Fixed revenant night vision not working.
    • +
    • Fixed the "X attacked Y" message showing up when welding vents.
    • +
    • Fixed the follow button on the cell door timer radio message not working.
    • +
    • Fixed the Jaws of Life being unable to force unpowered doors.
    • +
    • Fixed a number of preference options being unavailable when modifying preferences while observing.
    • +
    • Fixed an issue where deleting security records wouldn't clear that player's wanted status properly.
    • +
    • Fixed the cult "first meal" sacrifice objective not counting properly. Also clarified what this objective actually entailed.
    • +
    • Fixed IPC's ocassionally being selected as a changeling "escape with X identity" target.
    • +
    • The character records and disabilities menus in the preferences menu no longer uses the plain white background, but uses the better looking blue layout instead.
    • +
    + +

    15 March 2017

    +

    uraniummeltdown updated:

    +
      +
    • Plastic flaps can be deconstructed with tools and constructed using 5 sheets of plastic.
    • +
    • You can now damage grilles by throwing things at them.
    • +
    • You can rebuild broken grilles by using a metal rod on them.
    • +
    • Metal rods maximum amount reduced from 60 to 50.
    • +
    + +

    14 March 2017

    +

    uraniummeltdown updated:

    +
      +
    • Strong supply talismans can now summon 5 sheets of runed metal.
    • +
    + +

    13 March 2017

    +

    Kyep updated:

    +
      +
    • Syndicate mobs in the Wild West are no longer so stupid that they trip over, and die to, their own mines. This also means that they won't set their own buildings on fire anymore.
    • +
    • Phazons' phase ability now works again.
    • +
    • Phazons' toxin injector melee damage type (a weak melee attack) now works again.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Clicking on a tile with another tile and a crowbar or screwdriver in hand directly replaces the tile.
    • +
    + +

    12 March 2017

    +

    Crazylemon64 updated:

    +
      +
    • Kudzu should now be less of (but still) a station-destroying force of nature.
    • +
    • Bluespace kudzu now only pierces a single layer of walls before losing its "charge".
    • +
    • Aggressive spread now does not bust rwalls, but does attack obstructing objects in its path.
    • +
    • Kudzu now only spreads on space turfs when it has specific mutations to do so.
    • +
    • Kudzu events should be more interesting on their own.
    • +
    +

    Jovaniph updated:

    +
      +
    • Adds Vulpkanin EVA suit sprite
    • +
    +

    Kyep updated:

    +
      +
    • Adjusted Wizard Academy to make it both more lethal, and more rewarding.
    • +
    +

    Markolie updated:

    +
      +
    • The system for picking ghosts to inhabit cultist slaughter demons now shows a confirmation prompt like most other role checks.
    • +
    • Fixed an issue where you could join as a cultist slaughter demon despite having antagHUD enabled.
    • +
    • Fixed an issue where it was possible to weld statues without any fuel.
    • +
    • It is no longer possible to spam the firelock force message.
    • +
    +

    Twinmold93 updated:

    +
      +
    • Employment record laptop to Head of Personnel's Office. Moves package wrap that was there to meeting room to be paired with the hand labeler there.
    • +
    + +

    11 March 2017

    +

    Developed by XDTM, ported by davipatury updated:

    +
      +
    • Hallucinations have been modified to increase the creepiness factor and reduce the boring factor.
    • +
    • Added some new hallucinations.
    • +
    • Fixed a bug where the singularity hallucination was stunning for longer than intended and leaving the fake HUD crit icon permanently.
    • +
    +

    Flatty Patty updated:

    +
      +
    • all the tools have icons again
    • +
    +

    FlattyPatty updated:

    +
      +
    • Improved Nanotrasen click manufacturing procedures now allow the flashlights to make that classic clicking sound you know and love.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Buckshot now does a max of 70 damage, down from 90
    • +
    +

    KasparoVy updated:

    +
      +
    • Fixes a bug with certain tail markings rendering when they shouldn't.
    • +
    +

    Markolie updated:

    +
      +
    • Firelocks forced by AI's, cyborgs at range or admin ghosts will now autoclose if there's still an atmospherics alarm present.
    • +
    • Regular (non-heavy) firelocks will now properly respond to explosions (100% chance of being destroyed at severity 1 explosions and 50% at severity 2). Heavy firelocks are still only destroyed in severity 1 explosions.
    • +
    • Added a visible message to forcing airlocks with the Jaws of Life.
    • +
    +

    davipatury updated:

    +
      +
    • Ported Modular Computers from /tg/.
    • +
    • Ported Rapid Cable Layer from /vg/.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • EVA has 2 more EVA Suits
    • +
    • Removed Vox-only EVA suits (the grey ones in EVA)
    • +
    • Vox can now wear EVA suits
    • +
    + +

    10 March 2017

    +

    Jovaniph updated:

    +
      +
    • Recitence no longer makes a sound when turning
    • +
    +

    Markolie updated:

    +
      +
    • The DNA Vault station goal will now be marked as completed properly.
    • +
    • Multi-tile airlocks will now change their direction properly.
    • +
    • The atmos skirt loadout item will now be equipped properly on round start.
    • +
    • Fixes the inhand disabler sprite pointing the wrong way in some directions.
    • +
    • The Janicart will no longer act as a jetpack.
    • +
    • You can now resist out of a borer's control again.
    • +
    • Fixes the general antag ban not working on certain conversion antagonists.
    • +
    • Fixes removing the trunk from underneath a chute/bin causing all sorts of issues.
    • +
    • Fixes alt titles not showing up on ID's.
    • +
    • Mineral doors no longer block atmos (like they're supposed to).
    • +
    • Fixes the cortical borer hivemind talk not working.
    • +
    • Fixes detomatix cartridges not working *from* PDA's with an uplink (it now no longer *on* a PDA with an uplink to prevent blowing up fellow traitors).
    • +
    • Fixes NODROP interaction with secure closets.
    • +
    • Fixes some stray fruit at the Syndicate base on Z2.
    • +
    • Fixes an incorrect camera network in the courtroom.
    • +
    • Fixes an issue where AI's would go blind upon travelling into space.
    • +
    • The cortical borer hivemind talk key is now "bo".
    • +
    • Attempting to blow up an undetonatable PDA (such as the captain's) will now show a warning message. It will also no longer use up a charge.
    • +
    • Animals can now open mineral doors and mineral doors will no longer be closable if there's a mob inside.
    • +
    • Matter grippers can now carry firelock electronics as well as bluespace crystals (for construction).
    • +
    • Removes the pipe fitting on the table from atmospherics as it was broken.
    • +
    + +

    09 March 2017

    +

    Crazylemon64 updated:

    +
      +
    • Adds an "ethereal beacon", an admin-only structure usable to attract ghosts to an area.
    • +
    • Adds several transformer machines to streamline the ghost-to-PC process.
    • +
    +

    LordJike updated:

    +
      +
    • Space Fries are now made by deep-frying potato wedges instead of processing them.
    • +
    • Introducing carrots inside the food processor gives you carrot wedges now.
    • +
    • Now you can make carrot fries by deep-frying carrot wedges instead of formerly processing the whole carrots.
    • +
    +

    Markolie updated:

    +
      +
    • Tools now have a "usesound" and "toolspeed" variable which allows different tool (levels) to have different sounds and speeds.
    • +
    • Robots spawn with tools that are twice as fast as regular tools.
    • +
    • Abductor agents now spawn with a toolbelt with specialized abductor tools that are very fast.
    • +
    • Abductor surgery tools are now much faster.
    • +
    • Abductor (surgery) tools can now be constructed in R&D with a sufficiently high "abductor" research level.
    • +
    • The abductor multitool will now display what each wire does.
    • +
    • Admin ghosts can now interact with wires and see what each wire does.
    • +
    • Adds a set of unique tools for the Chief Engineer that he is given in a unique toolbelt at roundstart. These tools are faster and can be created in R&D with a sufficiently high R&D level.
    • +
    • The AI detector has been refactored to have much more robust AI tracking.
    • +
    + +

    08 March 2017

    +

    Alffd updated:

    +
      +
    • Farting on a bible now puts you at the mercy of the gods.
    • +
    • Removed automatic biblefarting gibbing.
    • +
    +

    FlaaaaaattestGuitar updated:

    +
      +
    • Magistrate now starts their shift with a pair of white gloves as well as Bridge and Meeting Room access.
    • +
    +

    Fox McCloud updated:

    +
      +
    • money is now far easier to use, and distribute in amounts you would like
    • +
    +

    Kyep updated:

    +
      +
    • Changed event probabilities, aiming for a more fun late game. In general, events that do very little (e.g: meaty ores, rogue drones) are less likely. Events that will keep people on their toes (e.g: anomalies) are more likely. Events that might cause people to observe rather than joining the round (e.g: Xenos) are less likely.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Wizard Hardsuit helmet and suit now have inhand sprites
    • +
    + +

    07 March 2017

    +

    Crazylemon64 updated:

    +
      +
    • IPCs now come with a power cord implant to use to recharge from APCs.
    • +
    • IPCs can now be genderless.
    • +
    +

    Kyep updated:

    +
      +
    • Deleted 'challenge' away mission.
    • +
    +

    MarsM0nd updated:

    +
      +
    • Cultists get shoes on usage of the armor talisman.
    • +
    • Cultists only get equipment if they have the slot for it free, weapons are always spawned.
    • +
    • The tome does a more fitting description of the talisman of armor.
    • +
    + +

    05 March 2017

    +

    Kyep updated:

    +
      +
    • Added Poison Pen, a stealthy way of applying a contact-based poison to paper. Available to Syndicate HoPs, QMs, and Cargo Techs.
    • +
    • Antags whose objectives are manually announced by an admin, or altered automatically as a result of their target cryoing, will now hear a warning sound. The sound is the same as the 'crew transfer vote called' sound. Additionally, the text notice for changed objectives is more obvious.
    • +
    +

    MarsM0nd updated:

    +
      +
    • The grey satchel uses now the correct sprite instead of the leather one.
    • +
    + +

    04 March 2017

    +

    Markolie updated:

    +
      +
    • Ghosts can now interact with ore dispensers, mining equipment vendors and laptop vendors.
    • +
    • Admins can now interact with crates, closets, false walls and conveyor switches if they have advanced interaction enabled.
    • +
    +

    davipatury updated:

    +
      +
    • Newscaster now uses Nano-UI.
    • +
    • Tank dispenser now uses Nano-UI.
    • +
    • Passive gate, pump and volume pump now uses Nano-UI.
    • +
    • Atmospherics filter and mixer now uses Nano-UI.
    • +
    • Wires now uses Nano-UI.
    • +
    + +

    03 March 2017

    +

    FlauntestGuitar updated:

    +
      +
    • You will now be prompted on a karma purchase to confirm that you clicked what you wanted to click
    • +
    +

    uraniummeltdown updated:

    +
      +
    • You can now change the input/output directons for Ore Redemption Machines by using a multitool on them with the panel open.
    • +
    • Bluespace RPED beams have a new sprite
    • +
    + +

    01 March 2017

    +

    Crazylemon64 updated:

    +
      +
    • Kudzu vines now can yield materials if carefully tended to
    • +
    +

    Fethas updated:

    +
      +
    • 2 second cooldown on the rest verb. You are not Neo, knock it off.
    • +
    • StopResting and StartResting Procs are not on the rest verb.
    • +
    • Various metastation fixes.
    • +
    +

    KasparoVy updated:

    +
      +
    • Plasmaman multiverse sword copies are now properly equipped (suit, helmet, internals, etc.)
    • +
    • Vox multiverse sword copies are now peoperly equipped (internals).
    • +
    +

    Kyep updated:

    +
      +
    • Fixed several Terror Spider things that should not be possible, like recharging wireless guns, the 'evil-looking spiderlings' instant meta, and spiderlings spacing themselves.
    • +
    • Several Terror Spider balance and fun tweaks, such as giving the Prince of Terror a new webbing ability, and ensuring queens/mothers can break open vents, so they cannot be completely shut out late-round.
    • +
    +

    Purpose2 updated:

    +
      +
    • Enables Cargo to order Wood planks
    • +
    + +

    28 February 2017

    +

    KasparoVy updated:

    +
      +
    • Plasmaman suits will now only auto-extinguish if you're actually on fire (and not just taking a shower).
    • +
    + +

    27 February 2017

    +

    uraniummeltdown updated:

    +
      +
    • Mineral statues are here! Use 5 sheets of any mineral including sandstone to make one. Be careful around plasma and uranium statues!
    • +
    • The mime's office now comes with a statue too.
    • +
    • Updated plasma, uranium and diamond floor sprites to TG's newer ones.
    • +
    + +

    26 February 2017

    +

    Crazylemon64 updated:

    +
      +
    • Immovable rod events now vanish after going through the station once
    • +
    • Firelocks can now be operated by AIs again
    • +
    • Barbers and captains get the right stuff now
    • +
    • It's now possible to have random floors or walls when mapping
    • +
    +

    KasparoVy updated:

    +
      +
    • Fixes a bug where you could get a part of a rigsuit stuck to your hand by deploying it twice.
    • +
    • Improves the readability of some rigsuit verbs.
    • +
    +

    Kyep updated:

    +
      +
    • players will no longer spawn with loadout items their job has no access to.
    • +
    • AI & Borg upload consoles now have to be on the station zlevel to work.
    • +
    +

    davipatury updated:

    +
      +
    • ATM now uses Nano-UI.
    • +
    + +

    25 February 2017

    +

    Crazylemon64 updated:

    +
      +
    • Telecomms monitor is now infused with fastitude
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Escape has been re-bushed.
    • +
    +

    KasparoVy updated:

    +
      +
    • Reagent plasma has a weak healing effect on Plasmamen when injected and will not poison them.
    • +
    • Reagent oxygen is as toxic to Vox as reagent plasma is to just about anyone.
    • +
    • Plasmamen now join the shift with 2 suit auto-extinguisher refill cartridges which, individually, will fully refill an empty Plasmaman suit's autoextinguisherl.
    • +
    • Plasmaman suits now auto-extinguish and will be able to do so 5 times before they can be refilled by a cartridge.
    • +
    • Plasmamen no longer burn in a vacuum or in plasma-pure environments.
    • +
    +

    davipatury updated:

    +
      +
    • Security Records now uses Nano-UI.
    • +
    + +

    24 February 2017

    +

    FalseIncarnate updated:

    +
      +
    • Corn and bananas can be properly deepfried into their special results again.
    • +
    • Rice can be properly ground into a reagent again.
    • +
    • Hydroponics trays once again are equipped with Bee-proof lids to keep unwanted pollination to a minimum. This only works if you actually toggle the lid closed though!
    • +
    • Plants age slightly slower, so your space farming should no longer feel like it outpaces a meth'd up blue hedgehog in sneakers.
    • +
    +

    Kyep updated:

    +
      +
    • Fixes blob spawns prompting players twice.
    • +
    +

    Markolie updated:

    +
      +
    • Mining pod weapons are once again functional. Compared to regular kinetic accelerators, the weak projectile has one additional range (3 --> 4). The regular projectile's damage is increased (40 --> 50) and deals more damage in pressurized environments (50% instead of 25%). The enhanced projectile is able to fire its kinetic projectile AoE against turfs and mobs.
    • +
    • Fixed an issue where it was impossible to log out from fax machines.
    • +
    • It is no longer possible to steal ID cards from identification computers/fax machine using telekinesis at range.
    • +
    • The follow link on death alarms now works.
    • +
    • Fixes an exploit where players could use the ambulance trolley to teleport.
    • +
    • The chef now properly shows a chef hat on character preview.
    • +
    • The nuclear ops game mode will no longer always result in a major crew victory.
    • +
    • Players with their face covered will no longer show their flavor text upon examine.
    • +
    • Fax machines now have an "Eject ID card" verb so you can remove the inserted ID when it is depowered.
    • +
    • Firelocks are now more lethal.
    • +
    • Firelocks now crush players standing inside them when they finish closing.
    • +
    • Firelocks can no longer be instantly opened by hand: it requires thirty seconds and will autoclose in five seconds if there is still an atmospherics alert present in the area. They can no longer be closed by hand. Heavy firelocks can not be forced by hand.
    • +
    • Atmospherics technicians can once again remotely modify all settings on air alarms through the central atmospherics console.
    • +
    +

    Purpose2 updated:

    +
      +
    • Captain's crown is now part of the random hats crate, and no longer spawns in their locker.
    • +
    +

    Twinmold93 updated:

    +
      +
    • Ability to label bloodpacks with a pen, so you can now label a bloodpack from donations without a handlabeler.
    • +
    • Bloodpacks will now change name to say if they are empty or not.
    • +
    +

    davipatury updated:

    +
      +
    • EFTPOS now uses Nano-UI.
    • +
    • Medical Records now uses Nano-UI.
    • +
    • Employment Records now uses Nano-UI.
    • +
    + +

    23 February 2017

    +

    Krausus updated:

    +
      +
    • Ghost candidate alert boxes ("Do you want to play as a thing?") will now have "No" as the leftmost, default option, which you will accidentally pick when it pops up while you're trying to type, but at least you won't be stuck as the thing when you didn't actually want to be that thing.
    • +
    +

    Markolie updated:

    +
      +
    • The meteor shield satellite station goal coverage goal has been increased tenfold.
    • +
    + +

    22 February 2017

    +

    KasparoVy updated:

    +
      +
    • You can now toggle on/off the gladiator helmet's face-shield with an action button. This is totally cosmetic. imgadd: Adds a bunch of new helmet sprites for Vox.
    • +
    • Slightly adjusts the Vox knight armour sprites (not the Templar armour) to look nicer with the new helmets.
    • +
    • The Admin 'Select Equipment' debug verb now appropriately equips Armalis when the 'Vox' option is selected.
    • +
    + +

    21 February 2017

    +

    Crazylemon64 updated:

    +
      +
    • Autolathes can be hacked again
    • +
    +

    KasparoVy updated:

    +
      +
    • Removes rogue super-bright pixel at top of Vulpkanin Adhara hairstyle north and south facing sprites.
    • +
    +

    Kyep updated:

    +
      +
    • Deleted clown planet away mission.
    • +
    • blobs now spawn with a player in control, instantly. There is no longer a 30 second period where they exist, but nobody is controlling them.
    • +
    • blobs now get extra time after spawn, before they are announced.
    • +
    +

    Markolie updated:

    +
      +
    • Megaphones can no longer be used by mute people.
    • +
    • Rechargers will no longer recharge stacks beyond their max amount or restack 0.5 sheets.
    • +
    • Ranged guardians now have a proper one second cooldown instead of 0.1 seconds.
    • +
    • Cult can no longer soul stone manifested ghosts.
    • +
    +

    davipatury updated:

    +
      +
    • Autolathe now uses Nano-UI.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Shuttle engines should now face the correct way
    • +
    + +

    20 February 2017

    +

    Markolie updated:

    +
      +
    • The chaplain on the Cyberiad map now has a one-use soulstone.
    • +
    • The chaplain's soul stone on MetaStation can now only be used once.
    • +
    +

    davipatury updated:

    +
      +
    • Shuttle Console now uses Nano-UI.
    • +
    +

    tigercat2000 updated:

    +
      +
    • The AI has a button next to radio messages to open the door closest to the speaker. ;AI, Open this fucking door!
    • +
    + +

    19 February 2017

    +

    Markolie updated:

    +
      +
    • Claw games no longer eat up all glass sheets in the stack when constructed.
    • +
    + +

    18 February 2017

    +

    Alffd updated:

    +
      +
    • Fixes missing entries in species/station for Vox cough and sneeze.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Centcomm has begun enforcing stricter security protocols after a recent influx of fax responses from Clown impersonators
    • +
    • Mind transfer abilities work again
    • +
    • Centcomm is no longer obnoxiously pedantic, regarding BSA deployment
    • +
    +

    Krausus updated:

    +
      +
    • End-of-round sounds will now play just in time for them to end as the server reboots, rather than starting the moment it reboots.
    • +
    +

    Kyep updated:

    +
      +
    • Added a 'take' option to ahelps/mhelps, so admins/mentors can quickly let the asker know their question is being looked at.
    • +
    +

    Markolie updated:

    +
      +
    • Vending machines, newscasters, biogenerators, plant DNA manipulators, seed extractors, bots, fax machines, photocopiers, AI slippers, cell door timers, airlocks, pipe dispensers and atmospherics machinery that open a window can now be viewed by ghosts.
    • +
    • Admins can now interact with mass driver, crematorium, ignition, light, flashers and flasher switches and door switches, as well as airlocks, windoors, firedoors and atmospherics machinery that do not open a window if they have advanced admin interaction enabled (under the "Admin" tab).
    • +
    • Slicing disposal pipes now shows a progress bar.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Shuttle engines have new sprites.
    • +
    + +

    17 February 2017

    +

    Crazylemon64 updated:

    +
      +
    • Space vines now have a mutation that lets them grow in a more intelligent manner
    • +
    +

    Ported by Markolie, developed by AnturK updated:

    +
      +
    • Station Goals have been ported from /tg/. These optional goals are big projects given to the station by Central Command, requiring interdepartmental cooperation and a huge number of resources to complete.
    • +
    • Three station goals have been added: bluespace artillery construction, meteor shield satellite network and DNA vault.
    • +
    • Fixes the "Messages" tab of the communications computer.
    • +
    + +

    16 February 2017

    +

    Crazylemon64 updated:

    +
      +
    • Slime people and Dionae now make sounds when coughing
    • +
    +

    KasparoVy updated:

    +
      +
    • Welding goggles and welding gas masks now properly affect your vision.
    • +
    +

    davipatury updated:

    +
      +
    • changed urnaium to uranium in wt-550 auto gun uranium magazine design
    • +
    +

    uraniummeltdown updated:

    +
      +
    • The wizard has a new spell, Rod Form, which allows him to transform into an immovable rod.
    • +
    • Ethereal beings no longer cause bananium floor tiles to squeak.
    • +
    + +

    15 February 2017

    +

    Alexshreds updated:

    +
      +
    • Coughing and sneezing now plays sounds.
    • +
    +

    Ausops updated:

    +
      +
    • Internals and plasma tanks have been resprited.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Phlogiston now ignites consistently upon application
    • +
    +

    FlimFlamm updated:

    +
      +
    • New decals for boxes. Just apply a pen to change them (while they're open)!
    • +
    +

    KasparoVy updated:

    +
      +
    • You can now choose to speak anonymously in deadchat from round-start game preferences.
    • +
    • Your decision to speak anonymously in deadchat now persists between ghostings.
    • +
    • Vox tails won't change colour when other Vox spawn in anymore.
    • +
    +

    Markolie updated:

    +
      +
    • Mine bots once again only do ten damage in pressurized areas
    • +
    +

    Twinmold93 updated:

    +
      +
    • Blob Conscious Split now properly scales the requirement of blob tiles to win.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Borers now have action buttons
    • +
    • Borer names are now dependent on generation
    • +
    + +

    14 February 2017

    +

    Developed by Cyberboss, ported by Markolie updated:

    +
      +
    • Progress bars will now stack vertically.
    • +
    • Progress bars will no longer be affected by lighting.
    • +
    +

    DrunkDwarf updated:

    +
      +
    • Adds a section to the Airlock menu of the RCD to allow specifying the name of the new Airlock
    • +
    +

    Fethas updated:

    +
      +
    • You can no longer put anything THAT IS ALREADY A CULTIST IN A SOULSTONE....AT ALL.
    • +
    • Readds missing beserker robe sprite.
    • +
    • Cap growth serum at 1.5
    • +
    +

    Fox McCloud updated:

    +
      +
    • Xenobiology console should be more responsive when using/exiting using it
    • +
    • Xenobiology console can now be loaded with a bag
    • +
    • Using monkey cubes on the Xenobiology console no longer makes you attempt to utilize the console
    • +
    +

    Markolie updated:

    +
      +
    • The kinetic accelerator sprite modkits now apply properly when the kinetic accelerator is empty.
    • +
    • Welding tools now once again have a proper in-hand when turned on.
    • +
    + +

    13 February 2017

    +

    Crazylemon64 updated:

    +
      +
    • Achieving higher growth rates on kudzu will result in a faster-growing vine when planted
    • +
    +

    Fethas updated:

    +
      +
    • Metastation: The escape shuttle doors should no longer be security access only.
    • +
    • Metastation: Hooks up disposals door control.
    • +
    • Cyberiad: Untriggers Neca and makes the floor tiles in the emergecny wing sec area plating.
    • +
    • Cyberiad: Moves the cargo mail room table onto the otherside of the window so you can actually OPEN IT.
    • +
    +

    Fluff12 updated:

    +
      +
    • Greys can now choose to speak in wingdings or not. The Voice option is right below Species in character creation if Grey is selected - make sure you have it set to what you want!
    • +
    +

    Fox McCloud updated:

    +
      +
    • improves the tatortot sprite
    • +
    +

    Kyep updated:

    +
      +
    • Playtime requirements for IAAs have been set at 5 hours (similar to Sec Officer). Playtime requirements for Captains and AI have been increased from 10 hours to 20 hours.
    • +
    • Mech-mounted teleporters are no longer massively overpowered. They now consume a huge amount of energy to use, to the point that crew mechs with them can only use them a few times. They can no longer be spammed. Dark Gygax mechs used by nuclear operatives get a better version of the teleporter, which has around 40 uses, and is more precise.
    • +
    • Fixed several bugs related to Terror Spider webs.
    • +
    • Terror Spiders have been rebalanced. Spiders are no longer spaceproof, princes are now proper minibosses, and more.
    • +
    • Several new classes of Terror Spiders (green, white, purple, queen, mother) have been added - including types which can breed. This creates new strategy around nest defense.
    • +
    +

    Markolie updated:

    +
      +
    • Fixed a number of genetics powers not working.
    • +
    • Posibrains can no longer whisper when silenced.
    • +
    • Syndicate turrets will no longer target the Syndicate pAI found on their outpost.
    • +
    • Fixed the "Swedish" disability occasionally hiding parts of speech.
    • +
    • Mouthless players can no longer eat crayons (such as IPC's).
    • +
    • Instruments can now be interacted with while buckled.
    • +
    • Emagging a single fax machine will no longer give all fax machines access to the Syndicate destination.
    • +
    • Evidence bags will now always show the item inside of them.
    • +
    • Spacepods leaving a trail of humans instead of ion trail effects.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Nuclear Operatives can customize the Declaration of War.
    • +
    • The RSF has a unique sprite.
    • +
    + +

    12 February 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes erroneous access on inner morgue door which was granting people with morgue access, access to the entirety of medical bay
    • +
    +

    Kyep updated:

    +
      +
    • added two more mining hardsuits to the mining outpost.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Whetstones have been resprited
    • +
    • Drying racks have new sprites.
    • +
    + +

    11 February 2017

    +

    Markolie updated:

    +
      +
    • Ports over the remaining Lavaland loot items from /tg/ (most developed by KorPhaeron).
    • +
    • Refactors the kinetic accelerator to use modkits instead of subtypes: these unique mods (such as more range or shorter cooldown) can be purchased from the mining vendor or built by R&D or robotics (developed by KorPhaeron).
    • +
    + +

    10 February 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes not being able to bloodcrawl in most sources of blood
    • +
    • Fixes slaughter demon whisper not working at all
    • +
    • Drying rack drying now properly uses NanoUI instead of a right-click verb
    • +
    • Fixes produce appearing stuck in a drying rack when it was empty
    • +
    • Fixes a few failed icon updates with the drying rack
    • +
    +

    KasparoVy, Krausus updated:

    +
      +
    • Adds the colourblindness gene. It is eye-dependent, and can be transferred from person-to-person with the eye organ.
    • +
    • Colourblindness can be detected by the advanced medical scanner just like blindness and short-sightedness.
    • +
    • Vulpkanin and Tajara can now choose to be uniquely colourblind in exchange for fantastic darksight. The default option is colour vision but low darksight.
    • +
    • Selecting mechanical or mechanically assisted eyes at character creation grants full colour vision, but standard Human darksight. This overrides the colour vision preference.
    • +
    • Mechanical(ly assisted) internal organs such as hearts and eyes are now appropriately named, and have appropriate sprites.
    • +
    • Vulpkanin and Tajara monkey-forms (Wolpins and Farwas) are incurably colourblind but have excellent darksight as they get nearly the same organs as their greater forms.
    • +
    • Increases reliability of turning into a monkey.
    • +
    • Fixes a bug with changelings lesser-forming, transforming and humanforming into a different identity.
    • +
    +

    Markolie updated:

    +
      +
    • Firelocks can now be constructed and deconstructed.
    • +
    • Firelocks no longer show a confirmation message when being opened.
    • +
    • Various map fixes (vents, scrubbers, firelocks and intercoms). Also removes the firelocks covering the windows in escape/cargo.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Ported Goonstation slash /vg/ lighting. Pretty.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Quantum Pads are now buildable in R&D!
    • +
    • Quantum Pads, once built, can be linked to other Quantum Pads using a multitool. Using a Pad which has been linked will teleport everything on the sending pad to the linked pad!
    • +
    • Pads do not need to be linked in pairs: Pad A can lead to Pad B which can lead to pad C.
    • +
    • Upgrading a Quantum Pad will reduce the cooldown, charge-up time, and power consumption.
    • +
    • Quantum Pads require a bluespace crystal, a micro manipulator, a capacitor and a cable piece.
    • +
    • Events now scale better with population.
    • +
    • Enabled immovable rod, slaughter demon and morph events.
    • +
    + +

    08 February 2017

    +

    Fox McCloud updated:

    +
      +
    • Grinding wheat and other products produces the proper reagents again
    • +
    + +

    07 February 2017

    +

    Fox MCCloud updated:

    +
      +
    • Tank transfer valves have in-hand icons
    • +
    • Tank transfer valves with large tanks (ie: jetpacks) cannot fit in backpacks
    • +
    +

    Fox McCloud updated:

    +
      +
    • fixes xeno eggs taking damgae from disablers
    • +
    • adjusts most botany plant reagents to have "plantmatter" as opposed to nutriment
    • +
    • Blumpkins now have plasma in them
    • +
    • Fixes plant grown diona not being allied with plants and vines
    • +
    • Water coolers now dispense cups when clicking on them with a free hand
    • +
    • reagent tank dispensing amount based on the container instead of the tank
    • +
    • Fixes beaker spilling when placing a beaker into an ice cream machine
    • +
    • Adds in 100,000 unit water tanks to cargo for 12 points
    • +
    • regular water tank cost reduced from 8 to 6 points
    • +
    • Monkey cubes in boxes no longer start off wrapped
    • +
    • All monkey cube boxes at cargo are the same price
    • +
    • Fixes Nymphs not being able to cross over top of hydroponics trays
    • +
    • Diona fertilizing and weed eating is handled by clicking on the tray as a nymph rather than verbs
    • +
    +

    KasparoVy updated:

    +
      +
    • Storage implants are now checked for steal objective items.
    • +
    +

    Kyep updated:

    +
      +
    • AI holograms now transfer between holopads as the AI moves around.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Engineering and Science crates now have new sprites
    • +
    • Changelings can recall the memories of an absorb victim
    • +
    • Changelings will recall some speech of their absorb victims
    • +
    • You can now create floor tiles from minerals. Be careful around plasma and uranium floors though.
    • +
    + +

    06 February 2017

    +

    Fox McCloud updated:

    +
      +
    • Fixes traitor banana peels having no sprite
    • +
    • Stunprods are constructed with igniters instead of wirecutters
    • +
    • Stunprods will spark when you stun someone with them
    • +
    • Expands the amount of cryodorm pods
    • +
    +

    KasparoVy updated:

    +
      +
    • IPC names with numbers now load correctly from SQL.
    • +
    +

    Kyep updated:

    +
      +
    • Autoprocess cloners will no longer clone people who cryo and ghost out, or otherwise deliberately remove themselves from the round.
    • +
    • Dead miners in UO45 away mission are no longer naked.
    • +
    • ERT and SST shuttle consoles now require the appropriate access to use.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • You can interact with an ore box by using an advanced mining scanner on it.
    • +
    • Xenobiology Console is now constructible, board has been added to the Circuit Imprinter.
    • +
    • Plasmaman IAA/Lawyers now have a unique suit.
    • +
    • AI control beacons are a new item created from the exosuit fabricator. When installed into a mech, it allows AIs to jump to and from that mech freely. Note that malfunctioning AIs with the domination power unlocked will instead be forced to dominate the mech.
    • +
    • Changelings have a new default ability: Hivemind Link. This lets you bring a neck-grabbed victim into the hivemind for a few minutes. You can talk to your victims and perhaps persuade them to help you, give you intel, or even a PDA code. Victims in crit will be stabilized.
    • +
    • Added new AI core sprites from TG
    • +
    • Added Vox rad suit, bombsuit hood, paramedic EVA suit sprites from /vg/
    • +
    • You can click AI displays as an AI to change them
    • +
    + +

    05 February 2017

    +

    Fethas updated:

    +
      +
    • Brings unholy water in line with its description.
    • +
    +

    Fox McCloud and Core0verload updated:

    +
      +
    • Dramatically overhauls the botany system; features more user friendly gene modification methods, more control over attributes and reagents in your plants, and more
    • +
    • Adds in drying rack for drying growns for smoking with rolled papers
    • +
    • Store spare seeds in the seed extractor
    • +
    • Adds in cloth; make clothing, satchels, backpacks, duffelbags and more.
    • +
    • Upgrading hydroponics trays impacts how quickly plants degrade
    • +
    • Bees slightly more effective at increasing plant yields
    • +
    • Overall growth rate of plants dramatically increased
    • +
    • Adds in the ability to construct bonfires with wooden logs; perfect for keeping you our your fellow spessman warm---forever
    • +
    • Adds in a few new bartender drinks and recipes, such as chocolate pudding, vanilla pudding, and pumpkin spice
    • +
    • Can now wear some flowers/ambrosia in your hair
    • +
    • Combining genes form different plants has unique effects (For instance, the battery gene with the recharging gene allows you to make insanely potent batteries)
    • +
    • Vines are now purely handled by the Kudzu plant
    • +
    • Botanists have been given morgue access
    • +
    +

    Ported by Markolie, developed by KorPhaeron and others from /tg/. The Hierophant was developed by ChangelingRain. updated:

    +
      +
    • Megafauna and their rewards have been added to the code. These are not on the map yet.
    • +
    • Fireball is now a targeted spell instead of a dumbfire spell.
    • +
    • Most spells, wands and staffs now have unique spell sounds.
    • +
    • Added a new nullrod type, the "spellblade".
    • +
    • Added bows, arrows and quivers. Currently only available for admins.
    • +
    • Added cockroaches. Currently only available for admins.
    • +
    • Added support for BYOND medals. Currently disabled.
    • +
    • Added a number of Lavaland objects (flora, basalt, food and stacks). Currently only available for admins.
    • +
    • Earmuffs can now be produced in autolathes.
    • +
    • Syndicate gun turrets are now subtypes of regular turrets: this makes them controllable with Syndicate ID's and improves their targeting.
    • +
    • Diona and Shadow People now receive a warning when they're not exposed/exposed to light.
    • +
    • The sniper AP rounds that Nuke Ops can purchase now have a chance of dismembering limbs.
    • +
    • Shadow People can now switch their night vision properly.
    • +
    • Certain messages in chat weren't showing up in their proper (large) size, such as the Nar'Sie spawned message. This has been resolved.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Supply ID skin is now selectable in the Agent ID and ID Computer
    • +
    + +

    03 February 2017

    +

    DrunkDwarf updated:

    +
      +
    • Set the Mr Chang's vending machine to be refillable
    • +
    • Added a Supply Crate to the Vending section of the Cargo Request Console for Chinese Refill Canisters
    • +
    + +

    02 February 2017

    +

    Alexshreds updated:

    +
      +
    • Deconstructing closets yields the proper amount of metal
    • +
    +

    Kyep updated:

    +
      +
    • Using the 'summon narsie' rune as cult, when you don't have the objective to do so, is now punished by the cult's god. Just as using the 'call forth the slaughter' rune, when you don't have the objective to do that, is already punished.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Engineering Cyborgs now have a digital copy of the station blueprints.
    • +
    + +

    31 January 2017

    +

    Ar3nn updated:

    +
      +
    • cursed cluwne mask now allows internals to be fed through it
    • +
    +

    FalseIncarnate updated:

    +
      +
    • All requests consoles can print off a single-use, pre-tagged Shipping Package for sending a single item via disposals to a destination of your choosing.
    • +
    • Shipping Packages can be used to tag packages wrapped with wrapping paper, in case you don't have access to cargo's destination tagger.
    • +
    • Requests Consoles log the printer and destination of all shipping labels printed from that particular console. There currently is no way to clear your mailing history, so mail responsibly.
    • +
    +

    Fethas updated:

    +
      +
    • Fixes a rune runtime.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • adds an admin-only laser carbine
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Your game window will now flash on receiving Admin PMs, being revived, and ghost roles. You can disable this in Game Preferences.
    • +
    + +

    30 January 2017

    +

    Alexshreds updated:

    +
      +
    • No more double traitor 241 Special
    • +
    + +

    29 January 2017

    +

    uraniummeltdown updated:

    +
      +
    • You can now take items directly out of a storage item in your backpack.
    • +
    + +

    27 January 2017

    +

    Alffd updated:

    +
      +
    • Adds missing hat and shoe sprites that were inadvertently deleted.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in stungloves (inaccessible to players)
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Injecting a rainbow slime extract with blood will create a consciousness transference potion.
    • +
    • Injecting a metal slime extract with water will create 15 sheets of glass and 5 sheets of reinforced glass.
    • +
    • Slime potions now check for proximity.
    • +
    + +

    26 January 2017

    +

    FalseIncarnate updated:

    +
      +
    • Plasma dust can now be used to rig lights and power cells, like the plasma reagent, with explosive results.
    • +
    +

    Fethas updated:

    +
      +
    • Adds two new holy weapon skins for people who belive in ghosts and worshipers of the silentfather.
    • +
    +

    FreeStylaLT updated:

    +
      +
    • AI sat transport tubes are no longer misaligned
    • +
    + +

    25 January 2017

    +

    FlattestGuitar updated:

    +
      +
    • Fixes shadowlings thrall scaling
    • +
    +

    scrubmcnoob updated:

    +
      +
    • Shadowling Thrall count now scales to a max of 25.
    • +
    • Shadowling Thralls lose lesser glare
    • +
    + +

    23 January 2017

    +

    FalseIncarnate updated:

    +
      +
    • Returns the ability to remove vacant soil with shovels and spades, and adds the ability to dig up plants in soil to remove them instantly.
    • +
    +

    Stratus updated:

    +
      +
    • NT Enforcer .45 pistol.
    • +
    • .45 and 9mm rubber bullets.
    • +
    • New shotgun ammo boxes.
    • +
    + +

    18 January 2017

    +

    AndriiYukhymchak updated:

    +
      +
    • multitool can now be used to swap directions of TEG's circulator
    • +
    +

    Fethas updated:

    +
      +
    • Adds in the check numbers proc to converting, I missed it from VG.
    • +
    • Removed a redundent sacrefice objective check AND fixed the sacrfice objective check so it actually PICKs on mode start.
    • +
    • changed the color of manfested ghost humans to grey...huehuehuehuehue(serously it helps tell them apart better).
    • +
    • mass convert objective now picks between 9 and 15 as a target instead of based on round pop..cuase 30 MIGHT be a bit much.
    • +
    • adds admin cult tools Bypass phase (missed this off vg) and cult mind speak(YOUR GOD IS DISPLEASED GIT GUD). Might be better in secret panel but it confuses me.
    • +
    • Removes errent invisaible animals from the narnar escape shuttle template.
    • +
    +

    KasparoVy updated:

    +
      +
    • Characters with the obese disability are now fat beneath their clothes.
    • +
    +

    Markolie updated:

    +
      +
    • Admin announcements are no longer sent to player in the lobby.
    • +
    • Regular announcements can now only be heard if you the player is alive, not deaf and in range of an enabled radio.
    • +
    + +

    17 January 2017

    +

    Crazylemon64 updated:

    +
      +
    • Joined Souls works now
    • +
    • Scribing the end rune now no longer is impossible
    • +
    +

    Krausus updated:

    +
      +
    • Fixed the exciting new emoji breaking chat entirely for IE8 users. :clap:
    • +
    + +

    16 January 2017

    +

    Alexshreds updated:

    +
      +
    • Revenants can now breathe in space.
    • +
    • Can no longer exploit RCDs for metal
    • +
    +

    Krausus updated:

    +
      +
    • You can now use pills and patches on people with full bellies.
    • +
    • The Randomized Character Slot option now actually works.
    • +
    + +

    15 January 2017

    +

    Funce updated:

    +
      +
    • dual-port air vents can now be unwrenched
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Broken and Burned bulbs are no longer forced on with every overload.
    • +
    • Only non-broken and non-burned bulbs actually break and spark on an overload.
    • +
    • Fixes a single syntax error in the Shadowling Ascendant descriptive text.
    • +
    + +

    14 January 2017

    +

    Crazylemon64 updated:

    +
      +
    • Bibles can now reveal runes as they did before
    • +
    +

    Krausus updated:

    +
      +
    • Players will no longer be informed of what cult may or may not exist on round start.
    • +
    + +

    13 January 2017

    +

    DarkPyrolord updated:

    +
      +
    • Removes the joy mask
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Cyborg tools (and other non-droppable tools) cannot be transferred to an open, empty Display Case
    • +
    • Jobs receive links to SOP and their Department SOP at roundstart. Space Law and Legal SOP links added to Security members, Magistrate and IAAs
    • +
    +

    uraniummeltdown updated:

    +
      +
    • You can see what sting you have equipped as changeling.
    • +
    • All species except IPCs can now be changelings and be affected by their genetic abilities.
    • +
    • Arm Blade can now pry open powered airlocks
    • +
    • Transformation Sting now costs 3 points and requires 50 chemicals
    • +
    • You can no longer transform people into Vox with Transformation Sting.
    • +
    • Removed Engorged Chemical Glands, Changelings now have the ability by default
    • +
    + +

    12 January 2017

    +

    TullyBurnalot updated:

    +
      +
    • Graffiti now have hidden (Admin-only) fingerprints added to them
    • +
    + +

    11 January 2017

    +

    Crazylemon64 updated:

    +
      +
    • Ghosts can now see if they're allowed to respawn or not at a glance
    • +
    • Cyborg sight modes are now actions, instead of items
    • +
    • Mining drones can now use meson sight again
    • +
    • It's no longer opposite day for the karma reminder preference
    • +
    +

    Lady Luck updated:

    +
      +
    • office laptops are now traversable
    • +
    +

    Markolie updated:

    +
      +
    • simple_animals now have an attack cooldown when attacking mechas.
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Atmos Console Boards now show in Computer Boards of Circuit Imprinter
    • +
    + +

    10 January 2017

    +

    Crazylemon updated:

    +
      +
    • Giant spiders now have their own role pref
    • +
    +

    Crazylemon64 updated:

    +
      +
    • pAIs can now adjust their radios
    • +
    • pAIs can now more reliably hear nearby whispers
    • +
    • pAIs can now whisper while inside a PDA
    • +
    • pAIs can no longer change their icon from being dead, while dead
    • +
    • Non-respawnable players are no longer prompted to submit a pAI when the opportunity is available
    • +
    • Borg sight modules work again
    • +
    +

    Fox McCloud updated:

    +
      +
    • different alert levels for how full you are from starving all the way to fat
    • +
    • There is now satiety and nutrition; being satisfied and full has a number of positive benefits; being unsatisfied and hungry has negative side effects
    • +
    • Some foods have vitamins in them which provide little nutrition, but greatly increase your satisfaction
    • +
    • Some food reagents have had their nutritional values tweaked
    • +
    • reagent numbers tweaked on most food items
    • +
    • Fixes the floral gun not properly working on Diona
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Wand of Death now reliably kills people by adding 300 Burn Damage. This includes self-casting
    • +
    • Minor flavour text visible on impact of target
    • +
    • pAI HUDs are now visual-only, restricting their access to editable records
    • +
    +

    pinatacolada updated:

    +
      +
    • IV drips now have adjustable rates
    • +
    +

    uraniummeltdown updated:

    +
      +
    • Mimes can now choose name on entry just like Clowns
    • +
    • Added many new costumes to the Autodrobe!
    • +
    + +

    09 January 2017

    +

    Crazylemon64 updated:

    +
      +
    • The operating table now checks for both either `lying` or `resting` - so surgery will work no matter what on unconscious people lying on your table.
    • +
    +

    Kyep updated:

    +
      +
    • Antags should no longer get bounced to lobby at round start in certain rare situations.
    • +
    + +

    07 January 2017

    +

    Markolie updated:

    +
      +
    • False walls now block atmospherics, unless it's open.
    • +
    + +

    06 January 2017

    +

    Crazylemon64 updated:

    +
      +
    • pAI UIs no longer break
    • +
    • The chem dispenser's UI now displays the remaining energy again
    • +
    • Shuttles no longer make buckling useless
    • +
    • You should no longer go mute randomly
    • +
    • You can now opt out of all requests on a role for a round
    • +
    • Morgue trays now have descriptions that correspond to each of the morgue light states
    • +
    • Waking up no longer auto-cancels resting.
    • +
    +

    Fethas updated:

    +
      +
    • ports parts TG neo-oldcult rscadd:Ports parts of cult from VG
    • +
    +

    KasparoVy updated:

    +
      +
    • Grey sprites have been tidied up and no longer have any random pixels hanging off.
    • +
    • Grey species-fitted tattoo sprites and the last Vox species-fitted tattoo sprite.
    • +
    +

    Krausus updated:

    +
      +
    • SDQL2 can now directly manipulate clients.
    • +
    +

    Kyep updated:

    +
      +
    • Mobs in vents no longer see vents/scrubbers as unwelded when they are welded, and vice versa.
    • +
    + +

    03 January 2017

    +

    KasparoVy updated:

    +
      +
    • The Vulpkanin Anita hairstyle no longer has rogue extra-bright pixels.
    • +
    +

    Kyep updated:

    +
      +
    • Added tracking for how much playtime each player has.
    • +
    • Added the ability to lock jobs based on playtime. E.g: must play for 10 hours to unlock HoS.
    • +
    + +

    02 January 2017

    +

    KasparoVy updated:

    +
      +
    • Particle Accelerators ordered from Cargo can now function.
    • +
    • Wrenching powerless machines in a powered area will no longer require you to toggle the lights (or whatever you did before to sort this).
    • +
    +

    Krausus updated:

    +
      +
    • The syndicate nuke and pinpointer locker will once again spawn into their ship, rather than into space near the station.
    • +
    +

    Kyep updated:

    +
      +
    • Terror Spiders can no longer create more than one web on a tile.
    • +
    + +

    01 January 2017

    +

    Kyep updated:

    +
      +
    • Added basic, AI-less versions of some Terror Spiders.
    • +
    + +

    31 December 2016

    +

    Crazylemon64 updated:

    +
      +
    • The home gateway now will send ghosts to the other end by default, now
    • +
    + +

    30 December 2016

    +

    Crazylemon updated:

    +
      +
    • The shuttle manipulator can now only be used by admins
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds Nano-Mob Hunter GO! PDA game cartridges and related stuff. Grab a cartridge from the cartridge vendor or loadout and join in on the hunt!
    • +
    • Adds Nano-Mob Hunter GO! Battle Terminals to the Holodeck and a Nano-Mob Hunter GO! Restoration Terminal to medbay's lobby.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes cyborg cryo oddities
    • +
    +

    KasparoVy updated:

    +
      +
    • Taking off noir glasses while noir mode is on will now give you your colour vision back.
    • +
    + +

    29 December 2016

    +

    Fethas updated:

    +
      +
    • Alternate shuttle/ferry template system from TG
    • +
    • Shuttle Manipulator
    • +
    • Better shuttle kills
    • +
    +

    Markolie updated:

    +
      +
    • The camera console has been refactored so there's no longer a delay when switching cameras.
    • +
    • The camera console should no longer lag for several seconds.
    • +
    + +

    25 December 2016

    +

    FalseIncarnate updated:

    +
      +
    • Santa's back and with-holding all your presents! Head through the gateway and show the Fat Man the strength of your holiday spirit (and advanced weaponry, you'll be needing that)!
    • +
    +

    KasparoVy updated:

    +
      +
    • Cameras will no longer be able to take photos of stuff outside your line of sight.
    • +
    • Cameras will now render disguises as you see them.
    • +
    + +

    23 December 2016

    +

    Crazylemon64 updated:

    +
      +
    • Welding overlays now update instantly
    • +
    • Being inside various structures will now obscure your vision
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes X-Ray not doing anything
    • +
    • Fixes nightvision not granting what its name implies
    • +
    • Fixes species/human darksight doing absolutely nothing
    • +
    +

    KasparoVy updated:

    +
      +
    • Characters will now be correctly assigned their species' genetic quirks at spawn.
    • +
    • Cloning will now correctly assign a characters species' genetic quirks.
    • +
    • Changing a character's species (via C.M.A. or whatever might call the set_species proc) will now correctly assign their species' genetic quirks.
    • +
    +

    Markolie updated:

    +
      +
    • Ruins no longer trigger power alarms.
    • +
    + +

    20 December 2016

    +

    TullyBurnalot updated:

    +
      +
    • Neurotoxin Spit now causes the spitter to move in space
    • +
    • Proximity Wet Floor Sign Mines can no longer appear in Surplus Crates
    • +
    + +

    14 December 2016

    +

    Fox McCloud updated:

    +
      +
    • Fixes the personal crafting cost of ED-209's being too expensive
    • +
    + +

    13 December 2016

    +

    TullyBurnalot updated:

    +
      +
    • Medbots no longer run after injured mobs if buckled. They also inform nearby players of this
    • +
    + +

    12 December 2016

    +

    Kyep updated:

    +
      +
    • Xenomorph resin walls no longer take damage from disabler beams. Only proper BRUTE or BURN damage hurts them now.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Throwing mobs behind you force moves them to behind you before actually throwing them, preventing throw-shoving
    • +
    + +

    09 December 2016

    +

    KasparoVy updated:

    +
      +
    • You can now define whether a hair style will cover glasses or not. Only long hair styles should cover glasses (default behaviour).
    • +
    • You can now define whether a facial hair style/head accessory will be rendered on top of hair or not.
    • +
    • Glasses no longer render on top of all hair styles, only sufficiently short ones.
    • +
    + +

    08 December 2016

    +

    Kyep updated:

    +
      +
    • Ensures cryo pods will properly auto-eject people whose organic parts (limbs) have been healed, but who still have damaged mechanical limbs.
    • +
    • Disabler shots no longer damage mechs.
    • +
    • On impact, both taser and disabler shots now produce a message saying that the mech is undamaged by them, instead of a message saying they 'hit'.
    • +
    • Fixed runtimes created when SIT, ERT, and some other mobs are spawned.
    • +
    • Fixed a bug causing SITs to be spawned with one less person than desired in some cases.
    • +
    + +

    07 December 2016

    +

    Markolie updated:

    +
      +
    • Verbs have been cleaned up: all karma verbs can now be found under "OOC" instead of "Special Verbs". Most admin verbs have been moved out of "Special Verbs" as well.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Unpowered Mining Vendors no longer accept IDs
    • +
    • Ore Redemption Machine and Mining Vendor can now be deconstructed if unpowered
    • +
    + +

    06 December 2016

    +

    Markolie updated:

    +
      +
    • The track button on the AI crew monitor now works.
    • +
    • Permanent door electrification by alt-clicking a door as an AI or setting it manually now works again.
    • +
    + +

    05 December 2016

    +

    KasparoVy updated:

    +
      +
    • Resolves an issue where cloned vampires could no longer drain blood, burn in the chapel or use their powers properly.
    • +
    + +

    04 December 2016

    +

    KasparoVy updated:

    +
      +
    • Resolves an issue with changeling regenerative stasis where changelings who initiated it while alive and died during the waiting period did not come back to life. Now they will, as intended.
    • +
    + +

    03 December 2016

    +

    Kyep updated:

    +
      +
    • the anti-ERP warning message on PDA message consoles is now accurate.
    • +
    + +

    01 December 2016

    +

    Crazylemon64 updated:

    +
      +
    • Cryo tubes no longer let you excessively multiply the efficiency of touch chems
    • +
    +

    KasparoVy updated:

    +
      +
    • The character preview icon in character creation is now more detailed and less blurry.
    • +
    • ID cards now show tails, body accessories and tail markings correctly.
    • +
    +

    Twinmold93 updated:

    +
      +
    • Pilots of spacepods will no longer be sent to the void when the space pod is destroyed in any method.
    • +
    • Pilots of spacepods will now get the same warnings for damage/core destruction that passengers get.
    • +
    + +

    29 November 2016

    +

    KasparoVy updated:

    +
      +
    • Head, body and tail markings are now loaded correctly from genes (UI).
    • +
    • Changes to a person's skin-tone gene are now immediately apparent.
    • +
    + +

    28 November 2016

    +

    Allfd updated:

    +
      +
    • Fixes an issue with the processing of GitHub changelog emoji in the php webhook.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • The RCD no longer shall work as a remote permissions control
    • +
    +

    KasparoVy updated:

    +
      +
    • Pressing the light switch in one OR will no longer turn off the lights for both.
    • +
    • The fire alarms in each OR now work independently of each-other.
    • +
    • The second operating room now has its own APC and wiring.
    • +
    + +

    26 November 2016

    +

    Fox McCloud updated:

    +
      +
    • Fixes faint emote doing nothing
    • +
    • Fixes Mickey Finn's Special Brew not functioning properly/not making you fall asleep
    • +
    + +

    23 November 2016

    +

    Fethas updated:

    +
      +
    • Fixes human jetpacks..maybe...
    • +
    +

    FlattestNerd updated:

    +
      +
    • the e20 will now get logged when it goes BEWM, as it should.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes double-breaking news newscaster
    • +
    + +

    22 November 2016

    +

    KasparoVy updated:

    +
      +
    • You now stutter when you're in shock/crit and when you've got the nervous disability as you used to.
    • +
    +

    Twinmold93 updated:

    +
      +
    • Runtime caused by lack of settlers in the Orion arcade game.
    • +
    + +

    20 November 2016

    +

    KasparoVy updated:

    +
      +
    • The DNA SE injectors one can find in the abandoned mining crates now correctly activate/deactivate the powers they may contain.
    • +
    + +

    15 November 2016

    +

    KasparoVy updated:

    +
      +
    • Adding cable to multiple computer frames at the same time while not having the correct amount of cables will no longer cause busted coils with a negative number of cables.
    • +
    + +

    13 November 2016

    +

    Fox McCloud updated:

    +
      +
    • Fixes BSA having peculiar results.
    • +
    + +

    07 November 2016

    +

    Crazylemon updated:

    +
      +
    • Status effects should work a little more consistently now
    • +
    +

    Crazylemon64 updated:

    +
      +
    • The mech-mounted plasma cutter can now be constructed again
    • +
    • Space pod lasers can now be constructed again
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes hunters not being weakened when crashing into a shield/wall
    • +
    • Fixes xeno stuns half the time intended
    • +
    • Fixes stopping, dropping, and rolling not properly weakening Xenos/Hulks
    • +
    +

    KasparoVy updated:

    +
      +
    • Fixes a bug where changing your alt head required two icon updates to show.
    • +
    • Fixes a bug where you couldn't choose head marking styles that would ordinarily be available regardless of your alt head.
    • +
    • Fixes a bug where Tajara couldn't choose undergarments.
    • +
    • Resolves an issue with the Vulpkanin Jagged hairstyle missing a pixel.
    • +
    +

    Twinmold93 updated:

    +
      +
    • Fixes a runtime issue caused by using the detective's scanner on the space hotel cleaver.
    • +
    • Scrubber pipe missing segment behind the operating theatres.
    • +
    + +

    23 October 2016

    +

    KasparoVy updated:

    +
      +
    • Refactors markings. Now split into head, body and tail markings.
    • +
    • Refactors morph again. Changes made while morphing are now reflected instantly on your sprite.
    • +
    • Darkens Vulpkanin and Tajara for improved colour fidelity. Species base colour changed to compensate. Add 27 to R, G and B values if Vulp, 15 if Taj to keep the same colour on your character.
    • +
    • Darkens Vulpkanin facial fur patterns for improved colour fidelity. Add 23 to the R, G and B values of your facial hair/head accessory to keep the same colour on your character.
    • +
    • Darkens Unathi frills and horns. Add 27 to the R, G and B values of your frills and 21 for horns to keep the same colour on your character.
    • +
    • Vulpkanin tails are now split-rendered. Tails overlap hair when facing north, but are overlapped by hair when facing all other directions. No other differences, only affects the fluffy husky tail.
    • +
    • The heads of tiger markings have been isolated and can now be coloured independently.
    • +
    • Hair can now cover facial hair, and glasses are no longer covered by facial hair and head accessories. Means that two-piece Vulpkanin facial fur patterns won't almost entirely cover whatever glasses they're wearing.
    • +
    • Tajaran head and facial hair have been darkened. Add 28 to the R, G and B values of your Tajara head/facial hair to keep the same colour on your character.
    • +
    • Vulpkanin head hair and one facial hair style has been darkened. Refer to PR notes for darkening factors.
    • +
    • The HAS_MARKINGS flag now represents all marking locations. The HAS_location_MARKINGS flags are for specific locations (head, body, tail).
    • +
    • Improves the quality of some Vulpkanin/Tajara/Unathi mask sprites.
    • +
    • Naked Humans and Skrell will no longer have exposed flesh poking out their wrists when facing east or west. Male Humans now no longer lack a butt pixel when facing east or west.
    • +
    • Mutated limbs now render correctly as soon as they're mutated.
    • +
    • Mobs will now correctly appear as fat/skinny.
    • +
    • Species with TAIL_OVERLAPPED will no longer wag tail at max speed when facing north.
    • +
    • Species with TAIL_OVERLAPPED and body accessories won't crash the game when they wag.
    • +
    • Tiger Head and Face markings adjusted so they don't look ugly on certain species' ears.
    • +
    • Fixes issue where Unathi dorsal stripe didn't render.
    • +
    • Tajaran ears are no longer in their hair sprites, but on their actual heads.
    • +
    • The adminbus body accessory now overrides the TAIL_OVERLAPPED flag and will now be rendered correctly on a body regardless of species bodyflags.
    • +
    • Changing a person's species via CMA will no longer result in a mob with all the same cosmetic attributes as the old species.
    • +
    • Dressers now have species fitting checks for undergarments. Drask are now able to wear undershirts and underwear like they were originally meant to.
    • +
    • Adds some head markings for Tajara and Vulpkanin.
    • +
    • Adds body marking(s) for Tajara, Vulpkanin, Unathi and Drask.
    • +
    • Adds tail markings for Vox and Vulpkanin.
    • +
    • Adds 5 Tajaran hairstyles.
    • +
    • Adds a tweaked version of an existing Vox hairstyle. Shouldn't clip with certain jackets as much.
    • +
    • Adds a hairstyle for Humans, Unathi and Vulpkanin.
    • +
    • Adds a facial hairstyle for Vulpkanin.
    • +
    • Adds secondary hair (head and facial) themes. Skrell can now colour their tentacle cloths independently, the beads in the Tajaran/Hippie braid hairstyles can be coloured and the same with the webbing in Unathi frills. Can be changed at nanomirrors, via morph and CMA.
    • +
    • Adds alternate heads. Unathi can now choose a head with a sharp snout. Can be changed via morph and CMA.
    • +
    • Helper procs to convert a hex colour into either R, G, or B.
    • +
    • Markings, body accessories, head accessories, alt heads and their colours (if they have colours) can now be randomized at the character preferences screen.
    • +
    • Adds a system that attempts to fit mobs with alternate heads with appropriate mask sprites. The sprites just need to be suffixed with the alt_head suffix in sprite_accessories.dm.
    • +
    • Adds mask sprites tweaked to fit the new Unathi alternate head to go along with the new alt. head mask fitting system.
    • +
    + +

    15 October 2016

    +

    Crazylemon64 updated:

    +
      +
    • The R&D console should now no longer freeze on the "Syncing Database" message or whatever.
    • +
    • Borg coolers and SMES boards can be made again
    • +
    • Maroon now works
    • +
    +

    FlattestGuitar updated:

    +
      +
    • pAIs no longer turn into debris when wiped
    • +
    • SNPCs no longer get targeted by assasinate objectives
    • +
    • fixes a hallucination runtime, actually making one more aspect of being high as f*** work for the first time in ages
    • +
    • NODROP items will no longer attempt to be dropped if your hand is broken
    • +
    +

    Fox McCloud updated:

    +
      +
    • Cloners will now put you inside the cloned body when it is fully grown as opposed to initially created
    • +
    • Examining a cloner will tell you the clone progress
    • +
    • Observers can now see a visual countdown of the cloning status progression
    • +
    • Atmos grenades cost increased from 6 to 11
    • +
    • Mice now have sprites when worn
    • +
    • Fixes various ghost alerts having barely visible icons
    • +
    • Fixes items being in two locations at once when loading things into the bio-generator or reagent grinder.
    • +
    +

    GeneralChaos81 updated:

    +
      +
    • Ability to place and remove conveyor belts and levers.
    • +
    +

    KasparoVy updated:

    +
      +
    • Botany, viro and xenobio bottles will no longer be invisible.
    • +
    +

    Krausus updated:

    +
      +
    • Fixed full chat panes scrolling unpredictably when trying to view old messages.
    • +
    • Fixed camera monitors immobilizing you if you reconnect while using one.
    • +
    • Fixed selecting datum types through SDQL2 never returning any datums.
    • +
    + +

    16 September 2016

    +

    Aurorablade updated:

    +
      +
    • *fart now has newtonian move if you have the Superfart power
    • +
    +

    Coldflame updated:

    +
      +
    • Adds three new variants of 10mm ammunition, AP, HP, and Incendiary. Currently admin-only.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Research data disks now have a description and name attached to them automatically, to make working with them less obnoxious.
    • +
    • Loading design disks now has a sound effect.
    • +
    • You can no longer feed non-design disks into the autolathe and destroy them on accident.
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Due to budget cuts expensive fax machines have been replaced with cheaper versions in some departments. Only essential personnel can fax Central Command. See your local IAA for details.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Added emergency nitrogen and plasma tanks, you can find two of each in the medical storage
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Updated Metastation's AI Sat, brig and escape shuttle
    • +
    • Updated other Meta areas to match most recent build. (Chapel, some maint, etc. - minor changes.)
    • +
    • Updated Cyberiad's AI Sat to latest tg version, lots of changes there - basically an entirely new Satellite.
    • +
    +

    IcyV updated:

    +
      +
    • Adds new bottle sprite
    • +
    • Fixes many bottles being locked to a single icon
    • +
    • Buckets can be worn as hats.
    • +
    +

    Improvedname updated:

    +
      +
    • Adds 4 epinephrine autoinjectors to nanomedplus vending machines
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds a Science departmental beret that you can obtain via the loadout system.
    • +
    +

    Krausus updated:

    +
      +
    • Fixed species-restricted items sometimes failing to "equip" to restricted species' non-equipment slots.
    • +
    • Players using very old versions of Internet Explorer will now receive explicit warnings that they're not supported.
    • +
    • View Variables will now consistently view the variables of what it's intended to.
    • +
    • Admins can now use the 'msay' command to speak directly to all mentors.
    • +
    • Added a new command, "Toggle Mentor Chat", to give mentors temporary access to 'msay'.
    • +
    • Fixed never being able to properly respond to a PM from a stealthed admin.
    • +
    +

    Kyep updated:

    +
      +
    • SST and SIT now have their own radio frequency.
    • +
    +

    LittleBigKid2000 updated:

    +
      +
    • The God Emperor of Mankind disk now works properly
    • +
    +

    TheDZD updated:

    +
      +
    • Xenomorph hunters' leap ability is now always blocked by shields rather than only 50% of the time.
    • +
    • Xenomorph hunters' leap ability being blocked now stuns them as if they had hit a wall. The leap still goes on a 3 second cooldown as normal.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Adds fluff item "Tacticool EyePro"
    • +
    + +

    01 September 2016

    +

    Crazylemon updated:

    +
      +
    • Dying of low blood is no longer capable of causing eternal death
    • +
    • Having your body brought back to life will no longer break your health doll
    • +
    +

    monster860 updated:

    +
      +
    • Fixes hotel SNPC's getting access that they shouldn't get.
    • +
    + +

    29 August 2016

    +

    Crazylemon updated:

    +
      +
    • You can now mend incisions after having cut open someone's ribcage.
    • +
    • Abductor surgery works again
    • +
    • Face repair surgery works again
    • +
    • The `to_chat` messages are now more descriptive when given a bad target
    • +
    • Admins can now VV by a ref string, directly via a verb
    • +
    • VV now builds its HTML using lists, making it much faster to open
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Upgrades the newscaster's liquid paper printing apparatus. Newspapers printed are higher quality now.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Mining Drones can now toggle meson vision on or off, a light, switch attack modes, or even drop their own ore
    • +
    • Ash storms no longer impact sheltered areas and mining mobs are immune to ash storms
    • +
    • Adds in two new end-round sounds
    • +
    • Fixes drones not being able to bump open doors
    • +
    +

    Fox McCloud and KorPhaeron updated:

    +
      +
    • Adds in mining shelters
    • +
    • Adds in a few more dice types and ensure dice are packed in bags and not pill bottles
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added additional coating to Turbine room.
    • +
    • Fixed leftover vent in Brig Physician's office
    • +
    • Fixed missing coated rwalls in Incinerator
    • +
    +

    Krausus updated:

    +
      +
    • Girders are no longer bulletproof.
    • +
    • Changelings' Swap Form ability now actually deducts its cost upon use, and shouldn't arbitrarily fail to work properly.
    • +
    • Fixed setting status display alerts through communications consoles.
    • +
    +

    Kyep updated:

    +
      +
    • Fixes 'SSD!' warning appearing in attack logs for admins, when the target player was dead and had ghosted out of their body
    • +
    +

    TheDZD updated:

    +
      +
    • Bookcases no longer force you to take out a book after clicking them
    • +
    • Fixes assorted things logging attacks incorrectly.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • AIs can no longer interact with nuclear bombs (Syndicate-brand included). AIs can still see the countdown
    • +
    • Mobs without appendixes can no longer contract appendicitis
    • +
    • Holosigns cannot be pulled around
    • +
    + +

    19 August 2016

    +

    Crazylemon updated:

    +
      +
    • pAIs should now save
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Repairing burn damage to robotic limbs now consumes cable in the process. Each length used repairs 3 burn damage, up to 15 damage per click.
    • +
    • Repairing brute damage to robotic limbs now uses 1 fuel per repair (click). Heal amount unchanged.
    • +
    • Self-repairing with cables or welders now incurs a 1 second delay between click and heal completion. Being repaired by a friend is still no delay (but requires a friend).
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in the Kinetic Smasher as a mining purchase
    • +
    • Fixes slap emote text being the wrong partial color
    • +
    • Fixes the attack text of simple animals attacking human mobs
    • +
    +

    IcyV updated:

    +
      +
    • Adds in an amount of new graffiti
    • +
    • Fixes the issue of other graffiti only being able to be done in black.
    • +
    +

    Krausus updated:

    +
      +
    • Flavor text and records are no longer horrifically butchered when saved in the database.
    • +
    +

    TheDZD updated:

    +
      +
    • Lowered genetic instability damage thresholds by 5 across the board. Effectively meaning that you can have one additional minor power without shifting into the next threshold.
    • +
    • Lowered the rate at which damage scales with instability, and the decreased upper cap on each damage type.
    • +
    • The base activation probability for powers is now 100%, rather than 45%. Abilities affected include everything except Cloak of Darkness, Chameleon, No Breathing, Hulk, Telekinesis, and X-Ray Vision, which all have their own independent activation chances (varying from 5% to 10%).
    • +
    • Increases activation chances of TK (10% to 15%), No Breathing (10% to 25%), Cloak of Darkness (10% to 25%), Hulk (5% to 15%), X-Ray Vision (10% to 15%), and Chameleon (10% to 25%).
    • +
    + +

    18 August 2016

    +

    Alexshreds updated:

    +
      +
    • pAIs can see the crew manifest again.
    • +
    • Engineers and Atmos Techs have access to the ORM
    • +
    +

    Ar3nn updated:

    +
      +
    • dusting playermobs now generates remains fitting for their race.
    • +
    +

    Chakishreds updated:

    +
      +
    • You can now click on objects in a gassy room at the expense of ninja floors.
    • +
    +

    Chopchop1614 updated:

    +
      +
    • fixes transformation sting not working.
    • +
    • transformation sting now checks if the target has DNA or not
    • +
    +

    Crazylemon updated:

    +
      +
    • Alt+Click should be quicker now
    • +
    • The Alt+Click panel vanishes only when you alt click a turf distant from yourself
    • +
    • Adds `json_to_object_arbitrary_vars`, a proc intended for use with SDQL
    • +
    • Eye color is tracked on the eyes only, instead of on the body.
    • +
    • The CMA panel no longer runtimes when you change species.
    • +
    • Deserializing a human now preserves hair and eyes.
    • +
    • Associative lists in VV now display properly again
    • +
    • Admins can now click on the DI panel buttons to debug the corresponding controller in VV
    • +
    • Fat people are now fat when naked.
    • +
    • Encased mobs can now examine
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Makes teleportation checks more consistent, which will ensure that teleporting in the away mission no longer works.
    • +
    • People on the space ruins level no longer count as dead for assassinate objectives.
    • +
    • Space border turfs will now regain their destination when over-written and replaced on the edge of the map
    • +
    • The space manager will no longer runtime if a space ruin writes on the edge of the map
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • ERT gloves reverted to how they used to be.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • WOLOLO! Traitor Chaplains can now WOLOLO with the new Missionary Staff and Robes. WOLOLO!
    • +
    +

    Fethas updated:

    +
      +
    • The whitelist will respect addons better, didn't even have to make a ban appeal..
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Detective's coolness variable cranked up to 14.5, they will no longer vomit over corpses.
    • +
    • Now you're less likely to vomit over a corpse if you're a normal human being.
    • +
    • golems now have their master saved in attack logs
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in formal captain's uniform and armor
    • +
    • Adds rapier to captain's locker
    • +
    • Adds lace up shoes to captain's locker
    • +
    • Adds crown to captain's locker
    • +
    • Dramatically speeds up conveyor belts
    • +
    • Appendicitis and Disease Outbreak events will no longer impact clientless mobs
    • +
    • Fixes bandolier being invisible on spawn
    • +
    • Removes the jukebox from the bar
    • +
    • Detective Scanner, Fedora Tipping, Pontificating, and Cap Flipping are now action buttons
    • +
    • Cane Gun and NT Rep's cane now acts as actual canes
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Fixed missing space transition tiles in emergency shuttle transit
    • +
    • Fixed lack of prisoner access to lower part of labor camp shuttle
    • +
    • Changed UO45's and MO19's away missions' external tiles to just airless ones.
    • +
    • Changed MO19's exterior to be more rock than ground, this is to make Linda cry less when this mission is passed.
    • +
    +

    General Chaos updated:

    +
      +
    • Ports TG's mech bay recharger code.
    • +
    +

    IcyV updated:

    +
      +
    • Adds an exploding chameleon flag for traitors.
    • +
    +

    KorPhaeron and Fox McCloud updated:

    +
      +
    • Merges Malf AI into traitor AI
    • +
    • Malf AI's starting CPU reduced from 100 to 50
    • +
    • Hacking APCs gives 10 additional CPU
    • +
    • Hacking APCs throws an alert to the AI when it's hacking that automatically clears when hacking is complete (sounds too)
    • +
    • Traitor AI's start off with a syndicate headset
    • +
    • Adds doomsday device module for AI's for 130 CPU; when activated, it will purge the station of all life if the AI is not destroyed after 7.5 minutes
    • +
    • Adds in AI upgrade modules which allows you to giving hacking abilities to the AI or allow it to have increase surveillance capabilities
    • +
    +

    Krausus updated:

    +
      +
    • Karma spending is now slightly more straightforward and sanity-checked.
    • +
    • Ghosts can now see non-crew antagonists in the Award Karma listing.
    • +
    • You can now ctrl+click on yourself to stop pulling something.
    • +
    +

    Kyep updated:

    +
      +
    • Added Syndicate Infiltration Teams (SITs), which are like Syndicate Strike Teams (SSTs) but focusing on stealth rather than direct combat. Useful for getting ghosts into rounds, spicing up rounds, having traitors with teamwork, and new kinds of traitor objectives like kidnap.
    • +
    • Fixed bug that Dust implants had no icon.
    • +
    +

    LittleBigKid2000 updated:

    +
      +
    • The arrivals checkpoint camera monitor is now connected to some camera networks by default.
    • +
    • Talking swords can now be understood by their wielders, and everyone else.
    • +
    • Engineering cyborgs now have floor painters. Absolutely nothing bad can happen because of this.
    • +
    +

    Norgad updated:

    +
      +
    • Coated Reinforced Walls now have unique sprites
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Trash Bags fit in satchels/bags/duffelbags, but cannot be transported after being filled up.
    • +
    • Advanced Mops clean faster, can clean more
    • +
    • Holosign Projectors can create more signs
    • +
    • Ghosts can no longer create dirt
    • +
    • Dirt creation slowed down. "Clean Station" may actually be remotely possible now
    • +
    • Janitorial Closet tidied up
    • +
    • Can fill Light Replacers with boxes directly
    • +
    • Can recycle 3 broken/burnt bulbs into a functioning one
    • +
    • Can no longer cheat around NODROP by inserting NODROP lightbulbs into Light Replacers
    • +
    • Ghosts can no longer trip Proximity Sensors
    • +
    • Ghosts can no longer trip Infrared Sensors
    • +
    • Effects (like hallucinations) can no longer trip Proximity and Infrared Sensors
    • +
    • IDs are no longer dropped if their owner cryos with the ID inside a PDA inside a bag (very specific, yes)
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Allows sechailer phrases to be selectable
    • +
    • Quick-equipping a PDA will now prioritize the PDA slot before the ID slot.
    • +
    +

    taukausanake updated:

    +
      +
    • Gives proper mix_messages for Uplink, Synthignon, and Synth 'n Soda drinks
    • +
    +

    tristan1333 updated:

    +
      +
    • Spacepod paint
    • +
    + +

    08 August 2016

    +

    Ar3nn updated:

    +
      +
    • Telekinesis no longer is subject to meatspace problems
    • +
    +

    Chakirski updated:

    +
      +
    • Added animal AI holograms.
    • +
    • .45 Magazine sprites for the M1911 are now longer invisible.
    • +
    • Hoodies no longer look like labcoats while in hand.
    • +
    • Ectoplasm spawns in cult mining rooms instead of an invisible "weapon".
    • +
    • Duffel bag descriptions and names no longer contain "duffle".
    • +
    • Syndicate medical duffel bags can now be seen while in hand.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Adds a "Save" buildmode for admins to preserve their creations for later. This is currently in an early stage, so don't be surprised by errors!
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Holy Water will no longer make you stutter for ages if you're not a cultist
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes Orion Ship message being unheard when held in-hand
    • +
    • Adds headphones into the game as a loadout item
    • +
    • Removes fireproof core malf AI power
    • +
    • upgrade turrets malf AI power CPU reduced from 50 to to 30
    • +
    • Overload machine cost increased from 15 to 20
    • +
    • Override machine cost increased from 15 to 30
    • +
    • can override/overload field generators again
    • +
    • Machine uprisers will slowly die if they aren't attacking someone
    • +
    • Adds in Hostile lockdown malf AI power for 30 CPU
    • +
    • Adds break air and fire alarms malf AI powers for 50 and 25 CPU respectively
    • +
    • AI's no longer have flood mode on air alarms by default
    • +
    • Adds in lip reading malf AI power for 30 CPU
    • +
    • Allows accessories to hypothetically grant armor to their wearer
    • +
    • Greytide spear illusions actually have an attack sound now
    • +
    • fixes the wormhole event being much shorter than intended
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Walls now melt when hot
    • +
    • Added actual coated rwalls - you can make them by clicking on an existing rwall with at least 2 plasteel in hand. Has infinite temp resistance.
    • +
    • Replaced all fake coated rwalls with new rwalls in both metastation (where they should be) and boxstation
    • +
    • Bandaging someone no longer stabs your eyes with bright green
    • +
    • Fixed repainted-to-wood metal flooring in courtroom - it's now actually wood
    • +
    • Fixed windoor in witness stand facing the wrong way
    • +
    +

    KasparoVy updated:

    +
      +
    • Traitors with the Maroon objective will no longer succeed if their target is in a locker on the shuttle.
    • +
    • Traitors with the Assassination objective will no longer fail if their target is assassinated/borged/debrained but on a Z-level greater than the derelict.
    • +
    +

    Krausus updated:

    +
      +
    • Fire will now totally consume you, rather than timidly hiding under your clothes.
    • +
    • Admin freeze overlays should no longer disappear from humans until they're actually unfrozen.
    • +
    +

    LittleBigKid2000 updated:

    +
      +
    • Adds cheap sunglasses. They provide no flash protection, but are available in the loadout and clothesmate.
    • +
    +

    Pinatacolada updated:

    +
      +
    • Makes the swedish gene spit out weird swedish chars and sounds
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Fixes "is too cumbersome to carry in one hand" from showing up to other players.
    • +
    +

    Yurivw updated:

    +
      +
    • Condimaster now actually makes bottles. Removed: Unused options in admin secret menu are now removed.
    • +
    +

    chopchop1614 updated:

    +
      +
    • fix bluespace crystals exploit
    • +
    + +

    03 August 2016

    +

    Fox McCloud updated:

    +
      +
    • Fixes a rare case where the singularity would escape containment when properly set up+contained
    • +
    +

    Krausus updated:

    +
      +
    • Non-respawnable ghosts will no longer qualify for mid-round rejoining (event antags, golems, posibrains, etc). Drones, PAIs, and ERTs are exceptions to this.
    • +
    • Cryodorms will no longer produce respawnable ghosts for the first 30 minutes of the round.
    • +
    • Fixed the spooky arrival shuttle. Cryo'd ghosts will now appear above their cryo pod, in the spooky cryodorms.
    • +
    • Cryodorms will now despawn you 90% faster if you willingly enter one.
    • +
    • Suiciding in the first 30 minutes of a round will no longer allow you to ghost and be respawnable.
    • +
    • Becoming a non-respawnable ghost lasts the entire round, even if you ghost in a respawnable manner later on.
    • +
    • You can no longer spam pinging posibrains, and cannot ping them at all if you cannot volunteer for one.
    • +
    • Missing limbs will now be grayed out on your health doll.
    • +
    +

    chopchop1614 updated:

    +
      +
    • Fixed the C4 labcoat exploding bug
    • +
    + +

    01 August 2016

    +

    Crazylemon64 updated:

    +
      +
    • Admins are now able to print a map of the z levels.
    • +
    • Admins are now capable of scrambling the z levels' transitions.
    • +
    • Janiborg trash bags no longer fit down disposals when empty
    • +
    +

    Fethas updated:

    +
      +
    • (Maybe?)..We actually check if the race HAS BLOOD before trying to suck them
    • +
    • Due to various complaints from tajarans having hand cramps, glove makers have removed plasteel from the fabric.
    • +
    • Plasmaman can no longer be vampires.
    • +
    • Removes the mask check on both victim AND vampire, also makes the message a bit more obscure, so it's up to your imagination of where you are biting them and with what.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Medical stacks now have 6 uses
    • +
    • Medical stacks now heal 25 burn/brute
    • +
    • Applying a medical stack to others is instant, no matter what
    • +
    • Applying any medical stack to yourself has a 2 second delay
    • +
    • Applying a splint to yourself has a 10 second delay
    • +
    • No more RNG fumbling of putting splints to yourself
    • +
    • Confirmation for applying medical stacks is now green
    • +
    • Advanced Medkits now have 2 trauma kits, 2 burn kits, a health analyzer, 1 roll of gauze, and medipen.
    • +
    • Amount of splints in medical vendors increased from 2 to 4
    • +
    • Fixes weird icon updates when getting healed by medical kits
    • +
    • Adds in object burning system that allows things to be lit on fire
    • +
    • being on fire should heat you up a bit quicker and do a bit more damage
    • +
    • Novaflowers ignite you rather than uselessly heating you up
    • +
    • Adjusts a few pyrotechnic chems to better fit with other tweaks to fire damage
    • +
    +

    IcyV updated:

    +
      +
    • Adds a unique axe for Atmos-traitors
    • +
    +

    Krausus updated:

    +
      +
    • Probably fixed some very specific items messing up View Variables for no adequately explicable reason.
    • +
    • Fixed round-end antagonist report failing to print due to null objectives.
    • +
    +

    Kyep updated:

    +
      +
    • Added atmos grenade kit to traitor uplink.
    • +
    • Fixed bug with adv pinpointers and CMO hypospray theft objectives. Fixes #5232
    • +
    +

    TheBeoni updated:

    +
      +
    • Adds "unique" jumpsuit for Pod Pilot so they can finally stop using security one Added picture because i do not like that red label
    • +
    +

    TheDZD updated:

    +
      +
    • Shadowling ascendance and badmins pressing the "Destroy All Lights" button should no longer bring the server to its knees.
    • +
    • Broken lights will no longer re-break.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Using ATMs leaves fingerprints behind
    • +
    +

    Twinmold updated:

    +
      +
    • Nuke Ops airtank connected to pipenet now.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Readded colored cable-cuffs.
    • +
    • Making stacks of metal rods now updates the icon correctly.
    • +
    + +

    28 July 2016

    +

    A Giant-Ass Mountain of Salt updated:

    +
      +
    • Re-adds PDA slot.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Adds an explosion buildmode
    • +
    • "Drop Everything" in VV no longer causes limbs to fall to the ground.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • IAAs can now select the classic secHUD in loadouts
    • +
    • adds bananas and suit jackets to the loadout system
    • +
    • adds dress shoes and fancy sandals to the loadout system
    • +
    • Miners can now get the mining coat from loadouts
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes organ repair surgery saying an organ wasn't damaged when it actually was
    • +
    • Removes the 1 burn heal from regular ointment
    • +
    • Regular bandages will now disinfect (in addition to stopping bleeding as they previously did)
    • +
    • Fixes a few crafting recipes not having the proper category
    • +
    • Fixes laser slugs not firing lasers
    • +
    • Adjusts the damage/consistency of improvised slugs
    • +
    • Adds in craftable bolas; throw them at someone to slow them down
    • +
    • Secvend starts off with e-bolas
    • +
    • Can make spears with personal crafting now
    • +
    • Fixes teacups and some other drinks having no sprite, in-hand, or object
    • +
    • adds alt-click rotating of chairs, disposal pipes, windows, the PA, emitters, and windoor assemblies
    • +
    • Cablecuffs are now made by opening the cable stack's crafting menu by using it in your hand
    • +
    • Fixes cablecuffs not having a unique in-hand icon
    • +
    • Fixes cable coils not having a unique in-hand icon
    • +
    • All cablecuffs will be red, regardless of what they're produced from
    • +
    • Fixes an unlimited metal exploit
    • +
    • IV Drip sprites updated; has visual feedback for if it's injecting or taking blood
    • +
    • IV Drip injection rate dramatically increased
    • +
    • Warning ping for when someone is low on blood
    • +
    • Support for species with exotic blood type
    • +
    • Alt-Click to toggle between modes
    • +
    • Sensory restoration virology symptom no longer has anti-stun properties nor heals brain damage, but has a lower acquisition level
    • +
    • Damage convert heals individual limbs instead of healing overall damage (actual impact is low)
    • +
    • Librarian now starts off with a bookbag
    • +
    • Bookbag can now hold Bibles, cult tomes, books, and spellbooks
    • +
    • Can empty a bookbag into a bookshelf
    • +
    • Fixes an exploit where you could generate wood out of thin air
    • +
    • Fixes blobspores doing more damage than intended
    • +
    +

    Fox-McCloud updated:

    +
      +
    • Adds in a few makeshift items/weapons: molotovs, grenade lances, golden bikehorn, paper bags, and DIY chainsaws
    • +
    • Fixes some personal crafting behaving as other than intended
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Fixed brig cell block APCs not getting power
    • +
    • Fixed space buggery Kyet made :angry:
    • +
    • Fixed missing light near labor shuttle dock
    • +
    • Fixed wrongly placed cobweb in solitary
    • +
    • Fixed basketball court not having a basketball
    • +
    • Added windows to brig processing entrance
    • +
    • Re-added the missing EOD and biohazard lockers in Armory
    • +
    • 6 gas masks from Armory
    • +
    • Added grid check into random events.
    • +
    +

    Krausus updated:

    +
      +
    • The voting panel now uses the browser datum, which means it looks nicer.
    • +
    • The voting panel now updates while a vote is in progress.
    • +
    • When a vote is started, it will now include a link to open the vote panel, as an alternative to typing in "vote".
    • +
    • Custom votes will now show full voting results upon completion.
    • +
    • Admins should no longer lose the "cancel vote" link in the voting panel.
    • +
    • View Variables should probably stop crashing admins.
    • +
    • The RnD console now shows an overlay while you're waiting for it to do work, rather than using a separate wait screen.
    • +
    • Admins now have click shortcuts for opening a player panel, showing mob info, and viewing variables. Specifics are in Hotkey Help.
    • +
    +

    Kyep updated:

    +
      +
    • Admins can now see attacks against SSD players more easily.
    • +
    • Clarified the text you get when examining a SSD player.
    • +
    • It is now possible for admins to remove a person's vamp thrall status.
    • +
    • Adds Vox, Greytide & Soviet loadouts to admin Select Equipment verb.
    • +
    • Fixes an issue with spy loadouts, and excessive access on loadouts in general
    • +
    +

    Spacemanspark updated:

    +
      +
    • Cardboard boxes now have their own specific name in the cardboard sheets menu.
    • +
    +

    TheDZD updated:

    +
      +
    • Fixes tempgun not recharging.
    • +
    • Fixes tempgun beams costing one tenth of what they are supposed to.
    • +
    • Admin-only jobs check for R_EVENT now, instead of R_ADMIN, as event-related tools should.
    • +
    • Mentors should no longer get spammed by the library checkout computer on occasion.
    • +
    • Mentors should no longer get spammed by mirrors due to body accessories.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • AI Integrity Restorers now destroy any AIs inside if they get EMP'd
    • +
    • AI Integrity Restorers can be deconstructed if broken via explosions. This kills the AI inside
    • +
    +

    Twinmold updated:

    +
      +
    • Can no longer destroy pods with anything other than brute and burn weapons.
    • +
    • Can no longer pull someone out of a pod when no one is actually in the pod.
    • +
    • Can now melee attack pods with weapons when harm intent is on.
    • +
    • Vox Objective 4 now calculates the kills vox raiders actually have, instead of always complete.
    • +
    +

    Ty-Omaha updated:

    +
      +
    • Gives Combat Gloves to Code Red ERT agents.
    • +
    • Gives Code Gamma Engineering ERT agents Combat Gloves.
    • +
    +

    monster860, clusterfack, and DeityLink updated:

    +
      +
    • Adds space parallax
    • +
    +

    tigercat2000 updated:

    +
      +
    • Removes space parallax, due to server overhead, input lag & bugs
    • +
    + +

    21 July 2016

    +

    Alffd updated:

    +
      +
    • Added a 6th Vulpkanin tail option.
    • +
    • Fixes animations, side view, and pixel fill for Vulpkanin tail 6
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Engineers can properly show up for work with their hats and coats to keep warm.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Tajarans and Unathi can now wear all shoe and glove types
    • +
    • Glove clipping removed except for black gloves, which makes them fingerless gloves
    • +
    • Adds sandals as a loadout option
    • +
    • Adds in simple animal mob spawners
    • +
    • Adds shielded hardsuit to the nuke ops uplink for 30 TC
    • +
    • Implements the powerfist and adds it to the uplink for 8 TC
    • +
    • Removed drinking glass shattering (regular bottle shattering is still a thing)
    • +
    • Captain's flask is now gold instead of silver
    • +
    • Bottles have a throwforce of 15
    • +
    • can crack eggs into drinking glasses
    • +
    • Detective's flask starts out with 30 units of whiskey
    • +
    • removes redundant object verbs that have an action button
    • +
    • Fixes up mindswap spell so it behaves more properly
    • +
    • Fixes genetic abilities action buttons not properly clearing
    • +
    • Fixes simple animals, silicons, and brains becoming perma deaf from flashbangs and other sources
    • +
    • ACTUALLY FIXES MINING APC
    • +
    • Fixes brig cell timers not having the option to flash people
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added new syndicate item Chameleon SecHUD to uplink store, available for all antags. It can morph into various eyewear while being a flashproof sechud.
    • +
    +

    Kyep updated:

    +
      +
    • Added new syndicate costumes to "select equipment" admin verb.
    • +
    +

    TullyBBurnalot updated:

    +
      +
    • More beds outside the Operating Theaters, Pajama Wardrobes outside and inside the Operating Theaters, an extra NanoMed Vendor, one Disposal Chute per OR, table with cards
    • +
    • Sinks moved closer to Surgical Tables, moved light fixtures in the Operating Theaters, tables with surgical tools now made of glass for maximum style points and Xenomorph Larva Whack-A-Mole
    • +
    +

    monster860 updated:

    +
      +
    • Brig timer UI reopening after being closed fixed.
    • +
    + +

    20 July 2016

    +

    Allfd updated:

    +
      +
    • Added hologram fluff sprites
    • +
    +

    Ar3nn updated:

    +
      +
    • Gets rid of some weird lattices floating in mid-space
    • +
    +

    Chakirski updated:

    +
      +
    • Adds M.E. Reaper sprite.
    • +
    • AI can now choose a 32x64 reaper hologram.
    • +
    • Cigarette packs no longer show near-duplicate messages when examined.
    • +
    +

    CrAzYPiLoT updated:

    +
      +
    • Ports randomized space ruins from /tg/ station. There is a number of maps which can be spawned at any location on the empty z-level at roundstart, and up to three random ones will be chosen each round. Credits to KorPhaeron.
    • +
    • Lays the groundwork for a future lavaland implementation, if we choose to have it.
    • +
    • Adds a feature to the map loader where areas with the right var set can be distinctly initialized on map load - meaning separate APCs, and the like.
    • +
    • Using a z-level specific initialization freeze system, large elaborate maps like the cyberiad can be loaded without a single runtime, with minimal impact on the round elsewhere.
    • +
    • Adds a delete mode to the "Fill" buildmode - just alt-click for the second corner, and everything within will be removed.
    • +
    • Adds a "Jump To" function in VV, which is useful for getting an idea of what exactly you're looking at.
    • +
    • Added view count to newscaster feeds and messages.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Abductors consoles link correctly again
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Plastic explosives are now a subtype of grenades. Shouldn't be any noticable difference for players.
    • +
    • Plastic explosives no longer use the wire datum. You may directly attach an assembly holder (Such as a remote signaller + igniter assembly)
    • +
    • Adds X-4 shaped charges, designed for breaching explosively without harming the user. Pick some up at your local nukies r us.
    • +
    • Replaces tablecrafting with personal crafting, click the hammer icon by your intent selector to use it.
    • +
    • Removes the PDA slot, your PDA can now go in your ID slot (Again).
    • +
    • You can now alt click to remove an ID from a PDA, for quick interaction while it's in your ID slot.
    • +
    • Adds an overlay for an ID while it's inserted into your PDA.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds new Bottler machine for making unique beverages! Order one from cargo today!
    • +
    • Adds 6 new drinks obtainable via the Bottler. Get brewing!
    • +
    • Grapes now can be properly juiced again, as they now have the right kitchen tag.
    • +
    • Adds effects to the Paradise Pop reagents. Drink them all to unlock their powers!
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in fans which can block atmospherics passing over them
    • +
    • All mass driver blast doors have a fan underneath them, allowing you to use them repeatedly instead of once
    • +
    • Fixes medical, security, and employment records not being displayed
    • +
    • Adds in a weather system
    • +
    • Removes most of the miner's uniform equipment from their lockers and puts it in a miner's wardrobe
    • +
    • Miners start off with a lot of their clothing equipment equipped to them
    • +
    • Miners now have unique headset sprites
    • +
    • Miners no longer have lanterns, but a seclite; they can attach this to their kinetic accelerators now
    • +
    • Miners have workboots instead of black shoes
    • +
    • Miners no longer have a default mining scanner but an advanced one that works at reduced range (5 instead of 7) and has a longer cooldown between pulses (5 instead of 3.5)
    • +
    • removed extra mining hardsuit from the outpost
    • +
    • removed medikit spam from outpost; now just a toxin kit and a regular medical kit
    • +
    • Bluespace crystals now earn you points and can be refined into bluespace polycrystal sheets
    • +
    • Spare vouchers from QM and HoP removed
    • +
    • removed armor from the fake tactical turtleneck
    • +
    • Can scan vending machines with your PDA to pay for items (if there's an ID in your PDA)
    • +
    • Sleepers no longer require a console to build, only the sleeper itself
    • +
    • Clicking on the sleeper brings up the menu that was previously brought up for the console
    • +
    • Adds in syndicate sleepers--these sleepers are not only syndie themed but also allow the user to inject chems into themselves while inside the sleepers
    • +
    • Sleepers can now inject silver sulfadiazine
    • +
    • removes cryofeeds from cryodorms and adds in 2 more cryopods
    • +
    • Fixes pre-spawned loaded belts not having proper overlays
    • +
    • nanites will no longer purge chems, but will now heal internal organ damage, attempt to mend fractures, and will no longer cure beneficial viruses
    • +
    • cold and hot drinks should now properly heat you up or cool you down (this also goes for medical reagents)
    • +
    • beer no longer reduces jitteriness
    • +
    • toxins special and antifreeze heat you up
    • +
    • banana juice and banana honk now heals monkeys
    • +
    • Fixes atrazine not killing nymphs
    • +
    • mining autoinjectors no longer poison you
    • +
    • combat hypospray now has omni+epinephrine+teporone
    • +
    • stimpack is now meth+coffee instead of meth+epinephrine
    • +
    • Cheese and synth meat amount creation scales with volume of the reaction
    • +
    • sprinkles now heals all members of sec (brig phys, sec pod pilot, magistrate, and IAA are no longer left out)
    • +
    • Fixes syndi+shielded+hos hardsuit sprite issues
    • +
    • Fixes wizard's who have a regular satchel set in their prefs winding up with none
    • +
    • Spellbooks are automatically bound to wizards at round start (no more ragin' exploitative mages)
    • +
    • Fixes mining outpost lacking an APC
    • +
    • Fixes being able to exploit and turn artificial bluespace crystals into regular bluespace crystals
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added courtroom, left of brig.
    • +
    • Remapped brig
    • +
    • Moved prisoner processing and evidence storage to the right of brig, next to Detective's office.
    • +
    • Changed current processing to Interrogation and a hallway.
    • +
    • Re-mapped Conference and Locker rooms.
    • +
    • Lots of other minor tweaks to brig.
    • +
    • Seriously, way too many small changes to list here, go and have a look at the brig yourself.
    • +
    • Removed temp. detainment and observation from brig.
    • +
    +

    KasparoVy updated:

    +
      +
    • Wearing a suit will no longer cause runtimes due to the way suit-collars are handled.
    • +
    • The north direction sprite of the Vulpkanin 'Patch' facial hair style won't hang a pixel off the head anymore.
    • +
    +

    Krausus updated:

    +
      +
    • All admins can now see "admin log" messages.
    • +
    • Admins can now toggle "admin log" messages on or off.
    • +
    • Admins will no longer be notified about ghosted admins jumping around.
    • +
    • Beating on simple animals will no longer be twice as noisy as intended.
    • +
    • Emergency Response Teams are now usable again.
    • +
    +

    Kyep updated:

    +
      +
    • adds botany, basketball court, individual cells, library computer and more to perma. Makes it far less boring.
    • +
    • Tracking implants are now useful, showing the implanted person's general location, and health status, on prisoner consoles.
    • +
    • The NODROP flag now works correctly on jumpsuits.
    • +
    • Improved admin 'select equipment' verb. ERT option now works, costumes get IDs and proper headsets, two new costumes added, and some outfits minorly tweaked (e.g: tunnel clowns get toolbelts).
    • +
    • Prevented NPCs being made into objective targets.
    • +
    +

    LittleBigKid2000 and TullyBBurnalot updated:

    +
      +
    • Stethoscopes can now be used to tell if a person's heart or lungs are damaged, or if they have any at all. Now they're actually useful instead of telling you the obvious in a vague way.
    • +
    • Stethoscopes can no longer be used to hear the heartbeat and breathing of a person that doesn't have a heart or lungs.
    • +
    +

    Tauka Usanake updated:

    +
      +
    • Adds a Hydroponics HUD and a night vision version of it that can both be created in R&D. It provides additional details on plants in hydro trays and soil plots. Shows the health, nutrient, water, toxin, pest, and weed level of the plant as well as whenever it is ready to be harvested or is dead.
    • +
    +

    TullyBBurnalot updated:

    +
      +
    • Handless cuffing no longer possible. Can still cuff people with one hand
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Mobs with PSY_RESISTANCE are no longer valid targets for REMOTE_VIEW
    • +
    • When emagged, Photocopiers now have a cooldown if used to copy butts
    • +
    +

    Twinmold updated:

    +
      +
    • Fixes removing ID cards from laptops with the Eject ID verb.
    • +
    +

    monster860 updated:

    +
      +
    • A bunch of interfaces now use /datum/browser.
    • +
    • The ChemMaster now uses the asset cache, eliminating the enormous lag spike when you first use it. Yey!
    • +
    • Fixes the window not closing when selecting an icon for the chem-master
    • +
    • Fixes the chem master window not updating when selecting an icon
    • +
    • The chem-master icon selection window now has a 4x5 grid of icons.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Gas tanks now have an action button for accessing their interface.
    • +
    • You can now shift-click on movable HUD elements (such as action buttons) to reset them to their initial position.
    • +
    • Implants with limited uses, such as freedom implants, now delete themselves when they run out of uses.
    • +
    + +

    13 July 2016

    +

    Ar3nn updated:

    +
      +
    • Adds a silence button to newscasters, which will silence the regular update sounds
    • +
    +

    Chakirski updated:

    +
      +
    • Adds new bacon sprites.
    • +
    • Bacon can now be cooked from the grill. Just grill raw bacon.
    • +
    • Raw cutlets are now sliceable into raw bacon strips.
    • +
    • Plasma and N20 look more gassy.
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Greys no longer speak in wingdings.
    • +
    • Greys now have a species-specific language.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Overall borg power useage has been lowered
    • +
    • Borgs who have completely run out of power can now still move around/see/talk, but they will be unable to interact with machinery/doors around them; they can still bump open doors, however. Borgs with no cell are still completely paralyzed and can't do anything.
    • +
    • IPCs are now properly impacted by space's burn damage
    • +
    • NT Rep's cane stuns for less and invokes a cooldown between use, similar to telebatons
    • +
    • Oxygen damage number changed a bit; damage is based upon volume lost more now
    • +
    • Species that have blood but are oxygen immune will now take tox damage
    • +
    • Health analyzers will now work with species with exotic blood and inform the user what type of exotic blood they have
    • +
    • Other machinery that display blood levels (op table, sleepers, advanced scanners, etc) will now work with exotic blood
    • +
    • Changeling regen will now properly restore blood if you have exotic blood fix Fixes being blurry for 20+ minutes when you were low on blood for a mere 3 minutes
    • +
    • Heart damage impacting blood volume removed
    • +
    • Nutrition draining when low on blood removed
    • +
    • Station cinematics shouldn't have inventory overlays over top of the animation
    • +
    • Station cinematics should properly clear off the screen and delete now
    • +
    • pAIs are no longer valid targets for gun turrets (like on the syndicate ship)
    • +
    • Adds in Rathen's secret, a new spell for the wizard that AoE stuns
    • +
    • Removed borg jetpacks
    • +
    • Adds in borg ion pulse system; borgs with ion pulse enabled consume extra power for each turf they move but can travel on space. Can upgrade any borg, at R&D with an ion pulse upgrade
    • +
    • Adds in cyborg self repair upgrade: very slowly repairs cyborgs at the cost of extra power. Available at R&D
    • +
    • Mining cyborg module tweaked slightly: GPS, shovel, mini welding tool and mini extinguisher added, wrench and screwdriver removed
    • +
    • reset borg module removes speed boost
    • +
    • Fixes borg's stun arm bypassing shields
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds Vox compatible versions of all jumpskirts.
    • +
    • Adds Vox compatible version of the CMO jumpsuit.
    • +
    +

    Krausus updated:

    +
      +
    • Players will ALMOST DEFINITELY never get stuck as plants anymore. I mean it this time!
    • +
    • Fixed morgue trays not updating themselves when you ghost into/out of your body.
    • +
    +

    Kyep updated:

    +
      +
    • Changed access requirement on lethal injection locker to sec access (same access required for the chair its right next to.
    • +
    • Changed access requirement on exile implant locker to armory access.
    • +
    • Ghosts no longer miss out on ERTs due to not knowing it was called, or not being able to find the verb. They are now prompted about joining an ERT when one is called.
    • +
    • Fixed a condition where 'we are assembling an ERT' message is broadcast, but no ERT is generated.
    • +
    • Typo fixes in ERT messages.
    • +
    • Entering a cryo pod, then deliberately selecting OOC->Ghost, and clicking yes on the prompt, will now instantly send you to long-term storage, removing you from the round, despawning your body, freeing your job slot, and giving a new objective to any antag that had you as a target.
    • +
    • Announcements about someone entering long-term storage via a cryopod now include that person's rank.
    • +
    • When an antag target cryos, the message the antag gets about their objectives changing is now clearer.
    • +
    +

    TheDZD updated:

    +
      +
    • Adds "salts" as a say verb for deadchat ghosts.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Universal Recorder added to NT Rep Locker
    • +
    • Box of recorder tapes added to NT Rep and IAA Locker
    • +
    • Fax Guide added to Captain, HoS, HoP, NT Rep and IAA Lockers
    • +
    • Butt copy alert added to photocopiers
    • +
    • Butt copy alert comes with *ping noise
    • +
    • Photocopiers start with 60 toner
    • +
    +

    Twinmold updated:

    +
      +
    • Vampires with sleeping carp (traitor+vampire rounds) can now suck people's blood like normal.
    • +
    +

    monster860 updated:

    +
      +
    • The ChemMaster now uses NanoUI! Yey!
    • +
    • Alerts are no broken ghostly outlines
    • +
    + +

    09 July 2016

    +

    Chakirski updated:

    +
      +
    • Adds disabled_component() to cyborgs.
    • +
    • EMPs now disable binary communication for as long as the stun time.
    • +
    • Syndicate thermal imaging glasses (mesons) can now be prescription upgraded like normal mesons.
    • +
    • Green glasses from the AutoDrobe can now be prescription upgraded.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Deepfryers are no longer arcane mysteries, and can be (de)constructed and upgraded.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Grenade have a chance to explode when the person holding them is shot
    • +
    • Flamethrowers can release their tank's contents if the person holding them is shot
    • +
    • Can no longer self-trigger blocked shield events (ie: no self-harm to trigger a reactive teleport armor)
    • +
    • Hugging someone/shaking them up bypasses shield checks (oh no, hugs of death)
    • +
    • Riot shields have a +30% chance to block thrown projectiles
    • +
    • Hunter pounces are now a thrown attack as far as shield go, and yes, can be blocked by riot shields now
    • +
    • Energy shields no longer block anything other than beam and energy projectiles
    • +
    • Being able to be pushed is based on the block chance of the item you're holding instead of it just being based on riot shields
    • +
    • Adds in cursed wizard heart, purchase it from the wizard's spell book for 1 point, but be wary of not keeping the heart beating...
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added a bunch of new items to maint, some rare uplink gear included. (see PR for full list)
    • +
    • made gas masks, nothing and extinguishers less common in maint
    • +
    +

    Krausus updated:

    +
      +
    • Players probably won't get stuck as plants forever anymore. Probably.
    • +
    • Refactored job ban checking, which should massively reduce round start-up time.
    • +
    • Job bans/unbans will now take effect instantly, rather than at the next server restart.
    • +
    +

    TheDZD updated:

    +
      +
    • DNA injectors no longer always activate powers that are supposed to have a chance to activate.
    • +
    • Dionae can no longer activate the radiation disability, nor the run superpower except via adminbus.
    • +
    • Adds genetic instability, which causes a variety of negative effects, including toxin damage, burn damage, cloneloss, and even gibbing. Effects get worse as stability gets lower, burn damage starts below 85 stability, tox and clone below 70, and gibbing once you're below 40.
    • +
    • Adds Curse of the Cluwne touch attack spell, which wizards can pick, heavily based off of the same spell from Goonstation. Said spell adds an unremovable honk tumor to the target, gives them NODROP neon green clown gear, makes them stutter, makes them almost eternally fat, confuses them, makes them clumsy and speak in Comic Sans, and severely brain damages them. Use it on a cluwne however...
    • +
    • Fixes a bug where honk tumors would cause NODROP items to still be moved, despite being unable to be unequipped.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • Botanist access to the morgue revoked
    • +
    • Added custom messages for evil faxes
    • +
    • Added unique text body for each non-evil fax template
    • +
    • Added a "Keep up the good work" fax template
    • +
    • Added a "ERT Instructions" fax template
    • +
    • Photocopiers can be emagged
    • +
    • Emagged photocopiers deal 30 burn damage to all mobs copying their butts
    • +
    • Deconstructing Comfy Chairs yields 2 metal sheets
    • +
    • Boxes no longer allowed inside evidence bags to prevent them going into themselves
    • +
    • Monocles are now prescription upgradable
    • +
    • Monocles added to Loadout selection
    • +
    • Spinning a revolver's chamber makes a noise again
    • +
    • Revenants can actually be killed now.
    • +
    • AntagHUD activation disqualifies player from rebooted drones
    • +
    • Sergeant Ian hat now visible
    • +
    +

    Twinmold updated:

    +
      +
    • Fixes the inconsistency of getting 2 metal rods when you wirecutter a destroyed grille down to 1.
    • +
    + +

    07 July 2016

    +

    Ar3nn updated:

    +
      +
    • Adds tech levels to RnD console main menu
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Chicks no longer lose their souls (literally) when becoming adults.
    • +
    • Intercoms, fire alarms, and air alarms no longer contain internal portals to a realm of infinite cables and circuit boards.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Space lube damage removed and duration reduced from 7 to 5
    • +
    • Azide and CLF3+Firefighting foam now play a bang sound when mixed
    • +
    • Can now pet pAI's with help intent
    • +
    • Fixes sechuds and nightvision sechuds having flash protection
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added windows and a missing firelock to Genetics/Cloning
    • +
    • Tweaked layout of Genetics slightly
    • +
    • Added photocopier to R&D.
    • +
    • Tweaked RD's office layout slightly
    • +
    • Changed access on Tcomms' external airlocks' buttons to be same as general Tcomms access
    • +
    • fixed the airless tiles in Assembly Line's windows
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds improved Vox mask/goggle sprites.
    • +
    • Adds Vox-compatible versions of most suits.
    • +
    • Adds species-fitting and icon override handling to clothing accessories and suit collars.
    • +
    • You can now open/close Clown Officer and Soldier coats.
    • +
    • Adds by-species tail hiding.
    • +
    • Tidies up and refactors the way the Captain's space helmet shows Vox hair but hides every other species'.
    • +
    • Reactive armour's sprite will now update as soon as you turn it on/off or EMP it.
    • +
    +

    Krausus updated:

    +
      +
    • Fixed borers dying in hosts who happened to be somewhere cold, such as space. Even if their host was in a space suit.
    • +
    • Fixed borers forgetting to detach from a host when it died.
    • +
    • Fixed borers being able to assume control of a dead host.
    • +
    • Fixed dead borers in a host being able to speak with the host and ghosts.
    • +
    • Fixed employees starting every shift at least 3 minutes late. You aren't getting paid to stand around, people!
    • +
    • Fixed animal beatdowns being twice as noisy as they should be.
    • +
    • Pod lock busters should now properly bust pod locks.
    • +
    • The late-stage effects of the "sensory destruction" disease symptom should now properly destroy your senses.
    • +
    • Autotraitor should now continue picking new in-game traitors, instead of picking one and dying.
    • +
    • Lacking a head no longer makes you immune to becoming a husk or skeleton.
    • +
    • Security and medical records should probably stop crashing people.
    • +
    • Altering details on an Agent ID Card will now actually update what's seen when examining the card.
    • +
    +

    Kyep updated:

    +
      +
    • Fixes NT Special Ops Officer's headset so he can correctly hear, and talk on, the Special Ops (deathsquad) channel.
    • +
    • Fixed oversight in keycard authentication devices that incorrectly treated trialmins like fullmins, resulting in situations where calling an ERT became impossible.
    • +
    • If an ERT request gets no answer for 5 minutes, admins now get a one time reminder that it was sent.
    • +
    +

    TheDZD updated:

    +
      +
    • Burst fire selection is now a proc, as it was meant to be, rather than a verb.
    • +
    +

    TullyBurnalot updated:

    +
      +
    • AI can no longer interact with IV Drips
    • +
    • Robots can no longer remove beakers/blood bags from IV Drips
    • +
    • Fixed clown door deconstruction
    • +
    • Fixed mime door deconstruction
    • +
    + +

    02 July 2016

    +

    Fethas updated:

    +
      +
    • adds comfirmation dialogs to transforms from player panel
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in laughter demons
    • +
    • Can summon laughter demons as a wizard
    • +
    • Chem master can produce instantaneous medical patches if all chems are safe
    • +
    • Can now purchase sniper rifle and associated ammo on uplink during nuke ops
    • +
    • Most melee and laser armor values halved or reduced; some bullet armor reduced slightly
    • +
    • Slowdown on most armor and spacesuits reduced by 1 (chaplain armor is still slow though)
    • +
    • Mining armor caps out at 60 melee resist as opposed to 80
    • +
    • Ling melee armor reduced; bullet and laser values buffed a bit and slowdown removed
    • +
    • Chameleon jumpsuit has a little bit of armor
    • +
    • Detective's forensic jacket now has identical armor to the native detective jacket
    • +
    • Armor penetration added to energy swords, chainsaws, scythes, and spears
    • +
    • Fixes stun batons, telebatons, and abductor batons piercing/bypassing shields
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Adds appropriate battle yells to sleeping carp
    • +
    +

    KasparoVy updated:

    +
      +
    • Engineer boots that've had their toes cut open now have a sprite.
    • +
    • Vox now have engineer workboot sprites.
    • +
    • Removes unused SWAT boot sprites that were really just copypasted jackboot sprites.
    • +
    +

    Krausus updated:

    +
      +
    • The late-join job listing is now big enough to show all the jobs at once, and organizes them into labeled categories.
    • +
    • Fixed Hotkey Help and hotkey mode toggle messages not appearing.
    • +
    • The late-join job listing will now ignore (mis)clicks for the first second after popping up.
    • +
    +

    Kyep updated:

    +
      +
    • "Loyalty" implants are now known as "Mindshield" implants
    • +
    • Admins playing CC jobs can no longer get antag status from autotraitor.
    • +
    +

    Tastyfish updated:

    +
      +
    • There's essentially a completely new space hotel map! Explorers rejoice!
    • +
    +

    TheDZD updated:

    +
      +
    • Chance for vampires to burn in the chapel has been greatly reduced (from a 35% chance down to 8% per tick).
    • +
    • Vampires do not scream from chapel/space burning until they actually start catching fire.
    • +
    • Threshold for vampires to catch fire from space/chapel burning changed from 60 health to 50 health.
    • +
    • Fire stacks from vampire burning no longer apply twice 35% of the time while below the health threshold.
    • +
    +

    VampyrBytes updated:

    +
      +
    • No more *me emoting from your corpse!
    • +
    +

    monster860 updated:

    +
      +
    • Fixes ghosts having a generic icon when darkness is toggled off
    • +
    +

    tigercat2000 updated:

    +
      +
    • There's a new tab in the character setup screen, "loadouts". This allows you to spawn with a limited number of preset items.
    • +
    • Character setup now uses #defines for the different tabs.
    • +
    + +

    28 June 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Replaced the current recycler sound with a new one.
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Adds workboots to be worn by engineers.
    • +
    • Fixes the scanner's search functionality.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • To save on adhesive costs, Nanotrasen has stopped gluing stools to the floor. The resulting bodily injuries probably won't cost more than the glue.
    • +
    +

    Fethas updated:

    +
      +
    • you can now pick up potted plants and stealth
    • +
    +

    FlattestGuitar updated:

    +
      +
    • changes some alcohol values, the weaker ones are no longer as weak
    • +
    • refactored alcohol, you can now take short breaks between sips and still pass out in a gentlemanly manner
    • +
    • different species have different levels of alcohol resistance, check in with your bartender for more information
    • +
    • The medical HUD will now be a bit smoother. Neat.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Warden starts off with a pair of Krav Maga Gloves
    • +
    • New Steal objective: steal the warden's krav maga gloves
    • +
    • Clonepods will automatically suck in nearby meat
    • +
    • Slime processors will automatically suck in nearby dead slimes
    • +
    • Actually fixes vamp chaplains
    • +
    • Fixes clumsy check on guns not working properly, resulting in people with glasses shooting themselves in the foot
    • +
    • pAI candidates can now see who requested them
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds Yi to Vox-pidgin syllables. (Port from VG.)
    • +
    • Adds framework for icon-based skin tones. (Port from VG.)
    • +
    • Adds Vox-compatibility for all remaining eyewear.
    • +
    • Raiders now get a random skin tone and eye colour on spawn.
    • +
    • Species default hair, facial hair and head-accessory colours can now be defined.
    • +
    • Newly created Vox mobs will spawn with the same hair colour as they used to have pre-greyscaling.
    • +
    • Noir vision will no longer grey out the HUD. (Port from VG.)
    • +
    • Tails will not be coloured if the person's species doesn't have skin colour.
    • +
    • Vox hair (head and facial) have been greyscaled and can now be customized by the full colour range.
    • +
    • IPC parts from the mech fabricator won't turn IPCs invisible upon attachment anymore.
    • +
    +

    Krausus updated:

    +
      +
    • Added a custom runtime error handler.
    • +
    • Added an in-game runtime viewer.
    • +
    +

    Kyep updated:

    +
      +
    • Admins now hear boink sound when faxed, command sends ERT request, etc
    • +
    • Admins can reply to faxes via radio
    • +
    • Admins can reply to faxes with pre-written fax templates
    • +
    • Admins can reply to faxes with 'evil faxes', special faxes that have negative effects on their intended recipient (and nobody else)
    • +
    • Admins can now join as "Nanotrasen Navy Officer", and "Special Operations Officer". They spawn on adminstation and ERT office, respectively. They are not announced and do not appear on crew manifest.
    • +
    • "Select equipment" verb outfits tweaked for consistency with the above job outfits
    • +
    • Teleporter on admin station now works.
    • +
    • Added antag-only warning to bee briefcase, to reduce chances of traitors killing themselves with it.
    • +
    +

    LittleBigKid2000 updated:

    +
      +
    • Space explorer corgis can now safely explore space
    • +
    +

    Norgad updated:

    +
      +
    • Maintenance around the incinerator has been expanded.
    • +
    • Engineering maintenance finally has an APC.
    • +
    • The incinerator has been moved eastward, there is now a construction area in it's previous location.
    • +
    +

    Tastyfish updated:

    +
      +
    • Cryo tubes, sleepers, and body scanners now eject random items the occupant dropped, upon the occupant being ejected.
    • +
    +

    TheDZD updated:

    +
      +
    • Adds an adminbuse gun that fires gun mimics, you can varedit the gun's `mimic_type` var to any gun path, and it'll fire that gun as mimics. By default it fires stetchkin pistol mimics.
    • +
    • Fixes minor issues caused by some guns having text paths for power cells.
    • +
    • Fixes some runtimes and inconsistencies with the telegun and temperature gun.
    • +
    • The Tesla engine has acquired a grudge for lockers, and will now smite any in its path.
    • +
    • Unstable bluespace teleportation devices have been removed from energy guns, meaning they should no longer teleport from one hand to another when switching firing modes.
    • +
    +

    Twinmold updated:

    +
      +
    • You can once again resist borer control with the Resist verb.
    • +
    +

    VampyrBytes updated:

    +
      +
    • Emotes can now be accessed through verbs as well as say *
    • +
    • Emotes accessed through say * no longer take parameters after a -
    • +
    • Emotes now take parameters through input boxes
    • +
    • Emotes now have support for blind and deaf characters
    • +
    • Emotes now personalise messages
    • +
    • Flip can now be targeted with or without a grab
    • +
    • All emotes that are affected by being muzzled now make the user make some kind of noise
    • +
    • monkeys now have access to all the emotes that the npc tries to perform
    • +
    • Leap genetics ability lets you jump over things
    • +
    +

    monster860 updated:

    +
      +
    • UI now gets it's own plane
    • +
    • RnD console now uses NanoUI! Sweet!
    • +
    • Fixes tranquillite being outside the box in the materials list. Mimes are supposed to be trapped inside a box, not outside one.
    • +
    • Replaces the weird unicode "x" character in some design names with the actual letter "x" so that it doesn't fuck up NanoUI
    • +
    • RCD gets a UI
    • +
    • RCD-built airlocks can now receive different types and accesses.
    • +
    • You can now shift-click to examine as silicon, instead of ctrl-shift-clicking, which is something absolutely no one would guess.
    • +
    • Pulsing multiple doors' "open door" wires at the same time using a remote signaller now actually opens them at the same time.
    • +
    • Fixes wormhole projector not having an icon.
    • +
    • Wormhole projector has 0 failchance now.
    • +
    • Portals made by wormhole projectors can be removed via a multitool
    • +
    • Fixes ghost being able to request docking at trader ship consoles
    • +
    +

    tigercat2000 updated:

    +
      +
    • Ported goon HTML chat from /vg/ / Goon
    • +
    • All uses of \black have been removed
    • +
    • All uses of \icon have been replaced with bicon()
    • +
    +

    tkdrg updated:

    +
      +
    • Admins now have a verb to wipe all scripts from telecomms.
    • +
    + +

    19 June 2016

    +

    DaveTheHeadcrab updated:

    +
      +
    • Defibs now must be used within 3 minutes of death.
    • +
    • Combat defibs now induce heart attack when you stun with them (Emagged defibs have a 10^ chance to do this)
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in the ability to make latex glove balloons (cable coil+latex glove)
    • +
    • Fixes latex gloves not having an in-hand icon for the left hand
    • +
    • Telephones will now ring when activated in-hand
    • +
    • Force on telephones removed
    • +
    • The break room privacy shutters now apply to all windows in the medical break room and not just the ones out front
    • +
    • His Grace grants massive stamina regeneration
    • +
    • pre-made styptic, silver sulfadiazine, and synth flesh patches now apply instantly
    • +
    • Styptic and Burn patches now have unique icons
    • +
    • Partially fixes graffiti so it's actually visible
    • +
    +

    FreeStylaLT updated:

    +
      +
    • changed its to it's in lockbox description
    • +
    • changed \red to formatting
    • +
    • changed stetchkin's price from 9 TC to 4 TC, suppressor's from 3 TC to 1 TC
    • +
    +

    KasparoVy updated:

    +
      +
    • Secure briefcase now has the same flags, hitsounds, attack verbs, throw speed and carrying capacity as a regular briefcase. Yes, it can hold paper bins now.
    • +
    • Dethralling a Shadowling thrall that has darksight activated clears their darksight.
    • +
    +

    LittleBigKid2000 updated:

    +
      +
    • The vox raider's base is now filled with nitrogen instead of regular dusty air.
    • +
    +

    TheDZD updated:

    +
      +
    • Teaches camera assemblies the meaning of the word "respect" (for NODROP items).
    • +
    • Sates the insatiable hunger that orange shoes once had for secborg cuffs.
    • +
    • Cryodorms will no longer kick you to lobby if you have logged off when they despawn your body, they will now always ghost you.
    • +
    • The defense values on the riot armor helmet is now identical to those on the riot armor suit.
    • +
    • Knight armor (including the chaplain's crusader armor) now has a slowdown of 1 instead of no slowdown.
    • +
    +

    Twinmold updated:

    +
      +
    • Fixes being able to eat cybernetic implants so you cannot eat them/force feed them to people.
    • +
    • Lowers the range of Malfunction from 4 tiles to 2 tiles, due to ability to insta-kill IPCs/incapacitate those with mechanical hearts.
    • +
    • Lowers amount of confusion given from Revenants from 50 to 20 per Defile.
    • +
    • Sets a maximum confused amount from the Revenant's Defile ability (now 30).
    • +
    • Makes Syndicate Bombs show a more accurate time remaining until detonation.
    • +
    +

    monster860 updated:

    +
      +
    • Makes stock parts build 5x faster
    • +
    • Adds a last-second loop-back sort pipe so that items with a mail tag don't end up on the disposals conveyer, and get flushed right back around. This enables an item to be sent from anywhere on the station to anywhere else on the station without going through the disposals conveyer.
    • +
    • Fixes a bug where drones can get stuck if they have their destination set to the RD office. This also fixes the bug where attempting to send a package from the test lab always ends up in the RD office.
    • +
    +

    tkdrg, Delimusca, Aranclanos, TheDZD updated:

    +
      +
    • Gun mimics (including wand, staff, projectile guns, and energy guns) created by the staff of animation will shoot things.
    • +
    • Mimics created by the staff of animation now have googly eyes.
    • +
    • Fixes the disturbing lack of death caused by wand of death projectiles.
    • +
    + +

    12 June 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Fixed the long-lasting bug of handcuffed people keeping their chainsaws.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • No more language message-spam on roundstart
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Adds a new icon for the detective's scanner.
    • +
    • Detectives scanner now has access to DNA and fingerprint records.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds three new chaplain weapons: pirate saber, multiverse sword, and possessed/talking sword
    • +
    • Fixes not being able to sheath the claymore in the Crusader Armor
    • +
    • Adds in a mocha drink
    • +
    • Fixes ice being unobtainable for the jobs that use it most
    • +
    • Fixes laser armor losing its reflecting ability
    • +
    • Fixes the lack of progress bars for more stack-based construction
    • +
    • Fixes Experimentor producing coffee machines instead of cups
    • +
    • Can deconvert mindslaves by removing their mindslave implant
    • +
    • Can deconvert Vampire thralls by feeding them holy water
    • +
    • Fixes mindslaves not having a HUD for the master and mindslave
    • +
    • Fixes being able to duplicate just about anything in the Experimentor
    • +
    • Fixes not being able to use tank transfer valves or one tank bombs in the Experimentor.
    • +
    • Fixes infinite-throw spam
    • +
    • Fixes being able to resist out of grabs by moving (that is to say, it'll actually work now)
    • +
    • Fixes passive grabs using the wrong HUD icon
    • +
    • Tabling duration reduced from 5 to 2
    • +
    • Can no longer wield double-bladed energy swords as a hulk
    • +
    • Fixes on map stools having the wrong offsets, making it look like you're not sitting on them
    • +
    +

    FreeStylaLT updated:

    +
      +
    • Added (Enabled) Mind Batterer for Traitors
    • +
    • Fixed uplink implant description (Said 5 when actually gave you 10 TCs)
    • +
    +

    Glorken updated:

    +
      +
    • Shifts Zeng-Hu left leg over in order to regain thigh gap.
    • +
    • Chops off a pixel on Bishop feet so that they fit into shoes.
    • +
    +

    KasparoVy updated:

    +
      +
    • Old placeholder IPC butt sprite replaced with the finished QR-code sprite.
    • +
    +

    Krausus updated:

    +
      +
    • Fixes ghosts failing to follow mobs that move in unusual ways
    • +
    • Fixed tape allowing mobs with sufficient access to move through solid objects.
    • +
    +

    Many -tg-station Coders, TheDZD updated:

    +
      +
    • Old gun code is now gone.
    • +
    • Ports the vast majority of TG's gun code and their guns (any previously unavailable guns, and newly-added guns will remain unavailable to players). Expect some changes that might not be listed here due to the sheer scope of this refactor.
    • +
    • Probably some new bugs.
    • +
    • A lot of old gun bugs.
    • +
    • Mouth suiciding with a gun no longer instantly kills you, you fire the gun at yourself at 5x damage (assuming it even did damage to begin with).
    • +
    • Mouth suicide shooting does not work on harm intent.
    • +
    • You can now bash people with guns while on harm intent instead of shooting them point-blank.
    • +
    • You can now mouth suicide other people, doing so still takes the full 12 seconds to mouth suicide, but has the same 5x damage multiplier.
    • +
    • Vox spike throwers are real guns that fire spike bullets now, instead of just being fake guns that threw spikes. They do 25 damage per hit, have 30 armor piercing, cause a 1 second stun (not the kind that drops you to the floor), and cause some bleeding. They have 2 round burst fire as well, and have 10 shots per clip. A new should should recharge every 20 or so seconds.
    • +
    • Xray lasers now have a maximum range of 15 tiles.
    • +
    • Zoomed guns now actually fire accurately while zoomed.
    • +
    • Using Suicide with guns now actually does gun-like things.
    • +
    • The clown no longer deletes guns if he fucks up with them due to being clumsy.
    • +
    • Emitters no longer become inaccurate over long ranges.
    • +
    • Power gloves now override middle-click and alt-click when worn.
    • +
    • Power gloves give a notification when worn.
    • +
    • Power gloves now have special examine text when examined by an antagonist.
    • +
    • Proto SMGs now only have a 21 shot clip.
    • +
    +

    Spacemanspark updated:

    +
      +
    • Adds the ability to make a more irritated buzz noise at people as a synthetic. The original buzz is still there.
    • +
    +

    Tauka Usanake updated:

    +
      +
    • Adds more belt icon overlays
    • +
    +

    Twinmold updated:

    +
      +
    • Nar'Sie AI Hologram and Error Sprite
    • +
    • Fixes space pod equipment variable. Can now properly install/uninstall equipment.
    • +
    • Check Seat verb no longer pulls out installed equipment.
    • +
    • You can now have a passenger in your pod if you have a passenger seat.
    • +
    +

    monster860 updated:

    +
      +
    • Adds comical implant. It is an implant that causes you to have a comic sans voice. It can be made in the protolathe using bananium.
    • +
    • The comical implant now spawns by default inside IPC clowns
    • +
    • Fixes the window getting stuck when you try to drag or resize a NanoUI window too fast with Fancy NanoUI enabled
    • +
    • Fixes a small quirk with the resize handle.
    • +
    • Fix javascript error in cargo UI
    • +
    +

    pinatacolada updated:

    +
      +
    • removes atmos tech SOP from supply SOP
    • +
    • Fixes defibing people without a heart
    • +
    • Fixes defib saying it didn't work stopping a heart attack when they do
    • +
    + +

    02 June 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Fixed a text problem in virtual gameboard description.
    • +
    • Made gameboards deconstructable and movable.
    • +
    • Added a light to gameboards. Pretty!
    • +
    +

    Crazylemon64 updated:

    +
      +
    • There will no longer be a mountain of startup runtimes when people have custom languages.
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Removes xenobio golem rune creation sound
    • +
    • Added overlays for sec belts that reflect the items stored therein.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes Chapel and Chaplain's office not having a light switch
    • +
    • Fixes mass driver only being usable once due to weird pressure
    • +
    • Fixes chapel being overly dark near coffins
    • +
    • Fixes not being able to sheath the claymore in the Crusader Armor
    • +
    +

    IK3I updated:

    +
      +
    • crate cargo system
    • +
    • passenger seat system
    • +
    • loot box secondary cargo system (install it and your pod has a standard inventory)
    • +
    • lock busters for the CE and Armory
    • +
    • incappacitated people can't operate the door controls anymore
    • +
    • Items dropped in a pod can now be scrounged up
    • +
    • security can rip you out of an unlocked pod
    • +
    • The pod code isn't full of tumors any more
    • +
    +

    Tastyfish updated:

    +
      +
    • Holsters now have an action button while on your suit again.
    • +
    +

    monster860 updated:

    +
      +
    • Adds the following words to the AI announcer: active, airlock, alcohol, arrival, arrivals, becoming, between, blob, briefing, camp, chair, chapel, closet, cyberiad, declared, detective, diona, dock, docked, docking, docks, drask, drunk, emag, equipment, evacuation, experimentor, gateway, hail, hallway, holoparasite, honk, hull, ian, imminent, interested, intruders, kida, kidan, labor, library, mime, mimes, miner, miners, mining, n2o, nuke, office, op, operational, ops, pod, pods, poly, pun, renault, representative, runtime, scrubbers, sequencer, skree, skrek, skrell, space, spider, spiders, still, stupid, swarmer, swarmers, sword, technology, teleport, teleported, teleporter, teleporting, tesla, tool, unathi, vacant, vault, vents, vulpkanin, weld, window, windows, yet
    • +
    + +

    31 May 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Fixes potential exploits involving door remotes.
    • +
    • Adds another type of remote door control.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Allows Chaplain to select a wide new range of null rod customizations
    • +
    • Slightly increases null rod damage (15->18)
    • +
    • Fixes abductors speaking other languages
    • +
    • Fixes traitors getting less TC on some game modes
    • +
    +

    QuinnAggeler updated:

    +
      +
    • All lazarus revived mobs become valid for pet collaring
    • +
    +

    Tastyfish updated:

    +
      +
    • Adds a suicide for light tubes.
    • +
    • Progress bars, buttons, and several of the values in UI's are now animated.
    • +
    • Deconstructing glass tables now gives a stack of 2 sheets of glass.
    • +
    +

    monster860 updated:

    +
      +
    • Upgrading the experimentor will no longer reduce the chance of upgrading an item's tech
    • +
    • Guest passes can now be attached to an ID card.
    • +
    • Adds a HoP guest pass computer, which is like a normal guest pass computer, but using an ID with ID computer access will allow it to issue guest passes with any access.
    • +
    • Adds the HoP guest pass computer to the HoP office.
    • +
    • Moves the guest pass computer in robotics to RnD.
    • +
    + +

    25 May 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Adds an unread change notification.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Removes Dragon's Breath Recipe
    • +
    • Removes Ghost Chilli Juice
    • +
    • Fixes buckled flipping over someone
    • +
    +

    IK3I updated:

    +
      +
    • Sleepers, scanners, and borg chargers no longer remove you from existence when destroyed
    • +
    • Hostile mobs are no longer fooled by your clever scanner and recharger tricks
    • +
    + +

    24 May 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Adds the ability to attach signalers to bear traps. Stealthy hunting!
    • +
    +

    Crazylemon64 updated:

    +
      +
    • You can now fasten the circulators in the TEG kit with a wrench - no adminbus needed to set it up, now
    • +
    • You can now rename cassette tapes with a pen.
    • +
    • You can now wipe data from a tape from its right-click menu.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds 4 new types of fudge for the chef to make: Peanut, Chocolate Cherry, Cookies 'n' Cream, and Turtle Fudge.
    • +
    • Normal fudge recipe now uses milk instead of cream.
    • +
    • Mutant/Modified/Enhanced plants will no longer infinitely increase their name length, and instead will be simply "mutant", "modified", or "enhanced" plant as determined by the last type of modification they were subject to.
    • +
    • Bees can no longer phase through hydroponics lids, giving botanists a way to finally stem the tide of pollination.
    • +
    • Premade beeboxes now spawn with the right type of bees, specifically of the worker caste.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Donk pockets have more omnizine, but only upon fully consuming the donk pocket
    • +
    • swarmers will drop an artificial bluespace crystal on death
    • +
    • Orion Trail guards now drop an energy shield and C20R on death
    • +
    • Reviving simple animals with strange reagent will prevent them from dropping any further loot
    • +
    +

    KasparoVy updated:

    +
      +
    • Rejuvenating a mob now unbuckles them correctly (if they're buckled to something).
    • +
    • Rejuvenating a mob will no longer remove their hair.
    • +
    • Rejuvenating a mob will no longer permanently blacken their eyes.
    • +
    • Rejuvenating a mob will no longer remove their prostheses with fleshy limbs, it will just fix the prostheses.
    • +
    • Rejuvenating a mob will not remove organs/limbs belonging to other species if said organs/limbs are in the same place(s) as the mob's default organs/limbs would be.
    • +
    • Fixes a runtime when trying to flip with an object other than a grab in your hand.
    • +
    • Doing a 'cybernetic repair' procedure on the head of a disfigured IPC will re-figure them.
    • +
    • Rejuvenating a mob will only regrow organs/limbs that are missing (by comparison to the standard organs for their species).
    • +
    • The regenerate_icons proc will now update skin tone and body accessories properly.
    • +
    • Organ rejuvenation now clears disfigurement and closes open wounds.
    • +
    • Rejuvenating a mob will end all in-progress surgeries.
    • +
    • Vox get their cortical stacks back, since the non-implant ones don't interfere with the Heist game-mode.
    • +
    • Rejuvenating a long-dead or husked mob will now clear the appropriate mutations.
    • +
    +

    QuinnAggeler updated:

    +
      +
    • Species disguise variable for clothing items
    • +
    • Species disguise string, "High-tech robot," for cardborg suit and helmet
    • +
    • ABSTRACT flagged clothing items will not be displayed on examination
    • +
    +

    Tastyfish updated:

    +
      +
    • Removes n2 pills healing vox oxyloss, and o2 pills poisoning vox.
    • +
    +

    monster860 updated:

    +
      +
    • Adds the floor painter. Sprite by FlattestGuitar
    • +
    + +

    20 May 2016

    +

    Fox McCloud updated:

    +
      +
    • Fixes Chaplains being able to be vampires
    • +
    • Cryopods will now always display the occupant's name
    • +
    +

    KasparoVy updated:

    +
      +
    • Fixes a runtime with Dioneae by repathing their limbs.
    • +
    +

    QuinnAggeler updated:

    +
      +
    • Makes dehydrated space carp description more accurate and informative
    • +
    +

    monster860 updated:

    +
      +
    • Adds the permanent teleporter. Use the circuitboard on a teleporter hub to set the target before constructing it.
    • +
    + +

    17 May 2016

    +

    AugRob updated:

    +
      +
    • Add screwdriver sound when opening/closing panels on airlocks
    • +
    +

    Fox MCCloud updated:

    +
      +
    • Removes "harm" traitor objective
    • +
    • Increases non-escape/hijack/die objectives from 1 to 2
    • +
    • Tweaks available objectives to traitors a bit
    • +
    +

    Fox McCloud updated:

    +
      +
    • Players can no longer see how many players have readied up or who has readied up
    • +
    • Hulks, Shadowlings, and Golems can no longer use laserpointers
    • +
    • Adds in the ability to flip over someone with *flip
    • +
    • Fixes and improves foam to better interact with reagents
    • +
    +

    KasparoVy updated:

    +
      +
    • Refactors hair so it's on the head (organ).
    • +
    • Adjusts some Vox hair style names so they're consistent with all others.
    • +
    • Refactors Morph and the order by which options are presented.
    • +
    • Players with heads of a different species than the body will now only be able to access the head accessories, hair/facial hair styles of the head's species.
    • +
    • Fixes some typos.
    • +
    • Fixes a bug where hairgrownium made you bald and super hairgrownium only changed the hair/facial hair styles of Humans.
    • +
    • Fixes a bug where Morph wouldn't correctly set eye colour or skin tone.
    • +
    • Fixes a typo that didn't really have any negative effect on the beard organ to begin with.
    • +
    • Fixes bugs where Alopecia and Facial Hypertrichosis disease symptoms wouldn't update player sprite correctly.
    • +
    • Adds a new Vox hairstyle.
    • +
    • You can now change your head accessory (and its colour), body markings (and their colour), and body accessory if you're a species that has such things via the Morph genetic power and C.M.A. (the bathroom SalonPro Nano-Mirrors and admin verbs).
    • +
    +

    monster860 updated:

    +
      +
    • Fixes sleep() in telecomms
    • +
    • Windows can now be constructed and deconstructed using RCD's.
    • +
    + +

    10 May 2016

    +

    Crazylemon64 updated:

    +
      +
    • Ragin' Mage creation works correctly again.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds a Briefcase Full of Bees as a Botanist-only traitor item (10 TC)
    • +
    • Fixes worker bees having an insatiable desire to murder bots. (Syndi-bees still murder them though)
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Robots now slur and stutter robotically
    • +
    • Adds tape gags. Click on someone with a roll of tape to shut them up!
    • +
    +

    Fox McCloud updated:

    +
      +
    • Removes material efficiency upgrades from the mech fab and protolathe
    • +
    • Ore redemption machine sheets/points per ore scaled from 1 up to 2 (down from 1 up to 4)
    • +
    • Fixes materials exploit duplication
    • +
    • Fixes the protolathe locking up under some circumstances
    • +
    • Updates the laser cannon to be range based: the further its projectile travels, the more damage it does. Base damage greatly reduced.
    • +
    • removes fungus from mushrooms
    • +
    • adds fungus to "mold" plant
    • +
    • adds mold seeds to hydro vendor
    • +
    • bumps up ???? reagent from 1 to 5 on bad recipes
    • +
    • Adds in 3 disease: Grave Fever, Space Kuru, and Non-contagious GBS
    • +
    • Adds Reagent to cause Space Kuru and Non-contagious GBS to traitor poison bottles
    • +
    • Initropidril now has a recipe
    • +
    • Adds a number of new reagents
    • +
    • Brain burgers now contain prions instead of mannitol
    • +
    • Scientists and chemists can no longer purchase traitor poison bottles
    • +
    • random drug bottles now have a much wider range of reagents in them
    • +
    • Fixes UI On slot machine saying it costs 5 credits when it's 10
    • +
    • Fixes abductors having tails
    • +
    • Fixes traitor scissors having a different hair-cutting sound
    • +
    • Fixes simple animals not dying right away when they reach zero health
    • +
    • Fixes a few farm animals, simple xenos, and a hivebot from having incorrect health
    • +
    • Buffed health pack usage on simple animals (should heal roughly 20 damage on them, per use)
    • +
    • Emotes no longer need to be purely lowercase to work
    • +
    • Chaplain can now select a green book as his Bible
    • +
    • Adds in His Grace, a hijack-only traitor item for the Chaplain
    • +
    +

    IK3I updated:

    +
      +
    • Added key and tumbler based pod locks
    • +
    • Made Pod Locks and keys buildable in Pod Fabricator
    • +
    • Made Pod Keys recoverable from cryo
    • +
    • Added lock to Security Pod
    • +
    • Added a key for Security Pod to HoS and Pod Pilot Offices
    • +
    • New sprites for several pieces of pod equipment
    • +
    • Using a multitool on a decalock now gives usable info
    • +
    +

    NTSAM updated:

    +
      +
    • Fixes the stuttery rainbow screen for IPCs.
    • +
    • Fixes the green IPC screen.
    • +
    +

    QuinnAggeler updated:

    +
      +
    • Adds a sound emote for the Drask
    • +
    • Gives Drask the ability to eat soap
    • +
    • Adds a racial flag for the Drask
    • +
    • Makes syndicate, paramedic, clown, and EVA helmets display correctly on Drask
    • +
    +

    tigercat2000 updated:

    +
      +
    • The station blueprints can now show you where wires/pipes/disposal pipes are supposed to go.
    • +
    + +

    04 May 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Adds gameboards to bar and permabrig.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • AIs are no longer created for temporary messages.
    • +
    +

    Fethas updated:

    +
      +
    • Sniper Rifles for nuke ops.
    • +
    • you can now actually shove heads on spears again.
    • +
    • Before i removed the traitor chemist item i cleaned up the harm reaction code paths.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • cheap lighters only damage your hand if you fail to properly use such a complicated contraption, not the whole body
    • +
    • ports /tg/ Foam Force guns, now you can shoot foam at your enemies /with style/
    • +
    +

    Fox McCloud updated:

    +
      +
    • Slime batteries now self-recharge.
    • +
    • Adds in door wands--control doors from range
    • +
    • Each head of staff (and the QM) starts off with a door wand to control the doors in their respective departments
    • +
    • Fixes nutrition alert icon kicking in too early
    • +
    • Adds in a new hairstyle
    • +
    • Fixes cig icons not updating under some circumstances
    • +
    • Updates the Tesla; it will now have to be "fed" or it can run out of energy; the rate at which it gains additional energy balls and power has been greatly lowered.
    • +
    • energy ball will now be drawn towards the singularity beacon
    • +
    • fuel tank explosions a bit stronger and will arc tesla blasts further
    • +
    • Tweaked some game mode population requirements to enhance general game mode balance and player experience.
    • +
    • Reworks overdosing to have more unique effects and also scale, in part, on volume
    • +
    • Epinephrine, Atropine, and Ephedrine have a lower OD threshold
    • +
    • Saline penetrates the skin
    • +
    • Synaptizine and Teporone now have OD threshold
    • +
    • Adds in berserker disease (treat with haloperidol)
    • +
    • Adds in Jenkem, a nasty gross drug made with toilet water
    • +
    • Adds in food poisoning; get it from eating poorly made food, from salmonella, or fungus
    • +
    • Adds in the Shock Revolver, a replacement for the stun revolver remove: removes the stun revolver remove: removes the prototype SMG+ammo from the protolathe
    • +
    +

    IK3I updated:

    +
      +
    • Can no longer holster items with No-Drop active.
    • +
    • Saves prosthesis users from Tox-Comp's wrath
    • +
    +

    KasparoVy updated:

    +
      +
    • Disembodied prosthetic heads that aren't monitors won't make you go bald when they're re-attached.
    • +
    • 'Optic' markings will disappear when your head gets removed, and reappear if it gets re-attached.
    • +
    • Disembodied prosthetic heads that aren't monitors will now be rendered with hair & facial hair.
    • +
    • Disembodied prosthetic heads with optical markings (markings with the head set as the origin) will be rendered with those markings.
    • +
    • Animated hair styles (e.g. screens) and head accessories (e.g. 2/3 new antennae) will now be animated properly.
    • +
    • 3 more antennae.
    • +
    • An alt. and monitor head model for every prosthetic brand but Zeng-hu. Morpheus only gets an alt model, not another monitor.
    • +
    • Animated optical markings to fit the new alt. heads.
    • +
    • Screen styles for the alt. Hesphiastos head.
    • +
    • Companies that make prosthetic body parts can (and do) now offer separate models for qualified recipients.
    • +
    • Removed the frames from screen styles in order to allow the same styles to be applied to all monitor heads.
    • +
    +

    LittleBigKid2000 updated:

    +
      +
    • Booze dispensers can now dispense synthanol
    • +
    +

    Norgad updated:

    +
      +
    • Adds a disposals chute to the Mechanic's Workshop
    • +
    +

    QuinnAggeler updated:

    +
      +
    • Adds the Drask as a 30KP race
    • +
    • Adds their language, Orluum
    • +
    • Adds a stylecolor for their language
    • +
    • Adds their butts (for photocopying)
    • +
    • Adds, at last, another race with skin tone (humies move over)
    • +
    • Adds a reason to make bad ice puns
    • +
    • Adds a check for brain death (brain damage of 120 or more) to the proc responsible for reviving IPCs
    • +
    +

    pinatacolada updated:

    +
      +
    • Makes fridge boards be selectable by screwdriving them
    • +
    • Virology fridge now accepts syringes, beakers, and bottles
    • +
    • Plasmamen security now spawn with their suit slot items in their bags
    • +
    • Pod pilots spawn with taser in the suit slot
    • +
    • removes armor from plasmamen magistrate suits
    • +
    + +

    25 April 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Adds buildable holographic gameboards that, when opened, produce a fully-functional JavaScript chess interface, which includes a chess AI. If you win, it will produce 80 tickets for your spending!
    • +
    +

    FlattestGuitar updated:

    +
      +
    • a human's species is now visible on examination
    • +
    +

    Fox McCloud updated:

    +
      +
    • Improves attack animations with items, making it more clear who's attacking you and with what
    • +
    • Updates Revolution game mode so it better scales with total player population
    • +
    • Head revs start off with a flash, spraycan, and chameleon security HUD
    • +
    • Add chameleon security hud, which is basically sec shades with the ability to disguise as a number of regular glasses
    • +
    • Updates mining loot crates to feature far more actual loot
    • +
    • Mining loot crates are now opened by inputting a 4 digit password and have 10 tries to guess the password string
    • +
    • Fixes bees, mech syringes, and darts not properly calling INGEST for a reagent
    • +
    +

    Meisaka updated:

    +
      +
    • The light on/off function for drones works again, toggling between lowest setting and off.
    • +
    • Guardians can toggle their lights off and on again.
    • +
    • AI, pAI, robots and drones can now use *yes emote without extra ss on the end.
    • +
    • emote *help for silicons updated/added.
    • +
    • *twitch_s emote changed to *twitches, incorrect variations of some emotes can no longer be used.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Added 4 new HUD styles, "Operative", "Plasmafire", "Retro", and "Slimecore"
    • +
    • You can now view HUD changes in real-time, by going to Preferences (top right tab) > Game Preferences and changing the HUD style (limited to humans).
    • +
    • There are now three HUD styles you can get via the f12 button- Full, which contains all of your buttons, Minimal, which only contains a few essential buttons, and None, which is a completely blank screen.
    • +
    • Removed the remaining aiming code due to maintainability issues and incompatibility with HUD styles.
    • +
    • Mobs with HUD's now use a unique subtype instead of an anti-OOP else-if chain.
    • +
    • Refactored how objects (IE, stuff you pick up) is rendered to the HUD. This should fix the reoccuring "stuff on my screen that definately isn't meant to be there" bug, but keep an eye out for things that do not appear.
    • +
    + +

    20 April 2016

    +

    Crazylemon64 updated:

    +
      +
    • Bureaucracy crates now contain granted and denied stamps.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Anomalies will now be properly neutralized by signals that match their code and frequency, instead of using the default frequency and their code.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Adds shot glasses.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Removes the ability to put a pAI into securitrons and ED-209's
    • +
    • Drinking glasses now have an in-hand sprite
    • +
    • DNA injectors no longer have a delay when used on yourself
    • +
    • DNA injectors no longer delete on use, but become used, much like auto-injectors
    • +
    • Fixes a bug where you can exploit the genetic scanner to get multiple injectors
    • +
    • Fixes not being able to cancel creating an DNA injector
    • +
    • remove spacesuits causing injections to the head to take longer
    • +
    • FIxes heat resist mutation not making you immune to high pressure, fire, or high temperatures
    • +
    • removes some not-well-known damage resists from cold/heat mutations
    • +
    • Re-maps botany a bit to make it more bee and botanist friendly
    • +
    • Adds in Abductors Game Mode
    • +
    +

    MarsM0nd updated:

    +
      +
    • Embeded object removal is now done with hemostat again
    • +
    • Borgs are able to do embeded object surgery
    • +
    +

    Tastyfish updated:

    +
      +
    • Makes the server startup substantially faster.
    • +
    +

    monster860 updated:

    +
      +
    • Crowbarring open a spesspod doors is no longer broken
    • +
    +

    tigercat2000 updated:

    +
      +
    • -tg- thrown alerts have been added. This means you get an alert when buckled or handcuffed or many many other things happen to you. It then gives you a tool tip when you hover over it, and it may or may not do something when you click it. Have fun!
    • +
    + +

    14 April 2016

    +

    Aurorablade updated:

    +
      +
    • Removes the !!FUN!! of having headslugs gold core spawnable.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Added in sounds (instead of a chat-based message) for when airlocks are bolted/unbolted
    • +
    • Added in sound for when airlocks deny access
    • +
    • cutting/pulsing wires will play a sound
    • +
    • ups nuke ops game mode population requirement from 20 to 30
    • +
    • Adds in mining drone upgrade modules to increase their health, combat capability, or reduce their ranged cooldowns
    • +
    • Adds in mining drone "AI upgrade" a sentience potion that only works on mining bots
    • +
    • Mining bots should be less likely to shoot you when attacking hostile mobs
    • +
    • Killer tomatoes actually live up to their name now and are hostile mobs
    • +
    • Killer tomatoes are an actual fruit now; activate it in your hands to make them into a mob
    • +
    • Killer tomatoes are directly mutated from regular tomatoes instead of blood tomatoes
    • +
    • Increased the yield of regular tomatoes by 1
    • +
    • Tweak some stats on the killer tomato seeds
    • +
    • Fixes the blind player preference not doing anything
    • +
    • Adds portaseeder to R&D
    • +
    • Scythes will conduct electricity now
    • +
    • Mini hoes play a slice sound instead of bludgeon sound
    • +
    • Plant analyzer properly has a description and origin tech
    • +
    • Can have hulk+dwarf mutations together
    • +
    • Can have heat+cold resist together
    • +
    • Can only remotely view people who also have remote view
    • +
    • Fixes cold mutation not having an overlay
    • +
    • Hallucinations will no longer tick down twice as fast as they should nor will they spawn twice as many hallucinations as they should
    • +
    • Incendiary mitochondria no longer asks who you want to cast it on (it always is meant to be cast on yourself)
    • +
    • Fixes permanent nearsightedness even when wearing prescription glasses
    • +
    +

    KasparoVy updated:

    +
      +
    • Head accessories now behave like facial hair: They will no longer be hidden by clothing items that BLOCKHEADHAIR (have the BLOCKHEADHAIR flag).
    • +
    • Wearing a piece of clothing that blocks head hair will no longer make head accessories (facial markings/horns/antennae) invisible until an icon update is triggered while the headwear is off.
    • +
    +

    Meisaka updated:

    +
      +
    • law manager no longer freaks out with Malf law
    • +
    +

    Tastyfish updated:

    +
      +
    • The /vg/ library computer interface has been ported, giving a much better use experience.
    • +
    • Books can now be flagged for inappropriate content.
    • +
    +

    TheDZD updated:

    +
      +
    • Removes shitty Caelcode bees.
    • +
    • Hydroponics can now manage bee colonies, bees produce honeycombs that can be ground to obtain honey, a decent nutriment+healing chemical
    • +
    • Hydroponics can inject a queen bee with a syringe of a reagent to alter her DNA to match that reagent, meaning all honeycombs produced will contain that reagent in small amounts
    • +
    • Bees with reagents will attack with that reagent. It takes 5u of a reagent to give a bee that reagent.
    • +
    • Added the ability to make Apiaries and Honey frames with wood
    • +
    • Added the ability to make Royal Bee Jelly from 10 Mutagen and 40 Honey
    • +
    • Added the ability to make more Queen Bees from Royal Bee Jelly by using it on an existing Queen, to split her into two Queens
    • +
    • Removes some snowflakey mob behavior from bears, snakes and panthers.
    • +
    • Hudson is feeling punny.
    • +
    • Hostile mob AI should now be a bit more cost-efficient.
    • +
    +

    monster860 updated:

    +
      +
    • Adds area editing, link mode, and fill mode to the buildmode tool
    • +
    + +

    12 April 2016

    +

    FalseIncarnate updated:

    +
      +
    • Adjusting the setting of a vendor circuit board is no longer random, but instead provides a select-able list.
    • +
    • Vendor Circuit Board design moved from the Circuit Imprinter to the Autolathe, acid requirement replaced by metal.
    • +
    • Burnt matches can no longer light cigarettes, pipes, or joints.
    • +
    +

    Fethas updated:

    +
      +
    • Nukes the cargo train code rscadd:Adds simple vehicle framework and converts secway/janicart/snowmobiles/bikes/cars/ambulance to it rscadd:Adds space speedbike, red and blue versions, yes you WILL need a spacesuit rscadd:Maps janicart and secway onto metastation (but not ambulance no pareamedic garage, no i am not mapping that)
    • +
    • You should now be able to operate on IPC eyes, SHOULD bugfix:hopefully surgery on diona works right
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in TraitorVamp; game mode that's essentially like TraitorChan, but with a Vampire instead of a Changeling
    • +
    • Vampires cannot use holoparasites
    • +
    • Malf AI will automatically lose if it exits the station z-level
    • +
    +

    Tastyfish updated:

    +
      +
    • All cats can kill mice now.
    • +
    • E-N can't suffocate.
    • +
    • Startup time is now shorter.
    • +
    • Removed the Station Collision away mission from rotation, due to multiple conceptual and technical issues.
    • +
    + +

    07 April 2016

    +

    Crazylemon64 updated:

    +
      +
    • Removes an offset from the advanced virus stealth calculation, causing viruses to be more stealthy than the sum of their symptoms.
    • +
    • Mulebots will now send announcements to relevant requests consoles on delivery again.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds logic gates, for doing illogical things in a logical manner.
    • +
    • Adds buildable light switches, for all your light toggling needs.
    • +
    • Fixes a resource duplication bug with mass driver buttons.
    • +
    +

    Fethas updated:

    +
      +
    • maybe makes them last longer...maybe..and fixes the event end message
    • +
    +

    Fox McCloud updated:

    +
      +
    • Maps in the slime management console to Xenobio
    • +
    • Reduces Xenobio monkey box count from 4 to 2
    • +
    • Fixes weakeyes having a negligible impact
    • +
    • Can spawn friendly animals with a new gold core reaction by injection with water
    • +
    • Hostile animal spawn increased from 3 to 5 for hostile gold cores
    • +
    • Swarmers, revenants, and morphs no longer gold core spawnable
    • +
    • Fixes invisible animal spawns from gold core/life reactions
    • +
    • Adds tape to the ArtVend
    • +
    • Can no longer use sentience potions on bots
    • +
    • Added in Plasma Dust reagent, acquired by grinding plasma sheets; it's more toxic than regular plasma and generates plasma gas when spilled onto turfs.
    • +
    • Slimecore reactions now require plasma dust as opposed to dispenser plasma
    • +
    • Added in new Rainbow slime; inject with plasma dust to get a random colored slime. Acquire by having 100 mutation chance on a slime when it splits.
    • +
    • Monkey Recycler can produce different types of monkey cubes; change the cube type by using a multitool on the recycler
    • +
    • Epinephrine/plasma reagents changing mutation rate has been removed
    • +
    • Mutation chance is inherited from slime generation to slime generation as opposed to being purely random.
    • +
    • New reactions added for red and blue extracts: red generates mutator, which increases mutation chance, and blue generates stabilizer, which decreases mutation chance.
    • +
    • Slime glycerol reaction removed
    • +
    • Slime cells are now high capacity cells (more power than before)
    • +
    • extract enhancer increases the slime core usage by 1 as oppose to setting it to three
    • +
    • slime enhancer increases slime cores by 1 as opposed to setting the core amount to 3
    • +
    • Chill reaction lowers body temperature slightly more so it doesn't just wear off instantly
    • +
    • Reduces Xenobio plasma sheets from 8 to 3 and removes that pesky boombox
    • +
    • Processors no longer produce 1 more slime core than intended
    • +
    • Less blank/spriteless/empty foods from the silver core reaction
    • +
    • Virology mix reactions now use plasma dust as opposed to plasma
    • +
    • Statues can no longer move/attack people unless they're in total darkness or all mobs viewing them are blinded
    • +
    • statues are invincible to anything other than full out gibbing.
    • +
    • Statues flicker lights spell range increased
    • +
    • Blind spell no longer impacts silicons
    • +
    • Fixes statues being able to attack/move whenever they feel like it, regardless of client statues
    • +
    • Fixes blind spell impacting the statue
    • +
    +

    Tastyfish updated:

    +
      +
    • Beepsky is no longer a pokemon.
    • +
    • pAI-controlled Bots now reliably speak human-understandable languages over the radio.
    • +
    • More floor blood for the blood gods. (Or rather, as much as there was supposed to be.)
    • +
    +

    tigercat2000 updated:

    +
      +
    • Items in your off hand will now count towards access.
    • +
    + +

    02 April 2016

    +

    Crazylemon64 updated:

    +
      +
    • Metal foam walls will now produce flooring on space tiles
    • +
    • Syringes will now draw water from slime people.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Let's you know when your container is full when filling from sinks.
    • +
    • Prevents splashing containers onto beakers and buckets that have a lid on them.
    • +
    • Pill bottles can now be labeled with a simple pen.
    • +
    • Beakers/buckets (and pill bottles) now accept 26 character labels from pens.
    • +
    +

    Fethas updated:

    +
      +
    • Various spells have had a tweak to stun/reveal/cast, some other number stuff...
    • +
    • Nightvision
    • +
    • harvest code is now in the abilites file.
    • +
    • New fluff objectives
    • +
    • Hell has recently remapped its blood transit system and you can now once again crawl through blood. We are sorry for the-GIVE US YOUR SOUL!
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Alcoholic beverages now have proper levels of ethanol in them. Good luck passing out after a beer.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in the Lusty Xenomorph Maid Mob; currently admin only.
    • +
    • Fixes xenomorph brains having the wrong sprite, no origin tech, and incorrect name
    • +
    • removes xenomorph egg from hotel
    • +
    • upgrades are no longer needed to for the available toys in the prize vendor
    • +
    • Implements Advanced Camera Consoles. A type of camera console that function like AI's vision style. Non-buildable/accessible.
    • +
    • Adds in Xenobiology Advance Cameras. A type of camera console that functions like advanced cameras, but only works in Xenobiology areas; can move around slimes and feed them with the console as well. Also non-buildable/accessible (for now).
    • +
    • Adds in cerulean slime reaction that generates a single use blueprint. On use it colors turfs a lavender color
    • +
    • Adds disease1 outbreak event
    • +
    • Adds appendecitis event
    • +
    • Roburgers now properly have nanomachines in them
    • +
    • Re-adds nanomachines
    • +
    • Experimentor properly generates nanomachines instead of itching powder
    • +
    • Fixes big roburgers having a healing reagent in them
    • +
    • Adds nanomachines to poison traitor bottles
    • +
    • Tajarans can now eat mice, chicks, parrots, and tribbles
    • +
    • Vulpkanin and Unathi can now eat mice, chicks, lizards, chickens, crabs, parrtos, and tribbles
    • +
    • fixes spawned changeling headcrab behavior
    • +
    +

    KasparoVy updated:

    +
      +
    • Incisions made at the beginning of embedded object removal surgery can now be closed in the same procedure.
    • +
    +

    ProperPants updated:

    +
      +
    • Maint drones have magboots.
    • +
    • Removed plastic from maint drones. Literally useless for station maintenance.
    • +
    • Increased starting amounts of some materials for maint drones and engi borgs.
    • +
    • Reduced the number of lines taken by Engineering cyborgs calling on materials stacks.
    • +
    • Operating tables can be deconstructed with a wrench.
    • +
    • Fixed and shortened description of metal sheets.
    • +
    +

    Tastyfish updated:

    +
      +
    • Bots can now be controlled by players, by opening them up and inserting a pAI. *beep
    • +
    • MULEbots can now access the engineering destination.
    • +
    • All MULEbot destinations should now have the correct load/unload direction, meaning the crates won't be dumped inside the flaps.
    • +
    • Diagnostic HUD's now give health and status information about bots.
    • +
    • MULEbot rampage blood tracks are now rendered correctly and handle UE traces as appropriate.
    • +
    • Bots should (hopefully) lag the game less now.
    • +
    • Beepsky contains 30% more potato.
    • +
    • Action progress bars are now smooth.
    • +
    • Clicking a filled inventory slot's square with an open hand now clicks the item in the slot.
    • +
    • Status displays now display the time when in Shuttle ETA mode and no shuttle activity is happening.
    • +
    • Shuttle ETA countdowns on status displays are now amber.
    • +
    • pAI's can now use the PDA chatrooms.
    • +
    • Adds treadmills to brig cells, to give the prisoners something productive to do.
    • +
    +

    TheDZD updated:

    +
      +
    • A lot of the guns and armor in the station collision, space hotel, academy, and wild west away missions have been removed/replaced.
    • +
    • Removes that fucking facehugger from station collision.
    • +
    +

    tigercat2000 updated:

    +
      +
    • Virus2 has been removed.
    • +
    • Virus1 is back. Viva la revolution.
    • +
    • You can now have up to 20 characters.
    • +
    + +

    26 March 2016

    +

    Fox McCloud updated:

    +
      +
    • Adds in dental implant surgery. Implant pills into people's teeth.
    • +
    • Major rebalance and Shadowling update (https://github.com/ParadiseSS13/Paradise/pull/3986 for details). In general, Shadowlings can no longer enthrall or engage in Shadowling like behavior, pre-hatch. Post-hatch, shadowlings are much more powerful, with a ride array of New abilities such as extending the shuttle or making thralls into lesser shadowlings. Shadowling gameplay should not revolve almost entirely around darkness, as opposed to pre-hatch shenanigans.
    • +
    • Robotics now has a "sterile" surgical area for performing augmentations
    • +
    • Adds the FixOVein and Bone Gel to the autolathe
    • +
    • ensures all surgical tools have origin tech on them; lowers origin tech on FixoVein
    • +
    +

    KasparoVy updated:

    +
      +
    • Slime People can now wear underwear.
    • +
    • Slime People can now wear undershirts.
    • +
    +

    TheDZD updated:

    +
      +
    • NT has removed trace amounts of a highly-addictive substance from the "100% real" cheese used in cheese-flavored snacks. As a result, incidence rates of crewmembers becoming addicted to Cheesie Honkers should reduce to zero.
    • +
    • After receiving complaints about crewmembers often being unable to physically function without a back-mounted barrel of coffee, NT has replaced station all sources of coffee on the station, including coffee beans themselves with a largely decaffeinated version. It was funny the first time almost every crewmember aboard the NSS Cyberiad was lugging around their own oil barrel filled with coffee, it wasn't so funny, nor good for productivity the eighteenth.
    • +
    + +

    25 March 2016

    +

    Crazylemon64 updated:

    +
      +
    • You now will actually have the correct `real_name` on your DNA.
    • +
    • No more roundstart runtimes regarding IPC hair.
    • +
    • Mitocholide rejuv will work more usefully now.
    • +
    • Limbs and cyborg modules will no longer appear in your screen.
    • +
    • Cyborg module icons are now persistent throughout logging in and out.
    • +
    • Various cyborg modules, like engineering, now use the proper icon.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Adds confetti grenades.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes Sleeping Carp combos not having an attack animation
    • +
    • Fixes several chems not properly healing brute/burn damage, consistently, as intended
    • +
    +

    KasparoVy updated:

    +
      +
    • Unbranded heads and groins no longer invisible.
    • +
    • Zeng-hu left leg will now be in line with the body when facing south.
    • +
    + +

    22 March 2016

    +

    Crazylemon64 updated:

    +
      +
    • Repairs all sorts of eldritch occurences that happen when you put an organic head on an IPC body, as well as some decapitation bugs
    • +
    • Makes heads keep hair on removal
    • +
    • Amputated limbs from a DNA-injected individual now will keep their appearance of the DNA-injected person
    • +
    • Wounds will vanish on their own now
    • +
    • Admins now have an "incarnate" option on the player panel when viewing ghosts for quick player instantiation
    • +
    • Fixes a runtime regarding failing a limb reconnection surgery
    • +
    • Copying a client's preferences now overrides the previous mob's DNA
    • +
    • A DNA injector is now more thorough, and affects the DNA of mobs' limbs and organs
    • +
    • DNA-lacking species can no longer be DNA-injected
    • +
    • Brains are now labeled again
    • +
    • Splashing mitocholide on dead organs will make them live again.
    • +
    • The body scanner now detects necrotic limbs and organs.
    • +
    • pAIs and Drones are now affected by EMPs and explosions while held.
    • +
    +

    Fethas updated:

    +
      +
    • Adds a surgery for infection treatmne/autopsys that is simply cut open, retract, cauterize
    • +
    • fixes a dumb error in internal bleeeding surgerys
    • +
    • Chaos types no longer random teleport, but will make the target hallucinate everyone looks like the guardian.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Adds a snow, navy and desert military jacket.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Removes random 1% chance to heal fire damage
    • +
    • Removes passive healing from resist heat mutation
    • +
    • Regen mutation heals every cycle (albeit less, on average), but doesn't cost hunger
    • +
    • Fixes not being able to speak over xeno common or hivemind when you receive the Xeno hive node
    • +
    • Adds in the ability to transfer non-locked metal+glass only designs from the protolathe to autolathe
    • +
    • Changes Outpost Mass Driver to prevent accidental spacings
    • +
    • Shadow people no longer dust on death, are rad immune+virus immune, and can be cloned. Slip immunity removed
    • +
    • Shadowlings no longer get hungry or fat and no longer dust on death
    • +
    +

    KasparoVy updated:

    +
      +
    • The ability to change your head, torso and groin as an IPC in the character creator. Non-IPCs cannot access the parts.
    • +
    • Head, torso and groin sprites for all mechanical limb/bodypart brands but Morpheus and the unbranded ones (since those already exist) from Polaris.
    • +
    • Faux-eye optics for non-Morpheus heads.
    • +
    • The ability to change optic (eye) colour if you've got a non-Morpheus head.
    • +
    • The ability to choose human hair styles (wigs) and facial hair styles (postiche) with non-Morpheus heads. Non-Morpheus heads cannot choose screens. Conversely, Morpheus heads cannot choose wigs or facial hair.
    • +
    • Two hair styles from Polaris.
    • +
    • The ability for IPCs to wear undergarments (shirts and trousers).
    • +
    • Antennae (colourable) for IPCs.
    • +
    • IPC monitor adjustment verb will now adjust optic colour if the head is non-Morpheus.
    • +
    • Combat/SWAT boots can now be toecut and jacksandals can't.
    • +
    • ASAP fix to what would've broken the ability to configure prostheses in character creation.
    • +
    • Adjusted masks no longer block CPR (including bandanas).
    • +
    • You can no longer run internals from adjusted breath masks (or airtight adjustable masks in general).
    • +
    +

    Regens updated:

    +
      +
    • Robotic hearts will now properly give the mob a heart attack instead of just damaging it when EMP'd
    • +
    • Assisted organs will now also take damage from EMP's
    • +
    • Internal robotic and assisted organs will now actually take damage from EMP's
    • +
    +

    Tastyfish updated:

    +
      +
    • Adds PDA chatrooms. Post memes! Talk to your fellow collaborators! Get caught!
    • +
    • You can now set the PDA messenger to automatically scroll down to new messages.
    • +
    • Pet collars now act as death alarms and can have ID's attached to them.
    • +
    • All domestic animals can now wear collars.
    • +
    • You can now make video cameras at the autolathe.
    • +
    +

    TheDZD updated:

    +
      +
    • Fixes an instance of old code being so incredibly, unbelievably, makes-me-want-to-stab-myself-in-the-eye-edly idiotic.
    • +
    +

    TravellingMerchant updated:

    +
      +
    • Kidan have new sprites!
    • +
    +

    tigercat2000 updated:

    +
      +
    • Nukeops now have an assault pod, they can use it for 30 TC. Loud and mean.
    • +
    • Lighting overlays can no longer go below 0 lum_r/g/b
    • +
    • Shuttles will work with lighting better.
    • +
    • Wizards can no longer teleport to prohibited areas such as Central Command.
    • +
    + +

    16 March 2016

    +

    Crazylemon64 updated:

    +
      +
    • Being in godmode now makes you immune to bombs
    • +
    • Science members now get compensated when they ship tech disks to centcomm.
    • +
    • Science crew are no longer paid when they "max" research.
    • +
    • Roboticists now get credit for making RIPLEYs and Firefighters
    • +
    • Slime people can now regrow limbs on a more lax nutrition requirement
    • +
    • Enhances the nutripump+ to let slime people regrow limbs with it active
    • +
    • Skeletons, slime people, IPCs, and Diona no longer leave blood when hit
    • +
    • Rejuvenating a slime person will no longer clog up their "blood"
    • +
    • Slime people will now regenerate "blood" from having water in their system
    • +
    • The decloner can now be created again
    • +
    • Environment smashing mobs can now destroy girders.
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Removes the check for species on the update_markings proc.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Xeno-botany is now more user-friendly, and less random letters/numbers.
    • +
    • Hydroponics now has a connector hooked up to the isolation tray and a new connector in their back room for those strange plants that like spewing plasma or eating nitrogen.
    • +
    • You can now (finally) build the xeno-botany machines, and science can print off their respective boards.
    • +
    +

    Fethas updated:

    +
      +
    • Syringes are no longer sharp
    • +
    • byond likes direct pathing so item/organ/internal not item/organ even if it shouldn't be in the internal_organs list. This was preventing the list from doing stuff correctly.
    • +
    • fixed ipc organ manipulation surgery, you can now insert a replacment ipc organ directly instead of needing a screwdriver in your main hand
    • +
    • nanopaste now will repair organs with robotic >= 2 instead of > 2 cuase i am an idiot
    • +
    • Fix, hopefully, for a runtime for clientless mobs whos head are cut off...
    • +
    • Hopefully fixes issues with diona eyes
    • +
    • Though shalt not eat robotic organs..including cybernetic implants..
    • +
    • ITS SURGERY_STEP/DETHRALL NOT SURGERY_STEP/INTERNAL/DETHRALL
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Adds three new synthanol drinks
    • +
    • Drinking synthanol is now a bad idea if you're organic
    • +
    • A glass of holy water now looks like normal water
    • +
    +

    Fox McCloud updated:

    +
      +
    • Adds in drink fizzing sound
    • +
    • Drink/bartender recipes use this new fizzing sound in addition to a few other recipes
    • +
    • Adds in a fuse burning sound
    • +
    • Bath salts, black powder, saltpetre, and charcoal use this sound now
    • +
    • Adds in a matchstrike+burning sound
    • +
    • Lighting a match triggers this new sound
    • +
    • Adds in scissors cutting sound
    • +
    • Cutting someone's hair uses this new sound
    • +
    • Adds in printer sounds
    • +
    • printing off papers from various devices typically uses these sounds
    • +
    • Adds computer ambience sounds
    • +
    • black box recorder and R&D core servers both play this sound at random rare intervals
    • +
    • Reduces the tech level (and requirement) for nanopaste
    • +
    • Reduces the tech level (and requirement) for the plasma pistol
    • +
    • Removes Nymph and drone tech levels
    • +
    • Reduces tech levels on the flora board
    • +
    • Adds tech level requirements to mech sleepers, mech syringe guns, mech tasers, and mech machine guns
    • +
    • Increases tech cost of the decloner
    • +
    • Removes the pacman generators
    • +
    • Removes emitter
    • +
    • Removes flora machine (functionless anyway)
    • +
    • Removes the pre-spawned nanopaste
    • +
    • Removes space suits
    • +
    • Removes excavation gear
    • +
    • Replaces the soil with actual hydroponic trays (more aesthetic than anything)
    • +
    • Removes most external asteroid access from the station
    • +
    • Excavation storage is now generic science storage
    • +
    • removed the plasma sheet
    • +
    • Fixes augments not showing up in R&D unless specifically searched for
    • +
    • Fixes some augments being unavailable in mech fabs
    • +
    • Fixes augments having no construction time
    • +
    • Fixes xenos not gaining plasma when breathing in plasma
    • +
    • Fixes plasma reagent not generating plasma for a person
    • +
    • Screaming has different sounds based on being male or female
    • +
    • Implements Goon's screaming sounds.
    • +
    • Screaming tone is now based on age of character instead of being random
    • +
    • Ups the cooldown on screaming from 2 seconds to 5 seconds
    • +
    • Removes chance for Whilhelm scream
    • +
    • Borgs can now scream
    • +
    • Monkey's now have a unique screaming sound
    • +
    • IPCs now scream like cyborgs
    • +
    • Updates slot machines to have higher jackpots and more payouts with more interesting sounds
    • +
    • Adds X-Ray, Thermal, Anti-tun, and Reviver implants to the nuke ops uplink (augments come with one auto-implanter) rcsadd: Adds in augment auto-implanter, which inserts and implant without surgery
    • +
    • tweaks a large number of chems; behaviors are largely retained, but new flavor messages, probabilities, etc may be present; overall, you can expect chems to do the same thing
    • +
    • Tabun re-replaced with Sarin rcsadd: New reagent: cholesterol: if overdosed on, it can cause a heart attack--fatty foods, cheese, eggs, and some meats all produce cholesterol in your body.
    • +
    • Mixing Sarin, Meth, or Cyanide will poison in a very small area of the reaction if you're not on internal OR not wearing a gas mask
    • +
    • Chemist warddrobe now has two gas masks
    • +
    • Teslium will now impact synthetics AND organics
    • +
    • Fixes facehuggers hugging already infected people
    • +
    • Fixes facehuggers hugging people while dead
    • +
    • Fixes Embryo's developing twice as fast as they should
    • +
    • Fixes up some behaviors with xeno eggs
    • +
    • Xeno acid can now melt through floors and the asteroid
    • +
    • Xeno's now play the gib sound when actually gibbed
    • +
    • Implements Changeling headcrabs/headspiders
    • +
    • Fixes xenos not throwing their organs when gibbed
    • +
    • Fixes swallowed mobs not being ejected when a human is gibbed
    • +
    • Adds in spider eggs reagent, an infectious reagent that requires surgery to correct
    • +
    • Fixes EMPs causing eye implant users to be permanently blind
    • +
    • Increases bag of holding's storage capacity
    • +
    • Removing a heart no longer kills the patient instantly, but induces a heart attack
    • +
    • Demon hearts will not work
    • +
    • Should now actually be able to re-insert hearts
    • +
    • Reworks addictions to bettter differentiate them betweeen overdosing and make them more realistic.
    • +
    • changes which chems are addictive, currently, the follow reagents are now addidctive: meth, crank, krokodil, bath salts, space drugs, perfluoradecalin, omnizine, coffee, nicotine, fliptonium, ultra lube, surge, fake cheese, weird cheese, ephedrine, diphenhydramine, teporone, and morphine
    • +
    • sleepers help you recover from addiction faster
    • +
    • Can now make cable coils in autolathes
    • +
    • Fixes the slot machine announcements not displaying properly
    • +
    +

    Tastyfish updated:

    +
      +
    • The super fart mutation now gives you a spell-like ability instead of augmenting the emote.
    • +
    • Vampire abilities are now in their own Vampire tab, as well being action buttons at the top, like spells.
    • +
    • Cloning a vampire no longer makes them lose their abilities.
    • +
    • Vampires can no longer hypnotize chaplains.
    • +
    • Being a full vampire (500+ total blood) actually makes you immune to holy water reliably now.
    • +
    • Some old away missions are back: Academy, Black Market Packers, Space Hotel, Station Collision, and Wild West. Go out and round up some hostiles!
    • +
    • Shuttle consoles now pair up to the engineering, mining, research, or labor shuttle when built or used before pairing, as long as the shuttle is near the console, or the shuttle is moved to be nearby.
    • +
    +

    monster860 updated:

    +
      +
    • Mining station now has a podbay.
    • +
    • Ore scooping module for the spacepod.
    • +
    • Three mining lasers for spacepod: Basic, normal, and burst.
    • +
    • Shooting weapons south or west of spacepod will actually hit adjacent targets now, and won't shoot through walls anymore.
    • +
    +

    taukausanake updated:

    +
      +
    • Mice can now be picked up like diona
    • +
    + +

    08 March 2016

    +

    Crazylemon64 updated:

    +
      +
    • Slime people are now more vulnerable to low temperatures.
    • +
    • Slime people are able to slowly regrow limbs at a high nutrition cost.
    • +
    • Slime people now slowly shift color based on reagents inside of them - disabled by default, toggle it with an IC verb
    • +
    • Slime people's cores are more vulnerable to damage
    • +
    • Species-related abilities now properly are removed - no more vox hair stylists, unfortunately.
    • +
    +

    Fethas updated:

    +
      +
    • the nest buckle now looks for the right organ path
    • +
    • Fixed some sprites.
    • +
    • No more putting no drops in rechargers,
    • +
    +

    Fox McCloud updated:

    +
      +
    • Implement's goon's gibbing sound
    • +
    • Implement's goon's gibbing sound for robots/silicons
    • +
    • Removes old gibbing sound
    • +
    +

    Spacemanspark updated:

    +
      +
    • Lazarus Injector's can now be emagged to activate their special features, alongside using EMPs on them.
    • +
    +

    Tastyfish updated:

    +
      +
    • Mimes now have a new ore, Tranquillite, used to bring peace and quiet to the station.
    • +
    • There are also permanent invisible walls and silent floors that can be made from tranquillite.
    • +
    • The Recitence mech is now buildable!
    • +
    • The Recitence mech is now playable!
    • +
    • Mid-round selection for various creatures and antagonists now consistently asks permission.
    • +
    +

    TheDZD updated:

    +
      +
    • Adds justice helmets with flashing lights and annoying sirens.
    • +
    • Adds crates containing said helmets.
    • +
    • Also includes a version of the helmet that can only be spawned by admins, and just has a single red light in the center instead of the stereotypical police blinkers.
    • +
    +

    monster860 updated:

    +
      +
    • Space pod transitions are now fixed.
    • +
    + +

    07 March 2016

    +

    Crazylemon64 updated:

    +
      +
    • People with VAREDIT can now write matrix variables
    • +
    • People with VAREDIT can now modify path variables
    • +
    • Refactors the variable editor code somewhat.
    • +
    • The buildmode area tool now shows reticules of what you've selected.
    • +
    • Switching mobs while using the buildmode tool no longer screws up your UI.
    • +
    • Refactors buildmode so it's no longer a special-case system.
    • +
    • Adds a copy mode to build mode, which lets you duplicate objects.
    • +
    • Any mob in buildmode can work at the fastest possible rate.
    • +
    • Fixed a problem where the icons of a person would not correctly update when changing gender.
    • +
    • One's hairstyle only adjusts on gender change if it's incompatible with your new gender.
    • +
    • Fixed a bug where a person's icon would only be updated if their sprite had a new layer added or removed.
    • +
    • You no longer lose your name when monkeyized and reverted - you'll still look like a monkey while you're a monkey, though.
    • +
    • Your organs will now match your gender when you are cloned.
    • +
    • Skeletons (when a body rots) no longer retain a fleshy torso.
    • +
    • Putting people in an active cryotube now produces the message on insertion, rather than release.
    • +
    • An EMP'd cloning pod will now display its sprites correctly.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Water Balloons can be filled from more sources than just beakers and watertanks.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes the "yeah" glasses so the sound doesn't vary and a message is displayed, on use
    • +
    • Noir mode only activates when the glasses are equipped to your actual eyes
    • +
    • Noir Glasses mode can be toggled on or off (defaults to off)
    • +
    • Mimes can no longer use spells and continue speaking
    • +
    • Mime abilities are now spells with proper icons
    • +
    • Mime wall now last 30 seconds, up from 5
    • +
    • forecfields/invisible walls now block air currents
    • +
    • Adds the Sleeping Carp scroll to the uplink for 17 TC
    • +
    • Fixes Shadowlings being able to use guns
    • +
    • Fixes sleeping carp scroll users being able to use guns
    • +
    • Fixes the Experimentor throwing one item at a time
    • +
    • Experimentor menu now automatically refreshes after use
    • +
    • Lowers surgery times across the board
    • +
    • Removes scalpels causing 1 damage on successful surgery
    • +
    • Removes random chance to fracture ribs on a successful surgery
    • +
    • Mining drills now have an edge
    • +
    +

    KasparoVy updated:

    +
      +
    • Jackets who have the verb available but are not intended to be adjusted will not have the action button available.
    • +
    • You can now adjust breath masks while buckled into beds and chairs.
    • +
    • Known issues with adjusted jackets using the wrong sprites.
    • +
    • Blueshield coat in hand and item icons.
    • +
    • Hulks now rip apart adjustable and droppable jackets. The items stored in the jackets get dropped on the ground.
    • +
    +

    Tastyfish updated:

    +
      +
    • Infrared emitters can now be rotated while already in an assembly via the UI popup.
    • +
    • The infrared emitter can no longer be hidden inside of boxes and still work.
    • +
    • The beach now has a border and is splashier.
    • +
    • Gives Psychiatrist a paper bin, clipboard, and multicolored pen.
    • +
    • Gives the Librarian / Jouralist a multicolored pen.
    • +
    • Gives the NT Representative a clipboard.
    • +
    • The ethanol-based neurotoxin drink is now called Neuro-toxin to avoid being confused with the deadly toxin.
    • +
    +

    VampyrBytes updated:

    +
      +
    • Fixes emotes ending with s needing 2. Emotes now work with grammatical options eg ping or pings, squish or squishes
    • +
    • Updated emote help with missing emotes. Help will also show any species specific emotes for your current species
    • +
    + +

    26 February 2016

    +

    FalseIncarnate updated:

    +
      +
    • Chocolate can now make you fat, as expected.
    • +
    +

    Fox McCloud updated:

    +
      +
    • stamina damage now regenerates slightly faster
    • +
    • Adds in whetstones for sharpening objects
    • +
    • Kitchen vendor starts off with 5 salt+pepper shakers
    • +
    • Can now point while lying or buckled
    • +
    • Fixes Capulettium Plus not silencing
    • +
    • Fixes slurring, stuttering, drugginess, and silences last half of what they should
    • +
    +

    KasparoVy updated:

    +
      +
    • Jackets that start open are recognized as actually being open already now. This fixes a bug with certain items that don't have an open state, or cases where it ended up giving an item the wrong icon (one that didn't exist)
    • +
    +

    Spacemanspark updated:

    +
      +
    • Fixes synthetics from giving off the proper message in the chat box when using the *yes and *no emotes.
    • +
    +

    Tastyfish updated:

    +
      +
    • Wheelchairs, janicarts, and ambulances can now go through doors according to the user's driver's access.
    • +
    + +

    24 February 2016

    +

    Crazylemon64 updated:

    +
      +
    • The defib should be more reliable on people who have ghosted
    • +
    • The defib will now give a message if the ghost is still haunting about
    • +
    • Attacking someone with an accessory will now let you put things on them without having to strip them.
    • +
    • Borers will now properly detach upon death of a mob they are controlling
    • +
    • Borers can now see their chemical count while in control of a mob
    • +
    • Borers can now silently communicate with their host - this is not available to the host until the borer has either begun to communicate, or has taken control at least once - this is to avoid spoiling that the borer exists
    • +
    • Borers won't be able to talk out loud inside of a host, by default - they can remove this safeguard with a verb under their borer tab. Borer hivespeak is unaffected.
    • +
    • Borers infesting and hiding are now silent.
    • +
    • Made borer's chem lists more nicely formatted
    • +
    • No more superspeed attacking simplemobs
    • +
    • New players now show up properly under the "who" verb when used as an admin
    • +
    • Mining drones will now automatically collect sand lying around
    • +
    • RIPLEYs can now drill asteroid turfs for sand
    • +
    • You can now load exosuit fuel generators with items containing their material - this means you can fuel yourself off of ores, but this will be highly inefficient and cost you mining points later on, as you can't take fuel back out.
    • +
    • You can now load the fuel generators from an ore box.
    • +
    • The plasma generator now produces 3x as much power from the same amount of fuel - this lets it even remotely compete with the uranium generator.
    • +
    • You can now light cigarettes off of burning mobs.
    • +
    • Exosuit tracking beacons now fit in boxes - prior, they were far too large for even a backpack, as they shared the same size as all other mecha equipment
    • +
    • Miners can now collect ore by walking over it with an ore satchel on.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds prize tickets as a replacement for physical arcade prizes.
    • +
    • Adds a buildable prize counter to exchange tickets for prizes.
    • +
    • Adds a bike. Despite what Prof. Oak might claim, you can ride it indoors.
    • +
    • Adds colorful wallets, for that old school arcade pride.
    • +
    • Fixes accidental removal of plump helmet biscuit recipe.
    • +
    • Temporarily adds a prize counter to the bar (Cyberiad) or dorms (MetaStation), and adds a max upgrade one to the Ninja Holding Area (Cyberiad z2)
    • +
    • Fixes Metastation. Seriously fixed a lot, just read the PR description for the full list.
    • +
    +

    FlattestGuitar updated:

    +
      +
    • Adds IPC alcohol and a few derivative drinks
    • +
    • IPCs can now drink and be fed from glasses
    • +
    +

    Fox McCloud updated:

    +
      +
    • Laser eyes mutation no longer drains nutrition
    • +
    • splits the EMP kit into two things: the standard EMP kit (2 grenades and an implant), and the EMP flashlight by itself
    • +
    • nerfs heart attacks so they do less damage
    • +
    • Pickpocket gloves now put the item you strip into your hands as opposed to the floor
    • +
    • Picketpocket gloves can now silently strip accessories
    • +
    • Pickpocket gloves will no longer give a message for messing up a pickpocket
    • +
    +

    KasparoVy updated:

    +
      +
    • Adjusting masks while they are not on the face will no longer turn off internals.
    • +
    • Adjusting masks while they are not on the face will now cause the mask to hide/reveal the wearer's identity the next time it's worn as intended.
    • +
    • Adds the ability to open/close bomber jackets.
    • +
    • Adds a security bomber jacket. This jacket inherits the protection and storage capabilities as a standard Security vest with additional bomber jacket benefits.
    • +
    • Adds UI button in top left of screen for jacket adjustment.
    • +
    • Replaces the standard bomber jacket in the Pod Pilot bay with the Security version.
    • +
    • Centralizes jacket/coat adjustment handling.
    • +
    • All jackets start closed by default.
    • +
    • Geneticist duffelbag on-mob sprite (for all species).
    • +
    • Vox-fitted backpacks, satchels, ERT backpacks, duffelbags and defib unit.
    • +
    • Refactors back-item icon generation.
    • +
    • Typo in the description of Santa's sack.
    • +
    • Missing punctuation and gender macros in the description of the bag of holding.
    • +
    • The tweak to back-icon generation fixes a bug where the wrong sprite name was being used to generate back-item icons.
    • +
    +

    PPI updated:

    +
      +
    • Adds the ability to hide papers in vents. You can now leave a romantic love letter, exchange information in secret, or hide papers infused with the power of nar'sie from sight.
    • +
    +

    Regen1 updated:

    +
      +
    • Adds the Immolator laser gun, a modified laser gun with 8 shots that will ignite mobs, can be made in R&D
    • +
    +

    Spacemanspark updated:

    +
      +
    • Adds *yes and *no emotes to Synthetics. Glory to Synthetica.
    • +
    +

    Tastyfish updated:

    +
      +
    • The PDA system has been completely redone behind the scenes! It should be functionally similar, although there is now a Home and Back button at the bottom as appropriate.
    • +
    • All of the heads now have multicolored pens.
    • +
    • EngiVend now has 10 camera assemblies.
    • +
    • Borgs can now use vending machines.
    • +
    • There are now picture frames that can be made from the autolathe or wood planks for papers, photos, posters, and canvases!
    • +
    +

    pinatacolada updated:

    +
      +
    • Makes the Protect Station AI law board no longer consider people that damage the station crew, instead of human
    • +
    +

    ppi updated:

    +
      +
    • When revealed Revenants will not be able to move at the maximum move speed, nor be able to pass through any solid object, like walls, windows, grills, computers and mechs.
    • +
    + +

    13 February 2016

    +

    Crazylemon64 updated:

    +
      +
    • Relaxes the check on what atoms you can follow to any movable atom
    • +
    • Mages are now more ragin
    • +
    • Admins can now adjust the total number of wizards at runtime by tweaking either max_mages, or players_per mage
    • +
    +

    DaveTheHeadcrab updated:

    +
      +
    • Adds new worn icons for duffelbags to better reflect their size, compliments of WJohn at /tg/
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds burritos, made from cutlets, beans, rice, capsacin oil (hotsauce), cheese, and flat dough (because we lack proper tortillas) in the microwave.
    • +
    • Adds chimichangas. You know you want a deep-fried burrito.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Updates some spell icons with better/higher quality icons
    • +
    • Updates unarmed attacks to allow for more customization
    • +
    • Updates martial arts so they factor in specie's attack messages and sounds
    • +
    • Re-balances Sleeping Carp fighting style
    • +
    • Re-balances Bo Staff
    • +
    • Rebalances Golem: they should now be spaceproof, fire+cold proof, rad proof, virus immune, clonable, parapen+syringe gun immune, deal increased melee damage. Their armor has been reduced to 55 melee across the board, their slip immunity removed, pain immunity removed, and they're slightly slower
    • +
    • Fixes Ei Nath generating two brains
    • +
    • Ensures the Necromatic Stone generates actual skeletons
    • +
    • Can now strip PDA/IDs from Golems
    • +
    • Fixes sleeping carp grab not being an instant aggressive grab
    • +
    • Fixes an exploit with declaring war on the station
    • +
    +

    KasparoVy updated:

    +
      +
    • Orange and purple bandanas for all station species.
    • +
    • The ability to colour bandanas with a crayon in a washing machine.
    • +
    • Refactors the bandana adjustment system.
    • +
    • Minor adjustments to Tajaran and Unathi bandana east/west sprites.
    • +
    • Adjusting a bandana will now take if off of your head/face and put it in an available hand. If both hands are available, it goes in the selected hand.
    • +
    • Adjusting a coloured bandana will no longer revert it to the original coloured icons anymore.
    • +
    • Adjusting a bandana from mask-style to hat-style means the bandana won't obscure your identity anymore.
    • +
    • Greys now use re-positioned smokeables. They no longer smoke out the eyes.
    • +
    +

    TheDZD updated:

    +
      +
    • Fixes spacepods being able to shoot through walls.
    • +
    • Lowers spacepod weapons fire delay.
    • +
    • Increases spacepod weapons energy costs.
    • +
    • Makes spacepods move at speeds not rivaling those of photon beams. They are now a hair bit faster than a person with a jetpack.
    • +
    • Reduces battery costs for spacepod movement.
    • +
    + +

    10 February 2016

    +

    Crazylemon64 updated:

    +
      +
    • The cloner now checks for NO_SCAN on the brain when scanning - unclonable species are now truly unclonable. You are still able to revive them with a brain transplant and a defib, however.
    • +
    • A tier-4 DNA scanner linked to a cloning system will now be able to reproduce a body from a brain's DNA, in event of the original corpse being gibbed or similar.
    • +
    • Species with organic limbs and NO_BLOOD will no longer bleed (though still on hit - write that off as "bone powder")
    • +
    • Skeletons now lack internal organs, except for the runic mind which exists in their head - an analogue for the brain
    • +
    • Skeletons that drink milk will be regenerated at a moderate pace, have a small chance of mending bones, and will praise the great name of mr skeltal
    • +
    • Adds a reagent system for species reacting to specific reagents
    • +
    • Slime People can now select from all human hairstyles, and their "hair" will be tinted a shade of their body.
    • +
    • Increases the frequency of the cortical borer event.
    • +
    • People with borers cannot commit suicide - this applies to a controlling borer, too.
    • +
    • Borers can no longer overdose their hosts.
    • +
    • Borers can now inject Saline-Glucose, Spaceacillin, Hydrocodone, Mitocholide, Salbutamol, Capulettium+, and Charcoal. Styptic was removed, as it's pathetic at healing when directly injected. Salicyclic acid was removed too, as its functionality is duplicated by both hydrocodone and saline-glucose.
    • +
    • A mind trapped by a cortical borer can now understand things it could understand when normally in its body.
    • +
    • Changes chemistry's welding tank to a wall-mounted version, to increase the room available.
    • +
    • You can now gib butterflies and lizards with a knife
    • +
    • Ghosts can now follow mecha
    • +
    • You can now access an R&D console by emagging it - it did nothing before.
    • +
    • Walls will now properly smooth and show damage.
    • +
    • Fixes the dialog that occurs when the AI shuts off to actually do what it says it does
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes not being able to attach IEDs to beartraps
    • +
    • Can no longer spamclick someone to death using headslamming on a toilet/urimal
    • +
    • Toilet/urinal headslamming now plays a sound
    • +
    • Toilet headslamming damage reduced slightly
    • +
    • Can now fill open reagent containers in a toilet to receive "toilet water".
    • +
    • No more message spam when someone fills a container using a sink
    • +
    • Can now wash your face using a sink, which washes away lipstick and wakes you up slightly
    • +
    • Washing things will now use progress bars
    • +
    • Ensures consuming a single syndicate donk pocket won't get you addicted to meth
    • +
    • Kinetic Accelerators and E-bows automatically reload
    • +
    +

    Glorken updated:

    +
      +
    • Added a Knight Arena for Holodeck.
    • +
    • Added red and blue claymore sprites.
    • +
    • Changed overrided to overrode when emagging Holodeck computer.
    • +
    +

    KasparoVy updated:

    +
      +
    • Vox versions of the Officer SWAT sechailer + HOS SWAT sechailer + Warden SWAT sechailer.
    • +
    • Resprited versions of most Human masks to fit Unathi, Tajara and Vulpkanin.
    • +
    • Warden now gets their own version of the SWAT sechailer in their locker.
    • +
    • HOS now gets the appropriate version of the SWAT sechailer in their locker.
    • +
    • Repositioned smokeables now available for Vox, Unathi, Tajara and Vulpkanin.
    • +
    • Properly shades Vox bandana down-state sprites.
    • +
    • Readds Tajaran bald hairstyle.
    • +
    • Alternate style of non-Human breath mask (incl. surgical/sterile mask) down-state positioning.
    • +
    • Corrects all non-Human species' breath mask (incl. surgical/sterile mask) down-state icons to use the right position style.
    • +
    • Minor adjustments to Tajaran breath mask up-state sprites.
    • +
    +

    PPI updated:

    +
      +
    • Adds a reconnect button to the File menu in the client.
    • +
    • Adds head patting
    • +
    +

    Regen updated:

    +
      +
    • Powersink can now drain a lot more power before going boom
    • +
    • Buffed the powersinks drain rate
    • +
    • Buffed explosion from an overloaded powersink, try to find it instead of overloading the grid.
    • +
    • Admin log warning before the powersink explodes
    • +
    +

    Spacemanspark updated:

    +
      +
    • Miners can now utilize the power of mob capsules to take along their lazarus injected mining creatures!
    • +
    • Store your Pokemo- er, sorry, I mean mining mobs that you've captured in the lazarus capsule belt.
    • +
    +

    Tastyfish updated:

    +
      +
    • Species that don't breathe can kill themselves now!
    • +
    • Suicide messages are now catered to your species.
    • +
    • Shortened the default pill & patch name when using the ChemMaster.
    • +
    • The chaplain now has a service radio headset, as Space Jesus intended.
    • +
    +

    TheDZD updated:

    +
      +
    • When Ahelping, "Question" is now "Mentorhelp" and "Player Complaint" is now "Adminhelp."
    • +
    • Mentorhelps and PM replies from mentors appear in a bold aqua blue color.
    • +
    • Adminhelps and PM replies from admins appear in a bold bright red color.
    • +
    • PM replies from players appear in a dull/dark purple color.
    • +
    • Adds admin attack log to players being converted to cult.
    • +
    • Adds shadowling thrall jobbans.
    • +
    • Jobbanned players who are converted to shadowling thrall, revolutionary, or cultist will have the control of their body offered up to eligible ghosts.
    • +
    + +

    31 January 2016

    +

    Crazylemon64 updated:

    +
      +
    • Syndicate borgs can now interact with station machinery
    • +
    • People with slime people limbs can now *squish
    • +
    • Skrell's vulnerability to alcohol is checked on their liver, now - a liver transplant will let them take alcohol like a champ - lacking a liver will have the same effect as being a skrell, when drinking
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Adds in the Magic Eight Ball toy, found in Claw Game prize orbs.
    • +
    • Adds in the Magic Conch Shell, an admin-only shell of power.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Updates Summon Guns and Magic to include many of the new guns
    • +
    • Summon Guns/Magic can no longer be used during Ragin' Mages
    • +
    +

    Tastyfish updated:

    +
      +
    • The emergency shuttle status in the Status tab now has ETA/ETD/etc like before.
    • +
    • Code Gamma+ now has a 5 minute emergency shuttle call, like Red.
    • +
    +

    pinatacolada updated:

    +
      +
    • Adds NanoUI to the operating computer
    • +
    • Adds health announcing, critical and oxygen damage aural alerts to the computer, with a menu to selectively turn them on and off
    • +
    + +

    29 January 2016

    +

    Crazylemon updated:

    +
      +
    • The DNA scanner has now undergone a seminar to recognize fake identities; It will now scan the actual person's identity, rather than their disguise (read: wearing a mask with or without someone else's ID).
    • +
    • Matter eater now allows you to eat humans as if you were fat.
    • +
    • Eating mobs with an aggressive grab now generates attack logs.
    • +
    +

    Crazylemon64 updated:

    +
      +
    • For a short while, there was a clerical error where all AI communications equipment was replaced with bananas. This has now been fixed.
    • +
    • Ghosts can now see the contents of smartfridges and look at the drone console
    • +
    • Humans now only produce one message when shaken while SSD
    • +
    • The supermatter no longer will irradiate everyone, everywhere, when it explodes.
    • +
    • Writing on paper will now add hidden admin fingerprints, so that you can't forge mean notes in someone else's name.
    • +
    • Brains are no longer able to escape their brain by being a sorcerer.
    • +
    • Astral projecting with other runes on the same tile will now no longer prevent you from re-entering
    • +
    • Voxxy that is become ex-voxxy no longer carry voxxy appearance! yaya!
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Allows plants to be identified as enhanced*. Enhancing plants results from using reagents (like saltpetre) that affect the stats of a seed instead of using mutagens/machines. *May not meet standards for being classified as "organic produce". (This was already possible, just renames enhanced plants for easier differentiation)
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes mutadone not working with some genetic mutations
    • +
    • Fixes banana honk and silencer being alcoholic
    • +
    • Fixes Kahlua being non-alcoholic
    • +
    • Fixes polonium not metabolizing
    • +
    • Fixes being able to receive free unlimited boxes from the Merchandise store
    • +
    • Adds in wooden bucklers
    • +
    • Re-adds roman shield to the costume vendor
    • +
    • Buffs Riot shield damage from 8 to 10
    • +
    • Adds in a Skeleton race
    • +
    • Tweaks the skeletons colors to be more realistic and to blend in less with the floor
    • +
    • Adds in lichdom spell for the wizard
    • +
    • Adds in lesser summon guns spell for wizard
    • +
    • adds in Mjolnir and the singularity hammer as weapons the wizard can purchase
    • +
    • Wizard can purchase the charge spell from the spell book
    • +
    • Wizard can purchase a healing staff from the spell book
    • +
    • Tweaks and lowers spell costs of utility spells for wizard
    • +
    • Re-organizes the spellbook to be better divided into categories and have a better window size
    • +
    • Knock now opens+unlocks lockers
    • +
    • Magic Missile has a slightly longer cooldown and no longer deals damage, but has a lower cooldown is upgraded
    • +
    +

    KasparoVy updated:

    +
      +
    • Navy blue Centcom Officer's beret for use by the Blueshield.
    • +
    • Adds the new navy blue beret to the Blueshield's locker.
    • +
    • Gives the Blueshield's berets (black and navy blue) the exact same strip delay and armour as the Security Officer's beret.
    • +
    • Adds TG energy katana back and belt sprite.
    • +
    • Bo staff back sprite.
    • +
    • Adjusts energy katana sprites to make the weapon stand out a bit more from the regular katana.
    • +
    • Cutting open the toes of footwear so species with feet-claws can wear them.
    • +
    • Toeless jackboots.
    • +
    • Cleans up glovesnipping and lighting a match with a shoe.
    • +
    • Lighting a match with a shoe produces a more appropriate message, handled at the same standard as glove-snippingboot-cutting.
    • +
    +

    Tastyfish updated:

    +
      +
    • Cargonia now has its own section in the manifest.
    • +
    +

    TheDZD updated:

    +
      +
    • Due to budget cuts and reports of operatives accidentally firing enough bullets to reach a state of what our scientists refer to as "enough dakka," Syndicate High Command has decided to restore the Syndicate Strike Team arsenal to using standard-issue L6 SAW ammunition.
    • +
    + +

    24 January 2016

    +

    KasparoVy updated:

    +
      +
    • Fixes markings overlaying underwear.
    • +
    • Nude icon in underwear.dmi
    • +
    • Fixes Vox robes not using the correct on-mob sprites.
    • +
    • Fixes unreported bug where there was a slim chance during character preview icon generation that a character with Security Officer set to high would get rendered with either the wrong beret sprite or no beret sprite at all.
    • +
    • Fixes an issue where Sigholt's fluff beret wasn't using the correct sprites.
    • +
    +

    Tastyfish updated:

    +
      +
    • Passively power-consuming borg modules, such as the peacekeeper movement and shield module, won't spam the user infinitely if they're low on power anymore.
    • +
    + +

    23 January 2016

    +

    Fox McCloud updated:

    +
      +
    • Removes Vampire HUD
    • +
    • moves the Vampire blood counter to a more easy to see location
    • +
    • Adds in a Changeling chemical counter display
    • +
    • Adds in a Changeling sting counter display
    • +
    • Vampire total blood and usable blood will now appear under status
    • +
    • Changes vampire blood display to be similar to ling chemical counter
    • +
    • Fixes unnecessary toxin damage being dealt on severe bloodloss
    • +
    • Fixes human mobs not receiving proper random names
    • +
    • Adds in knight armor
    • +
    • Grants the chaplain a set of crusader knight armor
    • +
    • Adds in cult-resistant ERT paranormal space suit
    • +
    • Allows the Chaplain to convert his null rod into a holy sword with crusader knight armor
    • +
    • Chaplain's closet is now a secure closet
    • +
    • Adds in Assault Gear crate to cargo
    • +
    • Adds in military assault belt
    • +
    • Adds in spaceworthy swat suits
    • +
    • tweaks bandolier to hold 2 additional shotgun shells
    • +
    • bartender starts off with +2 additional shells
    • +
    • Reduces the cost of the space suit crate and doubles its contents
    • +
    • Refactors knives so their behavior is more universal
    • +
    • Fixes Hulk not properly being removed when your health drops below a threshold
    • +
    • Fixes flickering vision in a mining mech
    • +
    +

    Tastyfish updated:

    +
      +
    • Poly has taken a seminar on the latest trends in engine operations.
    • +
    • Player-controller parrots can now hear their headsets.
    • +
    +

    Tigerbat2000 updated:

    +
      +
    • The nuclear disk escaping on the shuttle no longer counts as a syndicate minor victory.
    • +
    • Cultists can once again actually greentext the escape objective.
    • +
    + +

    20 January 2016

    +

    DarkPyrolord updated:

    +
      +
    • Adds in hardsuit sprites for Vulpkanin
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Allowed cheap lighters and individual matches to be put into cigarette packages at the cost of cigarette space.
    • +
    • Matches can now be lit and put out by striking the match on your shoes. Good for if you lose that matchbox, or want to just feel cool.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes brute damage on weapons not knocking people down.
    • +
    • Tweaks implant behavior to be more consistent and unified.
    • +
    • Lowers the pAI cooldown from 60 seconds to 5 seconds.
    • +
    • Raw telecrystal can now be used to charge uplink implants.
    • +
    • Fixes being unable to holster the pulse pistol
    • +
    • Fixes being able to holster shotguns
    • +
    +

    KasparoVy updated:

    +
      +
    • Improved shading on all Vulpkanin hardsuit tails.
    • +
    • Vulpkanin hardsuit helmet respriting (colour tweaks).
    • +
    • Vulpkanin hardsuit helmets with proper flashlight-on sprites.
    • +
    +

    Tastyfish updated:

    +
      +
    • The ID computer Access Report printout now separates the access list with commas so it's actually readable.
    • +
    • The ID computer Access Report printout isn't blank if you don't have an authorization card in anymore.
    • +
    • In the supply ordering & shuttle consoles, one can now cancel an order at either the Reason or Amount input dialogs.
    • +
    • Table flipping uses correct sprites.
    • +
    +

    TheDZD updated:

    +
      +
    • Adds world.Topic() handling so that users are notified in-game when pull requests are opened, closed, or merged on the Github repo.
    • +
    + +

    18 January 2016

    +

    Crazylemon updated:

    +
      +
    • New classes of shapeshifters have been sighted around the NSS Cyberiad...
    • +
    • Wizards now can't teleport to other antag spawn points.
    • +
    • Removes an extruding pixel from the left-facing IPC glider monitor sprite.
    • +
    • Ragin' Mages now spawn every 7 minutes, instead of 5. Admins can further adjust this by modifying the 'delay_per_mage' variable.
    • +
    • Ragin' Mages are now made with 100% less in-use souls (Apprentices won't have their consciousness yoinked).
    • +
    • It takes half an hour for the REAL chaos of ragin' mages to start, for at least a semblance of normality.
    • +
    +

    Dave The Headcrab updated:

    +
      +
    • Adds the advanced energy revolver, toggles between taser and laser modes.
    • +
    • Removes the detective's revolver from the blueshield's locker.
    • +
    • Changes the taser the blueshield starts with into an advanced energy revolver.
    • +
    +

    Deanthelis updated:

    +
      +
    • Added the ability for the Magnetic Gripper to pick up and place light tiles.
    • +
    +

    Fethas updated:

    +
      +
    • Readds the hud icon showing up for master and servent
    • +
    • adds mindslave datum hud thingy based on TGs gang huds
    • +
    +

    Fox McCloud updated:

    +
      +
    • Fixes not being able to add/remove Weapon Permit from IDs.
    • +
    • Fixes the energy sword being invisible in-hand when turned on.
    • +
    • Fixes the telebaton being invisible in-hand when extended.
    • +
    • Fixes eye-stabbing not having an attack animation or hitsound.
    • +
    • Fixes some kitchen utensils playing the wrong hit-sound and playing twice in some cases.
    • +
    • Fixes the butcher cleaver sprite being backwards.
    • +
    • Fixes the telebaton sprite being missing from the side.
    • +
    • Fixes the meat cleaver being invisible in-hand.
    • +
    • Corrects some grammatical descriptive errors for the elite syndicate hardsuit.
    • +
    • completely overhauls implants to TG's standards.
    • +
    • Adds storage implant.
    • +
    • Adds microbomb and macrobomb implants.
    • +
    • Adds in support for removing implants directly into cases.
    • +
    • Removes Bay style explosive implants.
    • +
    • Removes compressed matter implants.
    • +
    • Tweaks the uplink to reflect removal of the old implants and inclusion of the new.
    • +
    • Fixes/cuts down on the lag caused by monkey cubes.
    • +
    +

    Jey updated:

    +
      +
    • Inflatable walls and door can now be deflated by altclicking them
    • +
    • Fixed lag from expanding multiple monkeycubes at once.
    • +
    +

    KasparoVy updated:

    +
      +
    • Adds blank icons with standardized timings for species tail wagging, used in icon generation.
    • +
    • Fixes tails overlapping arms/limbs + gloves, etc. when facing EAST or WEST.
    • +
    • Ensures tails will overlap stuff as normal only when facing NORTH so as to avoid unwanted interference with the base sprite.
    • +
    • Tails now appear in ID cards, overlays things correctly.
    • +
    • Tails now overlay and are overlaid by things correctly in preview icons.
    • +
    • Modifies the positioning of tail icon generation in the ID card preview icon generation file.
    • +
    • Modifies the positioning of tail icon generation in the player preferences preview icon generation file.
    • +
    • Breaks limb generation into its own layer, breaks tail generation into a second layer that can be overlaid by limbs.
    • +
    • If the user's species is flagged to have a tail that is overlapped, TAIL_LAYER will now overlay the NORTH direction sprite of a tail now, while TAIL_UNDERLIMBS_LAYER gets all remaining directions. Otherwise icons are generated in the traditional manner.
    • +
    • Adjusts the Unathi right arm east direction and animated tail sprites, recolouring a random pixel and fixing a floating tail respectively.
    • +
    • Adjusts position of tail layer such that tails' north direction sprites will overlay backpacks (more importantly, satchel straps).
    • +
    • Accommodates admin-overrides to the body_accessory species check by setting the default animation template to Vulpkanin.
    • +
    • Adjusts north-direction Unathi static tail sprite, now attaches to the body in the correct location.
    • +
    • Adds some TG underwear.
    • +
    • Adds an NV science goggles worn sprite.
    • +
    • Ports Bay/TG berets.
    • +
    • Adjusts beret sprite, recolours strange orange pixels.
    • +
    • Adjusts NV science goggles object icon. Removed strange border and centered it.
    • +
    • Ports Polaris' PRs 761 and 778, brings over Ragnie's awesome Ward-Takahashi prosthetics.
    • +
    +

    Kyep updated:

    +
      +
    • Changing level to gamma/delta/epsilon now displays a special gamma/delta/epsilon sprite on status monitors
    • +
    • Changing level to green/blue now clears the status monitors, so they no longer show higher alert levels after the level is changed
    • +
    +

    NTSAM updated:

    +
      +
    • Added a rainbow IPC screen.
    • +
    +

    PPI updated:

    +
      +
    • Modifies the effective time limit to activate the Nuclear Challenge as Nukeops from two minutes to seven minutes
    • +
    +

    Tastyfish updated:

    +
      +
    • The QM now actually has a QM stamp instead of a fake one, as well as an approved and denied stamp.
    • +
    • New area named 'Genetics Maintenance' solidifying/relabelling the confusing area between the morge and Mech Bay as being fully maintenance again, but working correctly and with proper doors.
    • +
    • Fixed a few maintenance door names to be in parity to the rest of the station.
    • +
    • Added the ability to print the records photo of a crew member from a security records console. Useful for Wanted notices!
    • +
    +

    Tigercat2000 updated:

    +
      +
    • You can no longer use the gibber for monkies.
    • +
    • Cleaned up gibber.dm styling.
    • +
    • The fire alarm now uses NanoUI, with color coded alert levels.
    • +
    • Upgraded NanoUI (again), fancy FontAwesome icons.
    • +
    • Didn't add any butts. Yet.
    • +
    + +

    13 January 2016

    +

    Fox McCloud updated:

    +
      +
    • Fixes Rezadone not clearing mutated organs.
    • +
    • Clone damage immunity removed from Slime People, Shadowlings, Golems, and Vox
    • +
    • Explosions will no longer destroy things underneath turfs until the turf is exposed.
    • +
    • fixes a runtime related to revolver spinning.
    • +
    • fixes server loading taking an abnormally long time.
    • +
    +

    Kyep updated:

    +
      +
    • Blob, vine and virus outbreaks are now more clearly labeled as such, to avoid people confusing them with each other
    • +
    +

    Tastyfish updated:

    +
      +
    • NT Rep fountain pens and magistrate gold pens can now write in 5 different colors. The IAA gets a cheap plastic equivalent.
    • +
    + +

    11 January 2016

    +

    CrAzYPiLoT updated:

    +
      +
    • Fixes the footsteps sounds to the fullest.
    • +
    +

    Crazylemon updated:

    +
      +
    • Bomb guardians now automatically notify their master when they've set something to boom, so there's less accidental friendly fire
    • +
    • Bomb guardians are only notified that their trap failed, if it ACTUALLY FAILED.
    • +
    • Bomb guardians now are more aware of what is primed to explode.
    • +
    • Bomb guardian summoners can now defuse their guardian's bombs without harm.
    • +
    • Brought RAGIN' MAGES back up to function.
    • +
    +

    Dave The Headcrab updated:

    +
      +
    • Added a new icon for the soy and cafe latte drinks. Icons courtesy of Full Of Skittles, resident overlord of art.
    • +
    +

    Fox McCloud updated:

    +
      +
    • Re-arranges the armory and changes its contents minorly.
    • +
    • Adds in rubbershot ammo boxes.
    • +
    • Fixes Mutadone incurring a massive cost on the server.
    • +
    • Positronic brains can no longer speak binary.
    • +
    • Positronic brains can be prevented from speaking (or allowed) by toggling their speaker on/off.
    • +
    • IPC's positronic brains start off toggled off.
    • +
    • Fixes the supermatter announcement causing massive amounts of server lag.
    • +
    • Adds in tradable telecrystals.
    • +
    + +

    08 January 2016

    +

    Crazylemon updated:

    +
      +
    • Fully enables a system to allow species to have unique procs and verbs that come and go with the species.
    • +
    • IPCs lose their change monitor verb when changing species now. Gone are the days of recalling a past IPC life to perform self-barbery! Oh, woe is me!
    • +
    • Sleepers and Body Scanners will now reliably work when rotated
    • +
    • SSD humans should be asleep more reliably now.
    • +
    +

    Dave The Headcrab updated:

    +
      +
    • Nerfs the damage the Detective's revolver does from 15 brute to 5 brute.
    • +
    • Adds a 300 round capacity buckshot magizine that fits into the L6 Saw.
    • +
    • Adds a 25 round capacity 40mm HE magizine that fits into the L6 Saw.
    • +
    • Adds the 'Devastator' L6 SAW, starts off loaded with the buckshot magizine.
    • +
    • Gives the SST the 'Devastator' L6 Saw, and one of each mag type in their bag.
    • +
    +

    FalseIncarnate updated:

    +
      +
    • Plants will now begin to die over time if their age exceeds 5 times their TRAIT_MATURATION value.
    • +
    • Weed growth chance per process in trays has been slightly increased (Previously: 5% chance if no seed, 1% otherwise;Now: 6% / 3%).
    • +
    • Pest growth in trays has been slightly buffed. (Previously: 3% chance to increase by 0.1; Now: 5% chance to increase by 0.5)
    • +
    +

    Fethas updated:

    +
      +
    • Due to Archmage Steve leaving the nya-cromantic stone near the microwave, the true power of the stone has been unleashed. Subjects of the stone are not only ressurected ... but resurrected as catgirls ... We fired steve.
    • +
    +

    Fox McCloud updated:

    +
      +
    • fixes a bug relating to some brute/burn damage being dealt to human mobs.
    • +
    • Adds in overloading APCs, causing them to arc electricity to mobs in range.
    • +
    • Makes Engineering related APCs overload proof.
    • +
    • Implements the timestop spell.
    • +
    • Implements new sepia slime reaction which halts time in an AoE.
    • +
    • sentience potions no longer can make slimes sentient.
    • +
    • Removes Hulk instant stun.
    • +
    • Hulk damage increased.
    • +
    • Hulk wears off at a lower health threshold.
    • +
    • Fixes strange reagent not working on simple animals.
    • +
    • Reduces the amount shock damage and bounces for the Tesla engine.
    • +
    • Fixes Syndicate Cyborg's LMG being invisible.
    • +
    • Fixes the uplink kit having implanters that were both nameless and looked as if they had been used.
    • +
    +

    KasparoVy updated:

    +
      +
    • Added the security gasmask, sexy mime mask, bandanas, balaclava, welding gas mask and wrestling masks for Vox. Added adjusted-state sprites for the Vox breath, medical, and surgical masks.
    • +
    • Removed a duplicate of the human balaclava sprite.
    • +
    • Modifies the Vox plague-doctor, fake moustache, sterile and medical mask sprites to fit the Vox anatomy and animates the Vox SWAT mask. Corrects the names of some Vox mask adjusted-state sprites.
    • +
    +

    Tastyfish updated:

    +
      +
    • Fixed the pronouns in a few verbs and the door to 'Interrogation Observervtion'.
    • +
    +

    Tigercat2000 updated:

    +
      +
    • Added 96x96 (3x) res option to icons menu
    • +
    + +

    06 January 2016

    +

    Certhic updated:

    +
      +
    • Corrected some air alarms so that atmos computer can access them
    • +
    • Bodyscanner now sees mechanical parts in internal organs
    • +
    +

    Crazylemon64 updated:

    +
      +
    • Sleeping simple animals should tick down sleeping as normal - deaf simple mobs are no longer a thing
    • +
    +

    Tastyfish updated:

    +
      +
    • Instruments now use NanoUI.
    • +
    • Corrected the blueshield mission briefing.
    • +
    + +

    03 January 2016

    +

    TheDZD updated:

    +
      +
    • Ports over changelog system from /tg/station.
    • +
    +
    + +GoonStation 13 Development Team +
    + Coders: Stuntwaffle, Showtime, Pantaloons, Nannek, Keelin, Exadv1, hobnob, Justicefries, 0staf, sniperchance, AngriestIBM, BrianOBlivion
    + Spriters: Supernorn, Haruhi, Stuntwaffle, Pantaloons, Rho, SynthOrange, I Said No
    +
    +
    +

    Creative Commons License
    Except where otherwise noted, Goon Station 13 is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 License.
    Rights are currently extended to SomethingAwful Goons only.

    +

    Some icons by Yusuke Kamiyamane. All rights reserved. Licensed under a Creative Commons Attribution 3.0 License.

    +
    + + diff --git a/html/changelog.js b/html/archived_changelog/changelog.js similarity index 100% rename from html/changelog.js rename to html/archived_changelog/changelog.js diff --git a/html/changelogs/.all_changelog.yml b/html/archived_changelog/changelogs/.all_changelog.yml similarity index 97% rename from html/changelogs/.all_changelog.yml rename to html/archived_changelog/changelogs/.all_changelog.yml index 07c327faac8..0bd62e7a715 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/archived_changelog/changelogs/.all_changelog.yml @@ -11811,3 +11811,45 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - tweak: Cult whispering now uses your real name - bugfix: Fixed the invisible blob zombies - bugfix: A runtime in blob/factory/run_action +2020-04-26: + Cazdon: + - bugfix: Admin Roles no longer appear on manifest. + - tweak: Central Command PDA's no longer appear on the messenger list. + - bugfix: Potential Convertee's being unable to be converted. + Drakeven: + - bugfix: Fixed mislabeled traitor and mindslave special role. + Ionward: + - tweak: Grey, Tajaran, Unathi, and Vulpkanin now properly have species specific + fits for soft space suits. + - tweak: Vox can now wear soft space suits, such as EVA (Clown and Mime included), + NASA Void, and Syndicate suits. + - imageadd: Added Vox soft suit sprites. + JKnutson101: + - tweak: Combined the Rite of Tribute and Rite of Enlightenment into one Rite of + Offering. + - bugfix: Sacrificing now properly puts victims that have at one point had CKeys + into soul stones, or polls dead-chat to do so. + Kyep: + - tweak: Tweaked Greater Hellhound, added more non-violent options and one unique + combat spell. + SteelSlayer: + - bugfix: Fixes the "List SSDs and AFKs panel" showing everyone as the target of + an assassinate objective + - bugfix: The global objectives list is now viewable in the MC Globals menu + - bugfix: Reverts some terrible changes that are causing some bugs with traitors + - bugfix: Fixes AIs with the combat module not being able to hack APCs + TDSSS: + - rscdel: duplicate mecha definitions + - bugfix: blobbernaut vision blur now clears as intended. + - bugfix: fixed a bug preventing ticket system from working under some circumstances. + VeteranKyl: + - bugfix: DNA Samplers now check if the target species has DNA. + - bugfix: Fixed the envenomed blob's spore toxin not causing harm. + craftxbox: + - bugfix: fixed colors not working without regex + - bugfix: fixed text panel not loading when an invalid regex is added + - rscadd: polyfilled string.prototype.includes + moxian: + - bugfix: being in a locker no longer interferes with tracking implant tracking + - bugfix: locator no longer locates tracking implants on other z levels. + - bugfix: fixed singulo being unable to expand when placed next to containment wall diff --git a/html/changelogs/__CHANGELOG_README.txt b/html/archived_changelog/changelogs/__CHANGELOG_README.txt similarity index 100% rename from html/changelogs/__CHANGELOG_README.txt rename to html/archived_changelog/changelogs/__CHANGELOG_README.txt diff --git a/html/changelogs/example.yml b/html/archived_changelog/changelogs/example.yml similarity index 100% rename from html/changelogs/example.yml rename to html/archived_changelog/changelogs/example.yml diff --git a/html/chevron-expand.png b/html/archived_changelog/chevron-expand.png similarity index 100% rename from html/chevron-expand.png rename to html/archived_changelog/chevron-expand.png diff --git a/html/chevron.png b/html/archived_changelog/chevron.png similarity index 100% rename from html/chevron.png rename to html/archived_changelog/chevron.png diff --git a/html/cross-circle.png b/html/archived_changelog/cross-circle.png similarity index 100% rename from html/cross-circle.png rename to html/archived_changelog/cross-circle.png diff --git a/html/hard-hat-exclamation.png b/html/archived_changelog/hard-hat-exclamation.png similarity index 100% rename from html/hard-hat-exclamation.png rename to html/archived_changelog/hard-hat-exclamation.png diff --git a/html/image-minus.png b/html/archived_changelog/image-minus.png similarity index 100% rename from html/image-minus.png rename to html/archived_changelog/image-minus.png diff --git a/html/image-plus.png b/html/archived_changelog/image-plus.png similarity index 100% rename from html/image-plus.png rename to html/archived_changelog/image-plus.png diff --git a/html/music-minus.png b/html/archived_changelog/music-minus.png similarity index 100% rename from html/music-minus.png rename to html/archived_changelog/music-minus.png diff --git a/html/music-plus.png b/html/archived_changelog/music-plus.png similarity index 100% rename from html/music-plus.png rename to html/archived_changelog/music-plus.png diff --git a/html/archived_changelog/panels.css b/html/archived_changelog/panels.css new file mode 100644 index 00000000000..ac44cf54877 --- /dev/null +++ b/html/archived_changelog/panels.css @@ -0,0 +1,10 @@ +body {padding:0px;margin:0px;} +#top {position:fixed;top:5px;left:10%;width:80%;text-align:center;background-color:#fff;border:2px solid #ccc;} +#main {position:relative;top:50px;left:3%;width:96%;text-align:center;z-index:0;} +#searchable {table-layout:fixed;width:100%;text-align:center;"#f4f4f4";} +tr.norm {background-color:#f4f4f4;} +tr.title {background-color:#ccc;} +tr.alt {background-color:#e7e7e7;} +.small {font-size:80%;} +a {text-decoration:none;color:#a0a;} +a:hover {color:#d3d;} diff --git a/html/archived_changelog/search.js b/html/archived_changelog/search.js new file mode 100644 index 00000000000..abc47a97573 --- /dev/null +++ b/html/archived_changelog/search.js @@ -0,0 +1,33 @@ +function selectTextField(){ + var filter_text = document.getElementById('filter'); + filter_text.focus(); + filter_text.select(); +} +function updateSearch(){ + var input_form = document.getElementById('filter'); + var filter = input_form.value.toLowerCase(); + input_form.value = filter; + var table = document.getElementById('searchable'); + var alt_style = 'norm'; + for(var i = 0; i < table.rows.length; i++){ + try{ + var row = table.rows[i]; + if(row.className == 'title') continue; + var found=0; + for(var j = 0; j < row.cells.length; j++){ + var cell = row.cells[j]; + if(cell.innerText.toLowerCase().indexOf(filter) != -1){ + found=1; + break; + } + } + if(found == 0) row.style.display='none'; + else{ + row.style.display='block'; + row.className = alt_style; + if(alt_style == 'alt') alt_style = 'norm'; + else alt_style = 'alt'; + } + }catch(err) { } + } +} \ No newline at end of file diff --git a/html/spell-check.png b/html/archived_changelog/spell-check.png similarity index 100% rename from html/spell-check.png rename to html/archived_changelog/spell-check.png diff --git a/html/templates/footer.html b/html/archived_changelog/templates/footer.html similarity index 100% rename from html/templates/footer.html rename to html/archived_changelog/templates/footer.html diff --git a/html/templates/header.html b/html/archived_changelog/templates/header.html similarity index 100% rename from html/templates/header.html rename to html/archived_changelog/templates/header.html diff --git a/html/tick-circle.png b/html/archived_changelog/tick-circle.png similarity index 100% rename from html/tick-circle.png rename to html/archived_changelog/tick-circle.png diff --git a/html/wrench-screwdriver.png b/html/archived_changelog/wrench-screwdriver.png similarity index 100% rename from html/wrench-screwdriver.png rename to html/archived_changelog/wrench-screwdriver.png diff --git a/html/browser/marked-paradise.js b/html/browser/marked-paradise.js new file mode 100644 index 00000000000..03519139409 --- /dev/null +++ b/html/browser/marked-paradise.js @@ -0,0 +1,27 @@ +// Paradise-specific handling of marked.js. +// Basically we call it on element with id=markdown, and play with paragraphization a bit +// Requires marked.js to be loaded in order to be useful. + +var $ = document.querySelector.bind(document); +function parse(node) { + for (var i = 0; i < node.childNodes.length; i++) { + parse(node.childNodes[i]); + } + + if (!node.innerHTML) { + return; + } + + node.innerHTML = marked(node.innerHTML.replace(/
    /gi, '\n').replace(/\t/gi, ''), { breaks: false, gfm: false }) + // marked.js wraps content into

    tags, which is looks atrocious when we call it recursively. + // The following line unwraps it. + if (node.children.length == 1) { + node.innerHTML = node.children[0].innerHTML; + } +} + +window.onload = function() { + if ($('#markdown')) { + parse($('#markdown')); + } +} diff --git a/html/browser/marked.js b/html/browser/marked.js index fa151b6befd..758eb7563d5 100644 --- a/html/browser/marked.js +++ b/html/browser/marked.js @@ -3,34 +3,4 @@ * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT Licensed) * https://github.com/markedjs/marked */ -!function(e){"use strict";var _={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:f,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,nptable:f,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,table:f,lheading:/^([^\n]+)\n {0,3}(=|-){2,} *(?:\n+|$)/,paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,text:/^[^\n]+/};function a(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||m.defaults,this.rules=_.normal,this.options.pedantic?this.rules=_.pedantic:this.options.gfm&&(this.options.tables?this.rules=_.tables:this.rules=_.gfm)}_._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,_._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,_.def=i(_.def).replace("label",_._label).replace("title",_._title).getRegex(),_.bullet=/(?:[*+-]|\d{1,9}\.)/,_.item=/^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/,_.item=i(_.item,"gm").replace(/bull/g,_.bullet).getRegex(),_.list=i(_.list).replace(/bull/g,_.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+_.def.source+")").getRegex(),_._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",_._comment=//,_.html=i(_.html,"i").replace("comment",_._comment).replace("tag",_._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),_.paragraph=i(_.paragraph).replace("hr",_.hr).replace("heading",_.heading).replace("lheading",_.lheading).replace("tag",_._tag).getRegex(),_.blockquote=i(_.blockquote).replace("paragraph",_.paragraph).getRegex(),_.normal=d({},_),_.gfm=d({},_.normal,{fences:/^ {0,3}(`{3,}|~{3,})([^`\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/}),_.gfm.paragraph=i(_.paragraph).replace("(?!","(?!"+_.gfm.fences.source.replace("\\1","\\2")+"|"+_.list.source.replace("\\1","\\3")+"|").getRegex(),_.tables=d({},_.gfm,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/}),_.pedantic=d({},_.normal,{html:i("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",_._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/}),a.rules=_,a.lex=function(e,t){return new a(t).lex(e)},a.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},a.prototype.token=function(e,t){var n,r,s,i,l,o,a,h,p,u,c,g,f,d,k,m,b,x;for(e=e.replace(/^ +$/gm,"");e;)if((s=this.rules.newline.exec(e))&&(e=e.substring(s[0].length),1 ?/gm,""),x=1;b.match(/^ {0,3}>/);)x++,this.tokens.push({type:"blockquote_start"}),b=b.replace(/^ *> ?/gm,"");for(this.token(b,t),c=0;c?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:f,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(href(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong:/^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,em:/^_([^\s_])_(?!_)|^\*([^\s*"<\[])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s"<\[][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:f,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\?@\\[^_{|}~",n.em=i(n.em).replace(/punctuation/g,n._punctuation).getRegex(),n._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,n._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,n._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,n.autolink=i(n.autolink).replace("scheme",n._scheme).replace("email",n._email).getRegex(),n._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,n.tag=i(n.tag).replace("comment",_._comment).replace("attribute",n._attribute).getRegex(),n._label=/(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|`(?!`)|[^\[\]\\`])*?/,n._href=/\s*(<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*)/,n._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,n.link=i(n.link).replace("label",n._label).replace("href",n._href).replace("title",n._title).getRegex(),n.reflink=i(n.reflink).replace("label",n._label).getRegex(),n.normal=d({},n),n.pedantic=d({},n.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link:i(/^!?\[(label)\]\((.*?)\)/).replace("label",n._label).getRegex(),reflink:i(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",n._label).getRegex()}),n.gfm=d({},n.normal,{escape:i(n.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~+(?=\S)([\s\S]*?\S)~+/,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\/i.test(i[0])&&(this.inLink=!1),!this.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(i[0])?this.inRawBlock=!0:this.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(i[0])&&(this.inRawBlock=!1),e=e.substring(i[0].length),o+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(i[0]):u(i[0]):i[0];else if(i=this.rules.link.exec(e)){var a=k(i[2],"()");if(-1$/,"$1"),o+=this.outputLink(i,{href:p.escapes(r),title:p.escapes(s)}),this.inLink=!1}else if((i=this.rules.reflink.exec(e))||(i=this.rules.nolink.exec(e))){if(e=e.substring(i[0].length),t=(i[2]||i[1]).replace(/\s+/g," "),!(t=this.links[t.toLowerCase()])||!t.href){o+=i[0].charAt(0),e=i[0].substring(1)+e;continue}this.inLink=!0,o+=this.outputLink(i,t),this.inLink=!1}else if(i=this.rules.strong.exec(e))e=e.substring(i[0].length),o+=this.renderer.strong(this.output(i[4]||i[3]||i[2]||i[1]));else if(i=this.rules.em.exec(e))e=e.substring(i[0].length),o+=this.renderer.em(this.output(i[6]||i[5]||i[4]||i[3]||i[2]||i[1]));else if(i=this.rules.code.exec(e))e=e.substring(i[0].length),o+=this.renderer.codespan(u(i[2].trim(),!0));else if(i=this.rules.br.exec(e))e=e.substring(i[0].length),o+=this.renderer.br();else if(i=this.rules.del.exec(e))e=e.substring(i[0].length),o+=this.renderer.del(this.output(i[1]));else if(i=this.rules.autolink.exec(e))e=e.substring(i[0].length),r="@"===i[2]?"mailto:"+(n=u(this.mangle(i[1]))):n=u(i[1]),o+=this.renderer.link(r,null,n);else if(this.inLink||!(i=this.rules.url.exec(e))){if(i=this.rules.text.exec(e))e=e.substring(i[0].length),this.inRawBlock?o+=this.renderer.text(i[0]):o+=this.renderer.text(u(this.smartypants(i[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else{if("@"===i[2])r="mailto:"+(n=u(i[0]));else{for(;l=i[0],i[0]=this.rules._backpedal.exec(i[0])[0],l!==i[0];);n=u(i[0]),r="www."===i[1]?"http://"+n:n}e=e.substring(i[0].length),o+=this.renderer.link(r,null,n)}return o},p.escapes=function(e){return e?e.replace(p.rules._escapes,"$1"):e},p.prototype.outputLink=function(e,t){var n=t.href,r=t.title?u(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,u(e[1]))},p.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"â€").replace(/\.{3}/g,"…"):e},p.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",r=e.length,s=0;s'+(n?e:u(e,!0))+"\n":"

    "+(n?e:u(e,!0))+"
    "},r.prototype.blockquote=function(e){return"
    \n"+e+"
    \n"},r.prototype.html=function(e){return e},r.prototype.heading=function(e,t,n,r){return this.options.headerIds?"'+e+"\n":""+e+"\n"},r.prototype.hr=function(){return this.options.xhtml?"
    \n":"
    \n"},r.prototype.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"},r.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},r.prototype.checkbox=function(e){return" "},r.prototype.paragraph=function(e){return"

    "+e+"

    \n"},r.prototype.table=function(e,t){return t&&(t=""+t+""),"\n\n"+e+"\n"+t+"
    \n"},r.prototype.tablerow=function(e){return"\n"+e+"\n"},r.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"\n"},r.prototype.strong=function(e){return""+e+""},r.prototype.em=function(e){return""+e+""},r.prototype.codespan=function(e){return""+e+""},r.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},r.prototype.del=function(e){return""+e+""},r.prototype.link=function(e,t,n){if(null===(e=l(this.options.sanitize,this.options.baseUrl,e)))return n;var r='"},r.prototype.image=function(e,t,n){if(null===(e=l(this.options.sanitize,this.options.baseUrl,e)))return n;var r=''+n+'":">"},r.prototype.text=function(e){return e},s.prototype.strong=s.prototype.em=s.prototype.codespan=s.prototype.del=s.prototype.text=function(e){return e},s.prototype.link=s.prototype.image=function(e,t,n){return""+n},s.prototype.br=function(){return""},h.parse=function(e,t){return new h(t).parse(e)},h.prototype.parse=function(e){this.inline=new p(e.links,this.options),this.inlineText=new p(e.links,d({},this.options,{renderer:new s})),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},h.prototype.next=function(){return this.token=this.tokens.pop(),this.token},h.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},h.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},h.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,g(this.inlineText.output(this.token.text)),this.slugger);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,s="",i="";for(n="",e=0;e?@[\]^`{|}~]/g,"").replace(/\s/g,"-");if(this.seen.hasOwnProperty(t))for(var n=t;this.seen[n]++,t=n+"-"+this.seen[n],this.seen.hasOwnProperty(t););return this.seen[t]=0,t},u.escapeTest=/[&<>"']/,u.escapeReplace=/[&<>"']/g,u.replacements={"&":"&","<":"<",">":">",'"':""","'":"'"},u.escapeTestNoEncode=/[<>"']|&(?!#?\w+;)/,u.escapeReplaceNoEncode=/[<>"']|&(?!#?\w+;)/g;var o={},c=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function f(){}function d(e){for(var t,n,r=1;rt)n.splice(t);else for(;n.lengthAn error occurred:

    "+u(e.message+"",!0)+"
    ";throw e}}f.exec=f,m.options=m.setOptions=function(e){return d(m.defaults,e),m},m.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new r,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tables:!0,xhtml:!1}},m.defaults=m.getDefaults(),m.Parser=h,m.parser=h.parse,m.Renderer=r,m.TextRenderer=s,m.Lexer=a,m.lexer=a.lex,m.InlineLexer=p,m.inlineLexer=p.output,m.Slugger=t,m.parse=m,"undefined"!=typeof module&&"object"==typeof exports?module.exports=m:"function"==typeof define&&define.amd?define(function(){return m}):e.marked=m}(this||("undefined"!=typeof window?window:global)); -var $ = document.querySelector.bind(document); - -function parse(node) { - for (var i = 0; i < node.childNodes.length; i++) { - parse(node.childNodes[i]); - } - - if (!node.innerHTML || node.tagName === 'A') { - return; - } - - node.innerHTML = marked(node.innerHTML.replace(/
    /gi, '\n').replace(/\t/gi, ''), { breaks: true, gfm: false }); -} - -window.onload = function() { - var para = marked.Renderer.prototype.paragraph; - var field = ''; - marked.Renderer.prototype.paragraph = function(text) { - if (text.slice(0, field.length) === field || - text.slice(0, 2) === '= 0) { - return text; - } - return para(text); - }; - - if ($('#markdown')) { - parse($('#markdown')); - } -} +!function(e){"use strict";var _={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:f,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,nptable:f,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,table:f,lheading:/^([^\n]+)\n {0,3}(=|-){2,} *(?:\n+|$)/,paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,text:/^[^\n]+/};function a(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||m.defaults,this.rules=_.normal,this.options.pedantic?this.rules=_.pedantic:this.options.gfm&&(this.options.tables?this.rules=_.tables:this.rules=_.gfm)}_._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,_._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,_.def=i(_.def).replace("label",_._label).replace("title",_._title).getRegex(),_.bullet=/(?:[*+-]|\d{1,9}\.)/,_.item=/^( *)(bull) ?[^\n]*(?:\n(?!\1bull ?)[^\n]*)*/,_.item=i(_.item,"gm").replace(/bull/g,_.bullet).getRegex(),_.list=i(_.list).replace(/bull/g,_.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+_.def.source+")").getRegex(),_._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",_._comment=//,_.html=i(_.html,"i").replace("comment",_._comment).replace("tag",_._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),_.paragraph=i(_.paragraph).replace("hr",_.hr).replace("heading",_.heading).replace("lheading",_.lheading).replace("tag",_._tag).getRegex(),_.blockquote=i(_.blockquote).replace("paragraph",_.paragraph).getRegex(),_.normal=d({},_),_.gfm=d({},_.normal,{fences:/^ {0,3}(`{3,}|~{3,})([^`\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/}),_.gfm.paragraph=i(_.paragraph).replace("(?!","(?!"+_.gfm.fences.source.replace("\\1","\\2")+"|"+_.list.source.replace("\\1","\\3")+"|").getRegex(),_.tables=d({},_.gfm,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/}),_.pedantic=d({},_.normal,{html:i("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",_._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/}),a.rules=_,a.lex=function(e,t){return new a(t).lex(e)},a.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},a.prototype.token=function(e,t){var n,r,s,i,l,o,a,h,p,u,c,g,f,d,k,m,b,x;for(e=e.replace(/^ +$/gm,"");e;)if((s=this.rules.newline.exec(e))&&(e=e.substring(s[0].length),1 ?/gm,""),x=1;b.match(/^ {0,3}>/);)x++,this.tokens.push({type:"blockquote_start"}),b=b.replace(/^ *> ?/gm,"");for(this.token(b,t),c=0;c?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:f,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(href(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong:/^__([^\s_])__(?!_)|^\*\*([^\s*])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,em:/^_([^\s_])_(?!_)|^\*([^\s*"<\[])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_|[^\spunctuation])|^_([^\s_][\s\S]*?[^\s])_(?!_|[^\spunctuation])|^\*([^\s"<\[][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:f,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\?@\\[^_{|}~",n.em=i(n.em).replace(/punctuation/g,n._punctuation).getRegex(),n._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,n._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,n._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,n.autolink=i(n.autolink).replace("scheme",n._scheme).replace("email",n._email).getRegex(),n._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,n.tag=i(n.tag).replace("comment",_._comment).replace("attribute",n._attribute).getRegex(),n._label=/(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|`(?!`)|[^\[\]\\`])*?/,n._href=/\s*(<(?:\\[<>]?|[^\s<>\\])*>|[^\s\x00-\x1f]*)/,n._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,n.link=i(n.link).replace("label",n._label).replace("href",n._href).replace("title",n._title).getRegex(),n.reflink=i(n.reflink).replace("label",n._label).getRegex(),n.normal=d({},n),n.pedantic=d({},n.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link:i(/^!?\[(label)\]\((.*?)\)/).replace("label",n._label).getRegex(),reflink:i(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",n._label).getRegex()}),n.gfm=d({},n.normal,{escape:i(n.escape).replace("])","~|])").getRegex(),_extended_email:/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,url:/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~+(?=\S)([\s\S]*?\S)~+/,text:/^(`+|[^`])(?:[\s\S]*?(?:(?=[\\/i.test(i[0])&&(this.inLink=!1),!this.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(i[0])?this.inRawBlock=!0:this.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(i[0])&&(this.inRawBlock=!1),e=e.substring(i[0].length),o+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(i[0]):u(i[0]):i[0];else if(i=this.rules.link.exec(e)){var a=k(i[2],"()");if(-1$/,"$1"),o+=this.outputLink(i,{href:p.escapes(r),title:p.escapes(s)}),this.inLink=!1}else if((i=this.rules.reflink.exec(e))||(i=this.rules.nolink.exec(e))){if(e=e.substring(i[0].length),t=(i[2]||i[1]).replace(/\s+/g," "),!(t=this.links[t.toLowerCase()])||!t.href){o+=i[0].charAt(0),e=i[0].substring(1)+e;continue}this.inLink=!0,o+=this.outputLink(i,t),this.inLink=!1}else if(i=this.rules.strong.exec(e))e=e.substring(i[0].length),o+=this.renderer.strong(this.output(i[4]||i[3]||i[2]||i[1]));else if(i=this.rules.em.exec(e))e=e.substring(i[0].length),o+=this.renderer.em(this.output(i[6]||i[5]||i[4]||i[3]||i[2]||i[1]));else if(i=this.rules.code.exec(e))e=e.substring(i[0].length),o+=this.renderer.codespan(u(i[2].trim(),!0));else if(i=this.rules.br.exec(e))e=e.substring(i[0].length),o+=this.renderer.br();else if(i=this.rules.del.exec(e))e=e.substring(i[0].length),o+=this.renderer.del(this.output(i[1]));else if(i=this.rules.autolink.exec(e))e=e.substring(i[0].length),r="@"===i[2]?"mailto:"+(n=u(this.mangle(i[1]))):n=u(i[1]),o+=this.renderer.link(r,null,n);else if(this.inLink||!(i=this.rules.url.exec(e))){if(i=this.rules.text.exec(e))e=e.substring(i[0].length),this.inRawBlock?o+=this.renderer.text(i[0]):o+=this.renderer.text(u(this.smartypants(i[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else{if("@"===i[2])r="mailto:"+(n=u(i[0]));else{for(;l=i[0],i[0]=this.rules._backpedal.exec(i[0])[0],l!==i[0];);n=u(i[0]),r="www."===i[1]?"http://"+n:n}e=e.substring(i[0].length),o+=this.renderer.link(r,null,n)}return o},p.escapes=function(e){return e?e.replace(p.rules._escapes,"$1"):e},p.prototype.outputLink=function(e,t){var n=t.href,r=t.title?u(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,u(e[1]))},p.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"â€").replace(/\.{3}/g,"…"):e},p.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",r=e.length,s=0;s'+(n?e:u(e,!0))+"\n":"
    "+(n?e:u(e,!0))+"
    "},r.prototype.blockquote=function(e){return"
    \n"+e+"
    \n"},r.prototype.html=function(e){return e},r.prototype.heading=function(e,t,n,r){return this.options.headerIds?"'+e+"\n":""+e+"\n"},r.prototype.hr=function(){return this.options.xhtml?"
    \n":"
    \n"},r.prototype.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"},r.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},r.prototype.checkbox=function(e){return" "},r.prototype.paragraph=function(e){return"

    "+e+"

    \n"},r.prototype.table=function(e,t){return t&&(t=""+t+""),"\n\n"+e+"\n"+t+"
    \n"},r.prototype.tablerow=function(e){return"\n"+e+"\n"},r.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"\n"},r.prototype.strong=function(e){return""+e+""},r.prototype.em=function(e){return""+e+""},r.prototype.codespan=function(e){return""+e+""},r.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},r.prototype.del=function(e){return""+e+""},r.prototype.link=function(e,t,n){if(null===(e=l(this.options.sanitize,this.options.baseUrl,e)))return n;var r='
    "},r.prototype.image=function(e,t,n){if(null===(e=l(this.options.sanitize,this.options.baseUrl,e)))return n;var r=''+n+'":">"},r.prototype.text=function(e){return e},s.prototype.strong=s.prototype.em=s.prototype.codespan=s.prototype.del=s.prototype.text=function(e){return e},s.prototype.link=s.prototype.image=function(e,t,n){return""+n},s.prototype.br=function(){return""},h.parse=function(e,t){return new h(t).parse(e)},h.prototype.parse=function(e){this.inline=new p(e.links,this.options),this.inlineText=new p(e.links,d({},this.options,{renderer:new s})),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},h.prototype.next=function(){return this.token=this.tokens.pop(),this.token},h.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},h.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},h.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,g(this.inlineText.output(this.token.text)),this.slugger);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,s="",i="";for(n="",e=0;e?@[\]^`{|}~]/g,"").replace(/\s/g,"-");if(this.seen.hasOwnProperty(t))for(var n=t;this.seen[n]++,t=n+"-"+this.seen[n],this.seen.hasOwnProperty(t););return this.seen[t]=0,t},u.escapeTest=/[&<>"']/,u.escapeReplace=/[&<>"']/g,u.replacements={"&":"&","<":"<",">":">",'"':""","'":"'"},u.escapeTestNoEncode=/[<>"']|&(?!#?\w+;)/,u.escapeReplaceNoEncode=/[<>"']|&(?!#?\w+;)/g;var o={},c=/^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;function f(){}function d(e){for(var t,n,r=1;rt)n.splice(t);else for(;n.lengthAn error occurred:

    "+u(e.message+"",!0)+"
    ";throw e}}f.exec=f,m.options=m.setOptions=function(e){return d(m.defaults,e),m},m.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new r,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tables:!0,xhtml:!1}},m.defaults=m.getDefaults(),m.Parser=h,m.parser=h.parse,m.Renderer=r,m.TextRenderer=s,m.Lexer=a,m.lexer=a.lex,m.InlineLexer=p,m.inlineLexer=p.output,m.Slugger=t,m.parse=m,"undefined"!=typeof module&&"object"==typeof exports?module.exports=m:"function"==typeof define&&define.amd?define(function(){return m}):e.marked=m}(this||("undefined"!=typeof window?window:global)); \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-12459.yml b/html/changelogs/AutoChangeLog-pr-12459.yml deleted file mode 100644 index 18ab9dbd1f8..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12459.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Kyep" -delete-after: True -changes: - - tweak: "Tweaked Greater Hellhound, added more non-violent options and one unique combat spell." diff --git a/html/changelogs/AutoChangeLog-pr-12571.yml b/html/changelogs/AutoChangeLog-pr-12571.yml deleted file mode 100644 index d9d46a5766f..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12571.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "JKnutson101" -delete-after: True -changes: - - tweak: "Combined the Rite of Tribute and Rite of Enlightenment into one Rite of Offering." - - bugfix: "Sacrificing now properly puts victims that have at one point had CKeys into soul stones, or polls dead-chat to do so." diff --git a/html/changelogs/AutoChangeLog-pr-12596.yml b/html/changelogs/AutoChangeLog-pr-12596.yml deleted file mode 100644 index ca0b0e32f0d..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12596.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "Ionward" -delete-after: True -changes: - - tweak: "Grey, Tajaran, Unathi, and Vulpkanin now properly have species specific fits for soft space suits." - - tweak: "Vox can now wear soft space suits, such as EVA (Clown and Mime included), NASA Void, and Syndicate suits." - - imageadd: "Added Vox soft suit sprites." diff --git a/html/changelogs/AutoChangeLog-pr-12600.yml b/html/changelogs/AutoChangeLog-pr-12600.yml deleted file mode 100644 index 0b84030ed0a..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12600.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "SteelSlayer" -delete-after: True -changes: - - bugfix: "Fixes the \"List SSDs and AFKs panel\" showing everyone as the target of an assassinate objective" - - bugfix: "The global objectives list is now viewable in the MC Globals menu" diff --git a/html/changelogs/AutoChangeLog-pr-12655.yml b/html/changelogs/AutoChangeLog-pr-12655.yml deleted file mode 100644 index c32a92c9289..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12655.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "craftxbox" -delete-after: True -changes: - - bugfix: "fixed colors not working without regex" - - bugfix: "fixed text panel not loading when an invalid regex is added" - - rscadd: "polyfilled string.prototype.includes" diff --git a/html/changelogs/AutoChangeLog-pr-12665.yml b/html/changelogs/AutoChangeLog-pr-12665.yml deleted file mode 100644 index 7761e78cf63..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12665.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "TDSSS" -delete-after: True -changes: - - rscdel: "duplicate mecha definitions" diff --git a/html/changelogs/AutoChangeLog-pr-12717.yml b/html/changelogs/AutoChangeLog-pr-12717.yml deleted file mode 100644 index 6f11a3b38d0..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12717.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "moxian" -delete-after: True -changes: - - bugfix: "being in a locker no longer interferes with tracking implant tracking" - - bugfix: "locator no longer locates tracking implants on other z levels." diff --git a/html/changelogs/AutoChangeLog-pr-12720.yml b/html/changelogs/AutoChangeLog-pr-12720.yml deleted file mode 100644 index 0efc114b24e..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12720.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "moxian" -delete-after: True -changes: - - bugfix: "fixed singulo being unable to expand when placed next to containment wall" diff --git a/html/changelogs/AutoChangeLog-pr-12725.yml b/html/changelogs/AutoChangeLog-pr-12725.yml deleted file mode 100644 index 24b8ec37da8..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12725.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "TDSSS" -delete-after: True -changes: - - bugfix: "blobbernaut vision blur now clears as intended." diff --git a/html/changelogs/AutoChangeLog-pr-12740.yml b/html/changelogs/AutoChangeLog-pr-12740.yml deleted file mode 100644 index b2e1d3fff39..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12740.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Drakeven" -delete-after: True -changes: - - bugfix: "Fixed mislabeled traitor and mindslave special role." diff --git a/html/changelogs/AutoChangeLog-pr-12747.yml b/html/changelogs/AutoChangeLog-pr-12747.yml deleted file mode 100644 index ca9e96e84c1..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12747.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Cazdon" -delete-after: True -changes: - - bugfix: "Admin Roles no longer appear on manifest." - - tweak: "Central Command PDA's no longer appear on the messenger list." diff --git a/html/changelogs/AutoChangeLog-pr-12751.yml b/html/changelogs/AutoChangeLog-pr-12751.yml deleted file mode 100644 index 1dc7c27f527..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12751.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "TDSSS" -delete-after: True -changes: - - bugfix: "fixed a bug preventing ticket system from working under some circumstances." diff --git a/html/changelogs/AutoChangeLog-pr-12756.yml b/html/changelogs/AutoChangeLog-pr-12756.yml deleted file mode 100644 index 50e5e5e4bd9..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12756.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SteelSlayer" -delete-after: True -changes: - - bugfix: "Reverts some terrible changes that are causing some bugs with traitors" diff --git a/html/changelogs/AutoChangeLog-pr-12757.yml b/html/changelogs/AutoChangeLog-pr-12757.yml deleted file mode 100644 index 9cba05e588f..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12757.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "VeteranKyl" -delete-after: True -changes: - - bugfix: "DNA Samplers now check if the target species has DNA." diff --git a/html/changelogs/AutoChangeLog-pr-12760.yml b/html/changelogs/AutoChangeLog-pr-12760.yml deleted file mode 100644 index 92600e6ed76..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12760.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "SteelSlayer" -delete-after: True -changes: - - bugfix: "Fixes AIs with the combat module not being able to hack APCs" diff --git a/html/changelogs/AutoChangeLog-pr-12761.yml b/html/changelogs/AutoChangeLog-pr-12761.yml deleted file mode 100644 index 7355e826a7b..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12761.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "VeteranKyl" -delete-after: True -changes: - - bugfix: "Fixed the envenomed blob's spore toxin not causing harm." diff --git a/html/changelogs/AutoChangeLog-pr-12765.yml b/html/changelogs/AutoChangeLog-pr-12765.yml deleted file mode 100644 index b1ee7b0dd05..00000000000 --- a/html/changelogs/AutoChangeLog-pr-12765.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Cazdon" -delete-after: True -changes: - - bugfix: "Potential Convertee's being unable to be converted." diff --git a/html/create_object.html b/html/create_object.html index ac47cc7769b..90aa4e0d7e8 100644 --- a/html/create_object.html +++ b/html/create_object.html @@ -27,7 +27,7 @@
    - Type
    + Type
    Offset: A @@ -71,14 +71,16 @@ function updateSearch() { - old_search = document.spawner.filter.value; - + old_search = document.spawner.filter.value.toLowerCase(); + if (!old_search) + return; var filtered = new Array(); var i; for (i in objects) { - if(objects[i].search(old_search) < 0) + var caseInsensitiveObject = objects[i].toLowerCase(); + if(caseInsensitiveObject.search(old_search) < 0) { continue; } @@ -88,19 +90,6 @@ populateList(filtered); } - - function submitFirst(event) - { - if (!object_list.options.length) - { - return false; - } - - if (event.keyCode == 13 || event.which == 13) - { - object_list.options[0].selected = 'true'; - } - } diff --git a/html/nttc/.gitignore b/html/nttc/.gitignore deleted file mode 100644 index c2658d7d1b3..00000000000 --- a/html/nttc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules/ diff --git a/html/nttc/dist/bundle.css b/html/nttc/dist/bundle.css deleted file mode 100644 index 293fb16a941..00000000000 --- a/html/nttc/dist/bundle.css +++ /dev/null @@ -1,154 +0,0 @@ -/* Global */ -html, body { - background-color: #272727; - font-family: Verdana, Geneva, sans-serif; - font-size: 12px; - color: #fff; - margin: 0; - padding: 0; -} - -/* Navbar */ -#navbar { - background: #383838; - border-bottom: 2px solid #161616; - list-style-type: none; - height: 28px; - margin: 0; - padding: 0; -} - -#navbar > div { - background: #40628a; - border-radius: 5px 5px 0 0; - color: #ffffff; - display: block; - height: 80%; - float: left; - text-decoration: none; - padding: 0 7px 0 5px; - margin: 6px 0 0 5px; -} - -#navbar > div:hover { - background: #ffffff; - color: #40628a; - cursor: pointer; -} - -#navbar > img { - float: left; - margin: 2px 10px 2px 0; - height: 24px; -} - -#navbar > .title { - color: #a7a7a7; - float: right; - background: none; - font-size: 1.5em; - font-family: Helvetica; - text-decoration: bold; - padding: 0; - padding-right: 10px; - margin: 0; -} - -#navbar > .title:hover { - background: none; - color: #a7a7a7; - cursor: default; -} - -.btnActive { - background: #2f943c !important; - color: #fff !important; -} - -/* Content */ -#content { - min-height: 75%; - line-height: 1.5; - margin: 10px; -} - -/* Links */ -.link, .linkOn, .linkOff { - background: #40628a; - border: 1px solid #161616; - color: #ffffff; - cursor: pointer; - display: inline; - margin: 0 2px 0px 0; - min-width: 15px; - padding: 0px 4px 0px 4px; - text-align: center; - text-decoration: none; - user-select: none; - white-space: nowrap; -} - -.linkOn, .linkOn:link, .linkOn:visited, .linkOn:active, .linkOn:hover -{ - color: #ffffff; - background: #2f943c; - border-color: #24722e; -} - -.linkOff, .linkOff:link, .linkOff:visited, .linkOff:active, .linkOff:hover -{ - color: #ffffff; - background: #999999; - border-color: #666666; -} - -.linkActive:hover { - background: #507aac; -} - -.linkActive:active { - background: #2f943c; -} - -/* Config Tables */ -.tblConfig td { - padding-right: 40px; -} - -.tables { - border: 1px solid black; - text-align: center; -} - -.tables th { - border-bottom: 2px solid black; -} - -.tables th, .tables td { - border-right: 2px dotted black; - min-width: 70px; -} - -/* Footer */ -.footer { - height: 15px; - position: absolute; - right: 10px; - bottom: 10px; -} - -/* Hacking stuff. */ -.hack { - color: #fff; - text-shadow: 1px 1px #300; - font-size: 1.12em; -} -.hackBtn { - background-color: #a00 !important; -} -.hackBtn:hover { - background-color: #fff !important; -} -.hackBtn:hover .hack { - color: #000 !important; -} \ No newline at end of file diff --git a/html/nttc/dist/bundle.js b/html/nttc/dist/bundle.js deleted file mode 100644 index f91bf62551c..00000000000 --- a/html/nttc/dist/bundle.js +++ /dev/null @@ -1,10907 +0,0 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i\u20D2|\u205F\u200A|\u219D\u0338|\u2202\u0338|\u2220\u20D2|\u2229\uFE00|\u222A\uFE00|\u223C\u20D2|\u223D\u0331|\u223E\u0333|\u2242\u0338|\u224B\u0338|\u224D\u20D2|\u224E\u0338|\u224F\u0338|\u2250\u0338|\u2261\u20E5|\u2264\u20D2|\u2265\u20D2|\u2266\u0338|\u2267\u0338|\u2268\uFE00|\u2269\uFE00|\u226A\u0338|\u226A\u20D2|\u226B\u0338|\u226B\u20D2|\u227F\u0338|\u2282\u20D2|\u2283\u20D2|\u228A\uFE00|\u228B\uFE00|\u228F\u0338|\u2290\u0338|\u2293\uFE00|\u2294\uFE00|\u22B4\u20D2|\u22B5\u20D2|\u22D8\u0338|\u22D9\u0338|\u22DA\uFE00|\u22DB\uFE00|\u22F5\u0338|\u22F9\u0338|\u2933\u0338|\u29CF\u0338|\u29D0\u0338|\u2A6D\u0338|\u2A70\u0338|\u2A7D\u0338|\u2A7E\u0338|\u2AA1\u0338|\u2AA2\u0338|\u2AAC\uFE00|\u2AAD\uFE00|\u2AAF\u0338|\u2AB0\u0338|\u2AC5\u0338|\u2AC6\u0338|\u2ACB\uFE00|\u2ACC\uFE00|\u2AFD\u20E5|[\xA0-\u0113\u0116-\u0122\u0124-\u012B\u012E-\u014D\u0150-\u017E\u0192\u01B5\u01F5\u0237\u02C6\u02C7\u02D8-\u02DD\u0311\u0391-\u03A1\u03A3-\u03A9\u03B1-\u03C9\u03D1\u03D2\u03D5\u03D6\u03DC\u03DD\u03F0\u03F1\u03F5\u03F6\u0401-\u040C\u040E-\u044F\u0451-\u045C\u045E\u045F\u2002-\u2005\u2007-\u2010\u2013-\u2016\u2018-\u201A\u201C-\u201E\u2020-\u2022\u2025\u2026\u2030-\u2035\u2039\u203A\u203E\u2041\u2043\u2044\u204F\u2057\u205F-\u2063\u20AC\u20DB\u20DC\u2102\u2105\u210A-\u2113\u2115-\u211E\u2122\u2124\u2127-\u2129\u212C\u212D\u212F-\u2131\u2133-\u2138\u2145-\u2148\u2153-\u215E\u2190-\u219B\u219D-\u21A7\u21A9-\u21AE\u21B0-\u21B3\u21B5-\u21B7\u21BA-\u21DB\u21DD\u21E4\u21E5\u21F5\u21FD-\u2205\u2207-\u2209\u220B\u220C\u220F-\u2214\u2216-\u2218\u221A\u221D-\u2238\u223A-\u2257\u2259\u225A\u225C\u225F-\u2262\u2264-\u228B\u228D-\u229B\u229D-\u22A5\u22A7-\u22B0\u22B2-\u22BB\u22BD-\u22DB\u22DE-\u22E3\u22E6-\u22F7\u22F9-\u22FE\u2305\u2306\u2308-\u2310\u2312\u2313\u2315\u2316\u231C-\u231F\u2322\u2323\u232D\u232E\u2336\u233D\u233F\u237C\u23B0\u23B1\u23B4-\u23B6\u23DC-\u23DF\u23E2\u23E7\u2423\u24C8\u2500\u2502\u250C\u2510\u2514\u2518\u251C\u2524\u252C\u2534\u253C\u2550-\u256C\u2580\u2584\u2588\u2591-\u2593\u25A1\u25AA\u25AB\u25AD\u25AE\u25B1\u25B3-\u25B5\u25B8\u25B9\u25BD-\u25BF\u25C2\u25C3\u25CA\u25CB\u25EC\u25EF\u25F8-\u25FC\u2605\u2606\u260E\u2640\u2642\u2660\u2663\u2665\u2666\u266A\u266D-\u266F\u2713\u2717\u2720\u2736\u2758\u2772\u2773\u27C8\u27C9\u27E6-\u27ED\u27F5-\u27FA\u27FC\u27FF\u2902-\u2905\u290C-\u2913\u2916\u2919-\u2920\u2923-\u292A\u2933\u2935-\u2939\u293C\u293D\u2945\u2948-\u294B\u294E-\u2976\u2978\u2979\u297B-\u297F\u2985\u2986\u298B-\u2996\u299A\u299C\u299D\u29A4-\u29B7\u29B9\u29BB\u29BC\u29BE-\u29C5\u29C9\u29CD-\u29D0\u29DC-\u29DE\u29E3-\u29E5\u29EB\u29F4\u29F6\u2A00-\u2A02\u2A04\u2A06\u2A0C\u2A0D\u2A10-\u2A17\u2A22-\u2A27\u2A29\u2A2A\u2A2D-\u2A31\u2A33-\u2A3C\u2A3F\u2A40\u2A42-\u2A4D\u2A50\u2A53-\u2A58\u2A5A-\u2A5D\u2A5F\u2A66\u2A6A\u2A6D-\u2A75\u2A77-\u2A9A\u2A9D-\u2AA2\u2AA4-\u2AB0\u2AB3-\u2AC8\u2ACB\u2ACC\u2ACF-\u2ADB\u2AE4\u2AE6-\u2AE9\u2AEB-\u2AF3\u2AFD\uFB00-\uFB04]|\uD835[\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDCCF\uDD04\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDD6B]/g; - var encodeMap = {'\xAD':'shy','\u200C':'zwnj','\u200D':'zwj','\u200E':'lrm','\u2063':'ic','\u2062':'it','\u2061':'af','\u200F':'rlm','\u200B':'ZeroWidthSpace','\u2060':'NoBreak','\u0311':'DownBreve','\u20DB':'tdot','\u20DC':'DotDot','\t':'Tab','\n':'NewLine','\u2008':'puncsp','\u205F':'MediumSpace','\u2009':'thinsp','\u200A':'hairsp','\u2004':'emsp13','\u2002':'ensp','\u2005':'emsp14','\u2003':'emsp','\u2007':'numsp','\xA0':'nbsp','\u205F\u200A':'ThickSpace','\u203E':'oline','_':'lowbar','\u2010':'dash','\u2013':'ndash','\u2014':'mdash','\u2015':'horbar',',':'comma',';':'semi','\u204F':'bsemi',':':'colon','\u2A74':'Colone','!':'excl','\xA1':'iexcl','?':'quest','\xBF':'iquest','.':'period','\u2025':'nldr','\u2026':'mldr','\xB7':'middot','\'':'apos','\u2018':'lsquo','\u2019':'rsquo','\u201A':'sbquo','\u2039':'lsaquo','\u203A':'rsaquo','"':'quot','\u201C':'ldquo','\u201D':'rdquo','\u201E':'bdquo','\xAB':'laquo','\xBB':'raquo','(':'lpar',')':'rpar','[':'lsqb',']':'rsqb','{':'lcub','}':'rcub','\u2308':'lceil','\u2309':'rceil','\u230A':'lfloor','\u230B':'rfloor','\u2985':'lopar','\u2986':'ropar','\u298B':'lbrke','\u298C':'rbrke','\u298D':'lbrkslu','\u298E':'rbrksld','\u298F':'lbrksld','\u2990':'rbrkslu','\u2991':'langd','\u2992':'rangd','\u2993':'lparlt','\u2994':'rpargt','\u2995':'gtlPar','\u2996':'ltrPar','\u27E6':'lobrk','\u27E7':'robrk','\u27E8':'lang','\u27E9':'rang','\u27EA':'Lang','\u27EB':'Rang','\u27EC':'loang','\u27ED':'roang','\u2772':'lbbrk','\u2773':'rbbrk','\u2016':'Vert','\xA7':'sect','\xB6':'para','@':'commat','*':'ast','/':'sol','undefined':null,'&':'amp','#':'num','%':'percnt','\u2030':'permil','\u2031':'pertenk','\u2020':'dagger','\u2021':'Dagger','\u2022':'bull','\u2043':'hybull','\u2032':'prime','\u2033':'Prime','\u2034':'tprime','\u2057':'qprime','\u2035':'bprime','\u2041':'caret','`':'grave','\xB4':'acute','\u02DC':'tilde','^':'Hat','\xAF':'macr','\u02D8':'breve','\u02D9':'dot','\xA8':'die','\u02DA':'ring','\u02DD':'dblac','\xB8':'cedil','\u02DB':'ogon','\u02C6':'circ','\u02C7':'caron','\xB0':'deg','\xA9':'copy','\xAE':'reg','\u2117':'copysr','\u2118':'wp','\u211E':'rx','\u2127':'mho','\u2129':'iiota','\u2190':'larr','\u219A':'nlarr','\u2192':'rarr','\u219B':'nrarr','\u2191':'uarr','\u2193':'darr','\u2194':'harr','\u21AE':'nharr','\u2195':'varr','\u2196':'nwarr','\u2197':'nearr','\u2198':'searr','\u2199':'swarr','\u219D':'rarrw','\u219D\u0338':'nrarrw','\u219E':'Larr','\u219F':'Uarr','\u21A0':'Rarr','\u21A1':'Darr','\u21A2':'larrtl','\u21A3':'rarrtl','\u21A4':'mapstoleft','\u21A5':'mapstoup','\u21A6':'map','\u21A7':'mapstodown','\u21A9':'larrhk','\u21AA':'rarrhk','\u21AB':'larrlp','\u21AC':'rarrlp','\u21AD':'harrw','\u21B0':'lsh','\u21B1':'rsh','\u21B2':'ldsh','\u21B3':'rdsh','\u21B5':'crarr','\u21B6':'cularr','\u21B7':'curarr','\u21BA':'olarr','\u21BB':'orarr','\u21BC':'lharu','\u21BD':'lhard','\u21BE':'uharr','\u21BF':'uharl','\u21C0':'rharu','\u21C1':'rhard','\u21C2':'dharr','\u21C3':'dharl','\u21C4':'rlarr','\u21C5':'udarr','\u21C6':'lrarr','\u21C7':'llarr','\u21C8':'uuarr','\u21C9':'rrarr','\u21CA':'ddarr','\u21CB':'lrhar','\u21CC':'rlhar','\u21D0':'lArr','\u21CD':'nlArr','\u21D1':'uArr','\u21D2':'rArr','\u21CF':'nrArr','\u21D3':'dArr','\u21D4':'iff','\u21CE':'nhArr','\u21D5':'vArr','\u21D6':'nwArr','\u21D7':'neArr','\u21D8':'seArr','\u21D9':'swArr','\u21DA':'lAarr','\u21DB':'rAarr','\u21DD':'zigrarr','\u21E4':'larrb','\u21E5':'rarrb','\u21F5':'duarr','\u21FD':'loarr','\u21FE':'roarr','\u21FF':'hoarr','\u2200':'forall','\u2201':'comp','\u2202':'part','\u2202\u0338':'npart','\u2203':'exist','\u2204':'nexist','\u2205':'empty','\u2207':'Del','\u2208':'in','\u2209':'notin','\u220B':'ni','\u220C':'notni','\u03F6':'bepsi','\u220F':'prod','\u2210':'coprod','\u2211':'sum','+':'plus','\xB1':'pm','\xF7':'div','\xD7':'times','<':'lt','\u226E':'nlt','<\u20D2':'nvlt','=':'equals','\u2260':'ne','=\u20E5':'bne','\u2A75':'Equal','>':'gt','\u226F':'ngt','>\u20D2':'nvgt','\xAC':'not','|':'vert','\xA6':'brvbar','\u2212':'minus','\u2213':'mp','\u2214':'plusdo','\u2044':'frasl','\u2216':'setmn','\u2217':'lowast','\u2218':'compfn','\u221A':'Sqrt','\u221D':'prop','\u221E':'infin','\u221F':'angrt','\u2220':'ang','\u2220\u20D2':'nang','\u2221':'angmsd','\u2222':'angsph','\u2223':'mid','\u2224':'nmid','\u2225':'par','\u2226':'npar','\u2227':'and','\u2228':'or','\u2229':'cap','\u2229\uFE00':'caps','\u222A':'cup','\u222A\uFE00':'cups','\u222B':'int','\u222C':'Int','\u222D':'tint','\u2A0C':'qint','\u222E':'oint','\u222F':'Conint','\u2230':'Cconint','\u2231':'cwint','\u2232':'cwconint','\u2233':'awconint','\u2234':'there4','\u2235':'becaus','\u2236':'ratio','\u2237':'Colon','\u2238':'minusd','\u223A':'mDDot','\u223B':'homtht','\u223C':'sim','\u2241':'nsim','\u223C\u20D2':'nvsim','\u223D':'bsim','\u223D\u0331':'race','\u223E':'ac','\u223E\u0333':'acE','\u223F':'acd','\u2240':'wr','\u2242':'esim','\u2242\u0338':'nesim','\u2243':'sime','\u2244':'nsime','\u2245':'cong','\u2247':'ncong','\u2246':'simne','\u2248':'ap','\u2249':'nap','\u224A':'ape','\u224B':'apid','\u224B\u0338':'napid','\u224C':'bcong','\u224D':'CupCap','\u226D':'NotCupCap','\u224D\u20D2':'nvap','\u224E':'bump','\u224E\u0338':'nbump','\u224F':'bumpe','\u224F\u0338':'nbumpe','\u2250':'doteq','\u2250\u0338':'nedot','\u2251':'eDot','\u2252':'efDot','\u2253':'erDot','\u2254':'colone','\u2255':'ecolon','\u2256':'ecir','\u2257':'cire','\u2259':'wedgeq','\u225A':'veeeq','\u225C':'trie','\u225F':'equest','\u2261':'equiv','\u2262':'nequiv','\u2261\u20E5':'bnequiv','\u2264':'le','\u2270':'nle','\u2264\u20D2':'nvle','\u2265':'ge','\u2271':'nge','\u2265\u20D2':'nvge','\u2266':'lE','\u2266\u0338':'nlE','\u2267':'gE','\u2267\u0338':'ngE','\u2268\uFE00':'lvnE','\u2268':'lnE','\u2269':'gnE','\u2269\uFE00':'gvnE','\u226A':'ll','\u226A\u0338':'nLtv','\u226A\u20D2':'nLt','\u226B':'gg','\u226B\u0338':'nGtv','\u226B\u20D2':'nGt','\u226C':'twixt','\u2272':'lsim','\u2274':'nlsim','\u2273':'gsim','\u2275':'ngsim','\u2276':'lg','\u2278':'ntlg','\u2277':'gl','\u2279':'ntgl','\u227A':'pr','\u2280':'npr','\u227B':'sc','\u2281':'nsc','\u227C':'prcue','\u22E0':'nprcue','\u227D':'sccue','\u22E1':'nsccue','\u227E':'prsim','\u227F':'scsim','\u227F\u0338':'NotSucceedsTilde','\u2282':'sub','\u2284':'nsub','\u2282\u20D2':'vnsub','\u2283':'sup','\u2285':'nsup','\u2283\u20D2':'vnsup','\u2286':'sube','\u2288':'nsube','\u2287':'supe','\u2289':'nsupe','\u228A\uFE00':'vsubne','\u228A':'subne','\u228B\uFE00':'vsupne','\u228B':'supne','\u228D':'cupdot','\u228E':'uplus','\u228F':'sqsub','\u228F\u0338':'NotSquareSubset','\u2290':'sqsup','\u2290\u0338':'NotSquareSuperset','\u2291':'sqsube','\u22E2':'nsqsube','\u2292':'sqsupe','\u22E3':'nsqsupe','\u2293':'sqcap','\u2293\uFE00':'sqcaps','\u2294':'sqcup','\u2294\uFE00':'sqcups','\u2295':'oplus','\u2296':'ominus','\u2297':'otimes','\u2298':'osol','\u2299':'odot','\u229A':'ocir','\u229B':'oast','\u229D':'odash','\u229E':'plusb','\u229F':'minusb','\u22A0':'timesb','\u22A1':'sdotb','\u22A2':'vdash','\u22AC':'nvdash','\u22A3':'dashv','\u22A4':'top','\u22A5':'bot','\u22A7':'models','\u22A8':'vDash','\u22AD':'nvDash','\u22A9':'Vdash','\u22AE':'nVdash','\u22AA':'Vvdash','\u22AB':'VDash','\u22AF':'nVDash','\u22B0':'prurel','\u22B2':'vltri','\u22EA':'nltri','\u22B3':'vrtri','\u22EB':'nrtri','\u22B4':'ltrie','\u22EC':'nltrie','\u22B4\u20D2':'nvltrie','\u22B5':'rtrie','\u22ED':'nrtrie','\u22B5\u20D2':'nvrtrie','\u22B6':'origof','\u22B7':'imof','\u22B8':'mumap','\u22B9':'hercon','\u22BA':'intcal','\u22BB':'veebar','\u22BD':'barvee','\u22BE':'angrtvb','\u22BF':'lrtri','\u22C0':'Wedge','\u22C1':'Vee','\u22C2':'xcap','\u22C3':'xcup','\u22C4':'diam','\u22C5':'sdot','\u22C6':'Star','\u22C7':'divonx','\u22C8':'bowtie','\u22C9':'ltimes','\u22CA':'rtimes','\u22CB':'lthree','\u22CC':'rthree','\u22CD':'bsime','\u22CE':'cuvee','\u22CF':'cuwed','\u22D0':'Sub','\u22D1':'Sup','\u22D2':'Cap','\u22D3':'Cup','\u22D4':'fork','\u22D5':'epar','\u22D6':'ltdot','\u22D7':'gtdot','\u22D8':'Ll','\u22D8\u0338':'nLl','\u22D9':'Gg','\u22D9\u0338':'nGg','\u22DA\uFE00':'lesg','\u22DA':'leg','\u22DB':'gel','\u22DB\uFE00':'gesl','\u22DE':'cuepr','\u22DF':'cuesc','\u22E6':'lnsim','\u22E7':'gnsim','\u22E8':'prnsim','\u22E9':'scnsim','\u22EE':'vellip','\u22EF':'ctdot','\u22F0':'utdot','\u22F1':'dtdot','\u22F2':'disin','\u22F3':'isinsv','\u22F4':'isins','\u22F5':'isindot','\u22F5\u0338':'notindot','\u22F6':'notinvc','\u22F7':'notinvb','\u22F9':'isinE','\u22F9\u0338':'notinE','\u22FA':'nisd','\u22FB':'xnis','\u22FC':'nis','\u22FD':'notnivc','\u22FE':'notnivb','\u2305':'barwed','\u2306':'Barwed','\u230C':'drcrop','\u230D':'dlcrop','\u230E':'urcrop','\u230F':'ulcrop','\u2310':'bnot','\u2312':'profline','\u2313':'profsurf','\u2315':'telrec','\u2316':'target','\u231C':'ulcorn','\u231D':'urcorn','\u231E':'dlcorn','\u231F':'drcorn','\u2322':'frown','\u2323':'smile','\u232D':'cylcty','\u232E':'profalar','\u2336':'topbot','\u233D':'ovbar','\u233F':'solbar','\u237C':'angzarr','\u23B0':'lmoust','\u23B1':'rmoust','\u23B4':'tbrk','\u23B5':'bbrk','\u23B6':'bbrktbrk','\u23DC':'OverParenthesis','\u23DD':'UnderParenthesis','\u23DE':'OverBrace','\u23DF':'UnderBrace','\u23E2':'trpezium','\u23E7':'elinters','\u2423':'blank','\u2500':'boxh','\u2502':'boxv','\u250C':'boxdr','\u2510':'boxdl','\u2514':'boxur','\u2518':'boxul','\u251C':'boxvr','\u2524':'boxvl','\u252C':'boxhd','\u2534':'boxhu','\u253C':'boxvh','\u2550':'boxH','\u2551':'boxV','\u2552':'boxdR','\u2553':'boxDr','\u2554':'boxDR','\u2555':'boxdL','\u2556':'boxDl','\u2557':'boxDL','\u2558':'boxuR','\u2559':'boxUr','\u255A':'boxUR','\u255B':'boxuL','\u255C':'boxUl','\u255D':'boxUL','\u255E':'boxvR','\u255F':'boxVr','\u2560':'boxVR','\u2561':'boxvL','\u2562':'boxVl','\u2563':'boxVL','\u2564':'boxHd','\u2565':'boxhD','\u2566':'boxHD','\u2567':'boxHu','\u2568':'boxhU','\u2569':'boxHU','\u256A':'boxvH','\u256B':'boxVh','\u256C':'boxVH','\u2580':'uhblk','\u2584':'lhblk','\u2588':'block','\u2591':'blk14','\u2592':'blk12','\u2593':'blk34','\u25A1':'squ','\u25AA':'squf','\u25AB':'EmptyVerySmallSquare','\u25AD':'rect','\u25AE':'marker','\u25B1':'fltns','\u25B3':'xutri','\u25B4':'utrif','\u25B5':'utri','\u25B8':'rtrif','\u25B9':'rtri','\u25BD':'xdtri','\u25BE':'dtrif','\u25BF':'dtri','\u25C2':'ltrif','\u25C3':'ltri','\u25CA':'loz','\u25CB':'cir','\u25EC':'tridot','\u25EF':'xcirc','\u25F8':'ultri','\u25F9':'urtri','\u25FA':'lltri','\u25FB':'EmptySmallSquare','\u25FC':'FilledSmallSquare','\u2605':'starf','\u2606':'star','\u260E':'phone','\u2640':'female','\u2642':'male','\u2660':'spades','\u2663':'clubs','\u2665':'hearts','\u2666':'diams','\u266A':'sung','\u2713':'check','\u2717':'cross','\u2720':'malt','\u2736':'sext','\u2758':'VerticalSeparator','\u27C8':'bsolhsub','\u27C9':'suphsol','\u27F5':'xlarr','\u27F6':'xrarr','\u27F7':'xharr','\u27F8':'xlArr','\u27F9':'xrArr','\u27FA':'xhArr','\u27FC':'xmap','\u27FF':'dzigrarr','\u2902':'nvlArr','\u2903':'nvrArr','\u2904':'nvHarr','\u2905':'Map','\u290C':'lbarr','\u290D':'rbarr','\u290E':'lBarr','\u290F':'rBarr','\u2910':'RBarr','\u2911':'DDotrahd','\u2912':'UpArrowBar','\u2913':'DownArrowBar','\u2916':'Rarrtl','\u2919':'latail','\u291A':'ratail','\u291B':'lAtail','\u291C':'rAtail','\u291D':'larrfs','\u291E':'rarrfs','\u291F':'larrbfs','\u2920':'rarrbfs','\u2923':'nwarhk','\u2924':'nearhk','\u2925':'searhk','\u2926':'swarhk','\u2927':'nwnear','\u2928':'toea','\u2929':'tosa','\u292A':'swnwar','\u2933':'rarrc','\u2933\u0338':'nrarrc','\u2935':'cudarrr','\u2936':'ldca','\u2937':'rdca','\u2938':'cudarrl','\u2939':'larrpl','\u293C':'curarrm','\u293D':'cularrp','\u2945':'rarrpl','\u2948':'harrcir','\u2949':'Uarrocir','\u294A':'lurdshar','\u294B':'ldrushar','\u294E':'LeftRightVector','\u294F':'RightUpDownVector','\u2950':'DownLeftRightVector','\u2951':'LeftUpDownVector','\u2952':'LeftVectorBar','\u2953':'RightVectorBar','\u2954':'RightUpVectorBar','\u2955':'RightDownVectorBar','\u2956':'DownLeftVectorBar','\u2957':'DownRightVectorBar','\u2958':'LeftUpVectorBar','\u2959':'LeftDownVectorBar','\u295A':'LeftTeeVector','\u295B':'RightTeeVector','\u295C':'RightUpTeeVector','\u295D':'RightDownTeeVector','\u295E':'DownLeftTeeVector','\u295F':'DownRightTeeVector','\u2960':'LeftUpTeeVector','\u2961':'LeftDownTeeVector','\u2962':'lHar','\u2963':'uHar','\u2964':'rHar','\u2965':'dHar','\u2966':'luruhar','\u2967':'ldrdhar','\u2968':'ruluhar','\u2969':'rdldhar','\u296A':'lharul','\u296B':'llhard','\u296C':'rharul','\u296D':'lrhard','\u296E':'udhar','\u296F':'duhar','\u2970':'RoundImplies','\u2971':'erarr','\u2972':'simrarr','\u2973':'larrsim','\u2974':'rarrsim','\u2975':'rarrap','\u2976':'ltlarr','\u2978':'gtrarr','\u2979':'subrarr','\u297B':'suplarr','\u297C':'lfisht','\u297D':'rfisht','\u297E':'ufisht','\u297F':'dfisht','\u299A':'vzigzag','\u299C':'vangrt','\u299D':'angrtvbd','\u29A4':'ange','\u29A5':'range','\u29A6':'dwangle','\u29A7':'uwangle','\u29A8':'angmsdaa','\u29A9':'angmsdab','\u29AA':'angmsdac','\u29AB':'angmsdad','\u29AC':'angmsdae','\u29AD':'angmsdaf','\u29AE':'angmsdag','\u29AF':'angmsdah','\u29B0':'bemptyv','\u29B1':'demptyv','\u29B2':'cemptyv','\u29B3':'raemptyv','\u29B4':'laemptyv','\u29B5':'ohbar','\u29B6':'omid','\u29B7':'opar','\u29B9':'operp','\u29BB':'olcross','\u29BC':'odsold','\u29BE':'olcir','\u29BF':'ofcir','\u29C0':'olt','\u29C1':'ogt','\u29C2':'cirscir','\u29C3':'cirE','\u29C4':'solb','\u29C5':'bsolb','\u29C9':'boxbox','\u29CD':'trisb','\u29CE':'rtriltri','\u29CF':'LeftTriangleBar','\u29CF\u0338':'NotLeftTriangleBar','\u29D0':'RightTriangleBar','\u29D0\u0338':'NotRightTriangleBar','\u29DC':'iinfin','\u29DD':'infintie','\u29DE':'nvinfin','\u29E3':'eparsl','\u29E4':'smeparsl','\u29E5':'eqvparsl','\u29EB':'lozf','\u29F4':'RuleDelayed','\u29F6':'dsol','\u2A00':'xodot','\u2A01':'xoplus','\u2A02':'xotime','\u2A04':'xuplus','\u2A06':'xsqcup','\u2A0D':'fpartint','\u2A10':'cirfnint','\u2A11':'awint','\u2A12':'rppolint','\u2A13':'scpolint','\u2A14':'npolint','\u2A15':'pointint','\u2A16':'quatint','\u2A17':'intlarhk','\u2A22':'pluscir','\u2A23':'plusacir','\u2A24':'simplus','\u2A25':'plusdu','\u2A26':'plussim','\u2A27':'plustwo','\u2A29':'mcomma','\u2A2A':'minusdu','\u2A2D':'loplus','\u2A2E':'roplus','\u2A2F':'Cross','\u2A30':'timesd','\u2A31':'timesbar','\u2A33':'smashp','\u2A34':'lotimes','\u2A35':'rotimes','\u2A36':'otimesas','\u2A37':'Otimes','\u2A38':'odiv','\u2A39':'triplus','\u2A3A':'triminus','\u2A3B':'tritime','\u2A3C':'iprod','\u2A3F':'amalg','\u2A40':'capdot','\u2A42':'ncup','\u2A43':'ncap','\u2A44':'capand','\u2A45':'cupor','\u2A46':'cupcap','\u2A47':'capcup','\u2A48':'cupbrcap','\u2A49':'capbrcup','\u2A4A':'cupcup','\u2A4B':'capcap','\u2A4C':'ccups','\u2A4D':'ccaps','\u2A50':'ccupssm','\u2A53':'And','\u2A54':'Or','\u2A55':'andand','\u2A56':'oror','\u2A57':'orslope','\u2A58':'andslope','\u2A5A':'andv','\u2A5B':'orv','\u2A5C':'andd','\u2A5D':'ord','\u2A5F':'wedbar','\u2A66':'sdote','\u2A6A':'simdot','\u2A6D':'congdot','\u2A6D\u0338':'ncongdot','\u2A6E':'easter','\u2A6F':'apacir','\u2A70':'apE','\u2A70\u0338':'napE','\u2A71':'eplus','\u2A72':'pluse','\u2A73':'Esim','\u2A77':'eDDot','\u2A78':'equivDD','\u2A79':'ltcir','\u2A7A':'gtcir','\u2A7B':'ltquest','\u2A7C':'gtquest','\u2A7D':'les','\u2A7D\u0338':'nles','\u2A7E':'ges','\u2A7E\u0338':'nges','\u2A7F':'lesdot','\u2A80':'gesdot','\u2A81':'lesdoto','\u2A82':'gesdoto','\u2A83':'lesdotor','\u2A84':'gesdotol','\u2A85':'lap','\u2A86':'gap','\u2A87':'lne','\u2A88':'gne','\u2A89':'lnap','\u2A8A':'gnap','\u2A8B':'lEg','\u2A8C':'gEl','\u2A8D':'lsime','\u2A8E':'gsime','\u2A8F':'lsimg','\u2A90':'gsiml','\u2A91':'lgE','\u2A92':'glE','\u2A93':'lesges','\u2A94':'gesles','\u2A95':'els','\u2A96':'egs','\u2A97':'elsdot','\u2A98':'egsdot','\u2A99':'el','\u2A9A':'eg','\u2A9D':'siml','\u2A9E':'simg','\u2A9F':'simlE','\u2AA0':'simgE','\u2AA1':'LessLess','\u2AA1\u0338':'NotNestedLessLess','\u2AA2':'GreaterGreater','\u2AA2\u0338':'NotNestedGreaterGreater','\u2AA4':'glj','\u2AA5':'gla','\u2AA6':'ltcc','\u2AA7':'gtcc','\u2AA8':'lescc','\u2AA9':'gescc','\u2AAA':'smt','\u2AAB':'lat','\u2AAC':'smte','\u2AAC\uFE00':'smtes','\u2AAD':'late','\u2AAD\uFE00':'lates','\u2AAE':'bumpE','\u2AAF':'pre','\u2AAF\u0338':'npre','\u2AB0':'sce','\u2AB0\u0338':'nsce','\u2AB3':'prE','\u2AB4':'scE','\u2AB5':'prnE','\u2AB6':'scnE','\u2AB7':'prap','\u2AB8':'scap','\u2AB9':'prnap','\u2ABA':'scnap','\u2ABB':'Pr','\u2ABC':'Sc','\u2ABD':'subdot','\u2ABE':'supdot','\u2ABF':'subplus','\u2AC0':'supplus','\u2AC1':'submult','\u2AC2':'supmult','\u2AC3':'subedot','\u2AC4':'supedot','\u2AC5':'subE','\u2AC5\u0338':'nsubE','\u2AC6':'supE','\u2AC6\u0338':'nsupE','\u2AC7':'subsim','\u2AC8':'supsim','\u2ACB\uFE00':'vsubnE','\u2ACB':'subnE','\u2ACC\uFE00':'vsupnE','\u2ACC':'supnE','\u2ACF':'csub','\u2AD0':'csup','\u2AD1':'csube','\u2AD2':'csupe','\u2AD3':'subsup','\u2AD4':'supsub','\u2AD5':'subsub','\u2AD6':'supsup','\u2AD7':'suphsub','\u2AD8':'supdsub','\u2AD9':'forkv','\u2ADA':'topfork','\u2ADB':'mlcp','\u2AE4':'Dashv','\u2AE6':'Vdashl','\u2AE7':'Barv','\u2AE8':'vBar','\u2AE9':'vBarv','\u2AEB':'Vbar','\u2AEC':'Not','\u2AED':'bNot','\u2AEE':'rnmid','\u2AEF':'cirmid','\u2AF0':'midcir','\u2AF1':'topcir','\u2AF2':'nhpar','\u2AF3':'parsim','\u2AFD':'parsl','\u2AFD\u20E5':'nparsl','\u266D':'flat','\u266E':'natur','\u266F':'sharp','\xA4':'curren','\xA2':'cent','$':'dollar','\xA3':'pound','\xA5':'yen','\u20AC':'euro','\xB9':'sup1','\xBD':'half','\u2153':'frac13','\xBC':'frac14','\u2155':'frac15','\u2159':'frac16','\u215B':'frac18','\xB2':'sup2','\u2154':'frac23','\u2156':'frac25','\xB3':'sup3','\xBE':'frac34','\u2157':'frac35','\u215C':'frac38','\u2158':'frac45','\u215A':'frac56','\u215D':'frac58','\u215E':'frac78','\uD835\uDCB6':'ascr','\uD835\uDD52':'aopf','\uD835\uDD1E':'afr','\uD835\uDD38':'Aopf','\uD835\uDD04':'Afr','\uD835\uDC9C':'Ascr','\xAA':'ordf','\xE1':'aacute','\xC1':'Aacute','\xE0':'agrave','\xC0':'Agrave','\u0103':'abreve','\u0102':'Abreve','\xE2':'acirc','\xC2':'Acirc','\xE5':'aring','\xC5':'angst','\xE4':'auml','\xC4':'Auml','\xE3':'atilde','\xC3':'Atilde','\u0105':'aogon','\u0104':'Aogon','\u0101':'amacr','\u0100':'Amacr','\xE6':'aelig','\xC6':'AElig','\uD835\uDCB7':'bscr','\uD835\uDD53':'bopf','\uD835\uDD1F':'bfr','\uD835\uDD39':'Bopf','\u212C':'Bscr','\uD835\uDD05':'Bfr','\uD835\uDD20':'cfr','\uD835\uDCB8':'cscr','\uD835\uDD54':'copf','\u212D':'Cfr','\uD835\uDC9E':'Cscr','\u2102':'Copf','\u0107':'cacute','\u0106':'Cacute','\u0109':'ccirc','\u0108':'Ccirc','\u010D':'ccaron','\u010C':'Ccaron','\u010B':'cdot','\u010A':'Cdot','\xE7':'ccedil','\xC7':'Ccedil','\u2105':'incare','\uD835\uDD21':'dfr','\u2146':'dd','\uD835\uDD55':'dopf','\uD835\uDCB9':'dscr','\uD835\uDC9F':'Dscr','\uD835\uDD07':'Dfr','\u2145':'DD','\uD835\uDD3B':'Dopf','\u010F':'dcaron','\u010E':'Dcaron','\u0111':'dstrok','\u0110':'Dstrok','\xF0':'eth','\xD0':'ETH','\u2147':'ee','\u212F':'escr','\uD835\uDD22':'efr','\uD835\uDD56':'eopf','\u2130':'Escr','\uD835\uDD08':'Efr','\uD835\uDD3C':'Eopf','\xE9':'eacute','\xC9':'Eacute','\xE8':'egrave','\xC8':'Egrave','\xEA':'ecirc','\xCA':'Ecirc','\u011B':'ecaron','\u011A':'Ecaron','\xEB':'euml','\xCB':'Euml','\u0117':'edot','\u0116':'Edot','\u0119':'eogon','\u0118':'Eogon','\u0113':'emacr','\u0112':'Emacr','\uD835\uDD23':'ffr','\uD835\uDD57':'fopf','\uD835\uDCBB':'fscr','\uD835\uDD09':'Ffr','\uD835\uDD3D':'Fopf','\u2131':'Fscr','\uFB00':'fflig','\uFB03':'ffilig','\uFB04':'ffllig','\uFB01':'filig','fj':'fjlig','\uFB02':'fllig','\u0192':'fnof','\u210A':'gscr','\uD835\uDD58':'gopf','\uD835\uDD24':'gfr','\uD835\uDCA2':'Gscr','\uD835\uDD3E':'Gopf','\uD835\uDD0A':'Gfr','\u01F5':'gacute','\u011F':'gbreve','\u011E':'Gbreve','\u011D':'gcirc','\u011C':'Gcirc','\u0121':'gdot','\u0120':'Gdot','\u0122':'Gcedil','\uD835\uDD25':'hfr','\u210E':'planckh','\uD835\uDCBD':'hscr','\uD835\uDD59':'hopf','\u210B':'Hscr','\u210C':'Hfr','\u210D':'Hopf','\u0125':'hcirc','\u0124':'Hcirc','\u210F':'hbar','\u0127':'hstrok','\u0126':'Hstrok','\uD835\uDD5A':'iopf','\uD835\uDD26':'ifr','\uD835\uDCBE':'iscr','\u2148':'ii','\uD835\uDD40':'Iopf','\u2110':'Iscr','\u2111':'Im','\xED':'iacute','\xCD':'Iacute','\xEC':'igrave','\xCC':'Igrave','\xEE':'icirc','\xCE':'Icirc','\xEF':'iuml','\xCF':'Iuml','\u0129':'itilde','\u0128':'Itilde','\u0130':'Idot','\u012F':'iogon','\u012E':'Iogon','\u012B':'imacr','\u012A':'Imacr','\u0133':'ijlig','\u0132':'IJlig','\u0131':'imath','\uD835\uDCBF':'jscr','\uD835\uDD5B':'jopf','\uD835\uDD27':'jfr','\uD835\uDCA5':'Jscr','\uD835\uDD0D':'Jfr','\uD835\uDD41':'Jopf','\u0135':'jcirc','\u0134':'Jcirc','\u0237':'jmath','\uD835\uDD5C':'kopf','\uD835\uDCC0':'kscr','\uD835\uDD28':'kfr','\uD835\uDCA6':'Kscr','\uD835\uDD42':'Kopf','\uD835\uDD0E':'Kfr','\u0137':'kcedil','\u0136':'Kcedil','\uD835\uDD29':'lfr','\uD835\uDCC1':'lscr','\u2113':'ell','\uD835\uDD5D':'lopf','\u2112':'Lscr','\uD835\uDD0F':'Lfr','\uD835\uDD43':'Lopf','\u013A':'lacute','\u0139':'Lacute','\u013E':'lcaron','\u013D':'Lcaron','\u013C':'lcedil','\u013B':'Lcedil','\u0142':'lstrok','\u0141':'Lstrok','\u0140':'lmidot','\u013F':'Lmidot','\uD835\uDD2A':'mfr','\uD835\uDD5E':'mopf','\uD835\uDCC2':'mscr','\uD835\uDD10':'Mfr','\uD835\uDD44':'Mopf','\u2133':'Mscr','\uD835\uDD2B':'nfr','\uD835\uDD5F':'nopf','\uD835\uDCC3':'nscr','\u2115':'Nopf','\uD835\uDCA9':'Nscr','\uD835\uDD11':'Nfr','\u0144':'nacute','\u0143':'Nacute','\u0148':'ncaron','\u0147':'Ncaron','\xF1':'ntilde','\xD1':'Ntilde','\u0146':'ncedil','\u0145':'Ncedil','\u2116':'numero','\u014B':'eng','\u014A':'ENG','\uD835\uDD60':'oopf','\uD835\uDD2C':'ofr','\u2134':'oscr','\uD835\uDCAA':'Oscr','\uD835\uDD12':'Ofr','\uD835\uDD46':'Oopf','\xBA':'ordm','\xF3':'oacute','\xD3':'Oacute','\xF2':'ograve','\xD2':'Ograve','\xF4':'ocirc','\xD4':'Ocirc','\xF6':'ouml','\xD6':'Ouml','\u0151':'odblac','\u0150':'Odblac','\xF5':'otilde','\xD5':'Otilde','\xF8':'oslash','\xD8':'Oslash','\u014D':'omacr','\u014C':'Omacr','\u0153':'oelig','\u0152':'OElig','\uD835\uDD2D':'pfr','\uD835\uDCC5':'pscr','\uD835\uDD61':'popf','\u2119':'Popf','\uD835\uDD13':'Pfr','\uD835\uDCAB':'Pscr','\uD835\uDD62':'qopf','\uD835\uDD2E':'qfr','\uD835\uDCC6':'qscr','\uD835\uDCAC':'Qscr','\uD835\uDD14':'Qfr','\u211A':'Qopf','\u0138':'kgreen','\uD835\uDD2F':'rfr','\uD835\uDD63':'ropf','\uD835\uDCC7':'rscr','\u211B':'Rscr','\u211C':'Re','\u211D':'Ropf','\u0155':'racute','\u0154':'Racute','\u0159':'rcaron','\u0158':'Rcaron','\u0157':'rcedil','\u0156':'Rcedil','\uD835\uDD64':'sopf','\uD835\uDCC8':'sscr','\uD835\uDD30':'sfr','\uD835\uDD4A':'Sopf','\uD835\uDD16':'Sfr','\uD835\uDCAE':'Sscr','\u24C8':'oS','\u015B':'sacute','\u015A':'Sacute','\u015D':'scirc','\u015C':'Scirc','\u0161':'scaron','\u0160':'Scaron','\u015F':'scedil','\u015E':'Scedil','\xDF':'szlig','\uD835\uDD31':'tfr','\uD835\uDCC9':'tscr','\uD835\uDD65':'topf','\uD835\uDCAF':'Tscr','\uD835\uDD17':'Tfr','\uD835\uDD4B':'Topf','\u0165':'tcaron','\u0164':'Tcaron','\u0163':'tcedil','\u0162':'Tcedil','\u2122':'trade','\u0167':'tstrok','\u0166':'Tstrok','\uD835\uDCCA':'uscr','\uD835\uDD66':'uopf','\uD835\uDD32':'ufr','\uD835\uDD4C':'Uopf','\uD835\uDD18':'Ufr','\uD835\uDCB0':'Uscr','\xFA':'uacute','\xDA':'Uacute','\xF9':'ugrave','\xD9':'Ugrave','\u016D':'ubreve','\u016C':'Ubreve','\xFB':'ucirc','\xDB':'Ucirc','\u016F':'uring','\u016E':'Uring','\xFC':'uuml','\xDC':'Uuml','\u0171':'udblac','\u0170':'Udblac','\u0169':'utilde','\u0168':'Utilde','\u0173':'uogon','\u0172':'Uogon','\u016B':'umacr','\u016A':'Umacr','\uD835\uDD33':'vfr','\uD835\uDD67':'vopf','\uD835\uDCCB':'vscr','\uD835\uDD19':'Vfr','\uD835\uDD4D':'Vopf','\uD835\uDCB1':'Vscr','\uD835\uDD68':'wopf','\uD835\uDCCC':'wscr','\uD835\uDD34':'wfr','\uD835\uDCB2':'Wscr','\uD835\uDD4E':'Wopf','\uD835\uDD1A':'Wfr','\u0175':'wcirc','\u0174':'Wcirc','\uD835\uDD35':'xfr','\uD835\uDCCD':'xscr','\uD835\uDD69':'xopf','\uD835\uDD4F':'Xopf','\uD835\uDD1B':'Xfr','\uD835\uDCB3':'Xscr','\uD835\uDD36':'yfr','\uD835\uDCCE':'yscr','\uD835\uDD6A':'yopf','\uD835\uDCB4':'Yscr','\uD835\uDD1C':'Yfr','\uD835\uDD50':'Yopf','\xFD':'yacute','\xDD':'Yacute','\u0177':'ycirc','\u0176':'Ycirc','\xFF':'yuml','\u0178':'Yuml','\uD835\uDCCF':'zscr','\uD835\uDD37':'zfr','\uD835\uDD6B':'zopf','\u2128':'Zfr','\u2124':'Zopf','\uD835\uDCB5':'Zscr','\u017A':'zacute','\u0179':'Zacute','\u017E':'zcaron','\u017D':'Zcaron','\u017C':'zdot','\u017B':'Zdot','\u01B5':'imped','\xFE':'thorn','\xDE':'THORN','\u0149':'napos','\u03B1':'alpha','\u0391':'Alpha','\u03B2':'beta','\u0392':'Beta','\u03B3':'gamma','\u0393':'Gamma','\u03B4':'delta','\u0394':'Delta','\u03B5':'epsi','\u03F5':'epsiv','\u0395':'Epsilon','\u03DD':'gammad','\u03DC':'Gammad','\u03B6':'zeta','\u0396':'Zeta','\u03B7':'eta','\u0397':'Eta','\u03B8':'theta','\u03D1':'thetav','\u0398':'Theta','\u03B9':'iota','\u0399':'Iota','\u03BA':'kappa','\u03F0':'kappav','\u039A':'Kappa','\u03BB':'lambda','\u039B':'Lambda','\u03BC':'mu','\xB5':'micro','\u039C':'Mu','\u03BD':'nu','\u039D':'Nu','\u03BE':'xi','\u039E':'Xi','\u03BF':'omicron','\u039F':'Omicron','\u03C0':'pi','\u03D6':'piv','\u03A0':'Pi','\u03C1':'rho','\u03F1':'rhov','\u03A1':'Rho','\u03C3':'sigma','\u03A3':'Sigma','\u03C2':'sigmaf','\u03C4':'tau','\u03A4':'Tau','\u03C5':'upsi','\u03A5':'Upsilon','\u03D2':'Upsi','\u03C6':'phi','\u03D5':'phiv','\u03A6':'Phi','\u03C7':'chi','\u03A7':'Chi','\u03C8':'psi','\u03A8':'Psi','\u03C9':'omega','\u03A9':'ohm','\u0430':'acy','\u0410':'Acy','\u0431':'bcy','\u0411':'Bcy','\u0432':'vcy','\u0412':'Vcy','\u0433':'gcy','\u0413':'Gcy','\u0453':'gjcy','\u0403':'GJcy','\u0434':'dcy','\u0414':'Dcy','\u0452':'djcy','\u0402':'DJcy','\u0435':'iecy','\u0415':'IEcy','\u0451':'iocy','\u0401':'IOcy','\u0454':'jukcy','\u0404':'Jukcy','\u0436':'zhcy','\u0416':'ZHcy','\u0437':'zcy','\u0417':'Zcy','\u0455':'dscy','\u0405':'DScy','\u0438':'icy','\u0418':'Icy','\u0456':'iukcy','\u0406':'Iukcy','\u0457':'yicy','\u0407':'YIcy','\u0439':'jcy','\u0419':'Jcy','\u0458':'jsercy','\u0408':'Jsercy','\u043A':'kcy','\u041A':'Kcy','\u045C':'kjcy','\u040C':'KJcy','\u043B':'lcy','\u041B':'Lcy','\u0459':'ljcy','\u0409':'LJcy','\u043C':'mcy','\u041C':'Mcy','\u043D':'ncy','\u041D':'Ncy','\u045A':'njcy','\u040A':'NJcy','\u043E':'ocy','\u041E':'Ocy','\u043F':'pcy','\u041F':'Pcy','\u0440':'rcy','\u0420':'Rcy','\u0441':'scy','\u0421':'Scy','\u0442':'tcy','\u0422':'Tcy','\u045B':'tshcy','\u040B':'TSHcy','\u0443':'ucy','\u0423':'Ucy','\u045E':'ubrcy','\u040E':'Ubrcy','\u0444':'fcy','\u0424':'Fcy','\u0445':'khcy','\u0425':'KHcy','\u0446':'tscy','\u0426':'TScy','\u0447':'chcy','\u0427':'CHcy','\u045F':'dzcy','\u040F':'DZcy','\u0448':'shcy','\u0428':'SHcy','\u0449':'shchcy','\u0429':'SHCHcy','\u044A':'hardcy','\u042A':'HARDcy','\u044B':'ycy','\u042B':'Ycy','\u044C':'softcy','\u042C':'SOFTcy','\u044D':'ecy','\u042D':'Ecy','\u044E':'yucy','\u042E':'YUcy','\u044F':'yacy','\u042F':'YAcy','\u2135':'aleph','\u2136':'beth','\u2137':'gimel','\u2138':'daleth'}; - - var regexEscape = /["&'<>`]/g; - var escapeMap = { - '"': '"', - '&': '&', - '\'': ''', - '<': '<', - // See https://mathiasbynens.be/notes/ambiguous-ampersands: in HTML, the - // following is not strictly necessary unless it’s part of a tag or an - // unquoted attribute value. We’re only escaping it to support those - // situations, and for XML support. - '>': '>', - // In Internet Explorer ≤ 8, the backtick character can be used - // to break out of (un)quoted attribute values or HTML comments. - // See http://html5sec.org/#102, http://html5sec.org/#108, and - // http://html5sec.org/#133. - '`': '`' - }; - - var regexInvalidEntity = /&#(?:[xX][^a-fA-F0-9]|[^0-9xX])/; - var regexInvalidRawCodePoint = /[\0-\x08\x0B\x0E-\x1F\x7F-\x9F\uFDD0-\uFDEF\uFFFE\uFFFF]|[\uD83F\uD87F\uD8BF\uD8FF\uD93F\uD97F\uD9BF\uD9FF\uDA3F\uDA7F\uDABF\uDAFF\uDB3F\uDB7F\uDBBF\uDBFF][\uDFFE\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; - var regexDecode = /&(CounterClockwiseContourIntegral|DoubleLongLeftRightArrow|ClockwiseContourIntegral|NotNestedGreaterGreater|NotSquareSupersetEqual|DiacriticalDoubleAcute|NotRightTriangleEqual|NotSucceedsSlantEqual|NotPrecedesSlantEqual|CloseCurlyDoubleQuote|NegativeVeryThinSpace|DoubleContourIntegral|FilledVerySmallSquare|CapitalDifferentialD|OpenCurlyDoubleQuote|EmptyVerySmallSquare|NestedGreaterGreater|DoubleLongRightArrow|NotLeftTriangleEqual|NotGreaterSlantEqual|ReverseUpEquilibrium|DoubleLeftRightArrow|NotSquareSubsetEqual|NotDoubleVerticalBar|RightArrowLeftArrow|NotGreaterFullEqual|NotRightTriangleBar|SquareSupersetEqual|DownLeftRightVector|DoubleLongLeftArrow|leftrightsquigarrow|LeftArrowRightArrow|NegativeMediumSpace|blacktriangleright|RightDownVectorBar|PrecedesSlantEqual|RightDoubleBracket|SucceedsSlantEqual|NotLeftTriangleBar|RightTriangleEqual|SquareIntersection|RightDownTeeVector|ReverseEquilibrium|NegativeThickSpace|longleftrightarrow|Longleftrightarrow|LongLeftRightArrow|DownRightTeeVector|DownRightVectorBar|GreaterSlantEqual|SquareSubsetEqual|LeftDownVectorBar|LeftDoubleBracket|VerticalSeparator|rightleftharpoons|NotGreaterGreater|NotSquareSuperset|blacktriangleleft|blacktriangledown|NegativeThinSpace|LeftDownTeeVector|NotLessSlantEqual|leftrightharpoons|DoubleUpDownArrow|DoubleVerticalBar|LeftTriangleEqual|FilledSmallSquare|twoheadrightarrow|NotNestedLessLess|DownLeftTeeVector|DownLeftVectorBar|RightAngleBracket|NotTildeFullEqual|NotReverseElement|RightUpDownVector|DiacriticalTilde|NotSucceedsTilde|circlearrowright|NotPrecedesEqual|rightharpoondown|DoubleRightArrow|NotSucceedsEqual|NonBreakingSpace|NotRightTriangle|LessEqualGreater|RightUpTeeVector|LeftAngleBracket|GreaterFullEqual|DownArrowUpArrow|RightUpVectorBar|twoheadleftarrow|GreaterEqualLess|downharpoonright|RightTriangleBar|ntrianglerighteq|NotSupersetEqual|LeftUpDownVector|DiacriticalAcute|rightrightarrows|vartriangleright|UpArrowDownArrow|DiacriticalGrave|UnderParenthesis|EmptySmallSquare|LeftUpVectorBar|leftrightarrows|DownRightVector|downharpoonleft|trianglerighteq|ShortRightArrow|OverParenthesis|DoubleLeftArrow|DoubleDownArrow|NotSquareSubset|bigtriangledown|ntrianglelefteq|UpperRightArrow|curvearrowright|vartriangleleft|NotLeftTriangle|nleftrightarrow|LowerRightArrow|NotHumpDownHump|NotGreaterTilde|rightthreetimes|LeftUpTeeVector|NotGreaterEqual|straightepsilon|LeftTriangleBar|rightsquigarrow|ContourIntegral|rightleftarrows|CloseCurlyQuote|RightDownVector|LeftRightVector|nLeftrightarrow|leftharpoondown|circlearrowleft|SquareSuperset|OpenCurlyQuote|hookrightarrow|HorizontalLine|DiacriticalDot|NotLessGreater|ntriangleright|DoubleRightTee|InvisibleComma|InvisibleTimes|LowerLeftArrow|DownLeftVector|NotSubsetEqual|curvearrowleft|trianglelefteq|NotVerticalBar|TildeFullEqual|downdownarrows|NotGreaterLess|RightTeeVector|ZeroWidthSpace|looparrowright|LongRightArrow|doublebarwedge|ShortLeftArrow|ShortDownArrow|RightVectorBar|GreaterGreater|ReverseElement|rightharpoonup|LessSlantEqual|leftthreetimes|upharpoonright|rightarrowtail|LeftDownVector|Longrightarrow|NestedLessLess|UpperLeftArrow|nshortparallel|leftleftarrows|leftrightarrow|Leftrightarrow|LeftRightArrow|longrightarrow|upharpoonleft|RightArrowBar|ApplyFunction|LeftTeeVector|leftarrowtail|NotEqualTilde|varsubsetneqq|varsupsetneqq|RightTeeArrow|SucceedsEqual|SucceedsTilde|LeftVectorBar|SupersetEqual|hookleftarrow|DifferentialD|VerticalTilde|VeryThinSpace|blacktriangle|bigtriangleup|LessFullEqual|divideontimes|leftharpoonup|UpEquilibrium|ntriangleleft|RightTriangle|measuredangle|shortparallel|longleftarrow|Longleftarrow|LongLeftArrow|DoubleLeftTee|Poincareplane|PrecedesEqual|triangleright|DoubleUpArrow|RightUpVector|fallingdotseq|looparrowleft|PrecedesTilde|NotTildeEqual|NotTildeTilde|smallsetminus|Proportional|triangleleft|triangledown|UnderBracket|NotHumpEqual|exponentiale|ExponentialE|NotLessTilde|HilbertSpace|RightCeiling|blacklozenge|varsupsetneq|HumpDownHump|GreaterEqual|VerticalLine|LeftTeeArrow|NotLessEqual|DownTeeArrow|LeftTriangle|varsubsetneq|Intersection|NotCongruent|DownArrowBar|LeftUpVector|LeftArrowBar|risingdotseq|GreaterTilde|RoundImplies|SquareSubset|ShortUpArrow|NotSuperset|quaternions|precnapprox|backepsilon|preccurlyeq|OverBracket|blacksquare|MediumSpace|VerticalBar|circledcirc|circleddash|CircleMinus|CircleTimes|LessGreater|curlyeqprec|curlyeqsucc|diamondsuit|UpDownArrow|Updownarrow|RuleDelayed|Rrightarrow|updownarrow|RightVector|nRightarrow|nrightarrow|eqslantless|LeftCeiling|Equilibrium|SmallCircle|expectation|NotSucceeds|thickapprox|GreaterLess|SquareUnion|NotPrecedes|NotLessLess|straightphi|succnapprox|succcurlyeq|SubsetEqual|sqsupseteq|Proportion|Laplacetrf|ImaginaryI|supsetneqq|NotGreater|gtreqqless|NotElement|ThickSpace|TildeEqual|TildeTilde|Fouriertrf|rmoustache|EqualTilde|eqslantgtr|UnderBrace|LeftVector|UpArrowBar|nLeftarrow|nsubseteqq|subsetneqq|nsupseteqq|nleftarrow|succapprox|lessapprox|UpTeeArrow|upuparrows|curlywedge|lesseqqgtr|varepsilon|varnothing|RightFloor|complement|CirclePlus|sqsubseteq|Lleftarrow|circledast|RightArrow|Rightarrow|rightarrow|lmoustache|Bernoullis|precapprox|mapstoleft|mapstodown|longmapsto|dotsquare|downarrow|DoubleDot|nsubseteq|supsetneq|leftarrow|nsupseteq|subsetneq|ThinSpace|ngeqslant|subseteqq|HumpEqual|NotSubset|triangleq|NotCupCap|lesseqgtr|heartsuit|TripleDot|Leftarrow|Coproduct|Congruent|varpropto|complexes|gvertneqq|LeftArrow|LessTilde|supseteqq|MinusPlus|CircleDot|nleqslant|NotExists|gtreqless|nparallel|UnionPlus|LeftFloor|checkmark|CenterDot|centerdot|Mellintrf|gtrapprox|bigotimes|OverBrace|spadesuit|therefore|pitchfork|rationals|PlusMinus|Backslash|Therefore|DownBreve|backsimeq|backprime|DownArrow|nshortmid|Downarrow|lvertneqq|eqvparsl|imagline|imagpart|infintie|integers|Integral|intercal|LessLess|Uarrocir|intlarhk|sqsupset|angmsdaf|sqsubset|llcorner|vartheta|cupbrcap|lnapprox|Superset|SuchThat|succnsim|succneqq|angmsdag|biguplus|curlyvee|trpezium|Succeeds|NotTilde|bigwedge|angmsdah|angrtvbd|triminus|cwconint|fpartint|lrcorner|smeparsl|subseteq|urcorner|lurdshar|laemptyv|DDotrahd|approxeq|ldrushar|awconint|mapstoup|backcong|shortmid|triangle|geqslant|gesdotol|timesbar|circledR|circledS|setminus|multimap|naturals|scpolint|ncongdot|RightTee|boxminus|gnapprox|boxtimes|andslope|thicksim|angmsdaa|varsigma|cirfnint|rtriltri|angmsdab|rppolint|angmsdac|barwedge|drbkarow|clubsuit|thetasym|bsolhsub|capbrcup|dzigrarr|doteqdot|DotEqual|dotminus|UnderBar|NotEqual|realpart|otimesas|ulcorner|hksearow|hkswarow|parallel|PartialD|elinters|emptyset|plusacir|bbrktbrk|angmsdad|pointint|bigoplus|angmsdae|Precedes|bigsqcup|varkappa|notindot|supseteq|precneqq|precnsim|profalar|profline|profsurf|leqslant|lesdotor|raemptyv|subplus|notnivb|notnivc|subrarr|zigrarr|vzigzag|submult|subedot|Element|between|cirscir|larrbfs|larrsim|lotimes|lbrksld|lbrkslu|lozenge|ldrdhar|dbkarow|bigcirc|epsilon|simrarr|simplus|ltquest|Epsilon|luruhar|gtquest|maltese|npolint|eqcolon|npreceq|bigodot|ddagger|gtrless|bnequiv|harrcir|ddotseq|equivDD|backsim|demptyv|nsqsube|nsqsupe|Upsilon|nsubset|upsilon|minusdu|nsucceq|swarrow|nsupset|coloneq|searrow|boxplus|napprox|natural|asympeq|alefsym|congdot|nearrow|bigstar|diamond|supplus|tritime|LeftTee|nvinfin|triplus|NewLine|nvltrie|nvrtrie|nwarrow|nexists|Diamond|ruluhar|Implies|supmult|angzarr|suplarr|suphsub|questeq|because|digamma|Because|olcross|bemptyv|omicron|Omicron|rotimes|NoBreak|intprod|angrtvb|orderof|uwangle|suphsol|lesdoto|orslope|DownTee|realine|cudarrl|rdldhar|OverBar|supedot|lessdot|supdsub|topfork|succsim|rbrkslu|rbrksld|pertenk|cudarrr|isindot|planckh|lessgtr|pluscir|gesdoto|plussim|plustwo|lesssim|cularrp|rarrsim|Cayleys|notinva|notinvb|notinvc|UpArrow|Uparrow|uparrow|NotLess|dwangle|precsim|Product|curarrm|Cconint|dotplus|rarrbfs|ccupssm|Cedilla|cemptyv|notniva|quatint|frac35|frac38|frac45|frac56|frac58|frac78|tridot|xoplus|gacute|gammad|Gammad|lfisht|lfloor|bigcup|sqsupe|gbreve|Gbreve|lharul|sqsube|sqcups|Gcedil|apacir|llhard|lmidot|Lmidot|lmoust|andand|sqcaps|approx|Abreve|spades|circeq|tprime|divide|topcir|Assign|topbot|gesdot|divonx|xuplus|timesd|gesles|atilde|solbar|SOFTcy|loplus|timesb|lowast|lowbar|dlcorn|dlcrop|softcy|dollar|lparlt|thksim|lrhard|Atilde|lsaquo|smashp|bigvee|thinsp|wreath|bkarow|lsquor|lstrok|Lstrok|lthree|ltimes|ltlarr|DotDot|simdot|ltrPar|weierp|xsqcup|angmsd|sigmav|sigmaf|zeetrf|Zcaron|zcaron|mapsto|vsupne|thetav|cirmid|marker|mcomma|Zacute|vsubnE|there4|gtlPar|vsubne|bottom|gtrarr|SHCHcy|shchcy|midast|midcir|middot|minusb|minusd|gtrdot|bowtie|sfrown|mnplus|models|colone|seswar|Colone|mstpos|searhk|gtrsim|nacute|Nacute|boxbox|telrec|hairsp|Tcedil|nbumpe|scnsim|ncaron|Ncaron|ncedil|Ncedil|hamilt|Scedil|nearhk|hardcy|HARDcy|tcedil|Tcaron|commat|nequiv|nesear|tcaron|target|hearts|nexist|varrho|scedil|Scaron|scaron|hellip|Sacute|sacute|hercon|swnwar|compfn|rtimes|rthree|rsquor|rsaquo|zacute|wedgeq|homtht|barvee|barwed|Barwed|rpargt|horbar|conint|swarhk|roplus|nltrie|hslash|hstrok|Hstrok|rmoust|Conint|bprime|hybull|hyphen|iacute|Iacute|supsup|supsub|supsim|varphi|coprod|brvbar|agrave|Supset|supset|igrave|Igrave|notinE|Agrave|iiiint|iinfin|copysr|wedbar|Verbar|vangrt|becaus|incare|verbar|inodot|bullet|drcorn|intcal|drcrop|cularr|vellip|Utilde|bumpeq|cupcap|dstrok|Dstrok|CupCap|cupcup|cupdot|eacute|Eacute|supdot|iquest|easter|ecaron|Ecaron|ecolon|isinsv|utilde|itilde|Itilde|curarr|succeq|Bumpeq|cacute|ulcrop|nparsl|Cacute|nprcue|egrave|Egrave|nrarrc|nrarrw|subsup|subsub|nrtrie|jsercy|nsccue|Jsercy|kappav|kcedil|Kcedil|subsim|ulcorn|nsimeq|egsdot|veebar|kgreen|capand|elsdot|Subset|subset|curren|aacute|lacute|Lacute|emptyv|ntilde|Ntilde|lagran|lambda|Lambda|capcap|Ugrave|langle|subdot|emsp13|numero|emsp14|nvdash|nvDash|nVdash|nVDash|ugrave|ufisht|nvHarr|larrfs|nvlArr|larrhk|larrlp|larrpl|nvrArr|Udblac|nwarhk|larrtl|nwnear|oacute|Oacute|latail|lAtail|sstarf|lbrace|odblac|Odblac|lbrack|udblac|odsold|eparsl|lcaron|Lcaron|ograve|Ograve|lcedil|Lcedil|Aacute|ssmile|ssetmn|squarf|ldquor|capcup|ominus|cylcty|rharul|eqcirc|dagger|rfloor|rfisht|Dagger|daleth|equals|origof|capdot|equest|dcaron|Dcaron|rdquor|oslash|Oslash|otilde|Otilde|otimes|Otimes|urcrop|Ubreve|ubreve|Yacute|Uacute|uacute|Rcedil|rcedil|urcorn|parsim|Rcaron|Vdashl|rcaron|Tstrok|percnt|period|permil|Exists|yacute|rbrack|rbrace|phmmat|ccaron|Ccaron|planck|ccedil|plankv|tstrok|female|plusdo|plusdu|ffilig|plusmn|ffllig|Ccedil|rAtail|dfisht|bernou|ratail|Rarrtl|rarrtl|angsph|rarrpl|rarrlp|rarrhk|xwedge|xotime|forall|ForAll|Vvdash|vsupnE|preceq|bigcap|frac12|frac13|frac14|primes|rarrfs|prnsim|frac15|Square|frac16|square|lesdot|frac18|frac23|propto|prurel|rarrap|rangle|puncsp|frac25|Racute|qprime|racute|lesges|frac34|abreve|AElig|eqsim|utdot|setmn|urtri|Equal|Uring|seArr|uring|searr|dashv|Dashv|mumap|nabla|iogon|Iogon|sdote|sdotb|scsim|napid|napos|equiv|natur|Acirc|dblac|erarr|nbump|iprod|erDot|ucirc|awint|esdot|angrt|ncong|isinE|scnap|Scirc|scirc|ndash|isins|Ubrcy|nearr|neArr|isinv|nedot|ubrcy|acute|Ycirc|iukcy|Iukcy|xutri|nesim|caret|jcirc|Jcirc|caron|twixt|ddarr|sccue|exist|jmath|sbquo|ngeqq|angst|ccaps|lceil|ngsim|UpTee|delta|Delta|rtrif|nharr|nhArr|nhpar|rtrie|jukcy|Jukcy|kappa|rsquo|Kappa|nlarr|nlArr|TSHcy|rrarr|aogon|Aogon|fflig|xrarr|tshcy|ccirc|nleqq|filig|upsih|nless|dharl|nlsim|fjlig|ropar|nltri|dharr|robrk|roarr|fllig|fltns|roang|rnmid|subnE|subne|lAarr|trisb|Ccirc|acirc|ccups|blank|VDash|forkv|Vdash|langd|cedil|blk12|blk14|laquo|strns|diams|notin|vDash|larrb|blk34|block|disin|uplus|vdash|vBarv|aelig|starf|Wedge|check|xrArr|lates|lbarr|lBarr|notni|lbbrk|bcong|frasl|lbrke|frown|vrtri|vprop|vnsup|gamma|Gamma|wedge|xodot|bdquo|srarr|doteq|ldquo|boxdl|boxdL|gcirc|Gcirc|boxDl|boxDL|boxdr|boxdR|boxDr|TRADE|trade|rlhar|boxDR|vnsub|npart|vltri|rlarr|boxhd|boxhD|nprec|gescc|nrarr|nrArr|boxHd|boxHD|boxhu|boxhU|nrtri|boxHu|clubs|boxHU|times|colon|Colon|gimel|xlArr|Tilde|nsime|tilde|nsmid|nspar|THORN|thorn|xlarr|nsube|nsubE|thkap|xhArr|comma|nsucc|boxul|boxuL|nsupe|nsupE|gneqq|gnsim|boxUl|boxUL|grave|boxur|boxuR|boxUr|boxUR|lescc|angle|bepsi|boxvh|varpi|boxvH|numsp|Theta|gsime|gsiml|theta|boxVh|boxVH|boxvl|gtcir|gtdot|boxvL|boxVl|boxVL|crarr|cross|Cross|nvsim|boxvr|nwarr|nwArr|sqsup|dtdot|Uogon|lhard|lharu|dtrif|ocirc|Ocirc|lhblk|duarr|odash|sqsub|Hacek|sqcup|llarr|duhar|oelig|OElig|ofcir|boxvR|uogon|lltri|boxVr|csube|uuarr|ohbar|csupe|ctdot|olarr|olcir|harrw|oline|sqcap|omacr|Omacr|omega|Omega|boxVR|aleph|lneqq|lnsim|loang|loarr|rharu|lobrk|hcirc|operp|oplus|rhard|Hcirc|orarr|Union|order|ecirc|Ecirc|cuepr|szlig|cuesc|breve|reals|eDDot|Breve|hoarr|lopar|utrif|rdquo|Umacr|umacr|efDot|swArr|ultri|alpha|rceil|ovbar|swarr|Wcirc|wcirc|smtes|smile|bsemi|lrarr|aring|parsl|lrhar|bsime|uhblk|lrtri|cupor|Aring|uharr|uharl|slarr|rbrke|bsolb|lsime|rbbrk|RBarr|lsimg|phone|rBarr|rbarr|icirc|lsquo|Icirc|emacr|Emacr|ratio|simne|plusb|simlE|simgE|simeq|pluse|ltcir|ltdot|empty|xharr|xdtri|iexcl|Alpha|ltrie|rarrw|pound|ltrif|xcirc|bumpe|prcue|bumpE|asymp|amacr|cuvee|Sigma|sigma|iiint|udhar|iiota|ijlig|IJlig|supnE|imacr|Imacr|prime|Prime|image|prnap|eogon|Eogon|rarrc|mdash|mDDot|cuwed|imath|supne|imped|Amacr|udarr|prsim|micro|rarrb|cwint|raquo|infin|eplus|range|rangd|Ucirc|radic|minus|amalg|veeeq|rAarr|epsiv|ycirc|quest|sharp|quot|zwnj|Qscr|race|qscr|Qopf|qopf|qint|rang|Rang|Zscr|zscr|Zopf|zopf|rarr|rArr|Rarr|Pscr|pscr|prop|prod|prnE|prec|ZHcy|zhcy|prap|Zeta|zeta|Popf|popf|Zdot|plus|zdot|Yuml|yuml|phiv|YUcy|yucy|Yscr|yscr|perp|Yopf|yopf|part|para|YIcy|Ouml|rcub|yicy|YAcy|rdca|ouml|osol|Oscr|rdsh|yacy|real|oscr|xvee|andd|rect|andv|Xscr|oror|ordm|ordf|xscr|ange|aopf|Aopf|rHar|Xopf|opar|Oopf|xopf|xnis|rhov|oopf|omid|xmap|oint|apid|apos|ogon|ascr|Ascr|odot|odiv|xcup|xcap|ocir|oast|nvlt|nvle|nvgt|nvge|nvap|Wscr|wscr|auml|ntlg|ntgl|nsup|nsub|nsim|Nscr|nscr|nsce|Wopf|ring|npre|wopf|npar|Auml|Barv|bbrk|Nopf|nopf|nmid|nLtv|beta|ropf|Ropf|Beta|beth|nles|rpar|nleq|bnot|bNot|nldr|NJcy|rscr|Rscr|Vscr|vscr|rsqb|njcy|bopf|nisd|Bopf|rtri|Vopf|nGtv|ngtr|vopf|boxh|boxH|boxv|nges|ngeq|boxV|bscr|scap|Bscr|bsim|Vert|vert|bsol|bull|bump|caps|cdot|ncup|scnE|ncap|nbsp|napE|Cdot|cent|sdot|Vbar|nang|vBar|chcy|Mscr|mscr|sect|semi|CHcy|Mopf|mopf|sext|circ|cire|mldr|mlcp|cirE|comp|shcy|SHcy|vArr|varr|cong|copf|Copf|copy|COPY|malt|male|macr|lvnE|cscr|ltri|sime|ltcc|simg|Cscr|siml|csub|Uuml|lsqb|lsim|uuml|csup|Lscr|lscr|utri|smid|lpar|cups|smte|lozf|darr|Lopf|Uscr|solb|lopf|sopf|Sopf|lneq|uscr|spar|dArr|lnap|Darr|dash|Sqrt|LJcy|ljcy|lHar|dHar|Upsi|upsi|diam|lesg|djcy|DJcy|leqq|dopf|Dopf|dscr|Dscr|dscy|ldsh|ldca|squf|DScy|sscr|Sscr|dsol|lcub|late|star|Star|Uopf|Larr|lArr|larr|uopf|dtri|dzcy|sube|subE|Lang|lang|Kscr|kscr|Kopf|kopf|KJcy|kjcy|KHcy|khcy|DZcy|ecir|edot|eDot|Jscr|jscr|succ|Jopf|jopf|Edot|uHar|emsp|ensp|Iuml|iuml|eopf|isin|Iscr|iscr|Eopf|epar|sung|epsi|escr|sup1|sup2|sup3|Iota|iota|supe|supE|Iopf|iopf|IOcy|iocy|Escr|esim|Esim|imof|Uarr|QUOT|uArr|uarr|euml|IEcy|iecy|Idot|Euml|euro|excl|Hscr|hscr|Hopf|hopf|TScy|tscy|Tscr|hbar|tscr|flat|tbrk|fnof|hArr|harr|half|fopf|Fopf|tdot|gvnE|fork|trie|gtcc|fscr|Fscr|gdot|gsim|Gscr|gscr|Gopf|gopf|gneq|Gdot|tosa|gnap|Topf|topf|geqq|toea|GJcy|gjcy|tint|gesl|mid|Sfr|ggg|top|ges|gla|glE|glj|geq|gne|gEl|gel|gnE|Gcy|gcy|gap|Tfr|tfr|Tcy|tcy|Hat|Tau|Ffr|tau|Tab|hfr|Hfr|ffr|Fcy|fcy|icy|Icy|iff|ETH|eth|ifr|Ifr|Eta|eta|int|Int|Sup|sup|ucy|Ucy|Sum|sum|jcy|ENG|ufr|Ufr|eng|Jcy|jfr|els|ell|egs|Efr|efr|Jfr|uml|kcy|Kcy|Ecy|ecy|kfr|Kfr|lap|Sub|sub|lat|lcy|Lcy|leg|Dot|dot|lEg|leq|les|squ|div|die|lfr|Lfr|lgE|Dfr|dfr|Del|deg|Dcy|dcy|lne|lnE|sol|loz|smt|Cup|lrm|cup|lsh|Lsh|sim|shy|map|Map|mcy|Mcy|mfr|Mfr|mho|gfr|Gfr|sfr|cir|Chi|chi|nap|Cfr|vcy|Vcy|cfr|Scy|scy|ncy|Ncy|vee|Vee|Cap|cap|nfr|scE|sce|Nfr|nge|ngE|nGg|vfr|Vfr|ngt|bot|nGt|nis|niv|Rsh|rsh|nle|nlE|bne|Bfr|bfr|nLl|nlt|nLt|Bcy|bcy|not|Not|rlm|wfr|Wfr|npr|nsc|num|ocy|ast|Ocy|ofr|xfr|Xfr|Ofr|ogt|ohm|apE|olt|Rho|ape|rho|Rfr|rfr|ord|REG|ang|reg|orv|And|and|AMP|Rcy|amp|Afr|ycy|Ycy|yen|yfr|Yfr|rcy|par|pcy|Pcy|pfr|Pfr|phi|Phi|afr|Acy|acy|zcy|Zcy|piv|acE|acd|zfr|Zfr|pre|prE|psi|Psi|qfr|Qfr|zwj|Or|ge|Gg|gt|gg|el|oS|lt|Lt|LT|Re|lg|gl|eg|ne|Im|it|le|DD|wp|wr|nu|Nu|dd|lE|Sc|sc|pi|Pi|ee|af|ll|Ll|rx|gE|xi|pm|Xi|ic|pr|Pr|in|ni|mp|mu|ac|Mu|or|ap|Gt|GT|ii);|&(Aacute|Agrave|Atilde|Ccedil|Eacute|Egrave|Iacute|Igrave|Ntilde|Oacute|Ograve|Oslash|Otilde|Uacute|Ugrave|Yacute|aacute|agrave|atilde|brvbar|ccedil|curren|divide|eacute|egrave|frac12|frac14|frac34|iacute|igrave|iquest|middot|ntilde|oacute|ograve|oslash|otilde|plusmn|uacute|ugrave|yacute|AElig|Acirc|Aring|Ecirc|Icirc|Ocirc|THORN|Ucirc|acirc|acute|aelig|aring|cedil|ecirc|icirc|iexcl|laquo|micro|ocirc|pound|raquo|szlig|thorn|times|ucirc|Auml|COPY|Euml|Iuml|Ouml|QUOT|Uuml|auml|cent|copy|euml|iuml|macr|nbsp|ordf|ordm|ouml|para|quot|sect|sup1|sup2|sup3|uuml|yuml|AMP|ETH|REG|amp|deg|eth|not|reg|shy|uml|yen|GT|LT|gt|lt)(?!;)([=a-zA-Z0-9]?)|&#([0-9]+)(;?)|&#[xX]([a-fA-F0-9]+)(;?)|&([0-9a-zA-Z]+)/g; - var decodeMap = {'aacute':'\xE1','Aacute':'\xC1','abreve':'\u0103','Abreve':'\u0102','ac':'\u223E','acd':'\u223F','acE':'\u223E\u0333','acirc':'\xE2','Acirc':'\xC2','acute':'\xB4','acy':'\u0430','Acy':'\u0410','aelig':'\xE6','AElig':'\xC6','af':'\u2061','afr':'\uD835\uDD1E','Afr':'\uD835\uDD04','agrave':'\xE0','Agrave':'\xC0','alefsym':'\u2135','aleph':'\u2135','alpha':'\u03B1','Alpha':'\u0391','amacr':'\u0101','Amacr':'\u0100','amalg':'\u2A3F','amp':'&','AMP':'&','and':'\u2227','And':'\u2A53','andand':'\u2A55','andd':'\u2A5C','andslope':'\u2A58','andv':'\u2A5A','ang':'\u2220','ange':'\u29A4','angle':'\u2220','angmsd':'\u2221','angmsdaa':'\u29A8','angmsdab':'\u29A9','angmsdac':'\u29AA','angmsdad':'\u29AB','angmsdae':'\u29AC','angmsdaf':'\u29AD','angmsdag':'\u29AE','angmsdah':'\u29AF','angrt':'\u221F','angrtvb':'\u22BE','angrtvbd':'\u299D','angsph':'\u2222','angst':'\xC5','angzarr':'\u237C','aogon':'\u0105','Aogon':'\u0104','aopf':'\uD835\uDD52','Aopf':'\uD835\uDD38','ap':'\u2248','apacir':'\u2A6F','ape':'\u224A','apE':'\u2A70','apid':'\u224B','apos':'\'','ApplyFunction':'\u2061','approx':'\u2248','approxeq':'\u224A','aring':'\xE5','Aring':'\xC5','ascr':'\uD835\uDCB6','Ascr':'\uD835\uDC9C','Assign':'\u2254','ast':'*','asymp':'\u2248','asympeq':'\u224D','atilde':'\xE3','Atilde':'\xC3','auml':'\xE4','Auml':'\xC4','awconint':'\u2233','awint':'\u2A11','backcong':'\u224C','backepsilon':'\u03F6','backprime':'\u2035','backsim':'\u223D','backsimeq':'\u22CD','Backslash':'\u2216','Barv':'\u2AE7','barvee':'\u22BD','barwed':'\u2305','Barwed':'\u2306','barwedge':'\u2305','bbrk':'\u23B5','bbrktbrk':'\u23B6','bcong':'\u224C','bcy':'\u0431','Bcy':'\u0411','bdquo':'\u201E','becaus':'\u2235','because':'\u2235','Because':'\u2235','bemptyv':'\u29B0','bepsi':'\u03F6','bernou':'\u212C','Bernoullis':'\u212C','beta':'\u03B2','Beta':'\u0392','beth':'\u2136','between':'\u226C','bfr':'\uD835\uDD1F','Bfr':'\uD835\uDD05','bigcap':'\u22C2','bigcirc':'\u25EF','bigcup':'\u22C3','bigodot':'\u2A00','bigoplus':'\u2A01','bigotimes':'\u2A02','bigsqcup':'\u2A06','bigstar':'\u2605','bigtriangledown':'\u25BD','bigtriangleup':'\u25B3','biguplus':'\u2A04','bigvee':'\u22C1','bigwedge':'\u22C0','bkarow':'\u290D','blacklozenge':'\u29EB','blacksquare':'\u25AA','blacktriangle':'\u25B4','blacktriangledown':'\u25BE','blacktriangleleft':'\u25C2','blacktriangleright':'\u25B8','blank':'\u2423','blk12':'\u2592','blk14':'\u2591','blk34':'\u2593','block':'\u2588','bne':'=\u20E5','bnequiv':'\u2261\u20E5','bnot':'\u2310','bNot':'\u2AED','bopf':'\uD835\uDD53','Bopf':'\uD835\uDD39','bot':'\u22A5','bottom':'\u22A5','bowtie':'\u22C8','boxbox':'\u29C9','boxdl':'\u2510','boxdL':'\u2555','boxDl':'\u2556','boxDL':'\u2557','boxdr':'\u250C','boxdR':'\u2552','boxDr':'\u2553','boxDR':'\u2554','boxh':'\u2500','boxH':'\u2550','boxhd':'\u252C','boxhD':'\u2565','boxHd':'\u2564','boxHD':'\u2566','boxhu':'\u2534','boxhU':'\u2568','boxHu':'\u2567','boxHU':'\u2569','boxminus':'\u229F','boxplus':'\u229E','boxtimes':'\u22A0','boxul':'\u2518','boxuL':'\u255B','boxUl':'\u255C','boxUL':'\u255D','boxur':'\u2514','boxuR':'\u2558','boxUr':'\u2559','boxUR':'\u255A','boxv':'\u2502','boxV':'\u2551','boxvh':'\u253C','boxvH':'\u256A','boxVh':'\u256B','boxVH':'\u256C','boxvl':'\u2524','boxvL':'\u2561','boxVl':'\u2562','boxVL':'\u2563','boxvr':'\u251C','boxvR':'\u255E','boxVr':'\u255F','boxVR':'\u2560','bprime':'\u2035','breve':'\u02D8','Breve':'\u02D8','brvbar':'\xA6','bscr':'\uD835\uDCB7','Bscr':'\u212C','bsemi':'\u204F','bsim':'\u223D','bsime':'\u22CD','bsol':'\\','bsolb':'\u29C5','bsolhsub':'\u27C8','bull':'\u2022','bullet':'\u2022','bump':'\u224E','bumpe':'\u224F','bumpE':'\u2AAE','bumpeq':'\u224F','Bumpeq':'\u224E','cacute':'\u0107','Cacute':'\u0106','cap':'\u2229','Cap':'\u22D2','capand':'\u2A44','capbrcup':'\u2A49','capcap':'\u2A4B','capcup':'\u2A47','capdot':'\u2A40','CapitalDifferentialD':'\u2145','caps':'\u2229\uFE00','caret':'\u2041','caron':'\u02C7','Cayleys':'\u212D','ccaps':'\u2A4D','ccaron':'\u010D','Ccaron':'\u010C','ccedil':'\xE7','Ccedil':'\xC7','ccirc':'\u0109','Ccirc':'\u0108','Cconint':'\u2230','ccups':'\u2A4C','ccupssm':'\u2A50','cdot':'\u010B','Cdot':'\u010A','cedil':'\xB8','Cedilla':'\xB8','cemptyv':'\u29B2','cent':'\xA2','centerdot':'\xB7','CenterDot':'\xB7','cfr':'\uD835\uDD20','Cfr':'\u212D','chcy':'\u0447','CHcy':'\u0427','check':'\u2713','checkmark':'\u2713','chi':'\u03C7','Chi':'\u03A7','cir':'\u25CB','circ':'\u02C6','circeq':'\u2257','circlearrowleft':'\u21BA','circlearrowright':'\u21BB','circledast':'\u229B','circledcirc':'\u229A','circleddash':'\u229D','CircleDot':'\u2299','circledR':'\xAE','circledS':'\u24C8','CircleMinus':'\u2296','CirclePlus':'\u2295','CircleTimes':'\u2297','cire':'\u2257','cirE':'\u29C3','cirfnint':'\u2A10','cirmid':'\u2AEF','cirscir':'\u29C2','ClockwiseContourIntegral':'\u2232','CloseCurlyDoubleQuote':'\u201D','CloseCurlyQuote':'\u2019','clubs':'\u2663','clubsuit':'\u2663','colon':':','Colon':'\u2237','colone':'\u2254','Colone':'\u2A74','coloneq':'\u2254','comma':',','commat':'@','comp':'\u2201','compfn':'\u2218','complement':'\u2201','complexes':'\u2102','cong':'\u2245','congdot':'\u2A6D','Congruent':'\u2261','conint':'\u222E','Conint':'\u222F','ContourIntegral':'\u222E','copf':'\uD835\uDD54','Copf':'\u2102','coprod':'\u2210','Coproduct':'\u2210','copy':'\xA9','COPY':'\xA9','copysr':'\u2117','CounterClockwiseContourIntegral':'\u2233','crarr':'\u21B5','cross':'\u2717','Cross':'\u2A2F','cscr':'\uD835\uDCB8','Cscr':'\uD835\uDC9E','csub':'\u2ACF','csube':'\u2AD1','csup':'\u2AD0','csupe':'\u2AD2','ctdot':'\u22EF','cudarrl':'\u2938','cudarrr':'\u2935','cuepr':'\u22DE','cuesc':'\u22DF','cularr':'\u21B6','cularrp':'\u293D','cup':'\u222A','Cup':'\u22D3','cupbrcap':'\u2A48','cupcap':'\u2A46','CupCap':'\u224D','cupcup':'\u2A4A','cupdot':'\u228D','cupor':'\u2A45','cups':'\u222A\uFE00','curarr':'\u21B7','curarrm':'\u293C','curlyeqprec':'\u22DE','curlyeqsucc':'\u22DF','curlyvee':'\u22CE','curlywedge':'\u22CF','curren':'\xA4','curvearrowleft':'\u21B6','curvearrowright':'\u21B7','cuvee':'\u22CE','cuwed':'\u22CF','cwconint':'\u2232','cwint':'\u2231','cylcty':'\u232D','dagger':'\u2020','Dagger':'\u2021','daleth':'\u2138','darr':'\u2193','dArr':'\u21D3','Darr':'\u21A1','dash':'\u2010','dashv':'\u22A3','Dashv':'\u2AE4','dbkarow':'\u290F','dblac':'\u02DD','dcaron':'\u010F','Dcaron':'\u010E','dcy':'\u0434','Dcy':'\u0414','dd':'\u2146','DD':'\u2145','ddagger':'\u2021','ddarr':'\u21CA','DDotrahd':'\u2911','ddotseq':'\u2A77','deg':'\xB0','Del':'\u2207','delta':'\u03B4','Delta':'\u0394','demptyv':'\u29B1','dfisht':'\u297F','dfr':'\uD835\uDD21','Dfr':'\uD835\uDD07','dHar':'\u2965','dharl':'\u21C3','dharr':'\u21C2','DiacriticalAcute':'\xB4','DiacriticalDot':'\u02D9','DiacriticalDoubleAcute':'\u02DD','DiacriticalGrave':'`','DiacriticalTilde':'\u02DC','diam':'\u22C4','diamond':'\u22C4','Diamond':'\u22C4','diamondsuit':'\u2666','diams':'\u2666','die':'\xA8','DifferentialD':'\u2146','digamma':'\u03DD','disin':'\u22F2','div':'\xF7','divide':'\xF7','divideontimes':'\u22C7','divonx':'\u22C7','djcy':'\u0452','DJcy':'\u0402','dlcorn':'\u231E','dlcrop':'\u230D','dollar':'$','dopf':'\uD835\uDD55','Dopf':'\uD835\uDD3B','dot':'\u02D9','Dot':'\xA8','DotDot':'\u20DC','doteq':'\u2250','doteqdot':'\u2251','DotEqual':'\u2250','dotminus':'\u2238','dotplus':'\u2214','dotsquare':'\u22A1','doublebarwedge':'\u2306','DoubleContourIntegral':'\u222F','DoubleDot':'\xA8','DoubleDownArrow':'\u21D3','DoubleLeftArrow':'\u21D0','DoubleLeftRightArrow':'\u21D4','DoubleLeftTee':'\u2AE4','DoubleLongLeftArrow':'\u27F8','DoubleLongLeftRightArrow':'\u27FA','DoubleLongRightArrow':'\u27F9','DoubleRightArrow':'\u21D2','DoubleRightTee':'\u22A8','DoubleUpArrow':'\u21D1','DoubleUpDownArrow':'\u21D5','DoubleVerticalBar':'\u2225','downarrow':'\u2193','Downarrow':'\u21D3','DownArrow':'\u2193','DownArrowBar':'\u2913','DownArrowUpArrow':'\u21F5','DownBreve':'\u0311','downdownarrows':'\u21CA','downharpoonleft':'\u21C3','downharpoonright':'\u21C2','DownLeftRightVector':'\u2950','DownLeftTeeVector':'\u295E','DownLeftVector':'\u21BD','DownLeftVectorBar':'\u2956','DownRightTeeVector':'\u295F','DownRightVector':'\u21C1','DownRightVectorBar':'\u2957','DownTee':'\u22A4','DownTeeArrow':'\u21A7','drbkarow':'\u2910','drcorn':'\u231F','drcrop':'\u230C','dscr':'\uD835\uDCB9','Dscr':'\uD835\uDC9F','dscy':'\u0455','DScy':'\u0405','dsol':'\u29F6','dstrok':'\u0111','Dstrok':'\u0110','dtdot':'\u22F1','dtri':'\u25BF','dtrif':'\u25BE','duarr':'\u21F5','duhar':'\u296F','dwangle':'\u29A6','dzcy':'\u045F','DZcy':'\u040F','dzigrarr':'\u27FF','eacute':'\xE9','Eacute':'\xC9','easter':'\u2A6E','ecaron':'\u011B','Ecaron':'\u011A','ecir':'\u2256','ecirc':'\xEA','Ecirc':'\xCA','ecolon':'\u2255','ecy':'\u044D','Ecy':'\u042D','eDDot':'\u2A77','edot':'\u0117','eDot':'\u2251','Edot':'\u0116','ee':'\u2147','efDot':'\u2252','efr':'\uD835\uDD22','Efr':'\uD835\uDD08','eg':'\u2A9A','egrave':'\xE8','Egrave':'\xC8','egs':'\u2A96','egsdot':'\u2A98','el':'\u2A99','Element':'\u2208','elinters':'\u23E7','ell':'\u2113','els':'\u2A95','elsdot':'\u2A97','emacr':'\u0113','Emacr':'\u0112','empty':'\u2205','emptyset':'\u2205','EmptySmallSquare':'\u25FB','emptyv':'\u2205','EmptyVerySmallSquare':'\u25AB','emsp':'\u2003','emsp13':'\u2004','emsp14':'\u2005','eng':'\u014B','ENG':'\u014A','ensp':'\u2002','eogon':'\u0119','Eogon':'\u0118','eopf':'\uD835\uDD56','Eopf':'\uD835\uDD3C','epar':'\u22D5','eparsl':'\u29E3','eplus':'\u2A71','epsi':'\u03B5','epsilon':'\u03B5','Epsilon':'\u0395','epsiv':'\u03F5','eqcirc':'\u2256','eqcolon':'\u2255','eqsim':'\u2242','eqslantgtr':'\u2A96','eqslantless':'\u2A95','Equal':'\u2A75','equals':'=','EqualTilde':'\u2242','equest':'\u225F','Equilibrium':'\u21CC','equiv':'\u2261','equivDD':'\u2A78','eqvparsl':'\u29E5','erarr':'\u2971','erDot':'\u2253','escr':'\u212F','Escr':'\u2130','esdot':'\u2250','esim':'\u2242','Esim':'\u2A73','eta':'\u03B7','Eta':'\u0397','eth':'\xF0','ETH':'\xD0','euml':'\xEB','Euml':'\xCB','euro':'\u20AC','excl':'!','exist':'\u2203','Exists':'\u2203','expectation':'\u2130','exponentiale':'\u2147','ExponentialE':'\u2147','fallingdotseq':'\u2252','fcy':'\u0444','Fcy':'\u0424','female':'\u2640','ffilig':'\uFB03','fflig':'\uFB00','ffllig':'\uFB04','ffr':'\uD835\uDD23','Ffr':'\uD835\uDD09','filig':'\uFB01','FilledSmallSquare':'\u25FC','FilledVerySmallSquare':'\u25AA','fjlig':'fj','flat':'\u266D','fllig':'\uFB02','fltns':'\u25B1','fnof':'\u0192','fopf':'\uD835\uDD57','Fopf':'\uD835\uDD3D','forall':'\u2200','ForAll':'\u2200','fork':'\u22D4','forkv':'\u2AD9','Fouriertrf':'\u2131','fpartint':'\u2A0D','frac12':'\xBD','frac13':'\u2153','frac14':'\xBC','frac15':'\u2155','frac16':'\u2159','frac18':'\u215B','frac23':'\u2154','frac25':'\u2156','frac34':'\xBE','frac35':'\u2157','frac38':'\u215C','frac45':'\u2158','frac56':'\u215A','frac58':'\u215D','frac78':'\u215E','frasl':'\u2044','frown':'\u2322','fscr':'\uD835\uDCBB','Fscr':'\u2131','gacute':'\u01F5','gamma':'\u03B3','Gamma':'\u0393','gammad':'\u03DD','Gammad':'\u03DC','gap':'\u2A86','gbreve':'\u011F','Gbreve':'\u011E','Gcedil':'\u0122','gcirc':'\u011D','Gcirc':'\u011C','gcy':'\u0433','Gcy':'\u0413','gdot':'\u0121','Gdot':'\u0120','ge':'\u2265','gE':'\u2267','gel':'\u22DB','gEl':'\u2A8C','geq':'\u2265','geqq':'\u2267','geqslant':'\u2A7E','ges':'\u2A7E','gescc':'\u2AA9','gesdot':'\u2A80','gesdoto':'\u2A82','gesdotol':'\u2A84','gesl':'\u22DB\uFE00','gesles':'\u2A94','gfr':'\uD835\uDD24','Gfr':'\uD835\uDD0A','gg':'\u226B','Gg':'\u22D9','ggg':'\u22D9','gimel':'\u2137','gjcy':'\u0453','GJcy':'\u0403','gl':'\u2277','gla':'\u2AA5','glE':'\u2A92','glj':'\u2AA4','gnap':'\u2A8A','gnapprox':'\u2A8A','gne':'\u2A88','gnE':'\u2269','gneq':'\u2A88','gneqq':'\u2269','gnsim':'\u22E7','gopf':'\uD835\uDD58','Gopf':'\uD835\uDD3E','grave':'`','GreaterEqual':'\u2265','GreaterEqualLess':'\u22DB','GreaterFullEqual':'\u2267','GreaterGreater':'\u2AA2','GreaterLess':'\u2277','GreaterSlantEqual':'\u2A7E','GreaterTilde':'\u2273','gscr':'\u210A','Gscr':'\uD835\uDCA2','gsim':'\u2273','gsime':'\u2A8E','gsiml':'\u2A90','gt':'>','Gt':'\u226B','GT':'>','gtcc':'\u2AA7','gtcir':'\u2A7A','gtdot':'\u22D7','gtlPar':'\u2995','gtquest':'\u2A7C','gtrapprox':'\u2A86','gtrarr':'\u2978','gtrdot':'\u22D7','gtreqless':'\u22DB','gtreqqless':'\u2A8C','gtrless':'\u2277','gtrsim':'\u2273','gvertneqq':'\u2269\uFE00','gvnE':'\u2269\uFE00','Hacek':'\u02C7','hairsp':'\u200A','half':'\xBD','hamilt':'\u210B','hardcy':'\u044A','HARDcy':'\u042A','harr':'\u2194','hArr':'\u21D4','harrcir':'\u2948','harrw':'\u21AD','Hat':'^','hbar':'\u210F','hcirc':'\u0125','Hcirc':'\u0124','hearts':'\u2665','heartsuit':'\u2665','hellip':'\u2026','hercon':'\u22B9','hfr':'\uD835\uDD25','Hfr':'\u210C','HilbertSpace':'\u210B','hksearow':'\u2925','hkswarow':'\u2926','hoarr':'\u21FF','homtht':'\u223B','hookleftarrow':'\u21A9','hookrightarrow':'\u21AA','hopf':'\uD835\uDD59','Hopf':'\u210D','horbar':'\u2015','HorizontalLine':'\u2500','hscr':'\uD835\uDCBD','Hscr':'\u210B','hslash':'\u210F','hstrok':'\u0127','Hstrok':'\u0126','HumpDownHump':'\u224E','HumpEqual':'\u224F','hybull':'\u2043','hyphen':'\u2010','iacute':'\xED','Iacute':'\xCD','ic':'\u2063','icirc':'\xEE','Icirc':'\xCE','icy':'\u0438','Icy':'\u0418','Idot':'\u0130','iecy':'\u0435','IEcy':'\u0415','iexcl':'\xA1','iff':'\u21D4','ifr':'\uD835\uDD26','Ifr':'\u2111','igrave':'\xEC','Igrave':'\xCC','ii':'\u2148','iiiint':'\u2A0C','iiint':'\u222D','iinfin':'\u29DC','iiota':'\u2129','ijlig':'\u0133','IJlig':'\u0132','Im':'\u2111','imacr':'\u012B','Imacr':'\u012A','image':'\u2111','ImaginaryI':'\u2148','imagline':'\u2110','imagpart':'\u2111','imath':'\u0131','imof':'\u22B7','imped':'\u01B5','Implies':'\u21D2','in':'\u2208','incare':'\u2105','infin':'\u221E','infintie':'\u29DD','inodot':'\u0131','int':'\u222B','Int':'\u222C','intcal':'\u22BA','integers':'\u2124','Integral':'\u222B','intercal':'\u22BA','Intersection':'\u22C2','intlarhk':'\u2A17','intprod':'\u2A3C','InvisibleComma':'\u2063','InvisibleTimes':'\u2062','iocy':'\u0451','IOcy':'\u0401','iogon':'\u012F','Iogon':'\u012E','iopf':'\uD835\uDD5A','Iopf':'\uD835\uDD40','iota':'\u03B9','Iota':'\u0399','iprod':'\u2A3C','iquest':'\xBF','iscr':'\uD835\uDCBE','Iscr':'\u2110','isin':'\u2208','isindot':'\u22F5','isinE':'\u22F9','isins':'\u22F4','isinsv':'\u22F3','isinv':'\u2208','it':'\u2062','itilde':'\u0129','Itilde':'\u0128','iukcy':'\u0456','Iukcy':'\u0406','iuml':'\xEF','Iuml':'\xCF','jcirc':'\u0135','Jcirc':'\u0134','jcy':'\u0439','Jcy':'\u0419','jfr':'\uD835\uDD27','Jfr':'\uD835\uDD0D','jmath':'\u0237','jopf':'\uD835\uDD5B','Jopf':'\uD835\uDD41','jscr':'\uD835\uDCBF','Jscr':'\uD835\uDCA5','jsercy':'\u0458','Jsercy':'\u0408','jukcy':'\u0454','Jukcy':'\u0404','kappa':'\u03BA','Kappa':'\u039A','kappav':'\u03F0','kcedil':'\u0137','Kcedil':'\u0136','kcy':'\u043A','Kcy':'\u041A','kfr':'\uD835\uDD28','Kfr':'\uD835\uDD0E','kgreen':'\u0138','khcy':'\u0445','KHcy':'\u0425','kjcy':'\u045C','KJcy':'\u040C','kopf':'\uD835\uDD5C','Kopf':'\uD835\uDD42','kscr':'\uD835\uDCC0','Kscr':'\uD835\uDCA6','lAarr':'\u21DA','lacute':'\u013A','Lacute':'\u0139','laemptyv':'\u29B4','lagran':'\u2112','lambda':'\u03BB','Lambda':'\u039B','lang':'\u27E8','Lang':'\u27EA','langd':'\u2991','langle':'\u27E8','lap':'\u2A85','Laplacetrf':'\u2112','laquo':'\xAB','larr':'\u2190','lArr':'\u21D0','Larr':'\u219E','larrb':'\u21E4','larrbfs':'\u291F','larrfs':'\u291D','larrhk':'\u21A9','larrlp':'\u21AB','larrpl':'\u2939','larrsim':'\u2973','larrtl':'\u21A2','lat':'\u2AAB','latail':'\u2919','lAtail':'\u291B','late':'\u2AAD','lates':'\u2AAD\uFE00','lbarr':'\u290C','lBarr':'\u290E','lbbrk':'\u2772','lbrace':'{','lbrack':'[','lbrke':'\u298B','lbrksld':'\u298F','lbrkslu':'\u298D','lcaron':'\u013E','Lcaron':'\u013D','lcedil':'\u013C','Lcedil':'\u013B','lceil':'\u2308','lcub':'{','lcy':'\u043B','Lcy':'\u041B','ldca':'\u2936','ldquo':'\u201C','ldquor':'\u201E','ldrdhar':'\u2967','ldrushar':'\u294B','ldsh':'\u21B2','le':'\u2264','lE':'\u2266','LeftAngleBracket':'\u27E8','leftarrow':'\u2190','Leftarrow':'\u21D0','LeftArrow':'\u2190','LeftArrowBar':'\u21E4','LeftArrowRightArrow':'\u21C6','leftarrowtail':'\u21A2','LeftCeiling':'\u2308','LeftDoubleBracket':'\u27E6','LeftDownTeeVector':'\u2961','LeftDownVector':'\u21C3','LeftDownVectorBar':'\u2959','LeftFloor':'\u230A','leftharpoondown':'\u21BD','leftharpoonup':'\u21BC','leftleftarrows':'\u21C7','leftrightarrow':'\u2194','Leftrightarrow':'\u21D4','LeftRightArrow':'\u2194','leftrightarrows':'\u21C6','leftrightharpoons':'\u21CB','leftrightsquigarrow':'\u21AD','LeftRightVector':'\u294E','LeftTee':'\u22A3','LeftTeeArrow':'\u21A4','LeftTeeVector':'\u295A','leftthreetimes':'\u22CB','LeftTriangle':'\u22B2','LeftTriangleBar':'\u29CF','LeftTriangleEqual':'\u22B4','LeftUpDownVector':'\u2951','LeftUpTeeVector':'\u2960','LeftUpVector':'\u21BF','LeftUpVectorBar':'\u2958','LeftVector':'\u21BC','LeftVectorBar':'\u2952','leg':'\u22DA','lEg':'\u2A8B','leq':'\u2264','leqq':'\u2266','leqslant':'\u2A7D','les':'\u2A7D','lescc':'\u2AA8','lesdot':'\u2A7F','lesdoto':'\u2A81','lesdotor':'\u2A83','lesg':'\u22DA\uFE00','lesges':'\u2A93','lessapprox':'\u2A85','lessdot':'\u22D6','lesseqgtr':'\u22DA','lesseqqgtr':'\u2A8B','LessEqualGreater':'\u22DA','LessFullEqual':'\u2266','LessGreater':'\u2276','lessgtr':'\u2276','LessLess':'\u2AA1','lesssim':'\u2272','LessSlantEqual':'\u2A7D','LessTilde':'\u2272','lfisht':'\u297C','lfloor':'\u230A','lfr':'\uD835\uDD29','Lfr':'\uD835\uDD0F','lg':'\u2276','lgE':'\u2A91','lHar':'\u2962','lhard':'\u21BD','lharu':'\u21BC','lharul':'\u296A','lhblk':'\u2584','ljcy':'\u0459','LJcy':'\u0409','ll':'\u226A','Ll':'\u22D8','llarr':'\u21C7','llcorner':'\u231E','Lleftarrow':'\u21DA','llhard':'\u296B','lltri':'\u25FA','lmidot':'\u0140','Lmidot':'\u013F','lmoust':'\u23B0','lmoustache':'\u23B0','lnap':'\u2A89','lnapprox':'\u2A89','lne':'\u2A87','lnE':'\u2268','lneq':'\u2A87','lneqq':'\u2268','lnsim':'\u22E6','loang':'\u27EC','loarr':'\u21FD','lobrk':'\u27E6','longleftarrow':'\u27F5','Longleftarrow':'\u27F8','LongLeftArrow':'\u27F5','longleftrightarrow':'\u27F7','Longleftrightarrow':'\u27FA','LongLeftRightArrow':'\u27F7','longmapsto':'\u27FC','longrightarrow':'\u27F6','Longrightarrow':'\u27F9','LongRightArrow':'\u27F6','looparrowleft':'\u21AB','looparrowright':'\u21AC','lopar':'\u2985','lopf':'\uD835\uDD5D','Lopf':'\uD835\uDD43','loplus':'\u2A2D','lotimes':'\u2A34','lowast':'\u2217','lowbar':'_','LowerLeftArrow':'\u2199','LowerRightArrow':'\u2198','loz':'\u25CA','lozenge':'\u25CA','lozf':'\u29EB','lpar':'(','lparlt':'\u2993','lrarr':'\u21C6','lrcorner':'\u231F','lrhar':'\u21CB','lrhard':'\u296D','lrm':'\u200E','lrtri':'\u22BF','lsaquo':'\u2039','lscr':'\uD835\uDCC1','Lscr':'\u2112','lsh':'\u21B0','Lsh':'\u21B0','lsim':'\u2272','lsime':'\u2A8D','lsimg':'\u2A8F','lsqb':'[','lsquo':'\u2018','lsquor':'\u201A','lstrok':'\u0142','Lstrok':'\u0141','lt':'<','Lt':'\u226A','LT':'<','ltcc':'\u2AA6','ltcir':'\u2A79','ltdot':'\u22D6','lthree':'\u22CB','ltimes':'\u22C9','ltlarr':'\u2976','ltquest':'\u2A7B','ltri':'\u25C3','ltrie':'\u22B4','ltrif':'\u25C2','ltrPar':'\u2996','lurdshar':'\u294A','luruhar':'\u2966','lvertneqq':'\u2268\uFE00','lvnE':'\u2268\uFE00','macr':'\xAF','male':'\u2642','malt':'\u2720','maltese':'\u2720','map':'\u21A6','Map':'\u2905','mapsto':'\u21A6','mapstodown':'\u21A7','mapstoleft':'\u21A4','mapstoup':'\u21A5','marker':'\u25AE','mcomma':'\u2A29','mcy':'\u043C','Mcy':'\u041C','mdash':'\u2014','mDDot':'\u223A','measuredangle':'\u2221','MediumSpace':'\u205F','Mellintrf':'\u2133','mfr':'\uD835\uDD2A','Mfr':'\uD835\uDD10','mho':'\u2127','micro':'\xB5','mid':'\u2223','midast':'*','midcir':'\u2AF0','middot':'\xB7','minus':'\u2212','minusb':'\u229F','minusd':'\u2238','minusdu':'\u2A2A','MinusPlus':'\u2213','mlcp':'\u2ADB','mldr':'\u2026','mnplus':'\u2213','models':'\u22A7','mopf':'\uD835\uDD5E','Mopf':'\uD835\uDD44','mp':'\u2213','mscr':'\uD835\uDCC2','Mscr':'\u2133','mstpos':'\u223E','mu':'\u03BC','Mu':'\u039C','multimap':'\u22B8','mumap':'\u22B8','nabla':'\u2207','nacute':'\u0144','Nacute':'\u0143','nang':'\u2220\u20D2','nap':'\u2249','napE':'\u2A70\u0338','napid':'\u224B\u0338','napos':'\u0149','napprox':'\u2249','natur':'\u266E','natural':'\u266E','naturals':'\u2115','nbsp':'\xA0','nbump':'\u224E\u0338','nbumpe':'\u224F\u0338','ncap':'\u2A43','ncaron':'\u0148','Ncaron':'\u0147','ncedil':'\u0146','Ncedil':'\u0145','ncong':'\u2247','ncongdot':'\u2A6D\u0338','ncup':'\u2A42','ncy':'\u043D','Ncy':'\u041D','ndash':'\u2013','ne':'\u2260','nearhk':'\u2924','nearr':'\u2197','neArr':'\u21D7','nearrow':'\u2197','nedot':'\u2250\u0338','NegativeMediumSpace':'\u200B','NegativeThickSpace':'\u200B','NegativeThinSpace':'\u200B','NegativeVeryThinSpace':'\u200B','nequiv':'\u2262','nesear':'\u2928','nesim':'\u2242\u0338','NestedGreaterGreater':'\u226B','NestedLessLess':'\u226A','NewLine':'\n','nexist':'\u2204','nexists':'\u2204','nfr':'\uD835\uDD2B','Nfr':'\uD835\uDD11','nge':'\u2271','ngE':'\u2267\u0338','ngeq':'\u2271','ngeqq':'\u2267\u0338','ngeqslant':'\u2A7E\u0338','nges':'\u2A7E\u0338','nGg':'\u22D9\u0338','ngsim':'\u2275','ngt':'\u226F','nGt':'\u226B\u20D2','ngtr':'\u226F','nGtv':'\u226B\u0338','nharr':'\u21AE','nhArr':'\u21CE','nhpar':'\u2AF2','ni':'\u220B','nis':'\u22FC','nisd':'\u22FA','niv':'\u220B','njcy':'\u045A','NJcy':'\u040A','nlarr':'\u219A','nlArr':'\u21CD','nldr':'\u2025','nle':'\u2270','nlE':'\u2266\u0338','nleftarrow':'\u219A','nLeftarrow':'\u21CD','nleftrightarrow':'\u21AE','nLeftrightarrow':'\u21CE','nleq':'\u2270','nleqq':'\u2266\u0338','nleqslant':'\u2A7D\u0338','nles':'\u2A7D\u0338','nless':'\u226E','nLl':'\u22D8\u0338','nlsim':'\u2274','nlt':'\u226E','nLt':'\u226A\u20D2','nltri':'\u22EA','nltrie':'\u22EC','nLtv':'\u226A\u0338','nmid':'\u2224','NoBreak':'\u2060','NonBreakingSpace':'\xA0','nopf':'\uD835\uDD5F','Nopf':'\u2115','not':'\xAC','Not':'\u2AEC','NotCongruent':'\u2262','NotCupCap':'\u226D','NotDoubleVerticalBar':'\u2226','NotElement':'\u2209','NotEqual':'\u2260','NotEqualTilde':'\u2242\u0338','NotExists':'\u2204','NotGreater':'\u226F','NotGreaterEqual':'\u2271','NotGreaterFullEqual':'\u2267\u0338','NotGreaterGreater':'\u226B\u0338','NotGreaterLess':'\u2279','NotGreaterSlantEqual':'\u2A7E\u0338','NotGreaterTilde':'\u2275','NotHumpDownHump':'\u224E\u0338','NotHumpEqual':'\u224F\u0338','notin':'\u2209','notindot':'\u22F5\u0338','notinE':'\u22F9\u0338','notinva':'\u2209','notinvb':'\u22F7','notinvc':'\u22F6','NotLeftTriangle':'\u22EA','NotLeftTriangleBar':'\u29CF\u0338','NotLeftTriangleEqual':'\u22EC','NotLess':'\u226E','NotLessEqual':'\u2270','NotLessGreater':'\u2278','NotLessLess':'\u226A\u0338','NotLessSlantEqual':'\u2A7D\u0338','NotLessTilde':'\u2274','NotNestedGreaterGreater':'\u2AA2\u0338','NotNestedLessLess':'\u2AA1\u0338','notni':'\u220C','notniva':'\u220C','notnivb':'\u22FE','notnivc':'\u22FD','NotPrecedes':'\u2280','NotPrecedesEqual':'\u2AAF\u0338','NotPrecedesSlantEqual':'\u22E0','NotReverseElement':'\u220C','NotRightTriangle':'\u22EB','NotRightTriangleBar':'\u29D0\u0338','NotRightTriangleEqual':'\u22ED','NotSquareSubset':'\u228F\u0338','NotSquareSubsetEqual':'\u22E2','NotSquareSuperset':'\u2290\u0338','NotSquareSupersetEqual':'\u22E3','NotSubset':'\u2282\u20D2','NotSubsetEqual':'\u2288','NotSucceeds':'\u2281','NotSucceedsEqual':'\u2AB0\u0338','NotSucceedsSlantEqual':'\u22E1','NotSucceedsTilde':'\u227F\u0338','NotSuperset':'\u2283\u20D2','NotSupersetEqual':'\u2289','NotTilde':'\u2241','NotTildeEqual':'\u2244','NotTildeFullEqual':'\u2247','NotTildeTilde':'\u2249','NotVerticalBar':'\u2224','npar':'\u2226','nparallel':'\u2226','nparsl':'\u2AFD\u20E5','npart':'\u2202\u0338','npolint':'\u2A14','npr':'\u2280','nprcue':'\u22E0','npre':'\u2AAF\u0338','nprec':'\u2280','npreceq':'\u2AAF\u0338','nrarr':'\u219B','nrArr':'\u21CF','nrarrc':'\u2933\u0338','nrarrw':'\u219D\u0338','nrightarrow':'\u219B','nRightarrow':'\u21CF','nrtri':'\u22EB','nrtrie':'\u22ED','nsc':'\u2281','nsccue':'\u22E1','nsce':'\u2AB0\u0338','nscr':'\uD835\uDCC3','Nscr':'\uD835\uDCA9','nshortmid':'\u2224','nshortparallel':'\u2226','nsim':'\u2241','nsime':'\u2244','nsimeq':'\u2244','nsmid':'\u2224','nspar':'\u2226','nsqsube':'\u22E2','nsqsupe':'\u22E3','nsub':'\u2284','nsube':'\u2288','nsubE':'\u2AC5\u0338','nsubset':'\u2282\u20D2','nsubseteq':'\u2288','nsubseteqq':'\u2AC5\u0338','nsucc':'\u2281','nsucceq':'\u2AB0\u0338','nsup':'\u2285','nsupe':'\u2289','nsupE':'\u2AC6\u0338','nsupset':'\u2283\u20D2','nsupseteq':'\u2289','nsupseteqq':'\u2AC6\u0338','ntgl':'\u2279','ntilde':'\xF1','Ntilde':'\xD1','ntlg':'\u2278','ntriangleleft':'\u22EA','ntrianglelefteq':'\u22EC','ntriangleright':'\u22EB','ntrianglerighteq':'\u22ED','nu':'\u03BD','Nu':'\u039D','num':'#','numero':'\u2116','numsp':'\u2007','nvap':'\u224D\u20D2','nvdash':'\u22AC','nvDash':'\u22AD','nVdash':'\u22AE','nVDash':'\u22AF','nvge':'\u2265\u20D2','nvgt':'>\u20D2','nvHarr':'\u2904','nvinfin':'\u29DE','nvlArr':'\u2902','nvle':'\u2264\u20D2','nvlt':'<\u20D2','nvltrie':'\u22B4\u20D2','nvrArr':'\u2903','nvrtrie':'\u22B5\u20D2','nvsim':'\u223C\u20D2','nwarhk':'\u2923','nwarr':'\u2196','nwArr':'\u21D6','nwarrow':'\u2196','nwnear':'\u2927','oacute':'\xF3','Oacute':'\xD3','oast':'\u229B','ocir':'\u229A','ocirc':'\xF4','Ocirc':'\xD4','ocy':'\u043E','Ocy':'\u041E','odash':'\u229D','odblac':'\u0151','Odblac':'\u0150','odiv':'\u2A38','odot':'\u2299','odsold':'\u29BC','oelig':'\u0153','OElig':'\u0152','ofcir':'\u29BF','ofr':'\uD835\uDD2C','Ofr':'\uD835\uDD12','ogon':'\u02DB','ograve':'\xF2','Ograve':'\xD2','ogt':'\u29C1','ohbar':'\u29B5','ohm':'\u03A9','oint':'\u222E','olarr':'\u21BA','olcir':'\u29BE','olcross':'\u29BB','oline':'\u203E','olt':'\u29C0','omacr':'\u014D','Omacr':'\u014C','omega':'\u03C9','Omega':'\u03A9','omicron':'\u03BF','Omicron':'\u039F','omid':'\u29B6','ominus':'\u2296','oopf':'\uD835\uDD60','Oopf':'\uD835\uDD46','opar':'\u29B7','OpenCurlyDoubleQuote':'\u201C','OpenCurlyQuote':'\u2018','operp':'\u29B9','oplus':'\u2295','or':'\u2228','Or':'\u2A54','orarr':'\u21BB','ord':'\u2A5D','order':'\u2134','orderof':'\u2134','ordf':'\xAA','ordm':'\xBA','origof':'\u22B6','oror':'\u2A56','orslope':'\u2A57','orv':'\u2A5B','oS':'\u24C8','oscr':'\u2134','Oscr':'\uD835\uDCAA','oslash':'\xF8','Oslash':'\xD8','osol':'\u2298','otilde':'\xF5','Otilde':'\xD5','otimes':'\u2297','Otimes':'\u2A37','otimesas':'\u2A36','ouml':'\xF6','Ouml':'\xD6','ovbar':'\u233D','OverBar':'\u203E','OverBrace':'\u23DE','OverBracket':'\u23B4','OverParenthesis':'\u23DC','par':'\u2225','para':'\xB6','parallel':'\u2225','parsim':'\u2AF3','parsl':'\u2AFD','part':'\u2202','PartialD':'\u2202','pcy':'\u043F','Pcy':'\u041F','percnt':'%','period':'.','permil':'\u2030','perp':'\u22A5','pertenk':'\u2031','pfr':'\uD835\uDD2D','Pfr':'\uD835\uDD13','phi':'\u03C6','Phi':'\u03A6','phiv':'\u03D5','phmmat':'\u2133','phone':'\u260E','pi':'\u03C0','Pi':'\u03A0','pitchfork':'\u22D4','piv':'\u03D6','planck':'\u210F','planckh':'\u210E','plankv':'\u210F','plus':'+','plusacir':'\u2A23','plusb':'\u229E','pluscir':'\u2A22','plusdo':'\u2214','plusdu':'\u2A25','pluse':'\u2A72','PlusMinus':'\xB1','plusmn':'\xB1','plussim':'\u2A26','plustwo':'\u2A27','pm':'\xB1','Poincareplane':'\u210C','pointint':'\u2A15','popf':'\uD835\uDD61','Popf':'\u2119','pound':'\xA3','pr':'\u227A','Pr':'\u2ABB','prap':'\u2AB7','prcue':'\u227C','pre':'\u2AAF','prE':'\u2AB3','prec':'\u227A','precapprox':'\u2AB7','preccurlyeq':'\u227C','Precedes':'\u227A','PrecedesEqual':'\u2AAF','PrecedesSlantEqual':'\u227C','PrecedesTilde':'\u227E','preceq':'\u2AAF','precnapprox':'\u2AB9','precneqq':'\u2AB5','precnsim':'\u22E8','precsim':'\u227E','prime':'\u2032','Prime':'\u2033','primes':'\u2119','prnap':'\u2AB9','prnE':'\u2AB5','prnsim':'\u22E8','prod':'\u220F','Product':'\u220F','profalar':'\u232E','profline':'\u2312','profsurf':'\u2313','prop':'\u221D','Proportion':'\u2237','Proportional':'\u221D','propto':'\u221D','prsim':'\u227E','prurel':'\u22B0','pscr':'\uD835\uDCC5','Pscr':'\uD835\uDCAB','psi':'\u03C8','Psi':'\u03A8','puncsp':'\u2008','qfr':'\uD835\uDD2E','Qfr':'\uD835\uDD14','qint':'\u2A0C','qopf':'\uD835\uDD62','Qopf':'\u211A','qprime':'\u2057','qscr':'\uD835\uDCC6','Qscr':'\uD835\uDCAC','quaternions':'\u210D','quatint':'\u2A16','quest':'?','questeq':'\u225F','quot':'"','QUOT':'"','rAarr':'\u21DB','race':'\u223D\u0331','racute':'\u0155','Racute':'\u0154','radic':'\u221A','raemptyv':'\u29B3','rang':'\u27E9','Rang':'\u27EB','rangd':'\u2992','range':'\u29A5','rangle':'\u27E9','raquo':'\xBB','rarr':'\u2192','rArr':'\u21D2','Rarr':'\u21A0','rarrap':'\u2975','rarrb':'\u21E5','rarrbfs':'\u2920','rarrc':'\u2933','rarrfs':'\u291E','rarrhk':'\u21AA','rarrlp':'\u21AC','rarrpl':'\u2945','rarrsim':'\u2974','rarrtl':'\u21A3','Rarrtl':'\u2916','rarrw':'\u219D','ratail':'\u291A','rAtail':'\u291C','ratio':'\u2236','rationals':'\u211A','rbarr':'\u290D','rBarr':'\u290F','RBarr':'\u2910','rbbrk':'\u2773','rbrace':'}','rbrack':']','rbrke':'\u298C','rbrksld':'\u298E','rbrkslu':'\u2990','rcaron':'\u0159','Rcaron':'\u0158','rcedil':'\u0157','Rcedil':'\u0156','rceil':'\u2309','rcub':'}','rcy':'\u0440','Rcy':'\u0420','rdca':'\u2937','rdldhar':'\u2969','rdquo':'\u201D','rdquor':'\u201D','rdsh':'\u21B3','Re':'\u211C','real':'\u211C','realine':'\u211B','realpart':'\u211C','reals':'\u211D','rect':'\u25AD','reg':'\xAE','REG':'\xAE','ReverseElement':'\u220B','ReverseEquilibrium':'\u21CB','ReverseUpEquilibrium':'\u296F','rfisht':'\u297D','rfloor':'\u230B','rfr':'\uD835\uDD2F','Rfr':'\u211C','rHar':'\u2964','rhard':'\u21C1','rharu':'\u21C0','rharul':'\u296C','rho':'\u03C1','Rho':'\u03A1','rhov':'\u03F1','RightAngleBracket':'\u27E9','rightarrow':'\u2192','Rightarrow':'\u21D2','RightArrow':'\u2192','RightArrowBar':'\u21E5','RightArrowLeftArrow':'\u21C4','rightarrowtail':'\u21A3','RightCeiling':'\u2309','RightDoubleBracket':'\u27E7','RightDownTeeVector':'\u295D','RightDownVector':'\u21C2','RightDownVectorBar':'\u2955','RightFloor':'\u230B','rightharpoondown':'\u21C1','rightharpoonup':'\u21C0','rightleftarrows':'\u21C4','rightleftharpoons':'\u21CC','rightrightarrows':'\u21C9','rightsquigarrow':'\u219D','RightTee':'\u22A2','RightTeeArrow':'\u21A6','RightTeeVector':'\u295B','rightthreetimes':'\u22CC','RightTriangle':'\u22B3','RightTriangleBar':'\u29D0','RightTriangleEqual':'\u22B5','RightUpDownVector':'\u294F','RightUpTeeVector':'\u295C','RightUpVector':'\u21BE','RightUpVectorBar':'\u2954','RightVector':'\u21C0','RightVectorBar':'\u2953','ring':'\u02DA','risingdotseq':'\u2253','rlarr':'\u21C4','rlhar':'\u21CC','rlm':'\u200F','rmoust':'\u23B1','rmoustache':'\u23B1','rnmid':'\u2AEE','roang':'\u27ED','roarr':'\u21FE','robrk':'\u27E7','ropar':'\u2986','ropf':'\uD835\uDD63','Ropf':'\u211D','roplus':'\u2A2E','rotimes':'\u2A35','RoundImplies':'\u2970','rpar':')','rpargt':'\u2994','rppolint':'\u2A12','rrarr':'\u21C9','Rrightarrow':'\u21DB','rsaquo':'\u203A','rscr':'\uD835\uDCC7','Rscr':'\u211B','rsh':'\u21B1','Rsh':'\u21B1','rsqb':']','rsquo':'\u2019','rsquor':'\u2019','rthree':'\u22CC','rtimes':'\u22CA','rtri':'\u25B9','rtrie':'\u22B5','rtrif':'\u25B8','rtriltri':'\u29CE','RuleDelayed':'\u29F4','ruluhar':'\u2968','rx':'\u211E','sacute':'\u015B','Sacute':'\u015A','sbquo':'\u201A','sc':'\u227B','Sc':'\u2ABC','scap':'\u2AB8','scaron':'\u0161','Scaron':'\u0160','sccue':'\u227D','sce':'\u2AB0','scE':'\u2AB4','scedil':'\u015F','Scedil':'\u015E','scirc':'\u015D','Scirc':'\u015C','scnap':'\u2ABA','scnE':'\u2AB6','scnsim':'\u22E9','scpolint':'\u2A13','scsim':'\u227F','scy':'\u0441','Scy':'\u0421','sdot':'\u22C5','sdotb':'\u22A1','sdote':'\u2A66','searhk':'\u2925','searr':'\u2198','seArr':'\u21D8','searrow':'\u2198','sect':'\xA7','semi':';','seswar':'\u2929','setminus':'\u2216','setmn':'\u2216','sext':'\u2736','sfr':'\uD835\uDD30','Sfr':'\uD835\uDD16','sfrown':'\u2322','sharp':'\u266F','shchcy':'\u0449','SHCHcy':'\u0429','shcy':'\u0448','SHcy':'\u0428','ShortDownArrow':'\u2193','ShortLeftArrow':'\u2190','shortmid':'\u2223','shortparallel':'\u2225','ShortRightArrow':'\u2192','ShortUpArrow':'\u2191','shy':'\xAD','sigma':'\u03C3','Sigma':'\u03A3','sigmaf':'\u03C2','sigmav':'\u03C2','sim':'\u223C','simdot':'\u2A6A','sime':'\u2243','simeq':'\u2243','simg':'\u2A9E','simgE':'\u2AA0','siml':'\u2A9D','simlE':'\u2A9F','simne':'\u2246','simplus':'\u2A24','simrarr':'\u2972','slarr':'\u2190','SmallCircle':'\u2218','smallsetminus':'\u2216','smashp':'\u2A33','smeparsl':'\u29E4','smid':'\u2223','smile':'\u2323','smt':'\u2AAA','smte':'\u2AAC','smtes':'\u2AAC\uFE00','softcy':'\u044C','SOFTcy':'\u042C','sol':'/','solb':'\u29C4','solbar':'\u233F','sopf':'\uD835\uDD64','Sopf':'\uD835\uDD4A','spades':'\u2660','spadesuit':'\u2660','spar':'\u2225','sqcap':'\u2293','sqcaps':'\u2293\uFE00','sqcup':'\u2294','sqcups':'\u2294\uFE00','Sqrt':'\u221A','sqsub':'\u228F','sqsube':'\u2291','sqsubset':'\u228F','sqsubseteq':'\u2291','sqsup':'\u2290','sqsupe':'\u2292','sqsupset':'\u2290','sqsupseteq':'\u2292','squ':'\u25A1','square':'\u25A1','Square':'\u25A1','SquareIntersection':'\u2293','SquareSubset':'\u228F','SquareSubsetEqual':'\u2291','SquareSuperset':'\u2290','SquareSupersetEqual':'\u2292','SquareUnion':'\u2294','squarf':'\u25AA','squf':'\u25AA','srarr':'\u2192','sscr':'\uD835\uDCC8','Sscr':'\uD835\uDCAE','ssetmn':'\u2216','ssmile':'\u2323','sstarf':'\u22C6','star':'\u2606','Star':'\u22C6','starf':'\u2605','straightepsilon':'\u03F5','straightphi':'\u03D5','strns':'\xAF','sub':'\u2282','Sub':'\u22D0','subdot':'\u2ABD','sube':'\u2286','subE':'\u2AC5','subedot':'\u2AC3','submult':'\u2AC1','subne':'\u228A','subnE':'\u2ACB','subplus':'\u2ABF','subrarr':'\u2979','subset':'\u2282','Subset':'\u22D0','subseteq':'\u2286','subseteqq':'\u2AC5','SubsetEqual':'\u2286','subsetneq':'\u228A','subsetneqq':'\u2ACB','subsim':'\u2AC7','subsub':'\u2AD5','subsup':'\u2AD3','succ':'\u227B','succapprox':'\u2AB8','succcurlyeq':'\u227D','Succeeds':'\u227B','SucceedsEqual':'\u2AB0','SucceedsSlantEqual':'\u227D','SucceedsTilde':'\u227F','succeq':'\u2AB0','succnapprox':'\u2ABA','succneqq':'\u2AB6','succnsim':'\u22E9','succsim':'\u227F','SuchThat':'\u220B','sum':'\u2211','Sum':'\u2211','sung':'\u266A','sup':'\u2283','Sup':'\u22D1','sup1':'\xB9','sup2':'\xB2','sup3':'\xB3','supdot':'\u2ABE','supdsub':'\u2AD8','supe':'\u2287','supE':'\u2AC6','supedot':'\u2AC4','Superset':'\u2283','SupersetEqual':'\u2287','suphsol':'\u27C9','suphsub':'\u2AD7','suplarr':'\u297B','supmult':'\u2AC2','supne':'\u228B','supnE':'\u2ACC','supplus':'\u2AC0','supset':'\u2283','Supset':'\u22D1','supseteq':'\u2287','supseteqq':'\u2AC6','supsetneq':'\u228B','supsetneqq':'\u2ACC','supsim':'\u2AC8','supsub':'\u2AD4','supsup':'\u2AD6','swarhk':'\u2926','swarr':'\u2199','swArr':'\u21D9','swarrow':'\u2199','swnwar':'\u292A','szlig':'\xDF','Tab':'\t','target':'\u2316','tau':'\u03C4','Tau':'\u03A4','tbrk':'\u23B4','tcaron':'\u0165','Tcaron':'\u0164','tcedil':'\u0163','Tcedil':'\u0162','tcy':'\u0442','Tcy':'\u0422','tdot':'\u20DB','telrec':'\u2315','tfr':'\uD835\uDD31','Tfr':'\uD835\uDD17','there4':'\u2234','therefore':'\u2234','Therefore':'\u2234','theta':'\u03B8','Theta':'\u0398','thetasym':'\u03D1','thetav':'\u03D1','thickapprox':'\u2248','thicksim':'\u223C','ThickSpace':'\u205F\u200A','thinsp':'\u2009','ThinSpace':'\u2009','thkap':'\u2248','thksim':'\u223C','thorn':'\xFE','THORN':'\xDE','tilde':'\u02DC','Tilde':'\u223C','TildeEqual':'\u2243','TildeFullEqual':'\u2245','TildeTilde':'\u2248','times':'\xD7','timesb':'\u22A0','timesbar':'\u2A31','timesd':'\u2A30','tint':'\u222D','toea':'\u2928','top':'\u22A4','topbot':'\u2336','topcir':'\u2AF1','topf':'\uD835\uDD65','Topf':'\uD835\uDD4B','topfork':'\u2ADA','tosa':'\u2929','tprime':'\u2034','trade':'\u2122','TRADE':'\u2122','triangle':'\u25B5','triangledown':'\u25BF','triangleleft':'\u25C3','trianglelefteq':'\u22B4','triangleq':'\u225C','triangleright':'\u25B9','trianglerighteq':'\u22B5','tridot':'\u25EC','trie':'\u225C','triminus':'\u2A3A','TripleDot':'\u20DB','triplus':'\u2A39','trisb':'\u29CD','tritime':'\u2A3B','trpezium':'\u23E2','tscr':'\uD835\uDCC9','Tscr':'\uD835\uDCAF','tscy':'\u0446','TScy':'\u0426','tshcy':'\u045B','TSHcy':'\u040B','tstrok':'\u0167','Tstrok':'\u0166','twixt':'\u226C','twoheadleftarrow':'\u219E','twoheadrightarrow':'\u21A0','uacute':'\xFA','Uacute':'\xDA','uarr':'\u2191','uArr':'\u21D1','Uarr':'\u219F','Uarrocir':'\u2949','ubrcy':'\u045E','Ubrcy':'\u040E','ubreve':'\u016D','Ubreve':'\u016C','ucirc':'\xFB','Ucirc':'\xDB','ucy':'\u0443','Ucy':'\u0423','udarr':'\u21C5','udblac':'\u0171','Udblac':'\u0170','udhar':'\u296E','ufisht':'\u297E','ufr':'\uD835\uDD32','Ufr':'\uD835\uDD18','ugrave':'\xF9','Ugrave':'\xD9','uHar':'\u2963','uharl':'\u21BF','uharr':'\u21BE','uhblk':'\u2580','ulcorn':'\u231C','ulcorner':'\u231C','ulcrop':'\u230F','ultri':'\u25F8','umacr':'\u016B','Umacr':'\u016A','uml':'\xA8','UnderBar':'_','UnderBrace':'\u23DF','UnderBracket':'\u23B5','UnderParenthesis':'\u23DD','Union':'\u22C3','UnionPlus':'\u228E','uogon':'\u0173','Uogon':'\u0172','uopf':'\uD835\uDD66','Uopf':'\uD835\uDD4C','uparrow':'\u2191','Uparrow':'\u21D1','UpArrow':'\u2191','UpArrowBar':'\u2912','UpArrowDownArrow':'\u21C5','updownarrow':'\u2195','Updownarrow':'\u21D5','UpDownArrow':'\u2195','UpEquilibrium':'\u296E','upharpoonleft':'\u21BF','upharpoonright':'\u21BE','uplus':'\u228E','UpperLeftArrow':'\u2196','UpperRightArrow':'\u2197','upsi':'\u03C5','Upsi':'\u03D2','upsih':'\u03D2','upsilon':'\u03C5','Upsilon':'\u03A5','UpTee':'\u22A5','UpTeeArrow':'\u21A5','upuparrows':'\u21C8','urcorn':'\u231D','urcorner':'\u231D','urcrop':'\u230E','uring':'\u016F','Uring':'\u016E','urtri':'\u25F9','uscr':'\uD835\uDCCA','Uscr':'\uD835\uDCB0','utdot':'\u22F0','utilde':'\u0169','Utilde':'\u0168','utri':'\u25B5','utrif':'\u25B4','uuarr':'\u21C8','uuml':'\xFC','Uuml':'\xDC','uwangle':'\u29A7','vangrt':'\u299C','varepsilon':'\u03F5','varkappa':'\u03F0','varnothing':'\u2205','varphi':'\u03D5','varpi':'\u03D6','varpropto':'\u221D','varr':'\u2195','vArr':'\u21D5','varrho':'\u03F1','varsigma':'\u03C2','varsubsetneq':'\u228A\uFE00','varsubsetneqq':'\u2ACB\uFE00','varsupsetneq':'\u228B\uFE00','varsupsetneqq':'\u2ACC\uFE00','vartheta':'\u03D1','vartriangleleft':'\u22B2','vartriangleright':'\u22B3','vBar':'\u2AE8','Vbar':'\u2AEB','vBarv':'\u2AE9','vcy':'\u0432','Vcy':'\u0412','vdash':'\u22A2','vDash':'\u22A8','Vdash':'\u22A9','VDash':'\u22AB','Vdashl':'\u2AE6','vee':'\u2228','Vee':'\u22C1','veebar':'\u22BB','veeeq':'\u225A','vellip':'\u22EE','verbar':'|','Verbar':'\u2016','vert':'|','Vert':'\u2016','VerticalBar':'\u2223','VerticalLine':'|','VerticalSeparator':'\u2758','VerticalTilde':'\u2240','VeryThinSpace':'\u200A','vfr':'\uD835\uDD33','Vfr':'\uD835\uDD19','vltri':'\u22B2','vnsub':'\u2282\u20D2','vnsup':'\u2283\u20D2','vopf':'\uD835\uDD67','Vopf':'\uD835\uDD4D','vprop':'\u221D','vrtri':'\u22B3','vscr':'\uD835\uDCCB','Vscr':'\uD835\uDCB1','vsubne':'\u228A\uFE00','vsubnE':'\u2ACB\uFE00','vsupne':'\u228B\uFE00','vsupnE':'\u2ACC\uFE00','Vvdash':'\u22AA','vzigzag':'\u299A','wcirc':'\u0175','Wcirc':'\u0174','wedbar':'\u2A5F','wedge':'\u2227','Wedge':'\u22C0','wedgeq':'\u2259','weierp':'\u2118','wfr':'\uD835\uDD34','Wfr':'\uD835\uDD1A','wopf':'\uD835\uDD68','Wopf':'\uD835\uDD4E','wp':'\u2118','wr':'\u2240','wreath':'\u2240','wscr':'\uD835\uDCCC','Wscr':'\uD835\uDCB2','xcap':'\u22C2','xcirc':'\u25EF','xcup':'\u22C3','xdtri':'\u25BD','xfr':'\uD835\uDD35','Xfr':'\uD835\uDD1B','xharr':'\u27F7','xhArr':'\u27FA','xi':'\u03BE','Xi':'\u039E','xlarr':'\u27F5','xlArr':'\u27F8','xmap':'\u27FC','xnis':'\u22FB','xodot':'\u2A00','xopf':'\uD835\uDD69','Xopf':'\uD835\uDD4F','xoplus':'\u2A01','xotime':'\u2A02','xrarr':'\u27F6','xrArr':'\u27F9','xscr':'\uD835\uDCCD','Xscr':'\uD835\uDCB3','xsqcup':'\u2A06','xuplus':'\u2A04','xutri':'\u25B3','xvee':'\u22C1','xwedge':'\u22C0','yacute':'\xFD','Yacute':'\xDD','yacy':'\u044F','YAcy':'\u042F','ycirc':'\u0177','Ycirc':'\u0176','ycy':'\u044B','Ycy':'\u042B','yen':'\xA5','yfr':'\uD835\uDD36','Yfr':'\uD835\uDD1C','yicy':'\u0457','YIcy':'\u0407','yopf':'\uD835\uDD6A','Yopf':'\uD835\uDD50','yscr':'\uD835\uDCCE','Yscr':'\uD835\uDCB4','yucy':'\u044E','YUcy':'\u042E','yuml':'\xFF','Yuml':'\u0178','zacute':'\u017A','Zacute':'\u0179','zcaron':'\u017E','Zcaron':'\u017D','zcy':'\u0437','Zcy':'\u0417','zdot':'\u017C','Zdot':'\u017B','zeetrf':'\u2128','ZeroWidthSpace':'\u200B','zeta':'\u03B6','Zeta':'\u0396','zfr':'\uD835\uDD37','Zfr':'\u2128','zhcy':'\u0436','ZHcy':'\u0416','zigrarr':'\u21DD','zopf':'\uD835\uDD6B','Zopf':'\u2124','zscr':'\uD835\uDCCF','Zscr':'\uD835\uDCB5','zwj':'\u200D','zwnj':'\u200C'}; - var decodeMapLegacy = {'aacute':'\xE1','Aacute':'\xC1','acirc':'\xE2','Acirc':'\xC2','acute':'\xB4','aelig':'\xE6','AElig':'\xC6','agrave':'\xE0','Agrave':'\xC0','amp':'&','AMP':'&','aring':'\xE5','Aring':'\xC5','atilde':'\xE3','Atilde':'\xC3','auml':'\xE4','Auml':'\xC4','brvbar':'\xA6','ccedil':'\xE7','Ccedil':'\xC7','cedil':'\xB8','cent':'\xA2','copy':'\xA9','COPY':'\xA9','curren':'\xA4','deg':'\xB0','divide':'\xF7','eacute':'\xE9','Eacute':'\xC9','ecirc':'\xEA','Ecirc':'\xCA','egrave':'\xE8','Egrave':'\xC8','eth':'\xF0','ETH':'\xD0','euml':'\xEB','Euml':'\xCB','frac12':'\xBD','frac14':'\xBC','frac34':'\xBE','gt':'>','GT':'>','iacute':'\xED','Iacute':'\xCD','icirc':'\xEE','Icirc':'\xCE','iexcl':'\xA1','igrave':'\xEC','Igrave':'\xCC','iquest':'\xBF','iuml':'\xEF','Iuml':'\xCF','laquo':'\xAB','lt':'<','LT':'<','macr':'\xAF','micro':'\xB5','middot':'\xB7','nbsp':'\xA0','not':'\xAC','ntilde':'\xF1','Ntilde':'\xD1','oacute':'\xF3','Oacute':'\xD3','ocirc':'\xF4','Ocirc':'\xD4','ograve':'\xF2','Ograve':'\xD2','ordf':'\xAA','ordm':'\xBA','oslash':'\xF8','Oslash':'\xD8','otilde':'\xF5','Otilde':'\xD5','ouml':'\xF6','Ouml':'\xD6','para':'\xB6','plusmn':'\xB1','pound':'\xA3','quot':'"','QUOT':'"','raquo':'\xBB','reg':'\xAE','REG':'\xAE','sect':'\xA7','shy':'\xAD','sup1':'\xB9','sup2':'\xB2','sup3':'\xB3','szlig':'\xDF','thorn':'\xFE','THORN':'\xDE','times':'\xD7','uacute':'\xFA','Uacute':'\xDA','ucirc':'\xFB','Ucirc':'\xDB','ugrave':'\xF9','Ugrave':'\xD9','uml':'\xA8','uuml':'\xFC','Uuml':'\xDC','yacute':'\xFD','Yacute':'\xDD','yen':'\xA5','yuml':'\xFF'}; - var decodeMapNumeric = {'0':'\uFFFD','128':'\u20AC','130':'\u201A','131':'\u0192','132':'\u201E','133':'\u2026','134':'\u2020','135':'\u2021','136':'\u02C6','137':'\u2030','138':'\u0160','139':'\u2039','140':'\u0152','142':'\u017D','145':'\u2018','146':'\u2019','147':'\u201C','148':'\u201D','149':'\u2022','150':'\u2013','151':'\u2014','152':'\u02DC','153':'\u2122','154':'\u0161','155':'\u203A','156':'\u0153','158':'\u017E','159':'\u0178'}; - var invalidReferenceCodePoints = [1,2,3,4,5,6,7,8,11,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,64976,64977,64978,64979,64980,64981,64982,64983,64984,64985,64986,64987,64988,64989,64990,64991,64992,64993,64994,64995,64996,64997,64998,64999,65000,65001,65002,65003,65004,65005,65006,65007,65534,65535,131070,131071,196606,196607,262142,262143,327678,327679,393214,393215,458750,458751,524286,524287,589822,589823,655358,655359,720894,720895,786430,786431,851966,851967,917502,917503,983038,983039,1048574,1048575,1114110,1114111]; - - /*--------------------------------------------------------------------------*/ - - var stringFromCharCode = String.fromCharCode; - - var object = {}; - var hasOwnProperty = object.hasOwnProperty; - var has = function(object, propertyName) { - return hasOwnProperty.call(object, propertyName); - }; - - var contains = function(array, value) { - var index = -1; - var length = array.length; - while (++index < length) { - if (array[index] == value) { - return true; - } - } - return false; - }; - - var merge = function(options, defaults) { - if (!options) { - return defaults; - } - var result = {}; - var key; - for (key in defaults) { - // A `hasOwnProperty` check is not needed here, since only recognized - // option names are used anyway. Any others are ignored. - result[key] = has(options, key) ? options[key] : defaults[key]; - } - return result; - }; - - // Modified version of `ucs2encode`; see https://mths.be/punycode. - var codePointToSymbol = function(codePoint, strict) { - var output = ''; - if ((codePoint >= 0xD800 && codePoint <= 0xDFFF) || codePoint > 0x10FFFF) { - // See issue #4: - // “Otherwise, if the number is in the range 0xD800 to 0xDFFF or is - // greater than 0x10FFFF, then this is a parse error. Return a U+FFFD - // REPLACEMENT CHARACTER.†- if (strict) { - parseError('character reference outside the permissible Unicode range'); - } - return '\uFFFD'; - } - if (has(decodeMapNumeric, codePoint)) { - if (strict) { - parseError('disallowed character reference'); - } - return decodeMapNumeric[codePoint]; - } - if (strict && contains(invalidReferenceCodePoints, codePoint)) { - parseError('disallowed character reference'); - } - if (codePoint > 0xFFFF) { - codePoint -= 0x10000; - output += stringFromCharCode(codePoint >>> 10 & 0x3FF | 0xD800); - codePoint = 0xDC00 | codePoint & 0x3FF; - } - output += stringFromCharCode(codePoint); - return output; - }; - - var hexEscape = function(codePoint) { - return '&#x' + codePoint.toString(16).toUpperCase() + ';'; - }; - - var decEscape = function(codePoint) { - return '&#' + codePoint + ';'; - }; - - var parseError = function(message) { - throw Error('Parse error: ' + message); - }; - - /*--------------------------------------------------------------------------*/ - - var encode = function(string, options) { - options = merge(options, encode.options); - var strict = options.strict; - if (strict && regexInvalidRawCodePoint.test(string)) { - parseError('forbidden code point'); - } - var encodeEverything = options.encodeEverything; - var useNamedReferences = options.useNamedReferences; - var allowUnsafeSymbols = options.allowUnsafeSymbols; - var escapeCodePoint = options.decimal ? decEscape : hexEscape; - - var escapeBmpSymbol = function(symbol) { - return escapeCodePoint(symbol.charCodeAt(0)); - }; - - if (encodeEverything) { - // Encode ASCII symbols. - string = string.replace(regexAsciiWhitelist, function(symbol) { - // Use named references if requested & possible. - if (useNamedReferences && has(encodeMap, symbol)) { - return '&' + encodeMap[symbol] + ';'; - } - return escapeBmpSymbol(symbol); - }); - // Shorten a few escapes that represent two symbols, of which at least one - // is within the ASCII range. - if (useNamedReferences) { - string = string - .replace(/>\u20D2/g, '>⃒') - .replace(/<\u20D2/g, '<⃒') - .replace(/fj/g, 'fj'); - } - // Encode non-ASCII symbols. - if (useNamedReferences) { - // Encode non-ASCII symbols that can be replaced with a named reference. - string = string.replace(regexEncodeNonAscii, function(string) { - // Note: there is no need to check `has(encodeMap, string)` here. - return '&' + encodeMap[string] + ';'; - }); - } - // Note: any remaining non-ASCII symbols are handled outside of the `if`. - } else if (useNamedReferences) { - // Apply named character references. - // Encode `<>"'&` using named character references. - if (!allowUnsafeSymbols) { - string = string.replace(regexEscape, function(string) { - return '&' + encodeMap[string] + ';'; // no need to check `has()` here - }); - } - // Shorten escapes that represent two symbols, of which at least one is - // `<>"'&`. - string = string - .replace(/>\u20D2/g, '>⃒') - .replace(/<\u20D2/g, '<⃒'); - // Encode non-ASCII symbols that can be replaced with a named reference. - string = string.replace(regexEncodeNonAscii, function(string) { - // Note: there is no need to check `has(encodeMap, string)` here. - return '&' + encodeMap[string] + ';'; - }); - } else if (!allowUnsafeSymbols) { - // Encode `<>"'&` using hexadecimal escapes, now that they’re not handled - // using named character references. - string = string.replace(regexEscape, escapeBmpSymbol); - } - return string - // Encode astral symbols. - .replace(regexAstralSymbols, function($0) { - // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae - var high = $0.charCodeAt(0); - var low = $0.charCodeAt(1); - var codePoint = (high - 0xD800) * 0x400 + low - 0xDC00 + 0x10000; - return escapeCodePoint(codePoint); - }) - // Encode any remaining BMP symbols that are not printable ASCII symbols - // using a hexadecimal escape. - .replace(regexBmpWhitelist, escapeBmpSymbol); - }; - // Expose default options (so they can be overridden globally). - encode.options = { - 'allowUnsafeSymbols': false, - 'encodeEverything': false, - 'strict': false, - 'useNamedReferences': false, - 'decimal' : false - }; - - var decode = function(html, options) { - options = merge(options, decode.options); - var strict = options.strict; - if (strict && regexInvalidEntity.test(html)) { - parseError('malformed character reference'); - } - return html.replace(regexDecode, function($0, $1, $2, $3, $4, $5, $6, $7, $8) { - var codePoint; - var semicolon; - var decDigits; - var hexDigits; - var reference; - var next; - - if ($1) { - reference = $1; - // Note: there is no need to check `has(decodeMap, reference)`. - return decodeMap[reference]; - } - - if ($2) { - // Decode named character references without trailing `;`, e.g. `&`. - // This is only a parse error if it gets converted to `&`, or if it is - // followed by `=` in an attribute context. - reference = $2; - next = $3; - if (next && options.isAttributeValue) { - if (strict && next == '=') { - parseError('`&` did not start a character reference'); - } - return $0; - } else { - if (strict) { - parseError( - 'named character reference was not terminated by a semicolon' - ); - } - // Note: there is no need to check `has(decodeMapLegacy, reference)`. - return decodeMapLegacy[reference] + (next || ''); - } - } - - if ($4) { - // Decode decimal escapes, e.g. `𝌆`. - decDigits = $4; - semicolon = $5; - if (strict && !semicolon) { - parseError('character reference was not terminated by a semicolon'); - } - codePoint = parseInt(decDigits, 10); - return codePointToSymbol(codePoint, strict); - } - - if ($6) { - // Decode hexadecimal escapes, e.g. `𝌆`. - hexDigits = $6; - semicolon = $7; - if (strict && !semicolon) { - parseError('character reference was not terminated by a semicolon'); - } - codePoint = parseInt(hexDigits, 16); - return codePointToSymbol(codePoint, strict); - } - - // If we’re still here, `if ($7)` is implied; it’s an ambiguous - // ampersand for sure. https://mths.be/notes/ambiguous-ampersands - if (strict) { - parseError( - 'named character reference was not terminated by a semicolon' - ); - } - return $0; - }); - }; - // Expose default options (so they can be overridden globally). - decode.options = { - 'isAttributeValue': false, - 'strict': false - }; - - var escape = function(string) { - return string.replace(regexEscape, function($0) { - // Note: there is no need to check `has(escapeMap, $0)` here. - return escapeMap[$0]; - }); - }; - - /*--------------------------------------------------------------------------*/ - - var he = { - 'version': '1.2.0', - 'encode': encode, - 'decode': decode, - 'escape': escape, - 'unescape': decode - }; - - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - typeof define == 'function' && - typeof define.amd == 'object' && - define.amd - ) { - define(function() { - return he; - }); - } else if (freeExports && !freeExports.nodeType) { - if (freeModule) { // in Node.js, io.js, or RingoJS v0.8.0+ - freeModule.exports = he; - } else { // in Narwhal or RingoJS v0.7.0- - for (var key in he) { - has(he, key) && (freeExports[key] = he[key]); - } - } - } else { // in Rhino or a web browser - root.he = he; - } - -}(this)); - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],2:[function(require,module,exports){ -/*! - * jQuery JavaScript Library v3.3.1 - * https://jquery.com/ - * - * Includes Sizzle.js - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://jquery.org/license - * - * Date: 2018-01-20T17:24Z - */ -( function( global, factory ) { - - "use strict"; - - if ( typeof module === "object" && typeof module.exports === "object" ) { - - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 -// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode -// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common -// enough that all such attempts are guarded in a try block. -"use strict"; - -var arr = []; - -var document = window.document; - -var getProto = Object.getPrototypeOf; - -var slice = arr.slice; - -var concat = arr.concat; - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var fnToString = hasOwn.toString; - -var ObjectFunctionString = fnToString.call( Object ); - -var support = {}; - -var isFunction = function isFunction( obj ) { - - // Support: Chrome <=57, Firefox <=52 - // In some browsers, typeof returns "function" for HTML elements - // (i.e., `typeof document.createElement( "object" ) === "function"`). - // We don't want to classify *any* DOM node as a function. - return typeof obj === "function" && typeof obj.nodeType !== "number"; - }; - - -var isWindow = function isWindow( obj ) { - return obj != null && obj === obj.window; - }; - - - - - var preservedScriptAttributes = { - type: true, - src: true, - noModule: true - }; - - function DOMEval( code, doc, node ) { - doc = doc || document; - - var i, - script = doc.createElement( "script" ); - - script.text = code; - if ( node ) { - for ( i in preservedScriptAttributes ) { - if ( node[ i ] ) { - script[ i ] = node[ i ]; - } - } - } - doc.head.appendChild( script ).parentNode.removeChild( script ); - } - - -function toType( obj ) { - if ( obj == null ) { - return obj + ""; - } - - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; -} -/* global Symbol */ -// Defining this global in .eslintrc.json would create a danger of using the global -// unguarded in another place, it seems safer to define global only for this module - - - -var - version = "3.3.1", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android <=4.0 only - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; - -jQuery.fn = jQuery.prototype = { - - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - - // Return all the elements in a clean array - if ( num == null ) { - return slice.call( this ); - } - - // Return just the one element from the set - return num < 0 ? this[ num + this.length ] : this[ num ]; - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !isFunction( target ) ) { - target = {}; - } - - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { - - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = Array.isArray( copy ) ) ) ) { - - if ( copyIsArray ) { - copyIsArray = false; - clone = src && Array.isArray( src ) ? src : []; - - } else { - clone = src && jQuery.isPlainObject( src ) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend( { - - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - isPlainObject: function( obj ) { - var proto, Ctor; - - // Detect obvious negatives - // Use toString instead of jQuery.type to catch host objects - if ( !obj || toString.call( obj ) !== "[object Object]" ) { - return false; - } - - proto = getProto( obj ); - - // Objects with no prototype (e.g., `Object.create( null )`) are plain - if ( !proto ) { - return true; - } - - // Objects with prototype are plain iff they were constructed by a global Object function - Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; - return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; - }, - - isEmptyObject: function( obj ) { - - /* eslint-disable no-unused-vars */ - // See https://github.com/eslint/eslint/issues/6125 - var name; - - for ( name in obj ) { - return false; - } - return true; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - DOMEval( code ); - }, - - each: function( obj, callback ) { - var length, i = 0; - - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } - } - } - - return obj; - }, - - // Support: Android <=4.0 only - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -} ); - -if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; -} - -// Populate the class2type map -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -} ); - -function isArrayLike( obj ) { - - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = toType( obj ); - - if ( isFunction( obj ) || isWindow( obj ) ) { - return false; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.3 - * https://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2016-08-08 - */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + identifier + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } - - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, - - disabledAncestor = addCombinator( - function( elem ) { - return elem.disabled === true && ("form" in elem || "label" in elem); - }, - { dir: "parentNode", next: "legend" } - ); - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, - - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; - - results = results || []; - - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - context = context || document; - - if ( documentIsHTML ) { - - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { - - // ID selector - if ( (m = match[1]) ) { - - // Document context - if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - - // Element context - } else { - - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && - contains( context, elem ) && - elem.id === m ) { - - results.push( elem ); - return results; - } - } - - // Type selector - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && - context.getElementsByClassName ) { - - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // Take advantage of querySelectorAll - if ( support.qsa && - !compilerCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - - if ( nodeType !== 1 ) { - newContext = context; - newSelector = selector; - - // qSA looks outside Element context, which is not what we want - // Thanks to Andrew Dupont for this workaround technique - // Support: IE <=8 - // Exclude object elements - } else if ( context.nodeName.toLowerCase() !== "object" ) { - - // Capture the context ID, setting it first if necessary - if ( (nid = context.getAttribute( "id" )) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", (nid = expando) ); - } - - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[i] = "#" + nid + " " + toSelector( groups[i] ); - } - newSelector = groups.join( "," ); - - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement("fieldset"); - - try { - return !!fn( el ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - // release memory in IE - el = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { - - // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { - - // Only certain elements can match :enabled or :disabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled - if ( "form" in elem ) { - - // Check for inherited disabledness on relevant non-disabled elements: - // * listed form-associated elements in a disabled fieldset - // https://html.spec.whatwg.org/multipage/forms.html#category-listed - // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled - // * option elements in a disabled optgroup - // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled - // All such elements have a "form" property. - if ( elem.parentNode && elem.disabled === false ) { - - // Option elements defer to a parent optgroup if present - if ( "label" in elem ) { - if ( "label" in elem.parentNode ) { - return elem.parentNode.disabled === disabled; - } else { - return elem.disabled === disabled; - } - } - - // Support: IE 6 - 11 - // Use the isDisabled shortcut property to check for disabled fieldset ancestors - return elem.isDisabled === disabled || - - // Where there is no isDisabled, check manually - /* jshint -W018 */ - elem.isDisabled !== !disabled && - disabledAncestor( elem ) === disabled; - } - - return elem.disabled === disabled; - - // Try to winnow out elements that can't be disabled before trusting the disabled property. - // Some victims get caught in our net (label, legend, menu, track), but it shouldn't - // even exist on them, let alone have a boolean value. - } else if ( "label" in elem ) { - return elem.disabled === disabled; - } - - // Remaining elements are neither :enabled nor :disabled - return false; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, subWindow, - doc = node ? node.ownerDocument || node : preferredDoc; - - // Return early if doc is invalid or already selected - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); - - // Support: IE 9-11, Edge - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - if ( preferredDoc !== document && - (subWindow = document.defaultView) && subWindow.top !== subWindow ) { - - // Support: IE 11, Edge - if ( subWindow.addEventListener ) { - subWindow.addEventListener( "unload", unloadHandler, false ); - - // Support: IE 9 - 10 only - } else if ( subWindow.attachEvent ) { - subWindow.attachEvent( "onunload", unloadHandler ); - } - } - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert(function( el ) { - el.className = "i"; - return !el.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( el ) { - el.appendChild( document.createComment("") ); - return !el.getElementsByTagName("*").length; - }); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programmatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( el ) { - docElem.appendChild( el ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - }); - - // ID filter and find - if ( support.getById ) { - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var elem = context.getElementById( id ); - return elem ? [ elem ] : []; - } - }; - } else { - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - - // Support: IE 6 - 7 only - // getElementById is not reliable as a find shortcut - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var node, i, elems, - elem = context.getElementById( id ); - - if ( elem ) { - - // Verify the id attribute - node = elem.getAttributeNode("id"); - if ( node && node.value === id ) { - return [ elem ]; - } - - // Fall back on getElementsByName - elems = context.getElementsByName( id ); - i = 0; - while ( (elem = elems[i++]) ) { - node = elem.getAttributeNode("id"); - if ( node && node.value === id ) { - return [ elem ]; - } - } - } - - return []; - } - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See https://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( el ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // https://bugs.jquery.com/ticket/12359 - docElem.appendChild( el ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll("[msallowcapture^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push("~="); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !el.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibling-combinator selector` fails - if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push(".#.+[+~]"); - } - }); - - assert(function( el ) { - el.innerHTML = "" + - ""; - - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement("input"); - input.setAttribute( "type", "hidden" ); - el.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( el.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( el.querySelectorAll(":enabled").length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Support: IE9-11+ - // IE's :disabled selector does not pick up the children of disabled fieldsets - docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll(":disabled").length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( el ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( el, "*" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( el, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === document ? -1 : - b === document ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return document; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - !compilerCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch (e) {} - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; -}; - -Sizzle.escape = function( sel ) { - return (sel + "").replace( rcssescape, fcssescape ); -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType, - diff = false; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) { - - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - - // Seek `elem` from a previously-cached index - - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex && cache[ 2 ]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - } else { - // Use previously-cached element index if available - if ( useCache ) { - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex; - } - - // xml :nth-child(...) - // or :nth-last-child(...) or :nth(-last)?-of-type(...) - if ( diff === false ) { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) && - ++diff ) { - - // Cache the index of each encountered element - if ( useCache ) { - outerCache = node[ expando ] || (node[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); - - uniqueCache[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - // Don't keep the element (issue #299) - input[0] = null; - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": createDisabledPseudo( false ), - "disabled": createDisabledPseudo( true ), - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - skip = combinator.next, - key = skip || dir, - checkNonElements = base && key === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - return false; - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); - - if ( skip && skip === elem.nodeName.toLowerCase() ) { - elem = elem[ dir ] || elem; - } else if ( (oldCache = uniqueCache[ key ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - uniqueCache[ key ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - return false; - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context === document || context || outermost; - } - - // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - if ( !context && elem.ownerDocument !== document ) { - setDocument( elem ); - xml = !documentIsHTML; - } - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context || document, xml) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // `i` is now the count of elements visited above, and adding it to `matchedCount` - // makes the latter nonnegative. - matchedCount += i; - - // Apply set filters to unmatched elements - // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` - // equals `i`), unless we didn't visit _any_ elements in the above loop because we have - // no element matchers and no seed. - // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that - // case, which will result in a "00" `matchedCount` that differs from `i` but is also - // numerically zero. - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); - - results = results || []; - - // Try to minimize operations if there is only one selector in the list and no seed - // (the latter of which guarantees us context) - if ( match.length === 1 ) { - - // Reduce context if the leading compound selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - !context || rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( el ) { - // Should return 1, but returns 4 (following) - return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; -}); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( el ) { - el.innerHTML = ""; - return el.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( el ) { - el.innerHTML = ""; - el.firstChild.setAttribute( "value", "" ); - return el.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( el ) { - return el.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); -} - -return Sizzle; - -})( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; - -// Deprecated -jQuery.expr[ ":" ] = jQuery.expr.pseudos; -jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; -jQuery.escapeSelector = Sizzle.escape; - - - - -var dir = function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; -}; - - -var siblings = function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; -}; - - -var rneedsContext = jQuery.expr.match.needsContext; - - - -function nodeName( elem, name ) { - - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - -}; -var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); - - - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - return !!qualifier.call( elem, i, elem ) !== not; - } ); - } - - // Single element - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - } ); - } - - // Arraylike of elements (jQuery, arguments, Array) - if ( typeof qualifier !== "string" ) { - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) > -1 ) !== not; - } ); - } - - // Filtered directly for both simple and complex selectors - return jQuery.filter( qualifier, elements, not ); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - if ( elems.length === 1 && elem.nodeType === 1 ) { - return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; - } - - return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - } ) ); -}; - -jQuery.fn.extend( { - find: function( selector ) { - var i, ret, - len = this.length, - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - } ) ); - } - - ret = this.pushStack( [] ); - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - return len > 1 ? jQuery.uniqueSort( ret ) : ret; - }, - filter: function( selector ) { - return this.pushStack( winnow( this, selector || [], false ) ); - }, - not: function( selector ) { - return this.pushStack( winnow( this, selector || [], true ) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -} ); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - // Shortcut simple #id case for speed - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, - - init = jQuery.fn.init = function( selector, context, root ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Method init() accepts an alternate rootjQuery - // so migrate can support jQuery.sub (gh-2101) - root = root || rootjQuery; - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[ 0 ] === "<" && - selector[ selector.length - 1 ] === ">" && - selector.length >= 3 ) { - - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && ( match[ 1 ] || !context ) ) { - - // HANDLE: $(html) -> $(array) - if ( match[ 1 ] ) { - context = context instanceof jQuery ? context[ 0 ] : context; - - // Option to run scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[ 1 ], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - - // Properties of context are called as methods if possible - if ( isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[ 2 ] ); - - if ( elem ) { - - // Inject the element directly into the jQuery object - this[ 0 ] = elem; - this.length = 1; - } - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || root ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this[ 0 ] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( isFunction( selector ) ) { - return root.ready !== undefined ? - root.ready( selector ) : - - // Execute immediately if ready is not present - selector( jQuery ); - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - - // Methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend( { - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter( function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[ i ] ) ) { - return true; - } - } - } ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - targets = typeof selectors !== "string" && jQuery( selectors ); - - // Positional selectors never match, since there's no _selection_ context - if ( !rneedsContext.test( selectors ) ) { - for ( ; i < l; i++ ) { - for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { - - // Always skip document fragments - if ( cur.nodeType < 11 && ( targets ? - targets.index( cur ) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector( cur, selectors ) ) ) { - - matched.push( cur ); - break; - } - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); - }, - - // Determine the position of an element within the set - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // Index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.uniqueSort( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - } -} ); - -function sibling( cur, dir ) { - while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each( { - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return siblings( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return siblings( elem.firstChild ); - }, - contents: function( elem ) { - if ( nodeName( elem, "iframe" ) ) { - return elem.contentDocument; - } - - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only - // Treat the template element as a regular one in browsers that - // don't support it. - if ( nodeName( elem, "template" ) ) { - elem = elem.content || elem; - } - - return jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.uniqueSort( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -} ); -var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); - - - -// Convert String-formatted options into Object-formatted ones -function createOptions( options ) { - var object = {}; - jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { - object[ flag ] = true; - } ); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - createOptions( options ) : - jQuery.extend( {}, options ); - - var // Flag to know if list is currently firing - firing, - - // Last fire value for non-forgettable lists - memory, - - // Flag to know if list was already fired - fired, - - // Flag to prevent firing - locked, - - // Actual callback list - list = [], - - // Queue of execution data for repeatable lists - queue = [], - - // Index of currently firing callback (modified by add/remove as needed) - firingIndex = -1, - - // Fire callbacks - fire = function() { - - // Enforce single-firing - locked = locked || options.once; - - // Execute callbacks for all pending executions, - // respecting firingIndex overrides and runtime changes - fired = firing = true; - for ( ; queue.length; firingIndex = -1 ) { - memory = queue.shift(); - while ( ++firingIndex < list.length ) { - - // Run callback and check for early termination - if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && - options.stopOnFalse ) { - - // Jump to end and forget the data so .add doesn't re-fire - firingIndex = list.length; - memory = false; - } - } - } - - // Forget the data if we're done with it - if ( !options.memory ) { - memory = false; - } - - firing = false; - - // Clean up if we're done firing for good - if ( locked ) { - - // Keep an empty list if we have data for future add calls - if ( memory ) { - list = []; - - // Otherwise, this object is spent - } else { - list = ""; - } - } - }, - - // Actual Callbacks object - self = { - - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - - // If we have memory from a past run, we should fire after adding - if ( memory && !firing ) { - firingIndex = list.length - 1; - queue.push( memory ); - } - - ( function add( args ) { - jQuery.each( args, function( _, arg ) { - if ( isFunction( arg ) ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && toType( arg ) !== "string" ) { - - // Inspect recursively - add( arg ); - } - } ); - } )( arguments ); - - if ( memory && !firing ) { - fire(); - } - } - return this; - }, - - // Remove a callback from the list - remove: function() { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - - // Handle firing indexes - if ( index <= firingIndex ) { - firingIndex--; - } - } - } ); - return this; - }, - - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? - jQuery.inArray( fn, list ) > -1 : - list.length > 0; - }, - - // Remove all callbacks from the list - empty: function() { - if ( list ) { - list = []; - } - return this; - }, - - // Disable .fire and .add - // Abort any current/pending executions - // Clear all callbacks and values - disable: function() { - locked = queue = []; - list = memory = ""; - return this; - }, - disabled: function() { - return !list; - }, - - // Disable .fire - // Also disable .add unless we have memory (since it would have no effect) - // Abort any pending executions - lock: function() { - locked = queue = []; - if ( !memory && !firing ) { - list = memory = ""; - } - return this; - }, - locked: function() { - return !!locked; - }, - - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( !locked ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - queue.push( args ); - if ( !firing ) { - fire(); - } - } - return this; - }, - - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -function Identity( v ) { - return v; -} -function Thrower( ex ) { - throw ex; -} - -function adoptValue( value, resolve, reject, noValue ) { - var method; - - try { - - // Check for promise aspect first to privilege synchronous behavior - if ( value && isFunction( ( method = value.promise ) ) ) { - method.call( value ).done( resolve ).fail( reject ); - - // Other thenables - } else if ( value && isFunction( ( method = value.then ) ) ) { - method.call( value, resolve, reject ); - - // Other non-thenables - } else { - - // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: - // * false: [ value ].slice( 0 ) => resolve( value ) - // * true: [ value ].slice( 1 ) => resolve() - resolve.apply( undefined, [ value ].slice( noValue ) ); - } - - // For Promises/A+, convert exceptions into rejections - // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in - // Deferred#then to conditionally suppress rejection. - } catch ( value ) { - - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - reject.apply( undefined, [ value ] ); - } -} - -jQuery.extend( { - - Deferred: function( func ) { - var tuples = [ - - // action, add listener, callbacks, - // ... .then handlers, argument index, [final state] - [ "notify", "progress", jQuery.Callbacks( "memory" ), - jQuery.Callbacks( "memory" ), 2 ], - [ "resolve", "done", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 0, "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 1, "rejected" ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - "catch": function( fn ) { - return promise.then( null, fn ); - }, - - // Keep pipe for back-compat - pipe: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - - // Map tuples (progress, done, fail) to arguments (done, fail, progress) - var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; - - // deferred.progress(function() { bind to newDefer or newDefer.notify }) - // deferred.done(function() { bind to newDefer or newDefer.resolve }) - // deferred.fail(function() { bind to newDefer or newDefer.reject }) - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && isFunction( returned.promise ) ) { - returned.promise() - .progress( newDefer.notify ) - .done( newDefer.resolve ) - .fail( newDefer.reject ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - }, - then: function( onFulfilled, onRejected, onProgress ) { - var maxDepth = 0; - function resolve( depth, deferred, handler, special ) { - return function() { - var that = this, - args = arguments, - mightThrow = function() { - var returned, then; - - // Support: Promises/A+ section 2.3.3.3.3 - // https://promisesaplus.com/#point-59 - // Ignore double-resolution attempts - if ( depth < maxDepth ) { - return; - } - - returned = handler.apply( that, args ); - - // Support: Promises/A+ section 2.3.1 - // https://promisesaplus.com/#point-48 - if ( returned === deferred.promise() ) { - throw new TypeError( "Thenable self-resolution" ); - } - - // Support: Promises/A+ sections 2.3.3.1, 3.5 - // https://promisesaplus.com/#point-54 - // https://promisesaplus.com/#point-75 - // Retrieve `then` only once - then = returned && - - // Support: Promises/A+ section 2.3.4 - // https://promisesaplus.com/#point-64 - // Only check objects and functions for thenability - ( typeof returned === "object" || - typeof returned === "function" ) && - returned.then; - - // Handle a returned thenable - if ( isFunction( then ) ) { - - // Special processors (notify) just wait for resolution - if ( special ) { - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ) - ); - - // Normal processors (resolve) also hook into progress - } else { - - // ...and disregard older resolution values - maxDepth++; - - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ), - resolve( maxDepth, deferred, Identity, - deferred.notifyWith ) - ); - } - - // Handle all other returned values - } else { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Identity ) { - that = undefined; - args = [ returned ]; - } - - // Process the value(s) - // Default process is resolve - ( special || deferred.resolveWith )( that, args ); - } - }, - - // Only normal processors (resolve) catch and reject exceptions - process = special ? - mightThrow : - function() { - try { - mightThrow(); - } catch ( e ) { - - if ( jQuery.Deferred.exceptionHook ) { - jQuery.Deferred.exceptionHook( e, - process.stackTrace ); - } - - // Support: Promises/A+ section 2.3.3.3.4.1 - // https://promisesaplus.com/#point-61 - // Ignore post-resolution exceptions - if ( depth + 1 >= maxDepth ) { - - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Thrower ) { - that = undefined; - args = [ e ]; - } - - deferred.rejectWith( that, args ); - } - } - }; - - // Support: Promises/A+ section 2.3.3.3.1 - // https://promisesaplus.com/#point-57 - // Re-resolve promises immediately to dodge false rejection from - // subsequent errors - if ( depth ) { - process(); - } else { - - // Call an optional hook to record the stack, in case of exception - // since it's otherwise lost when execution goes async - if ( jQuery.Deferred.getStackHook ) { - process.stackTrace = jQuery.Deferred.getStackHook(); - } - window.setTimeout( process ); - } - }; - } - - return jQuery.Deferred( function( newDefer ) { - - // progress_handlers.add( ... ) - tuples[ 0 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onProgress ) ? - onProgress : - Identity, - newDefer.notifyWith - ) - ); - - // fulfilled_handlers.add( ... ) - tuples[ 1 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onFulfilled ) ? - onFulfilled : - Identity - ) - ); - - // rejected_handlers.add( ... ) - tuples[ 2 ][ 3 ].add( - resolve( - 0, - newDefer, - isFunction( onRejected ) ? - onRejected : - Thrower - ) - ); - } ).promise(); - }, - - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 5 ]; - - // promise.progress = list.add - // promise.done = list.add - // promise.fail = list.add - promise[ tuple[ 1 ] ] = list.add; - - // Handle state - if ( stateString ) { - list.add( - function() { - - // state = "resolved" (i.e., fulfilled) - // state = "rejected" - state = stateString; - }, - - // rejected_callbacks.disable - // fulfilled_callbacks.disable - tuples[ 3 - i ][ 2 ].disable, - - // rejected_handlers.disable - // fulfilled_handlers.disable - tuples[ 3 - i ][ 3 ].disable, - - // progress_callbacks.lock - tuples[ 0 ][ 2 ].lock, - - // progress_handlers.lock - tuples[ 0 ][ 3 ].lock - ); - } - - // progress_handlers.fire - // fulfilled_handlers.fire - // rejected_handlers.fire - list.add( tuple[ 3 ].fire ); - - // deferred.notify = function() { deferred.notifyWith(...) } - // deferred.resolve = function() { deferred.resolveWith(...) } - // deferred.reject = function() { deferred.rejectWith(...) } - deferred[ tuple[ 0 ] ] = function() { - deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); - return this; - }; - - // deferred.notifyWith = list.fireWith - // deferred.resolveWith = list.fireWith - // deferred.rejectWith = list.fireWith - deferred[ tuple[ 0 ] + "With" ] = list.fireWith; - } ); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( singleValue ) { - var - - // count of uncompleted subordinates - remaining = arguments.length, - - // count of unprocessed arguments - i = remaining, - - // subordinate fulfillment data - resolveContexts = Array( i ), - resolveValues = slice.call( arguments ), - - // the master Deferred - master = jQuery.Deferred(), - - // subordinate callback factory - updateFunc = function( i ) { - return function( value ) { - resolveContexts[ i ] = this; - resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( !( --remaining ) ) { - master.resolveWith( resolveContexts, resolveValues ); - } - }; - }; - - // Single- and empty arguments are adopted like Promise.resolve - if ( remaining <= 1 ) { - adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, - !remaining ); - - // Use .then() to unwrap secondary thenables (cf. gh-3000) - if ( master.state() === "pending" || - isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { - - return master.then(); - } - } - - // Multiple arguments are aggregated like Promise.all array elements - while ( i-- ) { - adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); - } - - return master.promise(); - } -} ); - - -// These usually indicate a programmer mistake during development, -// warn about them ASAP rather than swallowing them by default. -var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; - -jQuery.Deferred.exceptionHook = function( error, stack ) { - - // Support: IE 8 - 9 only - // Console exists when dev tools are open, which can happen at any time - if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { - window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); - } -}; - - - - -jQuery.readyException = function( error ) { - window.setTimeout( function() { - throw error; - } ); -}; - - - - -// The deferred used on DOM ready -var readyList = jQuery.Deferred(); - -jQuery.fn.ready = function( fn ) { - - readyList - .then( fn ) - - // Wrap jQuery.readyException in a function so that the lookup - // happens at the time of error handling instead of callback - // registration. - .catch( function( error ) { - jQuery.readyException( error ); - } ); - - return this; -}; - -jQuery.extend( { - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - } -} ); - -jQuery.ready.then = readyList.then; - -// The ready event handler and self cleanup method -function completed() { - document.removeEventListener( "DOMContentLoaded", completed ); - window.removeEventListener( "load", completed ); - jQuery.ready(); -} - -// Catch cases where $(document).ready() is called -// after the browser event has already occurred. -// Support: IE <=9 - 10 only -// Older IE sometimes signals "interactive" too soon -if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { - - // Handle it asynchronously to allow scripts the opportunity to delay ready - window.setTimeout( jQuery.ready ); - -} else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed ); -} - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( toType( key ) === "object" ) { - chainable = true; - for ( i in key ) { - access( elems, fn, i, key[ i ], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( - elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) - ); - } - } - } - - if ( chainable ) { - return elems; - } - - // Gets - if ( bulk ) { - return fn.call( elems ); - } - - return len ? fn( elems[ 0 ], key ) : emptyGet; -}; - - -// Matches dashed string for camelizing -var rmsPrefix = /^-ms-/, - rdashAlpha = /-([a-z])/g; - -// Used by camelCase as callback to replace() -function fcamelCase( all, letter ) { - return letter.toUpperCase(); -} - -// Convert dashed to camelCase; used by the css and data modules -// Support: IE <=9 - 11, Edge 12 - 15 -// Microsoft forgot to hump their vendor prefix (#9572) -function camelCase( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); -} -var acceptData = function( owner ) { - - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - - - -function Data() { - this.expando = jQuery.expando + Data.uid++; -} - -Data.uid = 1; - -Data.prototype = { - - cache: function( owner ) { - - // Check if the owner object already has a cache - var value = owner[ this.expando ]; - - // If not, create one - if ( !value ) { - value = {}; - - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return an empty object. - if ( acceptData( owner ) ) { - - // If it is a node unlikely to be stringify-ed or looped over - // use plain assignment - if ( owner.nodeType ) { - owner[ this.expando ] = value; - - // Otherwise secure it in a non-enumerable property - // configurable must be true to allow the property to be - // deleted when data is removed - } else { - Object.defineProperty( owner, this.expando, { - value: value, - configurable: true - } ); - } - } - } - - return value; - }, - set: function( owner, data, value ) { - var prop, - cache = this.cache( owner ); - - // Handle: [ owner, key, value ] args - // Always use camelCase key (gh-2257) - if ( typeof data === "string" ) { - cache[ camelCase( data ) ] = value; - - // Handle: [ owner, { properties } ] args - } else { - - // Copy the properties one-by-one to the cache object - for ( prop in data ) { - cache[ camelCase( prop ) ] = data[ prop ]; - } - } - return cache; - }, - get: function( owner, key ) { - return key === undefined ? - this.cache( owner ) : - - // Always use camelCase key (gh-2257) - owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; - }, - access: function( owner, key, value ) { - - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ( ( key && typeof key === "string" ) && value === undefined ) ) { - - return this.get( owner, key ); - } - - // When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, - cache = owner[ this.expando ]; - - if ( cache === undefined ) { - return; - } - - if ( key !== undefined ) { - - // Support array or space separated string of keys - if ( Array.isArray( key ) ) { - - // If key is an array of keys... - // We always set camelCase keys, so remove that. - key = key.map( camelCase ); - } else { - key = camelCase( key ); - - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - key = key in cache ? - [ key ] : - ( key.match( rnothtmlwhite ) || [] ); - } - - i = key.length; - - while ( i-- ) { - delete cache[ key[ i ] ]; - } - } - - // Remove the expando if there's no more data - if ( key === undefined || jQuery.isEmptyObject( cache ) ) { - - // Support: Chrome <=35 - 45 - // Webkit & Blink performance suffers when deleting properties - // from DOM nodes, so set to undefined instead - // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) - if ( owner.nodeType ) { - owner[ this.expando ] = undefined; - } else { - delete owner[ this.expando ]; - } - } - }, - hasData: function( owner ) { - var cache = owner[ this.expando ]; - return cache !== undefined && !jQuery.isEmptyObject( cache ); - } -}; -var dataPriv = new Data(); - -var dataUser = new Data(); - - - -// Implementation Summary -// -// 1. Enforce API surface and semantic compatibility with 1.9.x branch -// 2. Improve the module's maintainability by reducing the storage -// paths to a single mechanism. -// 3. Use the same single mechanism to support "private" and "user" data. -// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) -// 5. Avoid exposing implementation details on user objects (eg. expando properties) -// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 - -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /[A-Z]/g; - -function getData( data ) { - if ( data === "true" ) { - return true; - } - - if ( data === "false" ) { - return false; - } - - if ( data === "null" ) { - return null; - } - - // Only convert to a number if it doesn't change the string - if ( data === +data + "" ) { - return +data; - } - - if ( rbrace.test( data ) ) { - return JSON.parse( data ); - } - - return data; -} - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = getData( data ); - } catch ( e ) {} - - // Make sure we set the data so it isn't changed later - dataUser.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend( { - hasData: function( elem ) { - return dataUser.hasData( elem ) || dataPriv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return dataUser.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - dataUser.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to dataPriv methods, these can be deprecated. - _data: function( elem, name, data ) { - return dataPriv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - dataPriv.remove( elem, name ); - } -} ); - -jQuery.fn.extend( { - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = dataUser.get( elem ); - - if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE 11 only - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = camelCase( name.slice( 5 ) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - dataPriv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each( function() { - dataUser.set( this, key ); - } ); - } - - return access( this, function( value ) { - var data; - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - - // Attempt to get data from the cache - // The key will always be camelCased in Data - data = dataUser.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, key ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each( function() { - - // We always store the camelCased key - dataUser.set( this, key, value ); - } ); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each( function() { - dataUser.remove( this, key ); - } ); - } -} ); - - -jQuery.extend( { - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = dataPriv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || Array.isArray( data ) ) { - queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // Clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // Not public - generate a queueHooks object, or return the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { - empty: jQuery.Callbacks( "once memory" ).add( function() { - dataPriv.remove( elem, [ type + "queue", key ] ); - } ) - } ); - } -} ); - -jQuery.fn.extend( { - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[ 0 ], type ); - } - - return data === undefined ? - this : - this.each( function() { - var queue = jQuery.queue( this, type, data ); - - // Ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - } ); - }, - dequeue: function( type ) { - return this.each( function() { - jQuery.dequeue( this, type ); - } ); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -} ); -var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; - -var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); - - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var isHiddenWithinTree = function( elem, el ) { - - // isHiddenWithinTree might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - - // Inline style trumps all - return elem.style.display === "none" || - elem.style.display === "" && - - // Otherwise, check computed style - // Support: Firefox <=43 - 45 - // Disconnected elements can have computed display: none, so first confirm that elem is - // in the document. - jQuery.contains( elem.ownerDocument, elem ) && - - jQuery.css( elem, "display" ) === "none"; - }; - -var swap = function( elem, options, callback, args ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.apply( elem, args || [] ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; -}; - - - - -function adjustCSS( elem, prop, valueParts, tween ) { - var adjusted, scale, - maxIterations = 20, - currentValue = tween ? - function() { - return tween.cur(); - } : - function() { - return jQuery.css( elem, prop, "" ); - }, - initial = currentValue(), - unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), - - // Starting value computation is required for potential unit mismatches - initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && - rcssNum.exec( jQuery.css( elem, prop ) ); - - if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - - // Support: Firefox <=54 - // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) - initial = initial / 2; - - // Trust units reported by jQuery.css - unit = unit || initialInUnit[ 3 ]; - - // Iteratively approximate from a nonzero starting point - initialInUnit = +initial || 1; - - while ( maxIterations-- ) { - - // Evaluate and update our best guess (doubling guesses that zero out). - // Finish if the scale equals or crosses 1 (making the old*new product non-positive). - jQuery.style( elem, prop, initialInUnit + unit ); - if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { - maxIterations = 0; - } - initialInUnit = initialInUnit / scale; - - } - - initialInUnit = initialInUnit * 2; - jQuery.style( elem, prop, initialInUnit + unit ); - - // Make sure we update the tween properties later on - valueParts = valueParts || []; - } - - if ( valueParts ) { - initialInUnit = +initialInUnit || +initial || 0; - - // Apply relative offset (+=/-=) if specified - adjusted = valueParts[ 1 ] ? - initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : - +valueParts[ 2 ]; - if ( tween ) { - tween.unit = unit; - tween.start = initialInUnit; - tween.end = adjusted; - } - } - return adjusted; -} - - -var defaultDisplayMap = {}; - -function getDefaultDisplay( elem ) { - var temp, - doc = elem.ownerDocument, - nodeName = elem.nodeName, - display = defaultDisplayMap[ nodeName ]; - - if ( display ) { - return display; - } - - temp = doc.body.appendChild( doc.createElement( nodeName ) ); - display = jQuery.css( temp, "display" ); - - temp.parentNode.removeChild( temp ); - - if ( display === "none" ) { - display = "block"; - } - defaultDisplayMap[ nodeName ] = display; - - return display; -} - -function showHide( elements, show ) { - var display, elem, - values = [], - index = 0, - length = elements.length; - - // Determine new display value for elements that need to change - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - - display = elem.style.display; - if ( show ) { - - // Since we force visibility upon cascade-hidden elements, an immediate (and slow) - // check is required in this first loop unless we have a nonempty display value (either - // inline or about-to-be-restored) - if ( display === "none" ) { - values[ index ] = dataPriv.get( elem, "display" ) || null; - if ( !values[ index ] ) { - elem.style.display = ""; - } - } - if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { - values[ index ] = getDefaultDisplay( elem ); - } - } else { - if ( display !== "none" ) { - values[ index ] = "none"; - - // Remember what we're overwriting - dataPriv.set( elem, "display", display ); - } - } - } - - // Set the display of the elements in a second loop to avoid constant reflow - for ( index = 0; index < length; index++ ) { - if ( values[ index ] != null ) { - elements[ index ].style.display = values[ index ]; - } - } - - return elements; -} - -jQuery.fn.extend( { - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } - - return this.each( function() { - if ( isHiddenWithinTree( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - } ); - } -} ); -var rcheckableType = ( /^(?:checkbox|radio)$/i ); - -var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); - -var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); - - - -// We have to close these tags to support XHTML (#13200) -var wrapMap = { - - // Support: IE <=9 only - option: [ 1, "" ], - - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
    " ], - col: [ 2, "", "
    " ], - tr: [ 2, "", "
    " ], - td: [ 3, "", "
    " ], - - _default: [ 0, "", "" ] -}; - -// Support: IE <=9 only -wrapMap.optgroup = wrapMap.option; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - - -function getAll( context, tag ) { - - // Support: IE <=9 - 11 only - // Use typeof to avoid zero-argument method invocation on host objects (#15151) - var ret; - - if ( typeof context.getElementsByTagName !== "undefined" ) { - ret = context.getElementsByTagName( tag || "*" ); - - } else if ( typeof context.querySelectorAll !== "undefined" ) { - ret = context.querySelectorAll( tag || "*" ); - - } else { - ret = []; - } - - if ( tag === undefined || tag && nodeName( context, tag ) ) { - return jQuery.merge( [ context ], ret ); - } - - return ret; -} - - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - dataPriv.set( - elems[ i ], - "globalEval", - !refElements || dataPriv.get( refElements[ i ], "globalEval" ) - ); - } -} - - -var rhtml = /<|&#?\w+;/; - -function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( toType( elem ) === "object" ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( ( elem = nodes[ i++ ] ) ) { - - // Skip elements already in the context collection (trac-4087) - if ( selection && jQuery.inArray( elem, selection ) > -1 ) { - if ( ignored ) { - ignored.push( elem ); - } - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( ( elem = tmp[ j++ ] ) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; -} - - -( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE <=11 only - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -} )(); -var documentElement = document.documentElement; - - - -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -// Support: IE <=9 only -// See #13393 for more info -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -function on( elem, types, selector, data, fn, one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - on( elem, type, selector, data, types[ type ], one ); - } - return elem; - } - - if ( data == null && fn == null ) { - - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return elem; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return elem.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - } ); -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.get( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Ensure that invalid selectors throw exceptions at attach time - // Evaluate against documentElement in case elem is a non-element node (e.g., document) - if ( selector ) { - jQuery.find.matchesSelector( documentElement, selector ); - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !( events = elemData.events ) ) { - events = elemData.events = {}; - } - if ( !( eventHandle = elemData.handle ) ) { - eventHandle = elemData.handle = function( e ) { - - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend( { - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join( "." ) - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !( handlers = events[ type ] ) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || - special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); - - if ( !elemData || !( events = elemData.events ) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[ 2 ] && - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || - selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || - special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove data and the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - dataPriv.remove( elem, "handle events" ); - } - }, - - dispatch: function( nativeEvent ) { - - // Make a writable jQuery.Event from the native event object - var event = jQuery.event.fix( nativeEvent ); - - var i, j, ret, matched, handleObj, handlerQueue, - args = new Array( arguments.length ), - handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[ 0 ] = event; - - for ( i = 1; i < arguments.length; i++ ) { - args[ i ] = arguments[ i ]; - } - - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( ( handleObj = matched.handlers[ j++ ] ) && - !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or 2) have namespace(s) - // a subset or equal to those in the bound event (both can have no namespace). - if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || - handleObj.handler ).apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( ( event.result = ret ) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, handleObj, sel, matchedHandlers, matchedSelectors, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - if ( delegateCount && - - // Support: IE <=9 - // Black-hole SVG instance trees (trac-13180) - cur.nodeType && - - // Support: Firefox <=42 - // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) - // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click - // Support: IE 11 only - // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) - !( event.type === "click" && event.button >= 1 ) ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { - matchedHandlers = []; - matchedSelectors = {}; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matchedSelectors[ sel ] === undefined ) { - matchedSelectors[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) > -1 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matchedSelectors[ sel ] ) { - matchedHandlers.push( handleObj ); - } - } - if ( matchedHandlers.length ) { - handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); - } - } - } - } - - // Add the remaining (directly-bound) handlers - cur = this; - if ( delegateCount < handlers.length ) { - handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); - } - - return handlerQueue; - }, - - addProp: function( name, hook ) { - Object.defineProperty( jQuery.Event.prototype, name, { - enumerable: true, - configurable: true, - - get: isFunction( hook ) ? - function() { - if ( this.originalEvent ) { - return hook( this.originalEvent ); - } - } : - function() { - if ( this.originalEvent ) { - return this.originalEvent[ name ]; - } - }, - - set: function( value ) { - Object.defineProperty( this, name, { - enumerable: true, - configurable: true, - writable: true, - value: value - } ); - } - } ); - }, - - fix: function( originalEvent ) { - return originalEvent[ jQuery.expando ] ? - originalEvent : - new jQuery.Event( originalEvent ); - }, - - special: { - load: { - - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - } -}; - -jQuery.removeEvent = function( elem, type, handle ) { - - // This "if" is needed for plain objects - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle ); - } -}; - -jQuery.Event = function( src, props ) { - - // Allow instantiation without the 'new' keyword - if ( !( this instanceof jQuery.Event ) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - - // Support: Android <=2.3 only - src.returnValue === false ? - returnTrue : - returnFalse; - - // Create target properties - // Support: Safari <=6 - 7 only - // Target should not be a text node (#504, #13143) - this.target = ( src.target && src.target.nodeType === 3 ) ? - src.target.parentNode : - src.target; - - this.currentTarget = src.currentTarget; - this.relatedTarget = src.relatedTarget; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || Date.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - constructor: jQuery.Event, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - isSimulated: false, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && !this.isSimulated ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && !this.isSimulated ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Includes all common event props including KeyEvent and MouseEvent specific props -jQuery.each( { - altKey: true, - bubbles: true, - cancelable: true, - changedTouches: true, - ctrlKey: true, - detail: true, - eventPhase: true, - metaKey: true, - pageX: true, - pageY: true, - shiftKey: true, - view: true, - "char": true, - charCode: true, - key: true, - keyCode: true, - button: true, - buttons: true, - clientX: true, - clientY: true, - offsetX: true, - offsetY: true, - pointerId: true, - pointerType: true, - screenX: true, - screenY: true, - targetTouches: true, - toElement: true, - touches: true, - - which: function( event ) { - var button = event.button; - - // Add which for key events - if ( event.which == null && rkeyEvent.test( event.type ) ) { - return event.charCode != null ? event.charCode : event.keyCode; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { - if ( button & 1 ) { - return 1; - } - - if ( button & 2 ) { - return 3; - } - - if ( button & 4 ) { - return 2; - } - - return 0; - } - - return event.which; - } -}, jQuery.event.addProp ); - -// Create mouseenter/leave events using mouseover/out and event-time checks -// so that event delegation works in jQuery. -// Do the same for pointerenter/pointerleave and pointerover/pointerout -// -// Support: Safari 7 only -// Safari sends mouseenter too often; see: -// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 -// for the description of the bug (it existed in older Chrome versions as well). -jQuery.each( { - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mouseenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -} ); - -jQuery.fn.extend( { - - on: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn ); - }, - one: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? - handleObj.origType + "." + handleObj.namespace : - handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each( function() { - jQuery.event.remove( this, types, fn, selector ); - } ); - } -} ); - - -var - - /* eslint-disable max-len */ - - // See https://github.com/eslint/eslint/issues/3229 - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, - - /* eslint-enable */ - - // Support: IE <=10 - 11, Edge 12 - 13 only - // In IE/Edge using regex groups here causes severe slowdowns. - // See https://connect.microsoft.com/IE/feedback/details/1736512/ - rnoInnerhtml = /\s*$/g; - -// Prefer a tbody over its parent table for containing new rows -function manipulationTarget( elem, content ) { - if ( nodeName( elem, "table" ) && - nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { - - return jQuery( elem ).children( "tbody" )[ 0 ] || elem; - } - - return elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { - elem.type = elem.type.slice( 5 ); - } else { - elem.removeAttribute( "type" ); - } - - return elem; -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.access( src ); - pdataCur = dataPriv.set( dest, pdataOld ); - events = pdataOld.events; - - if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( dataUser.hasData( src ) ) { - udataOld = dataUser.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - dataUser.set( dest, udataCur ); - } -} - -// Fix IE bugs, see support tests -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -function domManip( collection, args, callback, ignored ) { - - // Flatten any nested arrays - args = concat.apply( [], args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = collection.length, - iNoClone = l - 1, - value = args[ 0 ], - valueIsFunction = isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( valueIsFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return collection.each( function( index ) { - var self = collection.eq( index ); - if ( valueIsFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - domManip( self, args, callback, ignored ); - } ); - } - - if ( l ) { - fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - // Require either new content or an interest in ignored elements to invoke the callback - if ( first || ignored ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item - // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( collection[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !dataPriv.access( node, "globalEval" ) && - jQuery.contains( doc, node ) ) { - - if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { - - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - DOMEval( node.textContent.replace( rcleanScript, "" ), doc, node ); - } - } - } - } - } - } - - return collection; -} - -function remove( elem, selector, keepData ) { - var node, - nodes = selector ? jQuery.filter( selector, elem ) : elem, - i = 0; - - for ( ; ( node = nodes[ i ] ) != null; i++ ) { - if ( !keepData && node.nodeType === 1 ) { - jQuery.cleanData( getAll( node ) ); - } - - if ( node.parentNode ) { - if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { - setGlobalEval( getAll( node, "script" ) ); - } - node.parentNode.removeChild( node ); - } - } - - return elem; -} - -jQuery.extend( { - htmlPrefilter: function( html ) { - return html.replace( rxhtmlTag, "<$1>" ); - }, - - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); - - // Fix IE cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - cleanData: function( elems ) { - var data, elem, type, - special = jQuery.event.special, - i = 0; - - for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { - if ( acceptData( elem ) ) { - if ( ( data = elem[ dataPriv.expando ] ) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataPriv.expando ] = undefined; - } - if ( elem[ dataUser.expando ] ) { - - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataUser.expando ] = undefined; - } - } - } - } -} ); - -jQuery.fn.extend( { - detach: function( selector ) { - return remove( this, selector, true ); - }, - - remove: function( selector ) { - return remove( this, selector ); - }, - - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each( function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - } ); - }, null, value, arguments.length ); - }, - - append: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - } ); - }, - - prepend: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - } ); - }, - - before: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - } ); - }, - - after: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - } ); - }, - - empty: function() { - var elem, - i = 0; - - for ( ; ( elem = this[ i ] ) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - } ); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = jQuery.htmlPrefilter( value ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch ( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var ignored = []; - - // Make the changes, replacing each non-ignored context element with the new content - return domManip( this, arguments, function( elem ) { - var parent = this.parentNode; - - if ( jQuery.inArray( this, ignored ) < 0 ) { - jQuery.cleanData( getAll( this ) ); - if ( parent ) { - parent.replaceChild( elem, this ); - } - } - - // Force callback invocation - }, ignored ); - } -} ); - -jQuery.each( { - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: Android <=4.0 only, PhantomJS 1 only - // .get() because push.apply(_, arraylike) throws on ancient WebKit - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -} ); -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); - -var getStyles = function( elem ) { - - // Support: IE <=11 only, Firefox <=30 (#15098, #14150) - // IE throws on elements created in popups - // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" - var view = elem.ownerDocument.defaultView; - - if ( !view || !view.opener ) { - view = window; - } - - return view.getComputedStyle( elem ); - }; - -var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); - - - -( function() { - - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computeStyleTests() { - - // This is a singleton, we need to execute it only once - if ( !div ) { - return; - } - - container.style.cssText = "position:absolute;left:-11111px;width:60px;" + - "margin-top:1px;padding:0;border:0"; - div.style.cssText = - "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + - "margin:auto;border:1px;padding:1px;" + - "width:60%;top:1%"; - documentElement.appendChild( container ).appendChild( div ); - - var divStyle = window.getComputedStyle( div ); - pixelPositionVal = divStyle.top !== "1%"; - - // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 - reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; - - // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 - // Some styles come back with percentage values, even though they shouldn't - div.style.right = "60%"; - pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; - - // Support: IE 9 - 11 only - // Detect misreporting of content dimensions for box-sizing:border-box elements - boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; - - // Support: IE 9 only - // Detect overflow:scroll screwiness (gh-3699) - div.style.position = "absolute"; - scrollboxSizeVal = div.offsetWidth === 36 || "absolute"; - - documentElement.removeChild( container ); - - // Nullify the div so it wouldn't be stored in the memory and - // it will also be a sign that checks already performed - div = null; - } - - function roundPixelMeasures( measure ) { - return Math.round( parseFloat( measure ) ); - } - - var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableMarginLeftVal, - container = document.createElement( "div" ), - div = document.createElement( "div" ); - - // Finish early in limited (non-browser) environments - if ( !div.style ) { - return; - } - - // Support: IE <=9 - 11 only - // Style of cloned element affects source element cloned (#8908) - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; - - jQuery.extend( support, { - boxSizingReliable: function() { - computeStyleTests(); - return boxSizingReliableVal; - }, - pixelBoxStyles: function() { - computeStyleTests(); - return pixelBoxStylesVal; - }, - pixelPosition: function() { - computeStyleTests(); - return pixelPositionVal; - }, - reliableMarginLeft: function() { - computeStyleTests(); - return reliableMarginLeftVal; - }, - scrollboxSize: function() { - computeStyleTests(); - return scrollboxSizeVal; - } - } ); -} )(); - - -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - - // Support: Firefox 51+ - // Retrieving style before computed somehow - // fixes an issue with getting wrong values - // on detached elements - style = elem.style; - - computed = computed || getStyles( elem ); - - // getPropertyValue is needed for: - // .css('filter') (IE 9 only, #12537) - // .css('--customProperty) (#3144) - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Android Browser returns percentage for some values, - // but width seems to be reliably pixels. - // This is against the CSSOM draft spec: - // https://drafts.csswg.org/cssom/#resolved-values - if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret !== undefined ? - - // Support: IE <=9 - 11 only - // IE returns zIndex value as an integer. - ret + "" : - ret; -} - - -function addGetHookIf( conditionFn, hookFn ) { - - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - - // Hook not needed (or it's not possible to use it due - // to missing dependency), remove it. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - return ( this.get = hookFn ).apply( this, arguments ); - } - }; -} - - -var - - // Swappable if display is none or starts with table - // except "table", "table-cell", or "table-caption" - // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rcustomProp = /^--/, - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }, - - cssPrefixes = [ "Webkit", "Moz", "ms" ], - emptyStyle = document.createElement( "div" ).style; - -// Return a css property mapped to a potentially vendor prefixed property -function vendorPropName( name ) { - - // Shortcut for names that are not vendor prefixed - if ( name in emptyStyle ) { - return name; - } - - // Check for vendor prefixed names - var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in emptyStyle ) { - return name; - } - } -} - -// Return a property mapped along what jQuery.cssProps suggests or to -// a vendor prefixed property. -function finalPropName( name ) { - var ret = jQuery.cssProps[ name ]; - if ( !ret ) { - ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; - } - return ret; -} - -function setPositiveNumber( elem, value, subtract ) { - - // Any relative (+/-) values have already been - // normalized at this point - var matches = rcssNum.exec( value ); - return matches ? - - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : - value; -} - -function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { - var i = dimension === "width" ? 1 : 0, - extra = 0, - delta = 0; - - // Adjustment may not be necessary - if ( box === ( isBorderBox ? "border" : "content" ) ) { - return 0; - } - - for ( ; i < 4; i += 2 ) { - - // Both box models exclude margin - if ( box === "margin" ) { - delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); - } - - // If we get here with a content-box, we're seeking "padding" or "border" or "margin" - if ( !isBorderBox ) { - - // Add padding - delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - - // For "border" or "margin", add border - if ( box !== "padding" ) { - delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - - // But still keep track of it otherwise - } else { - extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - - // If we get here with a border-box (content + padding + border), we're seeking "content" or - // "padding" or "margin" - } else { - - // For "content", subtract padding - if ( box === "content" ) { - delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } - - // For "content" or "padding", subtract border - if ( box !== "margin" ) { - delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } - - // Account for positive content-box scroll gutter when requested by providing computedVal - if ( !isBorderBox && computedVal >= 0 ) { - - // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border - // Assuming integer scroll gutter, subtract the rest and round down - delta += Math.max( 0, Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - computedVal - - delta - - extra - - 0.5 - ) ); - } - - return delta; -} - -function getWidthOrHeight( elem, dimension, extra ) { - - // Start with computed style - var styles = getStyles( elem ), - val = curCSS( elem, dimension, styles ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - valueIsBorderBox = isBorderBox; - - // Support: Firefox <=54 - // Return a confounding non-pixel value or feign ignorance, as appropriate. - if ( rnumnonpx.test( val ) ) { - if ( !extra ) { - return val; - } - val = "auto"; - } - - // Check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = valueIsBorderBox && - ( support.boxSizingReliable() || val === elem.style[ dimension ] ); - - // Fall back to offsetWidth/offsetHeight when value is "auto" - // This happens for inline elements with no explicit setting (gh-3571) - // Support: Android <=4.1 - 4.3 only - // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - if ( val === "auto" || - !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) { - - val = elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ]; - - // offsetWidth/offsetHeight provide border-box values - valueIsBorderBox = true; - } - - // Normalize "" and auto - val = parseFloat( val ) || 0; - - // Adjust for the element's box model - return ( val + - boxModelAdjustment( - elem, - dimension, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles, - - // Provide the current computed size to request scroll gutter calculation (gh-3589) - val - ) - ) + "px"; -} - -jQuery.extend( { - - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, - - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "animationIterationCount": true, - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: {}, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ), - style = elem.style; - - // Make sure that we're working with the right name. We don't - // want to query the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Gets hook for the prefixed version, then unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // Convert "+=" or "-=" to relative numbers (#7345) - if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { - value = adjustCSS( elem, name, ret ); - - // Fixes bug #9237 - type = "number"; - } - - // Make sure that null and NaN values aren't set (#7116) - if ( value == null || value !== value ) { - return; - } - - // If a number was passed in, add the unit (except for certain CSS properties) - if ( type === "number" ) { - value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); - } - - // background-* props affect original clone's values - if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { - style[ name ] = "inherit"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !( "set" in hooks ) || - ( value = hooks.set( elem, value, extra ) ) !== undefined ) { - - if ( isCustomProp ) { - style.setProperty( name, value ); - } else { - style[ name ] = value; - } - } - - } else { - - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && - ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { - - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, extra, styles ) { - var val, num, hooks, - origName = camelCase( name ), - isCustomProp = rcustomProp.test( name ); - - // Make sure that we're working with the right name. We don't - // want to modify the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } - - // Try prefixed name followed by the unprefixed name - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } - - // Convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Make numeric if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || isFinite( num ) ? num || 0 : val; - } - - return val; - } -} ); - -jQuery.each( [ "height", "width" ], function( i, dimension ) { - jQuery.cssHooks[ dimension ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - - // Certain elements can have dimension info if we invisibly show them - // but it must have a current display style that would benefit - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && - - // Support: Safari 8+ - // Table columns in Safari have non-zero offsetWidth & zero - // getBoundingClientRect().width unless display is changed. - // Support: IE <=11 only - // Running getBoundingClientRect on a disconnected node - // in IE throws an error. - ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? - swap( elem, cssShow, function() { - return getWidthOrHeight( elem, dimension, extra ); - } ) : - getWidthOrHeight( elem, dimension, extra ); - } - }, - - set: function( elem, value, extra ) { - var matches, - styles = getStyles( elem ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - subtract = extra && boxModelAdjustment( - elem, - dimension, - extra, - isBorderBox, - styles - ); - - // Account for unreliable border-box dimensions by comparing offset* to computed and - // faking a content-box to get border and padding (gh-3699) - if ( isBorderBox && support.scrollboxSize() === styles.position ) { - subtract -= Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - parseFloat( styles[ dimension ] ) - - boxModelAdjustment( elem, dimension, "border", false, styles ) - - 0.5 - ); - } - - // Convert to pixels if value adjustment is needed - if ( subtract && ( matches = rcssNum.exec( value ) ) && - ( matches[ 3 ] || "px" ) !== "px" ) { - - elem.style[ dimension ] = value; - value = jQuery.css( elem, dimension ); - } - - return setPositiveNumber( elem, value, subtract ); - } - }; -} ); - -jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, - function( elem, computed ) { - if ( computed ) { - return ( parseFloat( curCSS( elem, "marginLeft" ) ) || - elem.getBoundingClientRect().left - - swap( elem, { marginLeft: 0 }, function() { - return elem.getBoundingClientRect().left; - } ) - ) + "px"; - } - } -); - -// These hooks are used by animate to expand properties -jQuery.each( { - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i = 0, - expanded = {}, - - // Assumes a single number if not a string - parts = typeof value === "string" ? value.split( " " ) : [ value ]; - - for ( ; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( prefix !== "margin" ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -} ); - -jQuery.fn.extend( { - css: function( name, value ) { - return access( this, function( elem, name, value ) { - var styles, len, - map = {}, - i = 0; - - if ( Array.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; - - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } - - return map; - } - - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - } -} ); - - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || jQuery.easing._default; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - // Use a property on the element directly when it is not a DOM element, - // or when there is no matching style property that exists. - if ( tween.elem.nodeType !== 1 || - tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { - return tween.elem[ tween.prop ]; - } - - // Passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails. - // Simple values such as "10px" are parsed to Float; - // complex values such as "rotate(1rad)" are returned as-is. - result = jQuery.css( tween.elem, tween.prop, "" ); - - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - - // Use step hook for back compat. - // Use cssHook if its there. - // Use .style if available and use plain properties where available. - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.nodeType === 1 && - ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || - jQuery.cssHooks[ tween.prop ] ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Support: IE <=9 only -// Panic based approach to setting things on disconnected nodes -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p * Math.PI ) / 2; - }, - _default: "swing" -}; - -jQuery.fx = Tween.prototype.init; - -// Back compat <1.8 extension point -jQuery.fx.step = {}; - - - - -var - fxNow, inProgress, - rfxtypes = /^(?:toggle|show|hide)$/, - rrun = /queueHooks$/; - -function schedule() { - if ( inProgress ) { - if ( document.hidden === false && window.requestAnimationFrame ) { - window.requestAnimationFrame( schedule ); - } else { - window.setTimeout( schedule, jQuery.fx.interval ); - } - - jQuery.fx.tick(); - } -} - -// Animations created synchronously will run synchronously -function createFxNow() { - window.setTimeout( function() { - fxNow = undefined; - } ); - return ( fxNow = Date.now() ); -} - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; - - // If we include width, step value is 1 to do all cssExpand values, - // otherwise step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for ( ; i < 4; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -function createTween( value, prop, animation ) { - var tween, - collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { - - // We're done with this property - return tween; - } - } -} - -function defaultPrefilter( elem, props, opts ) { - var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, - isBox = "width" in props || "height" in props, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHiddenWithinTree( elem ), - dataShow = dataPriv.get( elem, "fxshow" ); - - // Queue-skipping animations hijack the fx hooks - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always( function() { - - // Ensure the complete handler is called before this completes - anim.always( function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - } ); - } ); - } - - // Detect show/hide animations - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.test( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { - - // Pretend to be hidden if this is a "show" and - // there is still data from a stopped show/hide - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; - - // Ignore all other no-op show/hide data - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - } - } - - // Bail out if this is a no-op like .hide().hide() - propTween = !jQuery.isEmptyObject( props ); - if ( !propTween && jQuery.isEmptyObject( orig ) ) { - return; - } - - // Restrict "overflow" and "display" styles during box animations - if ( isBox && elem.nodeType === 1 ) { - - // Support: IE <=9 - 11, Edge 12 - 15 - // Record all 3 overflow attributes because IE does not infer the shorthand - // from identically-valued overflowX and overflowY and Edge just mirrors - // the overflowX value there. - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Identify a display type, preferring old show/hide data over the CSS cascade - restoreDisplay = dataShow && dataShow.display; - if ( restoreDisplay == null ) { - restoreDisplay = dataPriv.get( elem, "display" ); - } - display = jQuery.css( elem, "display" ); - if ( display === "none" ) { - if ( restoreDisplay ) { - display = restoreDisplay; - } else { - - // Get nonempty value(s) by temporarily forcing visibility - showHide( [ elem ], true ); - restoreDisplay = elem.style.display || restoreDisplay; - display = jQuery.css( elem, "display" ); - showHide( [ elem ] ); - } - } - - // Animate inline elements as inline-block - if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { - if ( jQuery.css( elem, "float" ) === "none" ) { - - // Restore the original display value at the end of pure show/hide animations - if ( !propTween ) { - anim.done( function() { - style.display = restoreDisplay; - } ); - if ( restoreDisplay == null ) { - display = style.display; - restoreDisplay = display === "none" ? "" : display; - } - } - style.display = "inline-block"; - } - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always( function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - } ); - } - - // Implement show/hide animations - propTween = false; - for ( prop in orig ) { - - // General show/hide setup for this element animation - if ( !propTween ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); - } - - // Store hidden/visible for toggle so `.stop().toggle()` "reverses" - if ( toggle ) { - dataShow.hidden = !hidden; - } - - // Show elements before animating them - if ( hidden ) { - showHide( [ elem ], true ); - } - - /* eslint-disable no-loop-func */ - - anim.done( function() { - - /* eslint-enable no-loop-func */ - - // The final step of a "hide" animation is actually hiding the element - if ( !hidden ) { - showHide( [ elem ] ); - } - dataPriv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - } ); - } - - // Per-property setup - propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = propTween.start; - if ( hidden ) { - propTween.end = propTween.start; - propTween.start = 0; - } - } - } -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( Array.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // Not quite $.extend, this won't overwrite existing keys. - // Reusing 'index' because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -function Animation( elem, properties, options ) { - var result, - stopped, - index = 0, - length = Animation.prefilters.length, - deferred = jQuery.Deferred().always( function() { - - // Don't match elem in the :animated selector - delete tick.elem; - } ), - tick = function() { - if ( stopped ) { - return false; - } - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - - // Support: Android 2.3 only - // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, - index = 0, - length = animation.tweens.length; - - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ] ); - - // If there's more to do, yield - if ( percent < 1 && length ) { - return remaining; - } - - // If this was an empty animation, synthesize a final progress notification - if ( !length ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - } - - // Resolve the animation and report its conclusion - deferred.resolveWith( elem, [ animation ] ); - return false; - }, - animation = deferred.promise( { - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { - specialEasing: {}, - easing: jQuery.easing._default - }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - - // If we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - if ( stopped ) { - return this; - } - stopped = true; - for ( ; index < length; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // Resolve when we played the last frame; otherwise, reject - if ( gotoEnd ) { - deferred.notifyWith( elem, [ animation, 1, 0 ] ); - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - } ), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length; index++ ) { - result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - if ( isFunction( result.stop ) ) { - jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = - result.stop.bind( result ); - } - return result; - } - } - - jQuery.map( props, createTween, animation ); - - if ( isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - // Attach callbacks from options - animation - .progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); - - jQuery.fx.timer( - jQuery.extend( tick, { - elem: elem, - anim: animation, - queue: animation.opts.queue - } ) - ); - - return animation; -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweeners: { - "*": [ function( prop, value ) { - var tween = this.createTween( prop, value ); - adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); - return tween; - } ] - }, - - tweener: function( props, callback ) { - if ( isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.match( rnothtmlwhite ); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length; index++ ) { - prop = props[ index ]; - Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; - Animation.tweeners[ prop ].unshift( callback ); - } - }, - - prefilters: [ defaultPrefilter ], - - prefilter: function( callback, prepend ) { - if ( prepend ) { - Animation.prefilters.unshift( callback ); - } else { - Animation.prefilters.push( callback ); - } - } -} ); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !isFunction( easing ) && easing - }; - - // Go to the end state if fx are off - if ( jQuery.fx.off ) { - opt.duration = 0; - - } else { - if ( typeof opt.duration !== "number" ) { - if ( opt.duration in jQuery.fx.speeds ) { - opt.duration = jQuery.fx.speeds[ opt.duration ]; - - } else { - opt.duration = jQuery.fx.speeds._default; - } - } - } - - // Normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.fn.extend( { - fadeTo: function( speed, to, easing, callback ) { - - // Show any hidden elements after setting opacity to 0 - return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() - - // Animate to the value specified - .end().animate( { opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations, or finishing resolves immediately - if ( empty || dataPriv.get( this, "finish" ) ) { - anim.stop( true ); - } - }; - doAnimation.finish = doAnimation; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue && type !== false ) { - this.queue( type || "fx", [] ); - } - - return this.each( function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = dataPriv.get( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && - ( type == null || timers[ index ].queue === type ) ) { - - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // Start the next in the queue if the last step wasn't forced. - // Timers currently will call their complete callbacks, which - // will dequeue but only if they were gotoEnd. - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - } ); - }, - finish: function( type ) { - if ( type !== false ) { - type = type || "fx"; - } - return this.each( function() { - var index, - data = dataPriv.get( this ), - queue = data[ type + "queue" ], - hooks = data[ type + "queueHooks" ], - timers = jQuery.timers, - length = queue ? queue.length : 0; - - // Enable finishing flag on private data - data.finish = true; - - // Empty the queue first - jQuery.queue( this, type, [] ); - - if ( hooks && hooks.stop ) { - hooks.stop.call( this, true ); - } - - // Look for any active animations, and finish them - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && timers[ index ].queue === type ) { - timers[ index ].anim.stop( true ); - timers.splice( index, 1 ); - } - } - - // Look for any animations in the old queue and finish them - for ( index = 0; index < length; index++ ) { - if ( queue[ index ] && queue[ index ].finish ) { - queue[ index ].finish.call( this ); - } - } - - // Turn off finishing flag - delete data.finish; - } ); - } -} ); - -jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -} ); - -// Generate shortcuts for custom animations -jQuery.each( { - slideDown: genFx( "show" ), - slideUp: genFx( "hide" ), - slideToggle: genFx( "toggle" ), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -} ); - -jQuery.timers = []; -jQuery.fx.tick = function() { - var timer, - i = 0, - timers = jQuery.timers; - - fxNow = Date.now(); - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - - // Run the timer and safely remove it when done (allowing for external removal) - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } - fxNow = undefined; -}; - -jQuery.fx.timer = function( timer ) { - jQuery.timers.push( timer ); - jQuery.fx.start(); -}; - -jQuery.fx.interval = 13; -jQuery.fx.start = function() { - if ( inProgress ) { - return; - } - - inProgress = true; - schedule(); -}; - -jQuery.fx.stop = function() { - inProgress = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - - // Default speed - _default: 400 -}; - - -// Based off of the plugin by Clint Helfers, with permission. -// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ -jQuery.fn.delay = function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = window.setTimeout( next, time ); - hooks.stop = function() { - window.clearTimeout( timeout ); - }; - } ); -}; - - -( function() { - var input = document.createElement( "input" ), - select = document.createElement( "select" ), - opt = select.appendChild( document.createElement( "option" ) ); - - input.type = "checkbox"; - - // Support: Android <=4.3 only - // Default value for a checkbox should be "on" - support.checkOn = input.value !== ""; - - // Support: IE <=11 only - // Must access selectedIndex to make default options select - support.optSelected = opt.selected; - - // Support: IE <=11 only - // An input loses its value after becoming a radio - input = document.createElement( "input" ); - input.value = "t"; - input.type = "radio"; - support.radioValue = input.value === "t"; -} )(); - - -var boolHook, - attrHandle = jQuery.expr.attrHandle; - -jQuery.fn.extend( { - attr: function( name, value ) { - return access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each( function() { - jQuery.removeAttr( this, name ); - } ); - } -} ); - -jQuery.extend( { - attr: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set attributes on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - // Attribute hooks are determined by the lowercase version - // Grab necessary hook if one is defined - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - hooks = jQuery.attrHooks[ name.toLowerCase() ] || - ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); - } - - if ( value !== undefined ) { - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - } - - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - elem.setAttribute( name, value + "" ); - return value; - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - ret = jQuery.find.attr( elem, name ); - - // Non-existent attributes return null, we normalize to undefined - return ret == null ? undefined : ret; - }, - - attrHooks: { - type: { - set: function( elem, value ) { - if ( !support.radioValue && value === "radio" && - nodeName( elem, "input" ) ) { - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - } - }, - - removeAttr: function( elem, value ) { - var name, - i = 0, - - // Attribute names can contain non-HTML whitespace characters - // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 - attrNames = value && value.match( rnothtmlwhite ); - - if ( attrNames && elem.nodeType === 1 ) { - while ( ( name = attrNames[ i++ ] ) ) { - elem.removeAttribute( name ); - } - } - } -} ); - -// Hooks for boolean attributes -boolHook = { - set: function( elem, value, name ) { - if ( value === false ) { - - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - elem.setAttribute( name, name ); - } - return name; - } -}; - -jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { - var getter = attrHandle[ name ] || jQuery.find.attr; - - attrHandle[ name ] = function( elem, name, isXML ) { - var ret, handle, - lowercaseName = name.toLowerCase(); - - if ( !isXML ) { - - // Avoid an infinite loop by temporarily removing this function from the getter - handle = attrHandle[ lowercaseName ]; - attrHandle[ lowercaseName ] = ret; - ret = getter( elem, name, isXML ) != null ? - lowercaseName : - null; - attrHandle[ lowercaseName ] = handle; - } - return ret; - }; -} ); - - - - -var rfocusable = /^(?:input|select|textarea|button)$/i, - rclickable = /^(?:a|area)$/i; - -jQuery.fn.extend( { - prop: function( name, value ) { - return access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - return this.each( function() { - delete this[ jQuery.propFix[ name ] || name ]; - } ); - } -} ); - -jQuery.extend( { - prop: function( elem, name, value ) { - var ret, hooks, - nType = elem.nodeType; - - // Don't get/set properties on text, comment and attribute nodes - if ( nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { - - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && - ( ret = hooks.set( elem, value, name ) ) !== undefined ) { - return ret; - } - - return ( elem[ name ] = value ); - } - - if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { - return ret; - } - - return elem[ name ]; - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - - // Support: IE <=9 - 11 only - // elem.tabIndex doesn't always return the - // correct value when it hasn't been explicitly set - // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - // Use proper attribute retrieval(#12072) - var tabindex = jQuery.find.attr( elem, "tabindex" ); - - if ( tabindex ) { - return parseInt( tabindex, 10 ); - } - - if ( - rfocusable.test( elem.nodeName ) || - rclickable.test( elem.nodeName ) && - elem.href - ) { - return 0; - } - - return -1; - } - } - }, - - propFix: { - "for": "htmlFor", - "class": "className" - } -} ); - -// Support: IE <=11 only -// Accessing the selectedIndex property -// forces the browser to respect setting selected -// on the option -// The getter ensures a default option is selected -// when in an optgroup -// eslint rule "no-unused-expressions" is disabled for this code -// since it considers such accessions noop -if ( !support.optSelected ) { - jQuery.propHooks.selected = { - get: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent && parent.parentNode ) { - parent.parentNode.selectedIndex; - } - return null; - }, - set: function( elem ) { - - /* eslint no-unused-expressions: "off" */ - - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - }; -} - -jQuery.each( [ - "tabIndex", - "readOnly", - "maxLength", - "cellSpacing", - "cellPadding", - "rowSpan", - "colSpan", - "useMap", - "frameBorder", - "contentEditable" -], function() { - jQuery.propFix[ this.toLowerCase() ] = this; -} ); - - - - - // Strip and collapse whitespace according to HTML spec - // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace - function stripAndCollapse( value ) { - var tokens = value.match( rnothtmlwhite ) || []; - return tokens.join( " " ); - } - - -function getClass( elem ) { - return elem.getAttribute && elem.getAttribute( "class" ) || ""; -} - -function classesToArray( value ) { - if ( Array.isArray( value ) ) { - return value; - } - if ( typeof value === "string" ) { - return value.match( rnothtmlwhite ) || []; - } - return []; -} - -jQuery.fn.extend( { - addClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; - - if ( isFunction( value ) ) { - return this.each( function( j ) { - jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); - } ); - } - - if ( !arguments.length ) { - return this.attr( "class", "" ); - } - - classes = classesToArray( value ); - - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - - // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); - - if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - - // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) > -1 ) { - cur = cur.replace( " " + clazz + " ", " " ); - } - } - - // Only assign if different to avoid unneeded rendering. - finalValue = stripAndCollapse( cur ); - if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isValidValue = type === "string" || Array.isArray( value ); - - if ( typeof stateVal === "boolean" && isValidValue ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - - if ( isFunction( value ) ) { - return this.each( function( i ) { - jQuery( this ).toggleClass( - value.call( this, i, getClass( this ), stateVal ), - stateVal - ); - } ); - } - - return this.each( function() { - var className, i, self, classNames; - - if ( isValidValue ) { - - // Toggle individual class names - i = 0; - self = jQuery( this ); - classNames = classesToArray( value ); - - while ( ( className = classNames[ i++ ] ) ) { - - // Check each className given, space separated list - if ( self.hasClass( className ) ) { - self.removeClass( className ); - } else { - self.addClass( className ); - } - } - - // Toggle whole class name - } else if ( value === undefined || type === "boolean" ) { - className = getClass( this ); - if ( className ) { - - // Store className if set - dataPriv.set( this, "__className__", className ); - } - - // If the element has a class name or if we're passed `false`, - // then remove the whole classname (if there was one, the above saved it). - // Otherwise bring back whatever was previously saved (if anything), - // falling back to the empty string if nothing was stored. - if ( this.setAttribute ) { - this.setAttribute( "class", - className || value === false ? - "" : - dataPriv.get( this, "__className__" ) || "" - ); - } - } - } ); - }, - - hasClass: function( selector ) { - var className, elem, - i = 0; - - className = " " + selector + " "; - while ( ( elem = this[ i++ ] ) ) { - if ( elem.nodeType === 1 && - ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { - return true; - } - } - - return false; - } -} ); - - - - -var rreturn = /\r/g; - -jQuery.fn.extend( { - val: function( value ) { - var hooks, ret, valueIsFunction, - elem = this[ 0 ]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || - jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && - "get" in hooks && - ( ret = hooks.get( elem, "value" ) ) !== undefined - ) { - return ret; - } - - ret = elem.value; - - // Handle most common string cases - if ( typeof ret === "string" ) { - return ret.replace( rreturn, "" ); - } - - // Handle cases where value is null/undef or number - return ret == null ? "" : ret; - } - - return; - } - - valueIsFunction = isFunction( value ); - - return this.each( function( i ) { - var val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( valueIsFunction ) { - val = value.call( this, i, jQuery( this ).val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - - } else if ( typeof val === "number" ) { - val += ""; - - } else if ( Array.isArray( val ) ) { - val = jQuery.map( val, function( value ) { - return value == null ? "" : value + ""; - } ); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - } ); - } -} ); - -jQuery.extend( { - valHooks: { - option: { - get: function( elem ) { - - var val = jQuery.find.attr( elem, "value" ); - return val != null ? - val : - - // Support: IE <=10 - 11 only - // option.text throws exceptions (#14686, #14858) - // Strip and collapse whitespace - // https://html.spec.whatwg.org/#strip-and-collapse-whitespace - stripAndCollapse( jQuery.text( elem ) ); - } - }, - select: { - get: function( elem ) { - var value, option, i, - options = elem.options, - index = elem.selectedIndex, - one = elem.type === "select-one", - values = one ? null : [], - max = one ? index + 1 : options.length; - - if ( index < 0 ) { - i = max; - - } else { - i = one ? index : 0; - } - - // Loop through all the selected options - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Support: IE <=9 only - // IE8-9 doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && - - // Don't return options that are disabled or in a disabled optgroup - !option.disabled && - ( !option.parentNode.disabled || - !nodeName( option.parentNode, "optgroup" ) ) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - return values; - }, - - set: function( elem, value ) { - var optionSet, option, - options = elem.options, - values = jQuery.makeArray( value ), - i = options.length; - - while ( i-- ) { - option = options[ i ]; - - /* eslint-disable no-cond-assign */ - - if ( option.selected = - jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 - ) { - optionSet = true; - } - - /* eslint-enable no-cond-assign */ - } - - // Force browsers to behave consistently when non-matching value is set - if ( !optionSet ) { - elem.selectedIndex = -1; - } - return values; - } - } - } -} ); - -// Radios and checkboxes getter/setter -jQuery.each( [ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - set: function( elem, value ) { - if ( Array.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); - } - } - }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - return elem.getAttribute( "value" ) === null ? "on" : elem.value; - }; - } -} ); - - - - -// Return jQuery for attributes-only inclusion - - -support.focusin = "onfocusin" in window; - - -var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - stopPropagationCallback = function( e ) { - e.stopPropagation(); - }; - -jQuery.extend( jQuery.event, { - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; - - cur = lastElement = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "." ) > -1 ) { - - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split( "." ); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf( ":" ) < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join( "." ); - event.rnamespace = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === ( elem.ownerDocument || document ) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { - lastElement = cur; - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && - dataPriv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( ( !special._default || - special._default.apply( eventPath.pop(), data ) === false ) && - acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - - if ( event.isPropagationStopped() ) { - lastElement.addEventListener( type, stopPropagationCallback ); - } - - elem[ type ](); - - if ( event.isPropagationStopped() ) { - lastElement.removeEventListener( type, stopPropagationCallback ); - } - - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - // Piggyback on a donor event to simulate a different one - // Used only for `focus(in | out)` events - simulate: function( type, elem, event ) { - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true - } - ); - - jQuery.event.trigger( e, null, elem ); - } - -} ); - -jQuery.fn.extend( { - - trigger: function( type, data ) { - return this.each( function() { - jQuery.event.trigger( type, data, this ); - } ); - }, - triggerHandler: function( type, data ) { - var elem = this[ 0 ]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -} ); - - -// Support: Firefox <=44 -// Firefox doesn't have focus(in | out) events -// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 -// -// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 -// focus(in | out) events fire after focus & blur events, -// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order -// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 -if ( !support.focusin ) { - jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = dataPriv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = dataPriv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - dataPriv.remove( doc, fix ); - - } else { - dataPriv.access( doc, fix, attaches ); - } - } - }; - } ); -} -var location = window.location; - -var nonce = Date.now(); - -var rquery = ( /\?/ ); - - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE 9 - 11 only - // IE throws on parseFromString with invalid input. - try { - xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); - } catch ( e ) { - xml = undefined; - } - - if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; -}; - - -var - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, - rsubmittable = /^(?:input|select|textarea|keygen)/i; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( Array.isArray( obj ) ) { - - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - - // Item is non-scalar (array or object), encode its numeric index. - buildParams( - prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", - v, - traditional, - add - ); - } - } ); - - } else if ( !traditional && toType( obj ) === "object" ) { - - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - - // Serialize scalar item. - add( prefix, obj ); - } -} - -// Serialize an array of form elements or a set of -// key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, valueOrFunction ) { - - // If value is a function, invoke it and use its return value - var value = isFunction( valueOrFunction ) ? - valueOrFunction() : - valueOrFunction; - - s[ s.length ] = encodeURIComponent( key ) + "=" + - encodeURIComponent( value == null ? "" : value ); - }; - - // If an array was passed in, assume that it is an array of form elements. - if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - } ); - - } else { - - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ); -}; - -jQuery.fn.extend( { - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map( function() { - - // Can add propHook for "elements" to filter or add form elements - var elements = jQuery.prop( this, "elements" ); - return elements ? jQuery.makeArray( elements ) : this; - } ) - .filter( function() { - var type = this.type; - - // Use .is( ":disabled" ) so that fieldset[disabled] works - return this.name && !jQuery( this ).is( ":disabled" ) && - rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && - ( this.checked || !rcheckableType.test( type ) ); - } ) - .map( function( i, elem ) { - var val = jQuery( this ).val(); - - if ( val == null ) { - return null; - } - - if ( Array.isArray( val ) ) { - return jQuery.map( val, function( val ) { - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ); - } - - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - } ).get(); - } -} ); - - -var - r20 = /%20/g, - rhash = /#.*$/, - rantiCache = /([?&])_=[^&]*/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = "*/".concat( "*" ), - - // Anchor tag for parsing the document origin - originAnchor = document.createElement( "a" ); - originAnchor.href = location.href; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, - i = 0, - dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; - - if ( isFunction( func ) ) { - - // For each dataType in the dataTypeExpression - while ( ( dataType = dataTypes[ i++ ] ) ) { - - // Prepend if requested - if ( dataType[ 0 ] === "+" ) { - dataType = dataType.slice( 1 ) || "*"; - ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); - - // Otherwise append - } else { - ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); - } - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { - - var inspected = {}, - seekingTransport = ( structure === transports ); - - function inspect( dataType ) { - var selected; - inspected[ dataType ] = true; - jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { - var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); - if ( typeof dataTypeOrTransport === "string" && - !seekingTransport && !inspected[ dataTypeOrTransport ] ) { - - options.dataTypes.unshift( dataTypeOrTransport ); - inspect( dataTypeOrTransport ); - return false; - } else if ( seekingTransport ) { - return !( selected = dataTypeOrTransport ); - } - } ); - return selected; - } - - return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } - - return target; -} - -/* Handles responses to an ajax request: - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes; - - // Remove auto dataType and get content-type in the process - while ( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -/* Chain conversions given the request and the original response - * Also sets the responseXXX fields on the jqXHR instance - */ -function ajaxConvert( s, response, jqXHR, isSuccess ) { - var conv2, current, conv, tmp, prev, - converters = {}, - - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(); - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - current = dataTypes.shift(); - - // Convert to each sequential dataType - while ( current ) { - - if ( s.responseFields[ current ] ) { - jqXHR[ s.responseFields[ current ] ] = response; - } - - // Apply the dataFilter if provided - if ( !prev && isSuccess && s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - prev = current; - current = dataTypes.shift(); - - if ( current ) { - - // There's only work to do if current dataType is non-auto - if ( current === "*" ) { - - current = prev; - - // Convert response if prev dataType is non-auto and differs from current - } else if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split( " " ); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.unshift( tmp[ 1 ] ); - } - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s.throws ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { - state: "parsererror", - error: conv ? e : "No conversion from " + prev + " to " + current - }; - } - } - } - } - } - } - - return { state: "success", data: response }; -} - -jQuery.extend( { - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {}, - - ajaxSettings: { - url: location.href, - type: "GET", - isLocal: rlocalProtocol.test( location.protocol ), - global: true, - processData: true, - async: true, - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - "*": allTypes, - text: "text/plain", - html: "text/html", - xml: "application/xml, text/xml", - json: "application/json, text/javascript" - }, - - contents: { - xml: /\bxml\b/, - html: /\bhtml/, - json: /\bjson\b/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText", - json: "responseJSON" - }, - - // Data converters - // Keys separate source (or catchall "*") and destination types with a single space - converters: { - - // Convert anything to text - "* text": String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": JSON.parse, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - url: true, - context: true - } - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - return settings ? - - // Building a settings object - ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : - - // Extending ajaxSettings - ajaxExtend( jQuery.ajaxSettings, target ); - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var transport, - - // URL without anti-cache param - cacheURL, - - // Response headers - responseHeadersString, - responseHeaders, - - // timeout handle - timeoutTimer, - - // Url cleanup var - urlAnchor, - - // Request state (becomes false upon send and true upon completion) - completed, - - // To know if global events are to be dispatched - fireGlobals, - - // Loop variable - i, - - // uncached part of the url - uncached, - - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - - // Callbacks context - callbackContext = s.context || s, - - // Context for global events is callbackContext if it is a DOM node or jQuery collection - globalEventContext = s.context && - ( callbackContext.nodeType || callbackContext.jquery ) ? - jQuery( callbackContext ) : - jQuery.event, - - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks( "once memory" ), - - // Status-dependent callbacks - statusCode = s.statusCode || {}, - - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - - // Default abort message - strAbort = "canceled", - - // Fake xhr - jqXHR = { - readyState: 0, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( completed ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while ( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; - } - } - match = responseHeaders[ key.toLowerCase() ]; - } - return match == null ? null : match; - }, - - // Raw string - getAllResponseHeaders: function() { - return completed ? responseHeadersString : null; - }, - - // Caches the header - setRequestHeader: function( name, value ) { - if ( completed == null ) { - name = requestHeadersNames[ name.toLowerCase() ] = - requestHeadersNames[ name.toLowerCase() ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( completed == null ) { - s.mimeType = type; - } - return this; - }, - - // Status-dependent callbacks - statusCode: function( map ) { - var code; - if ( map ) { - if ( completed ) { - - // Execute the appropriate callbacks - jqXHR.always( map[ jqXHR.status ] ); - } else { - - // Lazy-add the new callbacks in a way that preserves old ones - for ( code in map ) { - statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; - } - } - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - var finalText = statusText || strAbort; - if ( transport ) { - transport.abort( finalText ); - } - done( 0, finalText ); - return this; - } - }; - - // Attach deferreds - deferred.promise( jqXHR ); - - // Add protocol if not provided (prefilters might expect it) - // Handle falsy url in the settings object (#10093: consistency with old signature) - // We also use the url parameter if available - s.url = ( ( url || s.url || location.href ) + "" ) - .replace( rprotocol, location.protocol + "//" ); - - // Alias method option to type as per ticket #12004 - s.type = options.method || options.type || s.method || s.type; - - // Extract dataTypes list - s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; - - // A cross-domain request is in order when the origin doesn't match the current origin. - if ( s.crossDomain == null ) { - urlAnchor = document.createElement( "a" ); - - // Support: IE <=8 - 11, Edge 12 - 15 - // IE throws exception on accessing the href property if url is malformed, - // e.g. http://example.com:80x/ - try { - urlAnchor.href = s.url; - - // Support: IE <=8 - 11 only - // Anchor's host property isn't correctly set when s.url is relative - urlAnchor.href = urlAnchor.href; - s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== - urlAnchor.protocol + "//" + urlAnchor.host; - } catch ( e ) { - - // If there is an error parsing the URL, assume it is crossDomain, - // it can be rejected by the transport if it is invalid - s.crossDomain = true; - } - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( completed ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) - fireGlobals = jQuery.event && s.global; - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger( "ajaxStart" ); - } - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Save the URL in case we're toying with the If-Modified-Since - // and/or If-None-Match header later on - // Remove hash to simplify url manipulation - cacheURL = s.url.replace( rhash, "" ); - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // Remember the hash so we can put it back - uncached = s.url.slice( cacheURL.length ); - - // If data is available and should be processed, append data to url - if ( s.data && ( s.processData || typeof s.data === "string" ) ) { - cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; - - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Add or update anti-cache param if needed - if ( s.cache === false ) { - cacheURL = cacheURL.replace( rantiCache, "$1" ); - uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; - } - - // Put hash and anti-cache on the URL that will be requested (gh-1732) - s.url = cacheURL + uncached; - - // Change '%20' to '+' if this is encoded form body content (gh-2658) - } else if ( s.data && s.processData && - ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { - s.data = s.data.replace( r20, "+" ); - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - if ( jQuery.lastModified[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); - } - if ( jQuery.etag[ cacheURL ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? - s.accepts[ s.dataTypes[ 0 ] ] + - ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && - ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { - - // Abort if not done already and return - return jqXHR.abort(); - } - - // Aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - completeDeferred.add( s.complete ); - jqXHR.done( s.success ); - jqXHR.fail( s.error ); - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - - // If request was aborted inside ajaxSend, stop there - if ( completed ) { - return jqXHR; - } - - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = window.setTimeout( function() { - jqXHR.abort( "timeout" ); - }, s.timeout ); - } - - try { - completed = false; - transport.send( requestHeaders, done ); - } catch ( e ) { - - // Rethrow post-completion exceptions - if ( completed ) { - throw e; - } - - // Propagate others as results - done( -1, e ); - } - } - - // Callback for when everything is done - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Ignore repeat invocations - if ( completed ) { - return; - } - - completed = true; - - // Clear timeout if it exists - if ( timeoutTimer ) { - window.clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Determine if successful - isSuccess = status >= 200 && status < 300 || status === 304; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // Convert no matter what (that way responseXXX fields are always set) - response = ajaxConvert( s, response, jqXHR, isSuccess ); - - // If successful, handle type chaining - if ( isSuccess ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - modified = jqXHR.getResponseHeader( "Last-Modified" ); - if ( modified ) { - jQuery.lastModified[ cacheURL ] = modified; - } - modified = jqXHR.getResponseHeader( "etag" ); - if ( modified ) { - jQuery.etag[ cacheURL ] = modified; - } - } - - // if no content - if ( status === 204 || s.type === "HEAD" ) { - statusText = "nocontent"; - - // if not modified - } else if ( status === 304 ) { - statusText = "notmodified"; - - // If we have data, let's convert it - } else { - statusText = response.state; - success = response.data; - error = response.error; - isSuccess = !error; - } - } else { - - // Extract error from statusText and normalize for non-aborts - error = statusText; - if ( status || !statusText ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger( "ajaxStop" ); - } - } - } - - return jqXHR; - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - } -} ); - -jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - - // Shift arguments if data argument was omitted - if ( isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - // The url can be an options object (which then must have .url) - return jQuery.ajax( jQuery.extend( { - url: url, - type: method, - dataType: type, - data: data, - success: callback - }, jQuery.isPlainObject( url ) && url ) ); - }; -} ); - - -jQuery._evalUrl = function( url ) { - return jQuery.ajax( { - url: url, - - // Make this explicit, since user can override this through ajaxSetup (#11264) - type: "GET", - dataType: "script", - cache: true, - async: false, - global: false, - "throws": true - } ); -}; - - -jQuery.fn.extend( { - wrapAll: function( html ) { - var wrap; - - if ( this[ 0 ] ) { - if ( isFunction( html ) ) { - html = html.call( this[ 0 ] ); - } - - // The elements to wrap the target around - wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); - - if ( this[ 0 ].parentNode ) { - wrap.insertBefore( this[ 0 ] ); - } - - wrap.map( function() { - var elem = this; - - while ( elem.firstElementChild ) { - elem = elem.firstElementChild; - } - - return elem; - } ).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( isFunction( html ) ) { - return this.each( function( i ) { - jQuery( this ).wrapInner( html.call( this, i ) ); - } ); - } - - return this.each( function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - } ); - }, - - wrap: function( html ) { - var htmlIsFunction = isFunction( html ); - - return this.each( function( i ) { - jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); - } ); - }, - - unwrap: function( selector ) { - this.parent( selector ).not( "body" ).each( function() { - jQuery( this ).replaceWith( this.childNodes ); - } ); - return this; - } -} ); - - -jQuery.expr.pseudos.hidden = function( elem ) { - return !jQuery.expr.pseudos.visible( elem ); -}; -jQuery.expr.pseudos.visible = function( elem ) { - return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); -}; - - - - -jQuery.ajaxSettings.xhr = function() { - try { - return new window.XMLHttpRequest(); - } catch ( e ) {} -}; - -var xhrSuccessStatus = { - - // File protocol always yields status code 0, assume 200 - 0: 200, - - // Support: IE <=9 only - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; - -jQuery.ajaxTransport( function( options ) { - var callback, errorCallback; - - // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(); - - xhr.open( - options.type, - options.url, - options.async, - options.username, - options.password - ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { - headers[ "X-Requested-With" ] = "XMLHttpRequest"; - } - - // Set headers - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - callback = errorCallback = xhr.onload = - xhr.onerror = xhr.onabort = xhr.ontimeout = - xhr.onreadystatechange = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - - // Support: IE <=9 only - // On a manual native abort, IE9 throws - // errors on any property access that is not readyState - if ( typeof xhr.status !== "number" ) { - complete( 0, "error" ); - } else { - complete( - - // File: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - - // Support: IE <=9 only - // IE9 has no XHR2 but throws on binary (trac-11426) - // For XHR2 non-text, let the caller handle it (gh-2498) - ( xhr.responseType || "text" ) !== "text" || - typeof xhr.responseText !== "string" ? - { binary: xhr.response } : - { text: xhr.responseText }, - xhr.getAllResponseHeaders() - ); - } - } - }; - }; - - // Listen to events - xhr.onload = callback(); - errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); - - // Support: IE 9 only - // Use onreadystatechange to replace onabort - // to handle uncaught aborts - if ( xhr.onabort !== undefined ) { - xhr.onabort = errorCallback; - } else { - xhr.onreadystatechange = function() { - - // Check readyState before timeout as it changes - if ( xhr.readyState === 4 ) { - - // Allow onerror to be called first, - // but that will not handle a native abort - // Also, save errorCallback to a variable - // as xhr.onerror cannot be accessed - window.setTimeout( function() { - if ( callback ) { - errorCallback(); - } - } ); - } - }; - } - - // Create the abort callback - callback = callback( "abort" ); - - try { - - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { - - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, - - abort: function() { - if ( callback ) { - callback(); - } - } - }; - } -} ); - - - - -// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) -jQuery.ajaxPrefilter( function( s ) { - if ( s.crossDomain ) { - s.contents.script = false; - } -} ); - -// Install script dataType -jQuery.ajaxSetup( { - accepts: { - script: "text/javascript, application/javascript, " + - "application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /\b(?:java|ecma)script\b/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -} ); - -// Handle cache's special case and crossDomain -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - } -} ); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function( s ) { - - // This transport only deals with cross domain requests - if ( s.crossDomain ) { - var script, callback; - return { - send: function( _, complete ) { - script = jQuery( " - - - - - - -
    - -
    - - - - \ No newline at end of file diff --git a/html/nttc/dist/tab_filtering.html b/html/nttc/dist/tab_filtering.html deleted file mode 100644 index 0e3943f151b..00000000000 --- a/html/nttc/dist/tab_filtering.html +++ /dev/null @@ -1,33 +0,0 @@ -
    -

    Configuration

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Announce Jobs?
    Job Announcement Format:
    Theme Jobs?
    Theme Names?
    Louder Command Members
    Announce Timecodes?
    Language Conversion?
    -
    diff --git a/html/nttc/dist/tab_firewall.html b/html/nttc/dist/tab_firewall.html deleted file mode 100644 index db8ee8a0f73..00000000000 --- a/html/nttc/dist/tab_firewall.html +++ /dev/null @@ -1,4 +0,0 @@ -
    -

    FIREWALL

    - -
    \ No newline at end of file diff --git a/html/nttc/dist/tab_hack.html b/html/nttc/dist/tab_hack.html deleted file mode 100644 index 189ac836954..00000000000 --- a/html/nttc/dist/tab_hack.html +++ /dev/null @@ -1,22 +0,0 @@ -
    -

    1337 HAaCCkEr MeNU!

    - - - - - - - - - -
    H*lp Tr%%ait0r i* $c/e#ce
    HoNKKk!!11!
    -
    - \ No newline at end of file diff --git a/html/nttc/dist/tab_home.html b/html/nttc/dist/tab_home.html deleted file mode 100644 index eb98b18a4db..00000000000 --- a/html/nttc/dist/tab_home.html +++ /dev/null @@ -1,9 +0,0 @@ -
    -

    Home

    - - - - - -
    Telecomms Activated?
    -
    diff --git a/html/nttc/dist/tab_regex.html b/html/nttc/dist/tab_regex.html deleted file mode 100644 index 3e3d0d90229..00000000000 --- a/html/nttc/dist/tab_regex.html +++ /dev/null @@ -1,4 +0,0 @@ -
    -

    Regex

    - -
    \ No newline at end of file diff --git a/html/nttc/dist/uiTitleFluff.png b/html/nttc/dist/uiTitleFluff.png deleted file mode 100644 index 513ba0c4965..00000000000 Binary files a/html/nttc/dist/uiTitleFluff.png and /dev/null differ diff --git a/html/nttc/gulpfile.js b/html/nttc/gulpfile.js deleted file mode 100644 index 710ebdf3e43..00000000000 --- a/html/nttc/gulpfile.js +++ /dev/null @@ -1,106 +0,0 @@ -/* Dependencies */ - -// Regular node dependencies -var child_process = require("child_process"); -var fs = require("fs"); -var path = require("path"); - -// Main compilers -var browserify = require("browserify"); -var gulp = require("gulp"); - -// Extras -var del = require("del"); -var concat = require("gulp-concat"); -var flatten = require("gulp-flatten"); -var rename = require("gulp-rename"); -var buffer = require("vinyl-buffer"); -var source = require("vinyl-source-stream"); - -/* Configuration */ -const watch_targets = [ - "./src/index.js", - "./src/css/*", - "./src/js/*", - "./src/html/**/*" -] - -const output = { - "css": "bundle.css", - "dest": "./dist/", - "js": "bundle.js" -}; - -/* Clean out the dist directory to get rid of any old build artifacts. */ -gulp.task("clean", function () { - del(output.dest + "*"); -}); - -/* This uses browserify to compress every single require() into a single javascript file. */ -gulp.task("browserify", ["clean"], function () { - var bundleStream = browserify("./src/index.js").bundle(); - - bundleStream - .pipe(source("index.js")) - .pipe(rename("bundle.js")) - .pipe(buffer()) - .pipe(gulp.dest(output.dest)) -}); - - -/* CSS concatenation and output. */ -gulp.task("css", ["clean"], function () { - gulp.src("./src/css/*.css") - .pipe(concat(output.css)) - .pipe(buffer()) - .pipe(gulp.dest(output.dest)) -}); - -/* Basically just copy-paste the html files into the dest, but flatten the directory structure. */ -gulp.task("etc", ["clean"], function () { - gulp.src("./src/html/**/*.html") - .pipe(flatten()) - .pipe(buffer()) - .pipe(gulp.dest(output.dest)); - gulp.src("./src/img/*") - .pipe(buffer()) - .pipe(gulp.dest(output.dest)); -}); - -// This runs all of the other defined tasks on "gulp" -gulp.task("default", ["css", "etc", "browserify"]) - -// Autoreload -gulp.task("reload", ["default"], function() { - child_process.exec("reload.bat", function (err, stdout) { - if (err) - throw err; - - var byond_cache = path.join(stdout.trim(), "BYOND", "cache"); - var files = fs.readdirSync(byond_cache); - for (let file of files) { - let filepath = path.join(byond_cache, file); - let stats = fs.statSync(filepath) - if (file.startsWith("tmp") && stats.isDirectory()) { - var tmpFiles = fs.readdirSync(filepath); - if (tmpFiles.includes("bundle.js")) { - setTimeout(function () {transfer_files(filepath)}, 500); - } - } - } - }); -}); - -function transfer_files(target) { - console.log("transfer_files") - let filesToTransfer = fs.readdirSync(path.join(".", "dist")); - for (let file of filesToTransfer) { - console.log(file, path.join(target, file)) - let filepath = path.join(".", "dist", file); - fs.createReadStream(filepath).pipe(fs.createWriteStream(path.join(target, file))) - } -} - -gulp.task("watch", function () { - gulp.watch(watch_targets, ["reload"]); -}); \ No newline at end of file diff --git a/html/nttc/package.json b/html/nttc/package.json deleted file mode 100644 index c1d547905c7..00000000000 --- a/html/nttc/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "nttc", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Tigercat2000", - "license": "AGPL-3.0-only", - "dependencies": { - "del": "^3.0.0", - "gulp-flatten": "^0.4.0", - "he": "^1.2.0", - "jquery": "^3.3.1" - }, - "devDependencies": { - "browserify": "^16.2.3", - "gulp": "^3.9.1", - "gulp-concat": "^2.6.1", - "gulp-rename": "^1.4.0", - "vinyl-buffer": "^1.0.1", - "vinyl-source-stream": "^2.0.0" - } -} diff --git a/html/nttc/reload.bat b/html/nttc/reload.bat deleted file mode 100644 index 39ad27c8815..00000000000 --- a/html/nttc/reload.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off - -for /f "tokens=3* delims= " %%a in ( - 'reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Personal"' -) do ( - set documents=%%a -) - -echo %documents% \ No newline at end of file diff --git a/html/nttc/src/css/index.css b/html/nttc/src/css/index.css deleted file mode 100644 index 293fb16a941..00000000000 --- a/html/nttc/src/css/index.css +++ /dev/null @@ -1,154 +0,0 @@ -/* Global */ -html, body { - background-color: #272727; - font-family: Verdana, Geneva, sans-serif; - font-size: 12px; - color: #fff; - margin: 0; - padding: 0; -} - -/* Navbar */ -#navbar { - background: #383838; - border-bottom: 2px solid #161616; - list-style-type: none; - height: 28px; - margin: 0; - padding: 0; -} - -#navbar > div { - background: #40628a; - border-radius: 5px 5px 0 0; - color: #ffffff; - display: block; - height: 80%; - float: left; - text-decoration: none; - padding: 0 7px 0 5px; - margin: 6px 0 0 5px; -} - -#navbar > div:hover { - background: #ffffff; - color: #40628a; - cursor: pointer; -} - -#navbar > img { - float: left; - margin: 2px 10px 2px 0; - height: 24px; -} - -#navbar > .title { - color: #a7a7a7; - float: right; - background: none; - font-size: 1.5em; - font-family: Helvetica; - text-decoration: bold; - padding: 0; - padding-right: 10px; - margin: 0; -} - -#navbar > .title:hover { - background: none; - color: #a7a7a7; - cursor: default; -} - -.btnActive { - background: #2f943c !important; - color: #fff !important; -} - -/* Content */ -#content { - min-height: 75%; - line-height: 1.5; - margin: 10px; -} - -/* Links */ -.link, .linkOn, .linkOff { - background: #40628a; - border: 1px solid #161616; - color: #ffffff; - cursor: pointer; - display: inline; - margin: 0 2px 0px 0; - min-width: 15px; - padding: 0px 4px 0px 4px; - text-align: center; - text-decoration: none; - user-select: none; - white-space: nowrap; -} - -.linkOn, .linkOn:link, .linkOn:visited, .linkOn:active, .linkOn:hover -{ - color: #ffffff; - background: #2f943c; - border-color: #24722e; -} - -.linkOff, .linkOff:link, .linkOff:visited, .linkOff:active, .linkOff:hover -{ - color: #ffffff; - background: #999999; - border-color: #666666; -} - -.linkActive:hover { - background: #507aac; -} - -.linkActive:active { - background: #2f943c; -} - -/* Config Tables */ -.tblConfig td { - padding-right: 40px; -} - -.tables { - border: 1px solid black; - text-align: center; -} - -.tables th { - border-bottom: 2px solid black; -} - -.tables th, .tables td { - border-right: 2px dotted black; - min-width: 70px; -} - -/* Footer */ -.footer { - height: 15px; - position: absolute; - right: 10px; - bottom: 10px; -} - -/* Hacking stuff. */ -.hack { - color: #fff; - text-shadow: 1px 1px #300; - font-size: 1.12em; -} -.hackBtn { - background-color: #a00 !important; -} -.hackBtn:hover { - background-color: #fff !important; -} -.hackBtn:hover .hack { - color: #000 !important; -} \ No newline at end of file diff --git a/html/nttc/src/html/index.html b/html/nttc/src/html/index.html deleted file mode 100644 index 80e7a40ac81..00000000000 --- a/html/nttc/src/html/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - NTSL - - - - - - - -
    - -
    - - - - \ No newline at end of file diff --git a/html/nttc/src/html/tabs/tab_filtering.html b/html/nttc/src/html/tabs/tab_filtering.html deleted file mode 100644 index 0e3943f151b..00000000000 --- a/html/nttc/src/html/tabs/tab_filtering.html +++ /dev/null @@ -1,33 +0,0 @@ -
    -

    Configuration

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Announce Jobs?
    Job Announcement Format:
    Theme Jobs?
    Theme Names?
    Louder Command Members
    Announce Timecodes?
    Language Conversion?
    -
    diff --git a/html/nttc/src/html/tabs/tab_firewall.html b/html/nttc/src/html/tabs/tab_firewall.html deleted file mode 100644 index db8ee8a0f73..00000000000 --- a/html/nttc/src/html/tabs/tab_firewall.html +++ /dev/null @@ -1,4 +0,0 @@ -
    -

    FIREWALL

    - -
    \ No newline at end of file diff --git a/html/nttc/src/html/tabs/tab_hack.html b/html/nttc/src/html/tabs/tab_hack.html deleted file mode 100644 index 189ac836954..00000000000 --- a/html/nttc/src/html/tabs/tab_hack.html +++ /dev/null @@ -1,22 +0,0 @@ -
    -

    1337 HAaCCkEr MeNU!

    - - - - - - - - - -
    H*lp Tr%%ait0r i* $c/e#ce
    HoNKKk!!11!
    -
    - \ No newline at end of file diff --git a/html/nttc/src/html/tabs/tab_home.html b/html/nttc/src/html/tabs/tab_home.html deleted file mode 100644 index eb98b18a4db..00000000000 --- a/html/nttc/src/html/tabs/tab_home.html +++ /dev/null @@ -1,9 +0,0 @@ -
    -

    Home

    - - - - - -
    Telecomms Activated?
    -
    diff --git a/html/nttc/src/html/tabs/tab_regex.html b/html/nttc/src/html/tabs/tab_regex.html deleted file mode 100644 index 3e3d0d90229..00000000000 --- a/html/nttc/src/html/tabs/tab_regex.html +++ /dev/null @@ -1,4 +0,0 @@ -
    -

    Regex

    - -
    \ No newline at end of file diff --git a/html/nttc/src/img/uiTitleFluff.png b/html/nttc/src/img/uiTitleFluff.png deleted file mode 100644 index 513ba0c4965..00000000000 Binary files a/html/nttc/src/img/uiTitleFluff.png and /dev/null differ diff --git a/html/nttc/src/index.js b/html/nttc/src/index.js deleted file mode 100644 index d6040629e53..00000000000 --- a/html/nttc/src/index.js +++ /dev/null @@ -1 +0,0 @@ -var main = require("./js/main.js") \ No newline at end of file diff --git a/html/nttc/src/js/link_loader.js b/html/nttc/src/js/link_loader.js deleted file mode 100644 index 6e5a26f78fe..00000000000 --- a/html/nttc/src/js/link_loader.js +++ /dev/null @@ -1,14 +0,0 @@ -var $ = require("jquery"); - -module.exports.reload = function () { - $(".linkActive") - .off("click") - .on("click", function (event) { - event.preventDefault(); - var href = $(this).data("href"); - if (href) { - href = window.byondSrc + href; - window.location.href = href; - } - }) -}; \ No newline at end of file diff --git a/html/nttc/src/js/main.js b/html/nttc/src/js/main.js deleted file mode 100644 index 99a553b061b..00000000000 --- a/html/nttc/src/js/main.js +++ /dev/null @@ -1,42 +0,0 @@ -var $ = require("jquery"); -var he = require("he"); -var templater = require("./templater.js") - -$(document).ready(function () { - if(window.originalConfig) { - window.config = JSON.parse(he.decode(window.originalConfig)) - } - - var current_tab = "home"; - - function tab(tabname) { - console.log(tabname) - loadtab(tabname); - } - - function loadtab(tabname) { - current_tab = tabname; - $.when($.ajax({ - url: "tab_" + tabname + ".html", - cache: false, - dataType: 'html'})) - .done(function (tabdata) { - $("#content").html(tabdata); - templater.parseCurrentPage(); - }); - } - - window.reload_tab = function() { - loadtab(current_tab) - } - - loadtab("home"); - $(".navBtn[data-tab='home']").addClass("btnActive"); - - $(".navBtn").click(function () { - $(".navBtn").removeClass("btnActive") - var toSwitch = $(this).data("tab"); - $(this).addClass("btnActive"); - tab(toSwitch); - }); -}); \ No newline at end of file diff --git a/html/nttc/src/js/templater.js b/html/nttc/src/js/templater.js deleted file mode 100644 index 14efb3d865c..00000000000 --- a/html/nttc/src/js/templater.js +++ /dev/null @@ -1,145 +0,0 @@ -var $ = require("jquery"); - -function createLink(href, text) { - let $link = $("
    "); - $link.addClass("link linkActive"); - $link.data("href", href); - $link.attr("unselectable", "on") - $link.text(text); - return $link; -} - -function link_onClick(event) { - event.preventDefault(); - let href = $(this).data("href") - if (href) { - href = window.byondSrc + href; - window.location.href = href; - } -} - -module.exports.parseCurrentPage = function () { - $("listBoat").each(function () { - var config_attr = $(this).data("config"); - if (!config_attr) - return; - - let th = $(this).data("header"); - - let dataList = config[config_attr]; - $(this).replaceWith(""); - - if (th) { - let assembledString = ""; - let split = th.split("|"); - for (let header in split) { - assembledString += ""; - } - assembledString += ""; - $("#WORK").append(assembledString); - } - - for (let key in dataList) { - let value = dataList[key]; - let $tr = $(""); - $tr.append($("\s*$/g,ge={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"
    "; - assembledString += split[header]; - assembledString += "
    ").text(key)); - $tr.append($("").text(value)); - let $td = $(""); - $td.append(createLink('table='+config_attr+';delete_row='+key, "X")) - $tr.append($td); - $("#WORK").append($tr); - } - - $(createLink('table='+config_attr+';create_row=1', "New")).insertAfter("#WORK").click(link_onClick); - $("#WORK .link").click(link_onClick); - $("#WORK").attr("id", null); - }); - - $("arrayBoat").each(function () { - var config_attr = $(this).data("config"); - if (!config_attr) - return; - - let th = $(this).data("header"); - - let dataList = config[config_attr]; - $(this).replaceWith(""); - - if (th) { - let assembledString = ""; - let split = th.split("|"); - for (let header in split) { - assembledString += ""; - } - assembledString += ""; - $("#WORK").append(assembledString); - } - - for (var i = 0; i < dataList.length; i++) { - let value = dataList[i]; - let $tr = $(""); - $tr.append($("\s*$/g,ge={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"
    "; - assembledString += split[header]; - assembledString += "
    ").text(value)); - let $td = $(""); - $td.append(createLink('array='+config_attr+';delete_item='+value, "X")) - $tr.append($td); - $("#WORK").append($tr); - } - - $(createLink('array='+config_attr+';create_item=1', "New")).insertAfter("#WORK").click(link_onClick); - $("#WORK .link").click(link_onClick); - $("#WORK").attr("id", null); - }); - - $("activeLink").each(function () { - let href = $(this).data("href"); - let simple_config = $(this).data("sconfig"); - let advanced_config = $(this).data("aconfig"); - let internalText = $(this).text(); - - $(this).replaceWith("
    ") - $("#WORK") - .addClass("link linkActive") - .data("href", href) - .text(internalText) - .on("click", link_onClick) - .attr("unselectable", "on") - - if (simple_config) { - if (window.config[simple_config]) { - $("#WORK") - .addClass("linkOn") - .text("Enabled") - } else { - $("#WORK") - .text("Disabled") - } - } - - if (advanced_config) { - if (window.config[advanced_config]) - $("#WORK").text(window.config[advanced_config]) - else - $("#WORK").text("Unset") - } - - $("#WORK").attr("id", null); - }); - - if (!window.secretsunlocked) { - $("div[data-locked='1']").hide() - } else { - $("div[data-locked='1']").show() - } - - $("configRead").each(function () { - let seeked = $(this).data("config"); - $(this).replaceWith("") - $("#WORK") - .text(window.config[seeked]) - .attr("id", null); - }); -} \ No newline at end of file diff --git a/html/nttc/src/package.json b/html/nttc/src/package.json deleted file mode 100644 index a40efa7ba1c..00000000000 --- a/html/nttc/src/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "nttc-src", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "Tigercat2000", - "license": "AGPL-3.0-only", - "dependencies": { - "he": "^1.1.1", - "jquery": "^3.3.1" - } -} diff --git a/icons/effects/genetics.dmi b/icons/effects/genetics.dmi index b177589f679..e51ce35e3ce 100644 Binary files a/icons/effects/genetics.dmi and b/icons/effects/genetics.dmi differ diff --git a/icons/goonstation/objects/objects.dmi b/icons/goonstation/objects/objects.dmi index 8dadb400668..2707ce8b9b8 100644 Binary files a/icons/goonstation/objects/objects.dmi and b/icons/goonstation/objects/objects.dmi differ diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi index 8ac73bf20d6..e55b06fe8f1 100644 Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ diff --git a/icons/mob/body_accessory_64.dmi b/icons/mob/body_accessory_64.dmi deleted file mode 100644 index 72d7f5e0d46..00000000000 Binary files a/icons/mob/body_accessory_64.dmi and /dev/null differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index aea3905e56a..88b28aff5a9 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index 849db6579a5..df6b8f4de1f 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ diff --git a/icons/mob/human_races/r_def_grey.dmi b/icons/mob/human_races/r_def_grey.dmi index b243f88e401..da6e9fd9c69 100644 Binary files a/icons/mob/human_races/r_def_grey.dmi and b/icons/mob/human_races/r_def_grey.dmi differ diff --git a/icons/mob/human_races/r_def_human.dmi b/icons/mob/human_races/r_def_human.dmi index 92ee97b4aba..804926811a2 100644 Binary files a/icons/mob/human_races/r_def_human.dmi and b/icons/mob/human_races/r_def_human.dmi differ diff --git a/icons/mob/human_races/r_grey.dmi b/icons/mob/human_races/r_grey.dmi index 1f66332a577..0e186b3e740 100644 Binary files a/icons/mob/human_races/r_grey.dmi and b/icons/mob/human_races/r_grey.dmi differ diff --git a/icons/mob/human_races/r_human.dmi b/icons/mob/human_races/r_human.dmi index 0cbbde7fb3a..9d6957f3272 100644 Binary files a/icons/mob/human_races/r_human.dmi and b/icons/mob/human_races/r_human.dmi differ diff --git a/icons/mob/human_races/r_nucleation.dmi b/icons/mob/human_races/r_nucleation.dmi index c67aa7fc70d..8c38c42a20e 100644 Binary files a/icons/mob/human_races/r_nucleation.dmi and b/icons/mob/human_races/r_nucleation.dmi differ diff --git a/icons/mob/human_races/r_plant.dmi b/icons/mob/human_races/r_plant.dmi index c728cb1cd1e..30052158ff6 100644 Binary files a/icons/mob/human_races/r_plant.dmi and b/icons/mob/human_races/r_plant.dmi differ diff --git a/icons/mob/human_races/r_tajaran.dmi b/icons/mob/human_races/r_tajaran.dmi index d15b5fc9544..0d0a8e96a4b 100644 Binary files a/icons/mob/human_races/r_tajaran.dmi and b/icons/mob/human_races/r_tajaran.dmi differ diff --git a/icons/mob/human_races/r_vulpkanin.dmi b/icons/mob/human_races/r_vulpkanin.dmi index 3bcdb3539b7..c974e1bbd40 100644 Binary files a/icons/mob/human_races/r_vulpkanin.dmi and b/icons/mob/human_races/r_vulpkanin.dmi differ diff --git a/icons/mob/human_races/tatt1.dmi b/icons/mob/human_races/tatt1.dmi index f2bf07ce613..477c569fecb 100644 Binary files a/icons/mob/human_races/tatt1.dmi and b/icons/mob/human_races/tatt1.dmi differ diff --git a/icons/mob/inhands/fluff_lefthand.dmi b/icons/mob/inhands/fluff_lefthand.dmi index 0415f69679f..daed1b89256 100644 Binary files a/icons/mob/inhands/fluff_lefthand.dmi and b/icons/mob/inhands/fluff_lefthand.dmi differ diff --git a/icons/mob/inhands/fluff_righthand.dmi b/icons/mob/inhands/fluff_righthand.dmi index 1ccd153af00..83666d38747 100644 Binary files a/icons/mob/inhands/fluff_righthand.dmi and b/icons/mob/inhands/fluff_righthand.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 3d02cfd7a58..fb8efeadfb1 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 265230ad369..e11fd688338 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index e83340855a6..ce6a3d96012 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/icons/mob/screen_alien.dmi b/icons/mob/screen_alien.dmi index c254b276bc5..209ec839939 100644 Binary files a/icons/mob/screen_alien.dmi and b/icons/mob/screen_alien.dmi differ diff --git a/icons/mob/species/drask/head.dmi b/icons/mob/species/drask/head.dmi index fd0d43ba44f..b9f0604c960 100644 Binary files a/icons/mob/species/drask/head.dmi and b/icons/mob/species/drask/head.dmi differ diff --git a/icons/mob/species/drask/suit.dmi b/icons/mob/species/drask/suit.dmi index a5fa1e95a3c..d75a28f2bee 100644 Binary files a/icons/mob/species/drask/suit.dmi and b/icons/mob/species/drask/suit.dmi differ diff --git a/icons/mob/species/grey/head.dmi b/icons/mob/species/grey/head.dmi index 745ef13e14a..4ff783bbb74 100644 Binary files a/icons/mob/species/grey/head.dmi and b/icons/mob/species/grey/head.dmi differ diff --git a/icons/mob/species/grey/suit.dmi b/icons/mob/species/grey/suit.dmi index 2766407b18b..3070f6627ea 100644 Binary files a/icons/mob/species/grey/suit.dmi and b/icons/mob/species/grey/suit.dmi differ diff --git a/icons/mob/species/plasmaman/helmet.dmi b/icons/mob/species/plasmaman/helmet.dmi index 88c3e51c70c..c0c3413bb71 100644 Binary files a/icons/mob/species/plasmaman/helmet.dmi and b/icons/mob/species/plasmaman/helmet.dmi differ diff --git a/icons/mob/species/plasmaman/uniform.dmi b/icons/mob/species/plasmaman/uniform.dmi index 6667746c438..f3d53d76db7 100644 Binary files a/icons/mob/species/plasmaman/uniform.dmi and b/icons/mob/species/plasmaman/uniform.dmi differ diff --git a/icons/mob/species/tajaran/suit.dmi b/icons/mob/species/tajaran/suit.dmi index 6d43df756c7..2f7d8f34907 100644 Binary files a/icons/mob/species/tajaran/suit.dmi and b/icons/mob/species/tajaran/suit.dmi differ diff --git a/icons/mob/species/vox/head.dmi b/icons/mob/species/vox/head.dmi index 6de29d2fd80..6c4b2b43f6a 100644 Binary files a/icons/mob/species/vox/head.dmi and b/icons/mob/species/vox/head.dmi differ diff --git a/icons/mob/species/vox/suit.dmi b/icons/mob/species/vox/suit.dmi index 467dcd713aa..730149860d5 100644 Binary files a/icons/mob/species/vox/suit.dmi and b/icons/mob/species/vox/suit.dmi differ diff --git a/icons/mob/species/vox/uniform.dmi b/icons/mob/species/vox/uniform.dmi index 3eb4fec6f6f..182fe4bfddb 100644 Binary files a/icons/mob/species/vox/uniform.dmi and b/icons/mob/species/vox/uniform.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index 6c622704fc7..d71fb9b1d21 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/suit_fat.dmi b/icons/mob/suit_fat.dmi deleted file mode 100644 index 1271be5fd54..00000000000 Binary files a/icons/mob/suit_fat.dmi and /dev/null differ diff --git a/icons/mob/uniform_fat.dmi b/icons/mob/uniform_fat.dmi deleted file mode 100644 index 31fdc67edae..00000000000 Binary files a/icons/mob/uniform_fat.dmi and /dev/null differ diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index adf304513c7..3d287a2365a 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/cloning.dmi b/icons/obj/cloning.dmi index 69abac9ee4f..83f5d6352d2 100644 Binary files a/icons/obj/cloning.dmi and b/icons/obj/cloning.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index 15405a4ab96..f942f9fd8cd 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/species/plasmaman/hats.dmi b/icons/obj/clothing/species/plasmaman/hats.dmi index 3a24c20bd93..f4064942316 100644 Binary files a/icons/obj/clothing/species/plasmaman/hats.dmi and b/icons/obj/clothing/species/plasmaman/hats.dmi differ diff --git a/icons/obj/clothing/species/plasmaman/uniform.dmi b/icons/obj/clothing/species/plasmaman/uniform.dmi index bc3f4d59a50..d41f12135e1 100644 Binary files a/icons/obj/clothing/species/plasmaman/uniform.dmi and b/icons/obj/clothing/species/plasmaman/uniform.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 95e515f9f86..7400d5d63ef 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/cult.dmi b/icons/obj/cult.dmi index 878bc71bdff..f592d142e87 100644 Binary files a/icons/obj/cult.dmi and b/icons/obj/cult.dmi differ diff --git a/icons/obj/custom_items.dmi b/icons/obj/custom_items.dmi index b632964978d..2b1c7edfa58 100644 Binary files a/icons/obj/custom_items.dmi and b/icons/obj/custom_items.dmi differ diff --git a/icons/obj/doors/airlocks/cult/runed/hell-overlays.dmi b/icons/obj/doors/airlocks/cult/runed/hell-overlays.dmi new file mode 100644 index 00000000000..a1b9596b5b5 Binary files /dev/null and b/icons/obj/doors/airlocks/cult/runed/hell-overlays.dmi differ diff --git a/icons/obj/doors/airlocks/cult/runed/hell.dmi b/icons/obj/doors/airlocks/cult/runed/hell.dmi new file mode 100644 index 00000000000..6deccac0c8d Binary files /dev/null and b/icons/obj/doors/airlocks/cult/runed/hell.dmi differ diff --git a/icons/obj/doors/airlocks/cult/unruned/hell-overlays.dmi b/icons/obj/doors/airlocks/cult/unruned/hell-overlays.dmi new file mode 100644 index 00000000000..2bbc8e386d5 Binary files /dev/null and b/icons/obj/doors/airlocks/cult/unruned/hell-overlays.dmi differ diff --git a/icons/obj/doors/airlocks/cult/unruned/hell.dmi b/icons/obj/doors/airlocks/cult/unruned/hell.dmi new file mode 100644 index 00000000000..0bd8a2a6fad Binary files /dev/null and b/icons/obj/doors/airlocks/cult/unruned/hell.dmi differ diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index 01295525b15..303ae139574 100644 Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi index 614bac4094b..f1d09247bbd 100644 Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi index bac18fe788d..bc7e927aab2 100644 Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ diff --git a/icons/obj/narsie.dmi b/icons/obj/narsie.dmi index 3c69e433404..0fdb1a0f88c 100644 Binary files a/icons/obj/narsie.dmi and b/icons/obj/narsie.dmi differ diff --git a/icons/obj/narsie_spawn_anim.dmi b/icons/obj/narsie_spawn_anim.dmi index 0aedcf38598..61ba867ff06 100644 Binary files a/icons/obj/narsie_spawn_anim.dmi and b/icons/obj/narsie_spawn_anim.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 33274c3fdb2..ca1dec37685 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 20a27b2781c..eb3901077b9 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/icons/obj/tcomms.dmi b/icons/obj/tcomms.dmi new file mode 100644 index 00000000000..651de700b35 Binary files /dev/null and b/icons/obj/tcomms.dmi differ diff --git a/icons/obj/terminals.dmi b/icons/obj/terminals.dmi index 45baaf3f7ba..c47cd86e6d3 100644 Binary files a/icons/obj/terminals.dmi and b/icons/obj/terminals.dmi differ diff --git a/icons/obj/toy.dmi b/icons/obj/toy.dmi index 511b578ad4a..1ef7016307d 100644 Binary files a/icons/obj/toy.dmi and b/icons/obj/toy.dmi differ diff --git a/icons/paper_icons/ntlogo.png b/icons/paper_icons/ntlogo.png index d5614a964ee..3aeae313238 100644 Binary files a/icons/paper_icons/ntlogo.png and b/icons/paper_icons/ntlogo.png differ diff --git a/icons/paper_icons/syndielogo.png b/icons/paper_icons/syndielogo.png new file mode 100644 index 00000000000..6b0c4966541 Binary files /dev/null and b/icons/paper_icons/syndielogo.png differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index a612d889222..7eccbce5a7d 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/icons/turf/walls/cult_wall.dmi b/icons/turf/walls/cult_wall.dmi index f539a3ed4ba..db9f60933d4 100644 Binary files a/icons/turf/walls/cult_wall.dmi and b/icons/turf/walls/cult_wall.dmi differ diff --git a/install-byond.sh b/install-byond.sh deleted file mode 100644 index cca44342c60..00000000000 --- a/install-byond.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -set -e -if [ -d "$HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}/byond/bin" ]; -then - echo "Using cached directory." -else - echo "Setting up BYOND." - mkdir -p "$HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}" - cd "$HOME/BYOND-${BYOND_MAJOR}.${BYOND_MINOR}" - curl "http://www.byond.com/download/build/${BYOND_MAJOR}/${BYOND_MAJOR}.${BYOND_MINOR}_byond_linux.zip" -o byond.zip - unzip byond.zip - cd byond - make here -fi diff --git a/interface/interface.dm b/interface/interface.dm index 4a140769f18..9a544fe7951 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -13,35 +13,6 @@ to_chat(src, "The wiki URL is not set in the server configuration.") return -/client/verb/changes() - set name = "Changelog" - set desc = "View the changelog." - set hidden = 1 - - getFiles( - 'html/88x31.png', - 'html/bug-minus.png', - 'html/cross-circle.png', - 'html/hard-hat-exclamation.png', - 'html/image-minus.png', - 'html/image-plus.png', - 'html/music-minus.png', - 'html/music-plus.png', - 'html/tick-circle.png', - 'html/wrench-screwdriver.png', - 'html/spell-check.png', - 'html/burn-exclamation.png', - 'html/chevron.png', - 'html/chevron-expand.png', - 'html/changelog.css', - 'html/changelog.js', - 'html/changelog.html' - ) - src << browse('html/changelog.html', "window=changes;size=675x650") - update_changelog_button() - if(prefs.lastchangelog != changelog_hash) //if it's already opened, no need to tell them they have unread changes - prefs.SetChangelog(src,changelog_hash) - /client/verb/forum() set name = "forum" set desc = "Visit the forum." diff --git a/libmariadb.so b/libmariadb.so new file mode 100644 index 00000000000..45c7741b556 Binary files /dev/null and b/libmariadb.so differ diff --git a/librust_g.so b/librust_g.so new file mode 100644 index 00000000000..d70052a39c9 Binary files /dev/null and b/librust_g.so differ diff --git a/nano/assets/libraries.min.js b/nano/assets/libraries.min.js index d0c1ef9a46f..7dff02479a9 100644 --- a/nano/assets/libraries.min.js +++ b/nano/assets/libraries.min.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(d,e){function t(e,t){return t.toUpperCase()}var f=[],c=f.slice,g=f.concat,a=f.push,r=f.indexOf,n={},i=n.toString,m=n.hasOwnProperty,v={},o="1.11.3",C=function(e,t){return new C.fn.init(e,t)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,l=/^-ms-/,u=/-([\da-z])/gi;function p(e){var t="length"in e&&e.length,n=C.type(e);return"function"!==n&&!C.isWindow(e)&&(!(1!==e.nodeType||!t)||("array"===n||0===t||"number"==typeof t&&0>10|55296,1023&i|56320)}function i(){v()}var e,d,x,o,r,g,p,m,w,u,c,v,T,s,y,b,a,h,C,_="sizzle"+1*new Date,E=n.document,S=0,N=0,l=oe(),D=oe(),k=oe(),j=function(e,t){return e===t&&(c=!0),0},A={}.hasOwnProperty,t=[],P=t.pop,H=t.push,M=t.push,L=t.slice,O=function(e,t){for(var n=0,i=e.length;n+~]|"+F+")"+F+"*"),Y=new RegExp("="+F+"*([^\\]'\"]*?)"+F+"*\\]","g"),Q=new RegExp($),J=new RegExp("^"+q+"$"),V={ID:new RegExp("^#("+W+")"),CLASS:new RegExp("^\\.("+W+")"),TAG:new RegExp("^("+W.replace("w","w*")+")"),ATTR:new RegExp("^"+R),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+F+"*(even|odd|(([+-]|)(\\d*)n|)"+F+"*(?:([+-]|)"+F+"*(\\d+)|))"+F+"*\\)|)","i"),bool:new RegExp("^(?:"+I+")$","i"),needsContext:new RegExp("^"+F+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+F+"*((?:-\\d)?\\d*)"+F+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,K=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,ee=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,te=/[+~]/,ne=/'|\\/g,ie=new RegExp("\\\\([\\da-f]{1,6}"+F+"?|("+F+")|.)","ig");try{M.apply(t=L.call(E.childNodes),E.childNodes),t[E.childNodes.length].nodeType}catch(e){M={apply:t.length?function(e,t){H.apply(e,L.call(t))}:function(e,t){for(var n=e.length,i=0;e[n++]=t[i++];);e.length=n-1}}}function re(e,t,n,i){var r,o,s,a,l,u,c,f,p,h;if((t?t.ownerDocument||t:E)!==T&&v(t),n=n||[],a=(t=t||T).nodeType,"string"!=typeof e||!e||1!==a&&9!==a&&11!==a)return n;if(!i&&y){if(11!==a&&(r=ee.exec(e)))if(s=r[1]){if(9===a){if(!(o=t.getElementById(s))||!o.parentNode)return n;if(o.id===s)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(s))&&C(t,o)&&o.id===s)return n.push(o),n}else{if(r[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=r[3])&&d.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(d.qsa&&(!b||!b.test(e))){if(f=c=_,p=t,h=1!==a&&e,1===a&&"object"!==t.nodeName.toLowerCase()){for(u=g(e),(c=t.getAttribute("id"))?f=c.replace(ne,"\\$&"):t.setAttribute("id",f),f="[id='"+f+"'] ",l=u.length;l--;)u[l]=f+ge(u[l]);p=te.test(e)&&he(t.parentNode)||t,h=u.join(",")}if(h)try{return M.apply(n,p.querySelectorAll(h)),n}catch(e){}finally{c||t.removeAttribute("id")}}}return m(e.replace(z,"$1"),t,n,i)}function oe(){var i=[];return function e(t,n){return i.push(t+" ")>x.cacheLength&&delete e[i.shift()],e[t+" "]=n}}function se(e){return e[_]=!0,e}function ae(e){var t=T.createElement("div");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){for(var n=e.split("|"),i=e.length;i--;)x.attrHandle[n[i]]=t}function ue(e,t){var n=t&&e,i=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||1<<31)-(~e.sourceIndex||1<<31);if(i)return i;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function ce(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function fe(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function pe(s){return se(function(o){return o=+o,se(function(e,t){for(var n,i=s([],e.length,o),r=i.length;r--;)e[n=i[r]]&&(e[n]=!(t[n]=e[n]))})})}function he(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in d=re.support={},r=re.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},v=re.setDocument=function(e){var t,n,l=e?e.ownerDocument||e:E;return l!==T&&9===l.nodeType&&l.documentElement?(s=(T=l).documentElement,(n=l.defaultView)&&n!==n.top&&(n.addEventListener?n.addEventListener("unload",i,!1):n.attachEvent&&n.attachEvent("onunload",i)),y=!r(l),d.attributes=ae(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ae(function(e){return e.appendChild(l.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=Z.test(l.getElementsByClassName),d.getById=ae(function(e){return s.appendChild(e).id=_,!l.getElementsByName||!l.getElementsByName(_).length}),d.getById?(x.find.ID=function(e,t){if(void 0!==t.getElementById&&y){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},x.filter.ID=function(e){var t=e.replace(ie,f);return function(e){return e.getAttribute("id")===t}}):(delete x.find.ID,x.filter.ID=function(e){var n=e.replace(ie,f);return function(e){var t=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}}),x.find.TAG=d.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,i=[],r=0,o=t.getElementsByTagName(e);if("*"!==e)return o;for(;n=o[r++];)1===n.nodeType&&i.push(n);return i},x.find.CLASS=d.getElementsByClassName&&function(e,t){if(y)return t.getElementsByClassName(e)},a=[],b=[],(d.qsa=Z.test(l.querySelectorAll))&&(ae(function(e){s.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&b.push("[*^$]="+F+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||b.push("\\["+F+"*(?:value|"+I+")"),e.querySelectorAll("[id~="+_+"-]").length||b.push("~="),e.querySelectorAll(":checked").length||b.push(":checked"),e.querySelectorAll("a#"+_+"+*").length||b.push(".#.+[+~]")}),ae(function(e){var t=l.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&b.push("name"+F+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||b.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),b.push(",.*:")})),(d.matchesSelector=Z.test(h=s.matches||s.webkitMatchesSelector||s.mozMatchesSelector||s.oMatchesSelector||s.msMatchesSelector))&&ae(function(e){d.disconnectedMatch=h.call(e,"div"),h.call(e,"[s!='']:x"),a.push("!=",$)}),b=b.length&&new RegExp(b.join("|")),a=a.length&&new RegExp(a.join("|")),t=Z.test(s.compareDocumentPosition),C=t||Z.test(s.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,i=t&&t.parentNode;return e===i||!(!i||1!==i.nodeType||!(n.contains?n.contains(i):e.compareDocumentPosition&&16&e.compareDocumentPosition(i)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return c=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===l||e.ownerDocument===E&&C(E,e)?-1:t===l||t.ownerDocument===E&&C(E,t)?1:u?O(u,e)-O(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return c=!0,0;var n,i=0,r=e.parentNode,o=t.parentNode,s=[e],a=[t];if(!r||!o)return e===l?-1:t===l?1:r?-1:o?1:u?O(u,e)-O(u,t):0;if(r===o)return ue(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)a.unshift(n);for(;s[i]===a[i];)i++;return i?ue(s[i],a[i]):s[i]===E?-1:a[i]===E?1:0},l):T},re.matches=function(e,t){return re(e,null,null,t)},re.matchesSelector=function(e,t){if((e.ownerDocument||e)!==T&&v(e),t=t.replace(Y,"='$1']"),d.matchesSelector&&y&&(!a||!a.test(t))&&(!b||!b.test(t)))try{var n=h.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(ie,f),e[3]=(e[3]||e[4]||e[5]||"").replace(ie,f),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||re.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&re.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&Q.test(n)&&(t=g(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(ie,f).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=l[e+" "];return t||(t=new RegExp("(^|"+F+")"+e+"("+F+"|$)"))&&l(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,i,r){return function(e){var t=re.attr(e,n);return null==t?"!="===i:!i||(t+="","="===i?t===r:"!="===i?t!==r:"^="===i?r&&0===t.indexOf(r):"*="===i?r&&-1(?:<\/\1>|)$/,x=/^.[^:#\[\.,]*$/;function w(e,n,i){if(C.isFunction(n))return C.grep(e,function(e,t){return!!n.call(e,t,e)!==i});if(n.nodeType)return C.grep(e,function(e){return e===n!==i});if("string"==typeof n){if(x.test(n))return C.filter(n,e,i);n=C.filter(n,e)}return C.grep(e,function(e){return 0<=C.inArray(e,n)!==i})}C.filter=function(e,t,n){var i=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===i.nodeType?C.find.matchesSelector(i,e)?[i]:[]:C.find.matches(e,C.grep(t,function(e){return 1===e.nodeType}))},C.fn.extend({find:function(e){var t,n=[],i=this,r=i.length;if("string"!=typeof e)return this.pushStack(C(e).filter(function(){for(t=0;t)[^>]*|#([\w-]*))$/;(C.fn.init=function(e,t){var n,i;if(!e)return this;if("string"!=typeof e)return e.nodeType?(this.context=this[0]=e,this.length=1,this):C.isFunction(e)?void 0!==T.ready?T.ready(e):e(C):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),C.makeArray(e,this));if(!(n="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&3<=e.length?[null,e,null]:E.exec(e))||!n[1]&&t)return!t||t.jquery?(t||T).find(e):this.constructor(t).find(e);if(n[1]){if(t=t instanceof C?t[0]:t,C.merge(this,C.parseHTML(n[1],t&&t.nodeType?t.ownerDocument||t:_,!0)),b.test(n[1])&&C.isPlainObject(t))for(n in t)C.isFunction(this[n])?this[n](t[n]):this.attr(n,t[n]);return this}if((i=_.getElementById(n[2]))&&i.parentNode){if(i.id!==n[2])return T.find(e);this.length=1,this[0]=i}return this.context=_,this.selector=e,this}).prototype=C.fn,T=C(_);var S=/^(?:parents|prev(?:Until|All))/,N={children:!0,contents:!0,next:!0,prev:!0};function D(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}C.extend({dir:function(e,t,n){for(var i=[],r=e[t];r&&9!==r.nodeType&&(void 0===n||1!==r.nodeType||!C(r).is(n));)1===r.nodeType&&i.push(r),r=r[t];return i},sibling:function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}}),C.fn.extend({has:function(e){var t,n=C(e,this),i=n.length;return this.filter(function(){for(t=0;t
    a",v.leadingWhitespace=3===t.firstChild.nodeType,v.tbody=!t.getElementsByTagName("tbody").length,v.htmlSerialize=!!t.getElementsByTagName("link").length,v.html5Clone="<:nav>"!==_.createElement("nav").cloneNode(!0).outerHTML,e.type="checkbox",e.checked=!0,n.appendChild(e),v.appendChecked=e.checked,t.innerHTML="",v.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue,n.appendChild(t),t.innerHTML="",v.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,v.noCloneEvent=!0,t.attachEvent&&(t.attachEvent("onclick",function(){v.noCloneEvent=!1}),t.cloneNode(!0).click()),null==v.deleteExpando){v.deleteExpando=!0;try{delete t.test}catch(e){v.deleteExpando=!1}}}(),function(){var e,t,n=_.createElement("div");for(e in{submit:!0,change:!0,focusin:!0})t="on"+e,(v[e+"Bubbles"]=t in d)||(n.setAttribute(t,"t"),v[e+"Bubbles"]=!1===n.attributes[t].expando);n=null}();var Y=/^(?:input|select|textarea)$/i,Q=/^key/,J=/^(?:mouse|pointer|contextmenu)|click/,V=/^(?:focusinfocus|focusoutblur)$/,G=/^([^.]*)(?:\.(.+)|)$/;function K(){return!0}function Z(){return!1}function ee(){try{return _.activeElement}catch(e){}}function te(e){var t=ne.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}C.event={global:{},add:function(e,t,n,i,r){var o,s,a,l,u,c,f,p,h,d,g,m=C._data(e);if(m){for(n.handler&&(n=(l=n).handler,r=l.selector),n.guid||(n.guid=C.guid++),(s=m.events)||(s=m.events={}),(c=m.handle)||((c=m.handle=function(e){return typeof C===L||e&&C.event.triggered===e.type?void 0:C.event.dispatch.apply(c.elem,arguments)}).elem=e),a=(t=(t||"").match(j)||[""]).length;a--;)h=g=(o=G.exec(t[a])||[])[1],d=(o[2]||"").split(".").sort(),h&&(u=C.event.special[h]||{},h=(r?u.delegateType:u.bindType)||h,u=C.event.special[h]||{},f=C.extend({type:h,origType:g,data:i,handler:n,guid:n.guid,selector:r,needsContext:r&&C.expr.match.needsContext.test(r),namespace:d.join(".")},l),(p=s[h])||((p=s[h]=[]).delegateCount=0,u.setup&&!1!==u.setup.call(e,i,d,c)||(e.addEventListener?e.addEventListener(h,c,!1):e.attachEvent&&e.attachEvent("on"+h,c))),u.add&&(u.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),r?p.splice(p.delegateCount++,0,f):p.push(f),C.event.global[h]=!0);e=null}},remove:function(e,t,n,i,r){var o,s,a,l,u,c,f,p,h,d,g,m=C.hasData(e)&&C._data(e);if(m&&(c=m.events)){for(u=(t=(t||"").match(j)||[""]).length;u--;)if(h=g=(a=G.exec(t[u])||[])[1],d=(a[2]||"").split(".").sort(),h){for(f=C.event.special[h]||{},p=c[h=(i?f.delegateType:f.bindType)||h]||[],a=a[2]&&new RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=p.length;o--;)s=p[o],!r&&g!==s.origType||n&&n.guid!==s.guid||a&&!a.test(s.namespace)||i&&i!==s.selector&&("**"!==i||!s.selector)||(p.splice(o,1),s.selector&&p.delegateCount--,f.remove&&f.remove.call(e,s));l&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,d,m.handle)||C.removeEvent(e,h,m.handle),delete c[h])}else for(h in c)C.event.remove(e,h+t[u],n,i,!0);C.isEmptyObject(c)&&(delete m.handle,C._removeData(e,"events"))}},trigger:function(e,t,n,i){var r,o,s,a,l,u,c,f=[n||_],p=m.call(e,"type")?e.type:e,h=m.call(e,"namespace")?e.namespace.split("."):[];if(s=u=n=n||_,3!==n.nodeType&&8!==n.nodeType&&!V.test(p+C.event.triggered)&&(0<=p.indexOf(".")&&(p=(h=p.split(".")).shift(),h.sort()),o=p.indexOf(":")<0&&"on"+p,(e=e[C.expando]?e:new C.Event(p,"object"==typeof e&&e)).isTrigger=i?2:3,e.namespace=h.join("."),e.namespace_re=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:C.makeArray(t,[e]),l=C.event.special[p]||{},i||!l.trigger||!1!==l.trigger.apply(n,t))){if(!i&&!l.noBubble&&!C.isWindow(n)){for(a=l.delegateType||p,V.test(a+p)||(s=s.parentNode);s;s=s.parentNode)f.push(s),u=s;u===(n.ownerDocument||_)&&f.push(u.defaultView||u.parentWindow||d)}for(c=0;(s=f[c++])&&!e.isPropagationStopped();)e.type=1]","i"),oe=/^\s+/,se=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ae=/<([\w:]+)/,le=/
    ","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:v.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},me=te(_).appendChild(_.createElement("div"));function ve(e,t){var n,i,r=0,o=typeof e.getElementsByTagName!==L?e.getElementsByTagName(t||"*"):typeof e.querySelectorAll!==L?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(i=n[r]);r++)!t||C.nodeName(i,t)?o.push(i):C.merge(o,ve(i,t));return void 0===t||t&&C.nodeName(e,t)?C.merge([e],o):o}function ye(e){X.test(e.type)&&(e.defaultChecked=e.checked)}function be(e,t){return C.nodeName(e,"table")&&C.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function xe(e){return e.type=(null!==C.find.attr(e,"type"))+"/"+e.type,e}function we(e){var t=he.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Te(e,t){for(var n,i=0;null!=(n=e[i]);i++)C._data(n,"globalEval",!t||C._data(t[i],"globalEval"))}function Ce(e,t){if(1===t.nodeType&&C.hasData(e)){var n,i,r,o=C._data(e),s=C._data(t,o),a=o.events;if(a)for(n in delete s.handle,s.events={},a)for(i=0,r=a[n].length;i")?o=e.cloneNode(!0):(me.innerHTML=e.outerHTML,me.removeChild(o=me.firstChild)),!(v.noCloneEvent&&v.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||C.isXMLDoc(e)))for(i=ve(o),a=ve(e),s=0;null!=(r=a[s]);++s)i[s]&&_e(r,i[s]);if(t)if(n)for(a=a||ve(e),i=i||ve(o),s=0;null!=(r=a[s]);s++)Ce(r,i[s]);else Ce(e,o);return 0<(i=ve(o,"script")).length&&Te(i,!l&&ve(e,"script")),i=a=r=null,o},buildFragment:function(e,t,n,i){for(var r,o,s,a,l,u,c,f=e.length,p=te(t),h=[],d=0;d")+c[2],r=c[0];r--;)a=a.lastChild;if(!v.leadingWhitespace&&oe.test(o)&&h.push(t.createTextNode(oe.exec(o)[0])),!v.tbody)for(r=(o="table"!==l||le.test(o)?""!==c[1]||le.test(o)?0:a:a.firstChild)&&o.childNodes.length;r--;)C.nodeName(u=o.childNodes[r],"tbody")&&!u.childNodes.length&&o.removeChild(u);for(C.merge(h,a.childNodes),a.textContent="";a.firstChild;)a.removeChild(a.firstChild);a=p.lastChild}else h.push(t.createTextNode(o));for(a&&p.removeChild(a),v.appendChecked||C.grep(ve(h,"input"),ye),d=0;o=h[d++];)if((!i||-1===C.inArray(o,i))&&(s=C.contains(o.ownerDocument,o),a=ve(p.appendChild(o),"script"),s&&Te(a),n))for(r=0;o=a[r++];)pe.test(o.type||"")&&n.push(o);return a=null,p},cleanData:function(e,t){for(var n,i,r,o,s=0,a=C.expando,l=C.cache,u=v.deleteExpando,c=C.event.special;null!=(n=e[s]);s++)if((t||C.acceptData(n))&&(o=(r=n[a])&&l[r])){if(o.events)for(i in o.events)c[i]?C.event.remove(n,i):C.removeEvent(n,i,o.handle);l[r]&&(delete l[r],u?delete n[a]:typeof n.removeAttribute!==L?n.removeAttribute(a):n[a]=null,f.push(r))}}}),C.fn.extend({text:function(e){return U(this,function(e){return void 0===e?C.text(this):this.empty().append((this[0]&&this[0].ownerDocument||_).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||be(this,e).appendChild(e)})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=be(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){for(var n,i=e?C.filter(e,this):this,r=0;null!=(n=i[r]);r++)t||1!==n.nodeType||C.cleanData(ve(n)),n.parentNode&&(t&&C.contains(n.ownerDocument,n)&&Te(ve(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&C.cleanData(ve(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&C.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return C.clone(this,e,t)})},html:function(e){return U(this,function(e){var t=this[0]||{},n=0,i=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(ie,""):void 0;if("string"==typeof e&&!ce.test(e)&&(v.htmlSerialize||!re.test(e))&&(v.leadingWhitespace||!oe.test(e))&&!ge[(ae.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(se,"<$1>");try{for(;n")).appendTo(t.documentElement))[0].contentWindow||Ee[0].contentDocument).document).write(),t.close(),n=De(e,t),Ee.detach()),Ne[e]=n),n}v.shrinkWrapBlocks=function(){return null!=Se?Se:(Se=!1,(t=_.getElementsByTagName("body")[0])&&t.style?(e=_.createElement("div"),(n=_.createElement("div")).style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",t.appendChild(n).appendChild(e),typeof e.style.zoom!==L&&(e.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",e.appendChild(_.createElement("div")).style.width="5px",Se=3!==e.offsetWidth),t.removeChild(n),Se):void 0);var e,t,n};var je,Ae,Pe,He,Me,Le,Oe,Ie,Fe,We=/^margin/,qe=new RegExp("^("+B+")(?!px)[a-z%]+$","i"),Re=/^(top|right|bottom|left)$/;function $e(t,n){return{get:function(){var e=t();if(null!=e){if(!e)return(this.get=n).apply(this,arguments);delete this.get}}}}function Be(){var e,t,n,i;(t=_.getElementsByTagName("body")[0])&&t.style&&(e=_.createElement("div"),(n=_.createElement("div")).style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",t.appendChild(n).appendChild(e),e.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",Le=Oe=!1,Fe=!0,d.getComputedStyle&&(Le="1%"!==(d.getComputedStyle(e,null)||{}).top,Oe="4px"===(d.getComputedStyle(e,null)||{width:"4px"}).width,(i=e.appendChild(_.createElement("div"))).style.cssText=e.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",e.style.width="1px",Fe=!parseFloat((d.getComputedStyle(i,null)||{}).marginRight),e.removeChild(i)),e.innerHTML="
    t
    ",(i=e.getElementsByTagName("td"))[0].style.cssText="margin:0;border:0;padding:0;display:none",(Ie=0===i[0].offsetHeight)&&(i[0].style.display="",i[1].style.display="none",Ie=0===i[0].offsetHeight),t.removeChild(n))}d.getComputedStyle?(je=function(e){return e.ownerDocument.defaultView.opener?e.ownerDocument.defaultView.getComputedStyle(e,null):d.getComputedStyle(e,null)},Ae=function(e,t,n){var i,r,o,s,a=e.style;return s=(n=n||je(e))?n.getPropertyValue(t)||n[t]:void 0,n&&(""!==s||C.contains(e.ownerDocument,e)||(s=C.style(e,t)),qe.test(s)&&We.test(t)&&(i=a.width,r=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=s,s=n.width,a.width=i,a.minWidth=r,a.maxWidth=o)),void 0===s?s:s+""}):_.documentElement.currentStyle&&(je=function(e){return e.currentStyle},Ae=function(e,t,n){var i,r,o,s,a=e.style;return null==(s=(n=n||je(e))?n[t]:void 0)&&a&&a[t]&&(s=a[t]),qe.test(s)&&!Re.test(t)&&(i=a.left,(o=(r=e.runtimeStyle)&&r.left)&&(r.left=e.currentStyle.left),a.left="fontSize"===t?"1em":s,s=a.pixelLeft+"px",a.left=i,o&&(r.left=o)),void 0===s?s:s+""||"auto"}),(Pe=_.createElement("div")).innerHTML="
    a",(He=(Me=Pe.getElementsByTagName("a")[0])&&Me.style)&&(He.cssText="float:left;opacity:.5",v.opacity="0.5"===He.opacity,v.cssFloat=!!He.cssFloat,Pe.style.backgroundClip="content-box",Pe.cloneNode(!0).style.backgroundClip="",v.clearCloneStyle="content-box"===Pe.style.backgroundClip,v.boxSizing=""===He.boxSizing||""===He.MozBoxSizing||""===He.WebkitBoxSizing,C.extend(v,{reliableHiddenOffsets:function(){return null==Ie&&Be(),Ie},boxSizingReliable:function(){return null==Oe&&Be(),Oe},pixelPosition:function(){return null==Le&&Be(),Le},reliableMarginRight:function(){return null==Fe&&Be(),Fe}})),C.swap=function(e,t,n,i){var r,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];for(o in r=n.apply(e,i||[]),t)e.style[o]=s[o];return r};var ze=/alpha\([^)]*\)/i,Ue=/opacity\s*=\s*([^)]*)/,Xe=/^(none|table(?!-c[ea]).+)/,Ye=new RegExp("^("+B+")(.*)$","i"),Qe=new RegExp("^([+-])=("+B+")","i"),Je={position:"absolute",visibility:"hidden",display:"block"},Ve={letterSpacing:"0",fontWeight:"400"},Ge=["Webkit","O","Moz","ms"];function Ke(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),i=t,r=Ge.length;r--;)if((t=Ge[r]+n)in e)return t;return i}function Ze(e,t){for(var n,i,r,o=[],s=0,a=e.length;s
    a",ut=at.getElementsByTagName("a")[0],ct=(lt=_.createElement("select")).appendChild(_.createElement("option")),st=at.getElementsByTagName("input")[0],ut.style.cssText="top:1px",v.getSetAttribute="t"!==at.className,v.style=/top/.test(ut.getAttribute("style")),v.hrefNormalized="/a"===ut.getAttribute("href"),v.checkOn=!!st.value,v.optSelected=ct.selected,v.enctype=!!_.createElement("form").enctype,lt.disabled=!0,v.optDisabled=!ct.disabled,(st=_.createElement("input")).setAttribute("value",""),v.input=""===st.getAttribute("value"),st.value="t",st.setAttribute("type","radio"),v.radioValue="t"===st.value;var xt=/\r/g;C.fn.extend({val:function(n){var i,e,r,t=this[0];return arguments.length?(r=C.isFunction(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=r?n.call(this,e,C(this).val()):n)?t="":"number"==typeof t?t+="":C.isArray(t)&&(t=C.map(t,function(e){return null==e?"":e+""})),(i=C.valHooks[this.type]||C.valHooks[this.nodeName.toLowerCase()])&&"set"in i&&void 0!==i.set(this,t,"value")||(this.value=t))})):t?(i=C.valHooks[t.type]||C.valHooks[t.nodeName.toLowerCase()])&&"get"in i&&void 0!==(e=i.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(xt,""):null==e?"":e:void 0}}),C.extend({valHooks:{option:{get:function(e){var t=C.find.attr(e,"value");return null!=t?t:C.trim(C.text(e))}},select:{get:function(e){for(var t,n,i=e.options,r=e.selectedIndex,o="select-one"===e.type||r<0,s=o?null:[],a=o?r+1:i.length,l=r<0?a:o?r:0;l").append(C.parseHTML(e)).find(i):e)}).complete(n&&function(e,t){s.each(n,r||[e.responseText,t,e])}),this},C.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){C.fn[t]=function(e){return this.on(t,e)}}),C.expr.filters.animated=function(t){return C.grep(C.timers,function(e){return t===e.elem}).length};var cn=d.document.documentElement;function fn(e){return C.isWindow(e)?e:9===e.nodeType&&(e.defaultView||e.parentWindow)}C.offset={setOffset:function(e,t,n){var i,r,o,s,a,l,u=C.css(e,"position"),c=C(e),f={};"static"===u&&(e.style.position="relative"),a=c.offset(),o=C.css(e,"top"),l=C.css(e,"left"),r=("absolute"===u||"fixed"===u)&&-1").outerWidth(1).jquery||D.each(["Width","Height"],function(e,n){var r="Width"===n?["Left","Right"]:["Top","Bottom"],i=n.toLowerCase(),o={innerWidth:D.fn.innerWidth,innerHeight:D.fn.innerHeight,outerWidth:D.fn.outerWidth,outerHeight:D.fn.outerHeight};function s(e,t,n,i){return D.each(r,function(){t-=parseFloat(D.css(e,"padding"+this))||0,n&&(t-=parseFloat(D.css(e,"border"+this+"Width"))||0),i&&(t-=parseFloat(D.css(e,"margin"+this))||0)}),t}D.fn["inner"+n]=function(e){return void 0===e?o["inner"+n].call(this):this.each(function(){D(this).css(i,s(this,e)+"px")})},D.fn["outer"+n]=function(e,t){return"number"!=typeof e?o["outer"+n].call(this,e):this.each(function(){D(this).css(i,s(this,e,!0,t)+"px")})}}),D.fn.addBack||(D.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),D("").data("a-b","a").removeData("a-b").data("a-b")&&(D.fn.removeData=(t=D.fn.removeData,function(e){return arguments.length?t.call(this,D.camelCase(e)):t.call(this)})),D.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),D.fn.extend({focus:(i=D.fn.focus,function(t,n){return"number"==typeof t?this.each(function(){var e=this;setTimeout(function(){D(e).focus(),n&&n.call(e)},t)}):i.apply(this,arguments)}),disableSelection:(n="onselectstart"in document.createElement("div")?"selectstart":"mousedown",function(){return this.bind(n+".ui-disableSelection",function(e){e.preventDefault()})}),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(e){if(void 0!==e)return this.css("zIndex",e);if(this.length)for(var t,n,i=D(this[0]);i.length&&i[0]!==document;){if(("absolute"===(t=i.css("position"))||"relative"===t||"fixed"===t)&&(n=parseInt(i.css("zIndex"),10),!isNaN(n)&&0!==n))return n;i=i.parent()}return 0}}),D.ui.plugin={add:function(e,t,n){var i,r=D.ui[e].prototype;for(i in n)r.plugins[i]=r.plugins[i]||[],r.plugins[i].push([t,n[i]])},call:function(e,t,n,i){var r,o=e.plugins[t];if(o&&(i||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(r=0;r",options:{disabled:!1,create:null},_createWidget:function(e,t){t=D(t||this.defaultElement||this)[0],this.element=D(t),this.uuid=a++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=D(),this.hoverable=D(),this.focusable=D(),t!==this&&(D.data(t,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===t&&this.destroy()}}),this.document=D(t.style?t.ownerDocument:t.document||t),this.window=D(this.document[0].defaultView||this.document[0].parentWindow)),this.options=D.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:D.noop,_getCreateEventData:D.noop,_create:D.noop,_init:D.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(D.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:D.noop,widget:function(){return this.element},option:function(e,t){var n,i,r,o=e;if(0===arguments.length)return D.widget.extend({},this.options);if("string"==typeof e)if(o={},e=(n=e.split(".")).shift(),n.length){for(i=o[e]=D.widget.extend({},this.options[e]),r=0;r=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}});!function(){D.ui=D.ui||{};var r,T,C=Math.max,_=Math.abs,E=Math.round,i=/left|center|right/,o=/top|center|bottom/,s=/[\+\-]\d+(\.[\d]+)?%?/,a=/^\w+/,l=/%$/,t=D.fn.position;function S(e,t,n){return[parseFloat(e[0])*(l.test(e[0])?t/100:1),parseFloat(e[1])*(l.test(e[1])?n/100:1)]}function N(e,t){return parseInt(D.css(e,t),10)||0}D.position={scrollbarWidth:function(){if(void 0!==r)return r;var e,t,n=D("
    "),i=n.children()[0];return D("body").append(n),e=i.offsetWidth,n.css("overflow","scroll"),e===(t=i.offsetWidth)&&(t=n[0].clientWidth),n.remove(),r=e-t},getScrollInfo:function(e){var t=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),n=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),i="scroll"===t||"auto"===t&&e.widthC(_(i),_(r))?o.important="horizontal":o.important="vertical",f.using.call(this,e,o)}),s.offset(D.extend(u,{using:e}))})},D.ui.position={fit:{left:function(e,t){var n,i=t.within,r=i.isWindow?i.scrollLeft:i.offset.left,o=i.width,s=e.left-t.collisionPosition.marginLeft,a=r-s,l=s+t.collisionWidth-o-r;t.collisionWidth>o?0o?0").css("position","absolute").appendTo(e.parent()).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(e){var t=this.document[0];if(this.handleElement.is(e.target))try{t.activeElement&&"body"!==t.activeElement.nodeName.toLowerCase()&&D(t.activeElement).blur()}catch(e){}},_mouseStart:function(e){var t=this.options;return this.helper=this._createHelper(e),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),D.ui.ddmanager&&(D.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=0n[2]&&(l=n[2]+this.offset.click.left),e.pageY-this.offset.click.top>n[3]&&(u=n[3]+this.offset.click.top)),s.grid&&(r=s.grid[1]?this.originalPageY+Math.round((u-this.originalPageY)/s.grid[1])*s.grid[1]:this.originalPageY,u=n?r-this.offset.click.top>=n[1]||r-this.offset.click.top>n[3]?r:r-this.offset.click.top>=n[1]?r-s.grid[1]:r+s.grid[1]:r,o=s.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/s.grid[0])*s.grid[0]:this.originalPageX,l=n?o-this.offset.click.left>=n[0]||o-this.offset.click.left>n[2]?o:o-this.offset.click.left>=n[0]?o-s.grid[0]:o+s.grid[0]:o),"y"===s.axis&&(l=this.originalPageX),"x"===s.axis&&(u=this.originalPageY)),{top:u-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:a?0:this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:a?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){"y"!==this.options.axis&&"auto"!==this.helper.css("right")&&(this.helper.width(this.helper.width()),this.helper.css("right","auto")),"x"!==this.options.axis&&"auto"!==this.helper.css("bottom")&&(this.helper.height(this.helper.height()),this.helper.css("bottom","auto"))},_trigger:function(e,t,n){return n=n||this._uiHash(),D.ui.plugin.call(this,e,[t,n,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),n.offset=this.positionAbs),D.Widget.prototype._trigger.call(this,e,t,n)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),D.ui.plugin.add("draggable","connectToSortable",{start:function(t,e,n){var i=D.extend({},e,{item:n.element});n.sortables=[],D(n.options.connectToSortable).each(function(){var e=D(this).sortable("instance");e&&!e.options.disabled&&(n.sortables.push(e),e.refreshPositions(),e._trigger("activate",t,i))})},stop:function(t,e,n){var i=D.extend({},e,{item:n.element});n.cancelHelperRemoval=!1,D.each(n.sortables,function(){var e=this;e.isOver?(e.isOver=0,n.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css("position"),top:e.placeholder.css("top"),left:e.placeholder.css("left")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger("deactivate",t,i))})},drag:function(n,i,r){D.each(r.sortables,function(){var e=!1,t=this;t.positionAbs=r.positionAbs,t.helperProportions=r.helperProportions,t.offset.click=r.offset.click,t._intersectsWith(t.containerCache)&&(e=!0,D.each(r.sortables,function(){return this.positionAbs=r.positionAbs,this.helperProportions=r.helperProportions,this.offset.click=r.offset.click,this!==t&&this._intersectsWith(this.containerCache)&&D.contains(t.element[0],this.element[0])&&(e=!1),e})),e?(t.isOver||(t.isOver=1,r._parent=i.helper.parent(),t.currentItem=i.helper.appendTo(t.element).data("ui-sortable-item",!0),t.options._helper=t.options.helper,t.options.helper=function(){return i.helper[0]},n.target=t.currentItem[0],t._mouseCapture(n,!0),t._mouseStart(n,!0,!0),t.offset.click.top=r.offset.click.top,t.offset.click.left=r.offset.click.left,t.offset.parent.left-=r.offset.parent.left-t.offset.parent.left,t.offset.parent.top-=r.offset.parent.top-t.offset.parent.top,r._trigger("toSortable",n),r.dropped=t.element,D.each(r.sortables,function(){this.refreshPositions()}),r.currentItem=r.element,t.fromOutside=r),t.currentItem&&(t._mouseDrag(n),i.position=t.position)):t.isOver&&(t.isOver=0,t.cancelHelperRemoval=!0,t.options._revert=t.options.revert,t.options.revert=!1,t._trigger("out",n,t._uiHash(t)),t._mouseStop(n,!0),t.options.revert=t.options._revert,t.options.helper=t.options._helper,t.placeholder&&t.placeholder.remove(),i.helper.appendTo(r._parent),r._refreshOffsets(n),i.position=r._generatePosition(n,!0),r._trigger("fromSortable",n),r.dropped=!1,D.each(r.sortables,function(){this.refreshPositions()}))})}}),D.ui.plugin.add("draggable","cursor",{start:function(e,t,n){var i=D("body"),r=n.options;i.css("cursor")&&(r._cursor=i.css("cursor")),i.css("cursor",r.cursor)},stop:function(e,t,n){var i=n.options;i._cursor&&D("body").css("cursor",i._cursor)}}),D.ui.plugin.add("draggable","opacity",{start:function(e,t,n){var i=D(t.helper),r=n.options;i.css("opacity")&&(r._opacity=i.css("opacity")),i.css("opacity",r.opacity)},stop:function(e,t,n){var i=n.options;i._opacity&&D(t.helper).css("opacity",i._opacity)}}),D.ui.plugin.add("draggable","scroll",{start:function(e,t,n){n.scrollParentNotHidden||(n.scrollParentNotHidden=n.helper.scrollParent(!1)),n.scrollParentNotHidden[0]!==n.document[0]&&"HTML"!==n.scrollParentNotHidden[0].tagName&&(n.overflowOffset=n.scrollParentNotHidden.offset())},drag:function(e,t,n){var i=n.options,r=!1,o=n.scrollParentNotHidden[0],s=n.document[0];o!==s&&"HTML"!==o.tagName?(i.axis&&"x"===i.axis||(n.overflowOffset.top+o.offsetHeight-e.pageY")[0],x=c.each,b.style.cssText="background-color:rgba(1,1,1,.5)",y.rgba=-1o.mod/2?i+=o.mod:i-r>o.mod/2&&(i-=o.mod)),u[n]=H((r-i)*s+i,t)))}),this[t](u)},blend:function(e){if(1===this._rgba[3])return this;var t=this._rgba.slice(),n=t.pop(),i=g(e)._rgba;return g(c.map(t,function(e,t){return(1-n)*i[t]+n*e}))},toRgbaString:function(){var e="rgba(",t=c.map(this._rgba,function(e,t){return null==e?2").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),t={width:n.width(),height:n.height()},r=document.activeElement;try{r.id}catch(e){r=document.body}return n.wrap(e),n[0]!==r&&!D.contains(n[0],r)||D(r).focus(),e=n.parent(),"static"===n.css("position")?(e.css({position:"relative"}),n.css({position:"relative"})):(D.extend(i,{position:n.css("position"),zIndex:n.css("z-index")}),D.each(["top","left","bottom","right"],function(e,t){i[t]=n.css(t),isNaN(parseInt(i[t],10))&&(i[t]="auto")}),n.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),n.css(t),e.css(i).show()},removeWrapper:function(e){var t=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),e[0]!==t&&!D.contains(e[0],t)||D(t).focus()),e},setTransition:function(i,e,r,o){return o=o||{},D.each(e,function(e,t){var n=i.cssUnit(t);0r&&0!==r||!1===i.call(e,o))&&jQuery.timer.remove(e,n,i)}a.timerID=i.timerID,s[n][i.timerID]||(s[n][i.timerID]=window.setInterval(a,t)),this.global.push(e)}},remove:function(e,t,n){var i,r=jQuery.data(e,this.dataKey);if(r){if(t){if(r[t]){if(n)n.timerID&&(window.clearInterval(r[t][n.timerID]),delete r[t][n.timerID]);else for(var n in r[t])window.clearInterval(r[t][n]),delete r[t][n];for(i in r[t])break;i||(i=null,delete r[t])}}else for(t in r)this.remove(e,t,n);for(i in r)break;i||jQuery.removeData(e,this.dataKey)}}}}),jQuery(window).bind("unload",function(){jQuery.each(jQuery.timer.global,function(e,t){jQuery.timer.remove(t)})}),function(){"use strict";var a={version:"1.0.1-nanoui",templateSettings:{evaluate:/\{\{([\s\S]+?)\}\}/g,interpolate:/\{\{:([\s\S]+?)\}\}/g,encode:/\{\{>([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,conditional:/\{\{\/?if\s*([\s\S]*?)\s*\}\}/g,conditionalElse:/\{\{else\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{\/?for\s*(?:\}\}|([\s\S]+?)\s*(?:\:\s*([\w$]+))?\s*(?:\:\s*([\w$]+))?\s*\}\})/g,props:/\{\{\/?props\s*(?:\}\}|([\s\S]+?)\s*(?:\:\s*([\w$]+))?\s*(?:\:\s*([\w$]+))?\s*\}\})/g,empty:/\{\{empty\}\}/g,varname:"data, config, helper",strip:!0,append:!0,selfcontained:!1},template:void 0,compile:void 0};function l(){var t={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},e=/&(?!#?\w+;)|<|>|"|'|\//g;return function(){return this?this.replace(e,function(e){return t[e]||e}):this}}"undefined"!=typeof module&&module.exports?module.exports=a:"function"==typeof define&&define.amd?define(function(){return a}):function(){return this||(0,eval)("this")}().doT=a,String.prototype.encodeHTML=l();var u={append:{start:"'+(",end:")+'",endencode:"||'').toString().encodeHTML()+'"},split:{start:"';out+=(",end:");out+='",endencode:"||'').toString().encodeHTML();out+='"}},c=/$^/;function f(e){return e.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}a.template=function(e,t,n){var i,r=(t=t||a.templateSettings).append?u.append:u.split,o=0,s=t.use||t.define?function i(r,e,o){return("string"==typeof e?e:e.toString()).replace(r.define||c,function(e,i,t,n){return 0===i.indexOf("def.")&&(i=i.substring(4)),i in o||(":"===t?(r.defineParams&&n.replace(r.defineParams,function(e,t,n){o[i]={arg:t,text:n}}),i in o||(o[i]=n)):new Function("def","def['"+i+"']="+n)(o)),""}).replace(r.use||c,function(e,t){r.useParams&&(t=t.replace(r.useParams,function(e,t,n,i){if(o[n]&&o[n].arg&&i){var r=(n+":"+i).replace(/'|\\/g,"_");return o.__exp=o.__exp||{},o.__exp[r]=o[n].text.replace(new RegExp("(^|[^\\w$])"+o[n].arg+"([^\\w$])","g"),"$1"+i+"$2"),t+"def.__exp['"+r+"']"}}));var n=new Function("def","return "+t)(o);return n?i(r,n,o):n})}(t,e,n||{}):e;s=("var out='"+(t.strip?s.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):s).replace(/'|\\/g,"\\$&").replace(t.interpolate||c,function(e,t){return r.start+f(t)+r.end}).replace(t.encode||c,function(e,t){return i=!0,r.start+f(t)+r.endencode}).replace(t.conditional||c,function(e,t){return t?"';if("+f(t)+"){out+='":"';}out+='"}).replace(t.conditionalElse||c,function(e,t){return t?"';}else if("+f(t)+"){out+='":"';}else{out+='"}).replace(t.iterate||c,function(e,t,n,i){if(!t)return"';} } out+='";o+=1,n=n||"value",i=i||"index",t=f(t);var r="arr"+o;return"';var "+r+"="+t+";if("+r+" && "+r+".length > 0){var "+n+","+i+"=-1,l"+o+"="+r+".length-1;while("+i+" 0){var "+n+";for( var "+i+" in "+r+"){ if (!"+r+".hasOwnProperty("+i+")) continue; "+n+"="+r+"["+i+"];out+='"}).replace(t.empty||c,function(e){return"';}}else{if(true){out+='"}).replace(t.evaluate||c,function(e,t){return"';"+f(t)+"out+='"})+"';return out;").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/\r/g,"\\r").replace(/(\s|;|\}|^|\{)out\+='';/g,"$1").replace(/\+''/g,"").replace(/(\s|;|\}|^|\{)out\+=''\+/g,"$1out+="),i&&t.selfcontained&&(s="String.prototype.encodeHTML=("+l.toString()+"());"+s);try{return new Function(t.varname,s)}catch(e){throw"undefined"!=typeof console&&console.log("Could not create a template function: "+s),e}},a.compile=function(e,t){return a.template(e,null,t)}}(),function(e,t){"use strict";"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.returnExports=t()}(this,function(){function n(e){try{var t=S.call(e).replace(/\/\/.*\n/g,"").replace(/\/\*[.\s\S]*\*\//g,"").replace(/\n/gm," ").replace(/ {2}/g," ");return N.test(t)}catch(e){return!1}}function p(e){if(!e)return!1;if("function"!=typeof e&&"object"!=typeof e)return!1;if(E)return function(e){try{return!n(e)&&(S.call(e),!0)}catch(e){return!1}}(e);if(n(e))return!1;var t=_.call(e);return"[object Function]"===t||"[object GeneratorFunction]"===t}var h,d,l=Array,e=l.prototype,a=Object,t=a.prototype,u=Function,i=u.prototype,v=String,r=v.prototype,y=Number,o=y.prototype,c=e.slice,s=e.splice,g=e.push,f=e.unshift,m=e.concat,b=e.join,x=i.call,w=i.apply,T=Math.max,C=Math.min,_=t.toString,E="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag,S=Function.prototype.toString,N=/^\s*class /,D=RegExp.prototype.exec;h=function(e){return"object"==typeof e&&(E?function(e){try{return D.call(e),!0}catch(e){return!1}}(e):"[object RegExp]"===_.call(e))};var k=String.prototype.valueOf;d=function(e){return"string"==typeof e||"object"==typeof e&&(E?function(e){try{return k.call(e),!0}catch(e){return!1}}(e):"[object String]"===_.call(e))};function j(e){var t=typeof e;return null===e||"object"!=t&&"function"!=t}function A(){}var P,H,M=a.defineProperty&&function(){try{var e={};for(var t in a.defineProperty(e,"x",{enumerable:!1,value:e}),e)return!1;return e.x===e}catch(e){return!1}}(),L=(P=t.hasOwnProperty,H=M?function(e,t,n,i){!i&&t in e||a.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:!0,value:n})}:function(e,t,n,i){!i&&t in e||(e[t]=n)},function(e,t,n){for(var i in t)P.call(t,i)&&H(e,i,t[i],n)}),O=y.isNaN||function(e){return e!=e},I=function(e){var t=+e;return O(t)?t=0:0!==t&&t!==1/0&&t!==-1/0&&(t=(0>>0};L(i,{bind:function(t){var n=this;if(!p(n))throw new TypeError("Function.prototype.bind called on incompatible "+n);for(var i,r=c.call(arguments,1),e=T(0,n.length-r.length),o=[],s=0;s=r)throw new TypeError("reduce of empty array with no initial value")}for(;s>10|55296,1023&i|56320)}function i(){v()}var e,d,x,o,r,g,p,m,w,u,c,v,T,s,y,b,a,h,C,_="sizzle"+ +new Date,E=n.document,S=0,N=0,l=oe(),D=oe(),k=oe(),j=function(e,t){return e===t&&(c=!0),0},A={}.hasOwnProperty,t=[],P=t.pop,H=t.push,M=t.push,L=t.slice,O=function(e,t){for(var n=0,i=e.length;n+~]|"+F+")"+F+"*"),Y=new RegExp("="+F+"*([^\\]'\"]*?)"+F+"*\\]","g"),Q=new RegExp($),J=new RegExp("^"+q+"$"),V={ID:new RegExp("^#("+W+")"),CLASS:new RegExp("^\\.("+W+")"),TAG:new RegExp("^("+W.replace("w","w*")+")"),ATTR:new RegExp("^"+R),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+F+"*(even|odd|(([+-]|)(\\d*)n|)"+F+"*(?:([+-]|)"+F+"*(\\d+)|))"+F+"*\\)|)","i"),bool:new RegExp("^(?:"+I+")$","i"),needsContext:new RegExp("^"+F+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+F+"*((?:-\\d)?\\d*)"+F+"*\\)|)(?=[^-]|$)","i")},G=/^(?:input|select|textarea|button)$/i,K=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,ee=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,te=/[+~]/,ne=/'|\\/g,ie=new RegExp("\\\\([\\da-f]{1,6}"+F+"?|("+F+")|.)","ig");try{M.apply(t=L.call(E.childNodes),E.childNodes),t[E.childNodes.length].nodeType}catch(e){M={apply:t.length?function(e,t){H.apply(e,L.call(t))}:function(e,t){for(var n=e.length,i=0;e[n++]=t[i++];);e.length=n-1}}}function re(e,t,n,i){var r,o,s,a,l,u,c,f,p,h;if((t?t.ownerDocument||t:E)!==T&&v(t),n=n||[],a=(t=t||T).nodeType,"string"!=typeof e||!e||1!==a&&9!==a&&11!==a)return n;if(!i&&y){if(11!==a&&(r=ee.exec(e)))if(s=r[1]){if(9===a){if(!(o=t.getElementById(s))||!o.parentNode)return n;if(o.id===s)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(s))&&C(t,o)&&o.id===s)return n.push(o),n}else{if(r[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=r[3])&&d.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(d.qsa&&(!b||!b.test(e))){if(f=c=_,p=t,h=1!==a&&e,1===a&&"object"!==t.nodeName.toLowerCase()){for(u=g(e),(c=t.getAttribute("id"))?f=c.replace(ne,"\\$&"):t.setAttribute("id",f),f="[id='"+f+"'] ",l=u.length;l--;)u[l]=f+ge(u[l]);p=te.test(e)&&he(t.parentNode)||t,h=u.join(",")}if(h)try{return M.apply(n,p.querySelectorAll(h)),n}catch(e){}finally{c||t.removeAttribute("id")}}}return m(e.replace(z,"$1"),t,n,i)}function oe(){var i=[];return function e(t,n){return i.push(t+" ")>x.cacheLength&&delete e[i.shift()],e[t+" "]=n}}function se(e){return e[_]=!0,e}function ae(e){var t=T.createElement("div");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function le(e,t){for(var n=e.split("|"),i=e.length;i--;)x.attrHandle[n[i]]=t}function ue(e,t){var n=t&&e,i=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||1<<31)-(~e.sourceIndex||1<<31);if(i)return i;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function ce(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function fe(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function pe(s){return se(function(o){return o=+o,se(function(e,t){for(var n,i=s([],e.length,o),r=i.length;r--;)e[n=i[r]]&&(e[n]=!(t[n]=e[n]))})})}function he(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in d=re.support={},r=re.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},v=re.setDocument=function(e){var t,n,l=e?e.ownerDocument||e:E;return l!==T&&9===l.nodeType&&l.documentElement?(s=(T=l).documentElement,(n=l.defaultView)&&n!==n.top&&(n.addEventListener?n.addEventListener("unload",i,!1):n.attachEvent&&n.attachEvent("onunload",i)),y=!r(l),d.attributes=ae(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ae(function(e){return e.appendChild(l.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=Z.test(l.getElementsByClassName),d.getById=ae(function(e){return s.appendChild(e).id=_,!l.getElementsByName||!l.getElementsByName(_).length}),d.getById?(x.find.ID=function(e,t){if(void 0!==t.getElementById&&y){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},x.filter.ID=function(e){var t=e.replace(ie,f);return function(e){return e.getAttribute("id")===t}}):(delete x.find.ID,x.filter.ID=function(e){var n=e.replace(ie,f);return function(e){var t=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}}),x.find.TAG=d.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,i=[],r=0,o=t.getElementsByTagName(e);if("*"!==e)return o;for(;n=o[r++];)1===n.nodeType&&i.push(n);return i},x.find.CLASS=d.getElementsByClassName&&function(e,t){if(y)return t.getElementsByClassName(e)},a=[],b=[],(d.qsa=Z.test(l.querySelectorAll))&&(ae(function(e){s.appendChild(e).innerHTML="
    ",e.querySelectorAll("[msallowcapture^='']").length&&b.push("[*^$]="+F+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||b.push("\\["+F+"*(?:value|"+I+")"),e.querySelectorAll("[id~="+_+"-]").length||b.push("~="),e.querySelectorAll(":checked").length||b.push(":checked"),e.querySelectorAll("a#"+_+"+*").length||b.push(".#.+[+~]")}),ae(function(e){var t=l.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&b.push("name"+F+"*[*^$|!~]?="),e.querySelectorAll(":enabled").length||b.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),b.push(",.*:")})),(d.matchesSelector=Z.test(h=s.matches||s.webkitMatchesSelector||s.mozMatchesSelector||s.oMatchesSelector||s.msMatchesSelector))&&ae(function(e){d.disconnectedMatch=h.call(e,"div"),h.call(e,"[s!='']:x"),a.push("!=",$)}),b=b.length&&new RegExp(b.join("|")),a=a.length&&new RegExp(a.join("|")),t=Z.test(s.compareDocumentPosition),C=t||Z.test(s.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,i=t&&t.parentNode;return e===i||!(!i||1!==i.nodeType||!(n.contains?n.contains(i):e.compareDocumentPosition&&16&e.compareDocumentPosition(i)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return c=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===l||e.ownerDocument===E&&C(E,e)?-1:t===l||t.ownerDocument===E&&C(E,t)?1:u?O(u,e)-O(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return c=!0,0;var n,i=0,r=e.parentNode,o=t.parentNode,s=[e],a=[t];if(!r||!o)return e===l?-1:t===l?1:r?-1:o?1:u?O(u,e)-O(u,t):0;if(r===o)return ue(e,t);for(n=e;n=n.parentNode;)s.unshift(n);for(n=t;n=n.parentNode;)a.unshift(n);for(;s[i]===a[i];)i++;return i?ue(s[i],a[i]):s[i]===E?-1:a[i]===E?1:0},l):T},re.matches=function(e,t){return re(e,null,null,t)},re.matchesSelector=function(e,t){if((e.ownerDocument||e)!==T&&v(e),t=t.replace(Y,"='$1']"),d.matchesSelector&&y&&(!a||!a.test(t))&&(!b||!b.test(t)))try{var n=h.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(ie,f),e[3]=(e[3]||e[4]||e[5]||"").replace(ie,f),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||re.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&re.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return V.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&Q.test(n)&&(t=g(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(ie,f).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=l[e+" "];return t||(t=new RegExp("(^|"+F+")"+e+"("+F+"|$)"))&&l(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,i,r){return function(e){var t=re.attr(e,n);return null==t?"!="===i:!i||(t+="","="===i?t===r:"!="===i?t!==r:"^="===i?r&&0===t.indexOf(r):"*="===i?r&&-1(?:<\/\1>|)$/,x=/^.[^:#\[\.,]*$/;function w(e,n,i){if(C.isFunction(n))return C.grep(e,function(e,t){return!!n.call(e,t,e)!==i});if(n.nodeType)return C.grep(e,function(e){return e===n!==i});if("string"==typeof n){if(x.test(n))return C.filter(n,e,i);n=C.filter(n,e)}return C.grep(e,function(e){return 0<=C.inArray(e,n)!==i})}C.filter=function(e,t,n){var i=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===i.nodeType?C.find.matchesSelector(i,e)?[i]:[]:C.find.matches(e,C.grep(t,function(e){return 1===e.nodeType}))},C.fn.extend({find:function(e){var t,n=[],i=this,r=i.length;if("string"!=typeof e)return this.pushStack(C(e).filter(function(){for(t=0;t)[^>]*|#([\w-]*))$/;(C.fn.init=function(e,t){var n,i;if(!e)return this;if("string"!=typeof e)return e.nodeType?(this.context=this[0]=e,this.length=1,this):C.isFunction(e)?void 0!==T.ready?T.ready(e):e(C):(void 0!==e.selector&&(this.selector=e.selector,this.context=e.context),C.makeArray(e,this));if(!(n="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&3<=e.length?[null,e,null]:E.exec(e))||!n[1]&&t)return!t||t.jquery?(t||T).find(e):this.constructor(t).find(e);if(n[1]){if(t=t instanceof C?t[0]:t,C.merge(this,C.parseHTML(n[1],t&&t.nodeType?t.ownerDocument||t:_,!0)),b.test(n[1])&&C.isPlainObject(t))for(n in t)C.isFunction(this[n])?this[n](t[n]):this.attr(n,t[n]);return this}if((i=_.getElementById(n[2]))&&i.parentNode){if(i.id!==n[2])return T.find(e);this.length=1,this[0]=i}return this.context=_,this.selector=e,this}).prototype=C.fn,T=C(_);var S=/^(?:parents|prev(?:Until|All))/,N={children:!0,contents:!0,next:!0,prev:!0};function D(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}C.extend({dir:function(e,t,n){for(var i=[],r=e[t];r&&9!==r.nodeType&&(void 0===n||1!==r.nodeType||!C(r).is(n));)1===r.nodeType&&i.push(r),r=r[t];return i},sibling:function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}}),C.fn.extend({has:function(e){var t,n=C(e,this),i=n.length;return this.filter(function(){for(t=0;t
    a",v.leadingWhitespace=3===t.firstChild.nodeType,v.tbody=!t.getElementsByTagName("tbody").length,v.htmlSerialize=!!t.getElementsByTagName("link").length,v.html5Clone="<:nav>"!==_.createElement("nav").cloneNode(!0).outerHTML,e.type="checkbox",e.checked=!0,n.appendChild(e),v.appendChecked=e.checked,t.innerHTML="",v.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue,n.appendChild(t),t.innerHTML="",v.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,v.noCloneEvent=!0,t.attachEvent&&(t.attachEvent("onclick",function(){v.noCloneEvent=!1}),t.cloneNode(!0).click()),null==v.deleteExpando){v.deleteExpando=!0;try{delete t.test}catch(e){v.deleteExpando=!1}}}(),function(){var e,t,n=_.createElement("div");for(e in{submit:!0,change:!0,focusin:!0})t="on"+e,(v[e+"Bubbles"]=t in d)||(n.setAttribute(t,"t"),v[e+"Bubbles"]=!1===n.attributes[t].expando);n=null}();var Y=/^(?:input|select|textarea)$/i,Q=/^key/,J=/^(?:mouse|pointer|contextmenu)|click/,V=/^(?:focusinfocus|focusoutblur)$/,G=/^([^.]*)(?:\.(.+)|)$/;function K(){return!0}function Z(){return!1}function ee(){try{return _.activeElement}catch(e){}}function te(e){var t=ne.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}C.event={global:{},add:function(e,t,n,i,r){var o,s,a,l,u,c,f,p,h,d,g,m=C._data(e);if(m){for(n.handler&&(n=(l=n).handler,r=l.selector),n.guid||(n.guid=C.guid++),(s=m.events)||(s=m.events={}),(c=m.handle)||((c=m.handle=function(e){return typeof C===L||e&&C.event.triggered===e.type?void 0:C.event.dispatch.apply(c.elem,arguments)}).elem=e),a=(t=(t||"").match(j)||[""]).length;a--;)h=g=(o=G.exec(t[a])||[])[1],d=(o[2]||"").split(".").sort(),h&&(u=C.event.special[h]||{},h=(r?u.delegateType:u.bindType)||h,u=C.event.special[h]||{},f=C.extend({type:h,origType:g,data:i,handler:n,guid:n.guid,selector:r,needsContext:r&&C.expr.match.needsContext.test(r),namespace:d.join(".")},l),(p=s[h])||((p=s[h]=[]).delegateCount=0,u.setup&&!1!==u.setup.call(e,i,d,c)||(e.addEventListener?e.addEventListener(h,c,!1):e.attachEvent&&e.attachEvent("on"+h,c))),u.add&&(u.add.call(e,f),f.handler.guid||(f.handler.guid=n.guid)),r?p.splice(p.delegateCount++,0,f):p.push(f),C.event.global[h]=!0);e=null}},remove:function(e,t,n,i,r){var o,s,a,l,u,c,f,p,h,d,g,m=C.hasData(e)&&C._data(e);if(m&&(c=m.events)){for(u=(t=(t||"").match(j)||[""]).length;u--;)if(h=g=(a=G.exec(t[u])||[])[1],d=(a[2]||"").split(".").sort(),h){for(f=C.event.special[h]||{},p=c[h=(i?f.delegateType:f.bindType)||h]||[],a=a[2]&&new RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=p.length;o--;)s=p[o],!r&&g!==s.origType||n&&n.guid!==s.guid||a&&!a.test(s.namespace)||i&&i!==s.selector&&("**"!==i||!s.selector)||(p.splice(o,1),s.selector&&p.delegateCount--,f.remove&&f.remove.call(e,s));l&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,d,m.handle)||C.removeEvent(e,h,m.handle),delete c[h])}else for(h in c)C.event.remove(e,h+t[u],n,i,!0);C.isEmptyObject(c)&&(delete m.handle,C._removeData(e,"events"))}},trigger:function(e,t,n,i){var r,o,s,a,l,u,c,f=[n||_],p=m.call(e,"type")?e.type:e,h=m.call(e,"namespace")?e.namespace.split("."):[];if(s=u=n=n||_,3!==n.nodeType&&8!==n.nodeType&&!V.test(p+C.event.triggered)&&(0<=p.indexOf(".")&&(p=(h=p.split(".")).shift(),h.sort()),o=p.indexOf(":")<0&&"on"+p,(e=e[C.expando]?e:new C.Event(p,"object"==typeof e&&e)).isTrigger=i?2:3,e.namespace=h.join("."),e.namespace_re=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:C.makeArray(t,[e]),l=C.event.special[p]||{},i||!l.trigger||!1!==l.trigger.apply(n,t))){if(!i&&!l.noBubble&&!C.isWindow(n)){for(a=l.delegateType||p,V.test(a+p)||(s=s.parentNode);s;s=s.parentNode)f.push(s),u=s;u===(n.ownerDocument||_)&&f.push(u.defaultView||u.parentWindow||d)}for(c=0;(s=f[c++])&&!e.isPropagationStopped();)e.type=1]","i"),oe=/^\s+/,se=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ae=/<([\w:]+)/,le=/
    ","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:v.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},me=te(_).appendChild(_.createElement("div"));function ve(e,t){var n,i,r=0,o=typeof e.getElementsByTagName!==L?e.getElementsByTagName(t||"*"):typeof e.querySelectorAll!==L?e.querySelectorAll(t||"*"):void 0;if(!o)for(o=[],n=e.childNodes||e;null!=(i=n[r]);r++)!t||C.nodeName(i,t)?o.push(i):C.merge(o,ve(i,t));return void 0===t||t&&C.nodeName(e,t)?C.merge([e],o):o}function ye(e){X.test(e.type)&&(e.defaultChecked=e.checked)}function be(e,t){return C.nodeName(e,"table")&&C.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function xe(e){return e.type=(null!==C.find.attr(e,"type"))+"/"+e.type,e}function we(e){var t=he.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Te(e,t){for(var n,i=0;null!=(n=e[i]);i++)C._data(n,"globalEval",!t||C._data(t[i],"globalEval"))}function Ce(e,t){if(1===t.nodeType&&C.hasData(e)){var n,i,r,o=C._data(e),s=C._data(t,o),a=o.events;if(a)for(n in delete s.handle,s.events={},a)for(i=0,r=a[n].length;i")?o=e.cloneNode(!0):(me.innerHTML=e.outerHTML,me.removeChild(o=me.firstChild)),!(v.noCloneEvent&&v.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||C.isXMLDoc(e)))for(i=ve(o),a=ve(e),s=0;null!=(r=a[s]);++s)i[s]&&_e(r,i[s]);if(t)if(n)for(a=a||ve(e),i=i||ve(o),s=0;null!=(r=a[s]);s++)Ce(r,i[s]);else Ce(e,o);return 0<(i=ve(o,"script")).length&&Te(i,!l&&ve(e,"script")),i=a=r=null,o},buildFragment:function(e,t,n,i){for(var r,o,s,a,l,u,c,f=e.length,p=te(t),h=[],d=0;d")+c[2],r=c[0];r--;)a=a.lastChild;if(!v.leadingWhitespace&&oe.test(o)&&h.push(t.createTextNode(oe.exec(o)[0])),!v.tbody)for(r=(o="table"!==l||le.test(o)?""!==c[1]||le.test(o)?0:a:a.firstChild)&&o.childNodes.length;r--;)C.nodeName(u=o.childNodes[r],"tbody")&&!u.childNodes.length&&o.removeChild(u);for(C.merge(h,a.childNodes),a.textContent="";a.firstChild;)a.removeChild(a.firstChild);a=p.lastChild}else h.push(t.createTextNode(o));for(a&&p.removeChild(a),v.appendChecked||C.grep(ve(h,"input"),ye),d=0;o=h[d++];)if((!i||-1===C.inArray(o,i))&&(s=C.contains(o.ownerDocument,o),a=ve(p.appendChild(o),"script"),s&&Te(a),n))for(r=0;o=a[r++];)pe.test(o.type||"")&&n.push(o);return a=null,p},cleanData:function(e,t){for(var n,i,r,o,s=0,a=C.expando,l=C.cache,u=v.deleteExpando,c=C.event.special;null!=(n=e[s]);s++)if((t||C.acceptData(n))&&(o=(r=n[a])&&l[r])){if(o.events)for(i in o.events)c[i]?C.event.remove(n,i):C.removeEvent(n,i,o.handle);l[r]&&(delete l[r],u?delete n[a]:typeof n.removeAttribute!==L?n.removeAttribute(a):n[a]=null,f.push(r))}}}),C.fn.extend({text:function(e){return U(this,function(e){return void 0===e?C.text(this):this.empty().append((this[0]&&this[0].ownerDocument||_).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||be(this,e).appendChild(e)})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=be(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){for(var n,i=e?C.filter(e,this):this,r=0;null!=(n=i[r]);r++)t||1!==n.nodeType||C.cleanData(ve(n)),n.parentNode&&(t&&C.contains(n.ownerDocument,n)&&Te(ve(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){for(var e,t=0;null!=(e=this[t]);t++){for(1===e.nodeType&&C.cleanData(ve(e,!1));e.firstChild;)e.removeChild(e.firstChild);e.options&&C.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return C.clone(this,e,t)})},html:function(e){return U(this,function(e){var t=this[0]||{},n=0,i=this.length;if(void 0===e)return 1===t.nodeType?t.innerHTML.replace(ie,""):void 0;if("string"==typeof e&&!ce.test(e)&&(v.htmlSerialize||!re.test(e))&&(v.leadingWhitespace||!oe.test(e))&&!ge[(ae.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(se,"<$1>");try{for(;n")).appendTo(t.documentElement))[0].contentWindow||Ee[0].contentDocument).document).write(),t.close(),n=De(e,t),Ee.detach()),Ne[e]=n),n}v.shrinkWrapBlocks=function(){return null!=Se?Se:(Se=!1,(t=_.getElementsByTagName("body")[0])&&t.style?(e=_.createElement("div"),(n=_.createElement("div")).style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",t.appendChild(n).appendChild(e),typeof e.style.zoom!==L&&(e.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",e.appendChild(_.createElement("div")).style.width="5px",Se=3!==e.offsetWidth),t.removeChild(n),Se):void 0);var e,t,n};var je,Ae,Pe,He,Me,Le,Oe,Ie,Fe,We=/^margin/,qe=new RegExp("^("+B+")(?!px)[a-z%]+$","i"),Re=/^(top|right|bottom|left)$/;function $e(t,n){return{get:function(){var e=t();if(null!=e){if(!e)return(this.get=n).apply(this,arguments);delete this.get}}}}function Be(){var e,t,n,i;(t=_.getElementsByTagName("body")[0])&&t.style&&(e=_.createElement("div"),(n=_.createElement("div")).style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",t.appendChild(n).appendChild(e),e.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",Le=Oe=!1,Fe=!0,d.getComputedStyle&&(Le="1%"!==(d.getComputedStyle(e,null)||{}).top,Oe="4px"===(d.getComputedStyle(e,null)||{width:"4px"}).width,(i=e.appendChild(_.createElement("div"))).style.cssText=e.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",e.style.width="1px",Fe=!parseFloat((d.getComputedStyle(i,null)||{}).marginRight),e.removeChild(i)),e.innerHTML="
    t
    ",(i=e.getElementsByTagName("td"))[0].style.cssText="margin:0;border:0;padding:0;display:none",(Ie=0===i[0].offsetHeight)&&(i[0].style.display="",i[1].style.display="none",Ie=0===i[0].offsetHeight),t.removeChild(n))}d.getComputedStyle?(je=function(e){return e.ownerDocument.defaultView.opener?e.ownerDocument.defaultView.getComputedStyle(e,null):d.getComputedStyle(e,null)},Ae=function(e,t,n){var i,r,o,s,a=e.style;return s=(n=n||je(e))?n.getPropertyValue(t)||n[t]:void 0,n&&(""!==s||C.contains(e.ownerDocument,e)||(s=C.style(e,t)),qe.test(s)&&We.test(t)&&(i=a.width,r=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=s,s=n.width,a.width=i,a.minWidth=r,a.maxWidth=o)),void 0===s?s:s+""}):_.documentElement.currentStyle&&(je=function(e){return e.currentStyle},Ae=function(e,t,n){var i,r,o,s,a=e.style;return null==(s=(n=n||je(e))?n[t]:void 0)&&a&&a[t]&&(s=a[t]),qe.test(s)&&!Re.test(t)&&(i=a.left,(o=(r=e.runtimeStyle)&&r.left)&&(r.left=e.currentStyle.left),a.left="fontSize"===t?"1em":s,s=a.pixelLeft+"px",a.left=i,o&&(r.left=o)),void 0===s?s:s+""||"auto"}),(Pe=_.createElement("div")).innerHTML="
    a",(He=(Me=Pe.getElementsByTagName("a")[0])&&Me.style)&&(He.cssText="float:left;opacity:.5",v.opacity="0.5"===He.opacity,v.cssFloat=!!He.cssFloat,Pe.style.backgroundClip="content-box",Pe.cloneNode(!0).style.backgroundClip="",v.clearCloneStyle="content-box"===Pe.style.backgroundClip,v.boxSizing=""===He.boxSizing||""===He.MozBoxSizing||""===He.WebkitBoxSizing,C.extend(v,{reliableHiddenOffsets:function(){return null==Ie&&Be(),Ie},boxSizingReliable:function(){return null==Oe&&Be(),Oe},pixelPosition:function(){return null==Le&&Be(),Le},reliableMarginRight:function(){return null==Fe&&Be(),Fe}})),C.swap=function(e,t,n,i){var r,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];for(o in r=n.apply(e,i||[]),t)e.style[o]=s[o];return r};var ze=/alpha\([^)]*\)/i,Ue=/opacity\s*=\s*([^)]*)/,Xe=/^(none|table(?!-c[ea]).+)/,Ye=new RegExp("^("+B+")(.*)$","i"),Qe=new RegExp("^([+-])=("+B+")","i"),Je={position:"absolute",visibility:"hidden",display:"block"},Ve={letterSpacing:"0",fontWeight:"400"},Ge=["Webkit","O","Moz","ms"];function Ke(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),i=t,r=Ge.length;r--;)if((t=Ge[r]+n)in e)return t;return i}function Ze(e,t){for(var n,i,r,o=[],s=0,a=e.length;s
    a",ut=at.getElementsByTagName("a")[0],ct=(lt=_.createElement("select")).appendChild(_.createElement("option")),st=at.getElementsByTagName("input")[0],ut.style.cssText="top:1px",v.getSetAttribute="t"!==at.className,v.style=/top/.test(ut.getAttribute("style")),v.hrefNormalized="/a"===ut.getAttribute("href"),v.checkOn=!!st.value,v.optSelected=ct.selected,v.enctype=!!_.createElement("form").enctype,lt.disabled=!0,v.optDisabled=!ct.disabled,(st=_.createElement("input")).setAttribute("value",""),v.input=""===st.getAttribute("value"),st.value="t",st.setAttribute("type","radio"),v.radioValue="t"===st.value;var xt=/\r/g;C.fn.extend({val:function(n){var i,e,r,t=this[0];return arguments.length?(r=C.isFunction(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=r?n.call(this,e,C(this).val()):n)?t="":"number"==typeof t?t+="":C.isArray(t)&&(t=C.map(t,function(e){return null==e?"":e+""})),(i=C.valHooks[this.type]||C.valHooks[this.nodeName.toLowerCase()])&&"set"in i&&void 0!==i.set(this,t,"value")||(this.value=t))})):t?(i=C.valHooks[t.type]||C.valHooks[t.nodeName.toLowerCase()])&&"get"in i&&void 0!==(e=i.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(xt,""):null==e?"":e:void 0}}),C.extend({valHooks:{option:{get:function(e){var t=C.find.attr(e,"value");return null!=t?t:C.trim(C.text(e))}},select:{get:function(e){for(var t,n,i=e.options,r=e.selectedIndex,o="select-one"===e.type||r<0,s=o?null:[],a=o?r+1:i.length,l=r<0?a:o?r:0;l").append(C.parseHTML(e)).find(i):e)}).complete(n&&function(e,t){s.each(n,r||[e.responseText,t,e])}),this},C.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){C.fn[t]=function(e){return this.on(t,e)}}),C.expr.filters.animated=function(t){return C.grep(C.timers,function(e){return t===e.elem}).length};var cn=d.document.documentElement;function fn(e){return C.isWindow(e)?e:9===e.nodeType&&(e.defaultView||e.parentWindow)}C.offset={setOffset:function(e,t,n){var i,r,o,s,a,l,u=C.css(e,"position"),c=C(e),f={};"static"===u&&(e.style.position="relative"),a=c.offset(),o=C.css(e,"top"),l=C.css(e,"left"),r=("absolute"===u||"fixed"===u)&&-1").outerWidth(1).jquery||D.each(["Width","Height"],function(e,n){var r="Width"===n?["Left","Right"]:["Top","Bottom"],i=n.toLowerCase(),o={innerWidth:D.fn.innerWidth,innerHeight:D.fn.innerHeight,outerWidth:D.fn.outerWidth,outerHeight:D.fn.outerHeight};function s(e,t,n,i){return D.each(r,function(){t-=parseFloat(D.css(e,"padding"+this))||0,n&&(t-=parseFloat(D.css(e,"border"+this+"Width"))||0),i&&(t-=parseFloat(D.css(e,"margin"+this))||0)}),t}D.fn["inner"+n]=function(e){return void 0===e?o["inner"+n].call(this):this.each(function(){D(this).css(i,s(this,e)+"px")})},D.fn["outer"+n]=function(e,t){return"number"!=typeof e?o["outer"+n].call(this,e):this.each(function(){D(this).css(i,s(this,e,!0,t)+"px")})}}),D.fn.addBack||(D.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),D("").data("a-b","a").removeData("a-b").data("a-b")&&(D.fn.removeData=(t=D.fn.removeData,function(e){return arguments.length?t.call(this,D.camelCase(e)):t.call(this)})),D.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),D.fn.extend({focus:(i=D.fn.focus,function(t,n){return"number"==typeof t?this.each(function(){var e=this;setTimeout(function(){D(e).focus(),n&&n.call(e)},t)}):i.apply(this,arguments)}),disableSelection:(n="onselectstart"in document.createElement("div")?"selectstart":"mousedown",function(){return this.bind(n+".ui-disableSelection",function(e){e.preventDefault()})}),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(e){if(void 0!==e)return this.css("zIndex",e);if(this.length)for(var t,n,i=D(this[0]);i.length&&i[0]!==document;){if(("absolute"===(t=i.css("position"))||"relative"===t||"fixed"===t)&&(n=parseInt(i.css("zIndex"),10),!isNaN(n)&&0!==n))return n;i=i.parent()}return 0}}),D.ui.plugin={add:function(e,t,n){var i,r=D.ui[e].prototype;for(i in n)r.plugins[i]=r.plugins[i]||[],r.plugins[i].push([t,n[i]])},call:function(e,t,n,i){var r,o=e.plugins[t];if(o&&(i||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(r=0;r",options:{disabled:!1,create:null},_createWidget:function(e,t){t=D(t||this.defaultElement||this)[0],this.element=D(t),this.uuid=a++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=D(),this.hoverable=D(),this.focusable=D(),t!==this&&(D.data(t,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===t&&this.destroy()}}),this.document=D(t.style?t.ownerDocument:t.document||t),this.window=D(this.document[0].defaultView||this.document[0].parentWindow)),this.options=D.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:D.noop,_getCreateEventData:D.noop,_create:D.noop,_init:D.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(D.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:D.noop,widget:function(){return this.element},option:function(e,t){var n,i,r,o=e;if(0===arguments.length)return D.widget.extend({},this.options);if("string"==typeof e)if(o={},e=(n=e.split(".")).shift(),n.length){for(i=o[e]=D.widget.extend({},this.options[e]),r=0;r=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}});!function(){D.ui=D.ui||{};var r,T,C=Math.max,_=Math.abs,E=Math.round,i=/left|center|right/,o=/top|center|bottom/,s=/[\+\-]\d+(\.[\d]+)?%?/,a=/^\w+/,l=/%$/,u=D.fn.position;function S(e,t,n){return[parseFloat(e[0])*(l.test(e[0])?t/100:1),parseFloat(e[1])*(l.test(e[1])?n/100:1)]}function N(e,t){return parseInt(D.css(e,t),10)||0}D.position={scrollbarWidth:function(){if(void 0!==r)return r;var e,t,n=D("
    "),i=n.children()[0];return D("body").append(n),e=i.offsetWidth,n.css("overflow","scroll"),e===(t=i.offsetWidth)&&(t=n[0].clientWidth),n.remove(),r=e-t},getScrollInfo:function(e){var t=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),n=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),i="scroll"===t||"auto"===t&&e.widthC(_(i),_(r))?o.important="horizontal":o.important="vertical",f.using.call(this,e,o)}),s.offset(D.extend(u,{using:e}))})},D.ui.position={fit:{left:function(e,t){var n,i=t.within,r=i.isWindow?i.scrollLeft:i.offset.left,o=i.width,s=e.left-t.collisionPosition.marginLeft,a=r-s,l=s+t.collisionWidth-o-r;t.collisionWidth>o?0o?0").css("position","absolute").appendTo(e.parent()).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(e){var t=this.document[0];if(this.handleElement.is(e.target))try{t.activeElement&&"body"!==t.activeElement.nodeName.toLowerCase()&&D(t.activeElement).blur()}catch(e){}},_mouseStart:function(e){var t=this.options;return this.helper=this._createHelper(e),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),D.ui.ddmanager&&(D.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=0n[2]&&(l=n[2]+this.offset.click.left),e.pageY-this.offset.click.top>n[3]&&(u=n[3]+this.offset.click.top)),s.grid&&(r=s.grid[1]?this.originalPageY+Math.round((u-this.originalPageY)/s.grid[1])*s.grid[1]:this.originalPageY,u=!n||r-this.offset.click.top>=n[1]||r-this.offset.click.top>n[3]?r:r-this.offset.click.top>=n[1]?r-s.grid[1]:r+s.grid[1],o=s.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/s.grid[0])*s.grid[0]:this.originalPageX,l=!n||o-this.offset.click.left>=n[0]||o-this.offset.click.left>n[2]?o:o-this.offset.click.left>=n[0]?o-s.grid[0]:o+s.grid[0]),"y"===s.axis&&(l=this.originalPageX),"x"===s.axis&&(u=this.originalPageY)),{top:u-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:a?0:this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:a?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){"y"!==this.options.axis&&"auto"!==this.helper.css("right")&&(this.helper.width(this.helper.width()),this.helper.css("right","auto")),"x"!==this.options.axis&&"auto"!==this.helper.css("bottom")&&(this.helper.height(this.helper.height()),this.helper.css("bottom","auto"))},_trigger:function(e,t,n){return n=n||this._uiHash(),D.ui.plugin.call(this,e,[t,n,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),n.offset=this.positionAbs),D.Widget.prototype._trigger.call(this,e,t,n)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),D.ui.plugin.add("draggable","connectToSortable",{start:function(t,e,n){var i=D.extend({},e,{item:n.element});n.sortables=[],D(n.options.connectToSortable).each(function(){var e=D(this).sortable("instance");e&&!e.options.disabled&&(n.sortables.push(e),e.refreshPositions(),e._trigger("activate",t,i))})},stop:function(t,e,n){var i=D.extend({},e,{item:n.element});n.cancelHelperRemoval=!1,D.each(n.sortables,function(){var e=this;e.isOver?(e.isOver=0,n.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css("position"),top:e.placeholder.css("top"),left:e.placeholder.css("left")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger("deactivate",t,i))})},drag:function(n,i,r){D.each(r.sortables,function(){var e=!1,t=this;t.positionAbs=r.positionAbs,t.helperProportions=r.helperProportions,t.offset.click=r.offset.click,t._intersectsWith(t.containerCache)&&(e=!0,D.each(r.sortables,function(){return this.positionAbs=r.positionAbs,this.helperProportions=r.helperProportions,this.offset.click=r.offset.click,this!==t&&this._intersectsWith(this.containerCache)&&D.contains(t.element[0],this.element[0])&&(e=!1),e})),e?(t.isOver||(t.isOver=1,r._parent=i.helper.parent(),t.currentItem=i.helper.appendTo(t.element).data("ui-sortable-item",!0),t.options._helper=t.options.helper,t.options.helper=function(){return i.helper[0]},n.target=t.currentItem[0],t._mouseCapture(n,!0),t._mouseStart(n,!0,!0),t.offset.click.top=r.offset.click.top,t.offset.click.left=r.offset.click.left,t.offset.parent.left-=r.offset.parent.left-t.offset.parent.left,t.offset.parent.top-=r.offset.parent.top-t.offset.parent.top,r._trigger("toSortable",n),r.dropped=t.element,D.each(r.sortables,function(){this.refreshPositions()}),r.currentItem=r.element,t.fromOutside=r),t.currentItem&&(t._mouseDrag(n),i.position=t.position)):t.isOver&&(t.isOver=0,t.cancelHelperRemoval=!0,t.options._revert=t.options.revert,t.options.revert=!1,t._trigger("out",n,t._uiHash(t)),t._mouseStop(n,!0),t.options.revert=t.options._revert,t.options.helper=t.options._helper,t.placeholder&&t.placeholder.remove(),i.helper.appendTo(r._parent),r._refreshOffsets(n),i.position=r._generatePosition(n,!0),r._trigger("fromSortable",n),r.dropped=!1,D.each(r.sortables,function(){this.refreshPositions()}))})}}),D.ui.plugin.add("draggable","cursor",{start:function(e,t,n){var i=D("body"),r=n.options;i.css("cursor")&&(r._cursor=i.css("cursor")),i.css("cursor",r.cursor)},stop:function(e,t,n){var i=n.options;i._cursor&&D("body").css("cursor",i._cursor)}}),D.ui.plugin.add("draggable","opacity",{start:function(e,t,n){var i=D(t.helper),r=n.options;i.css("opacity")&&(r._opacity=i.css("opacity")),i.css("opacity",r.opacity)},stop:function(e,t,n){var i=n.options;i._opacity&&D(t.helper).css("opacity",i._opacity)}}),D.ui.plugin.add("draggable","scroll",{start:function(e,t,n){n.scrollParentNotHidden||(n.scrollParentNotHidden=n.helper.scrollParent(!1)),n.scrollParentNotHidden[0]!==n.document[0]&&"HTML"!==n.scrollParentNotHidden[0].tagName&&(n.overflowOffset=n.scrollParentNotHidden.offset())},drag:function(e,t,n){var i=n.options,r=!1,o=n.scrollParentNotHidden[0],s=n.document[0];o!==s&&"HTML"!==o.tagName?(i.axis&&"x"===i.axis||(n.overflowOffset.top+o.offsetHeight-e.pageY")[0],x=c.each,b.style.cssText="background-color:rgba(1,1,1,.5)",y.rgba=-1
    ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),t={width:n.width(),height:n.height()},r=document.activeElement;try{r.id}catch(e){r=document.body}return n.wrap(e),n[0]!==r&&!D.contains(n[0],r)||D(r).focus(),e=n.parent(),"static"===n.css("position")?(e.css({position:"relative"}),n.css({position:"relative"})):(D.extend(i,{position:n.css("position"),zIndex:n.css("z-index")}),D.each(["top","left","bottom","right"],function(e,t){i[t]=n.css(t),isNaN(parseInt(i[t],10))&&(i[t]="auto")}),n.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),n.css(t),e.css(i).show()},removeWrapper:function(e){var t=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),e[0]!==t&&!D.contains(e[0],t)||D(t).focus()),e},setTransition:function(i,e,r,o){return o=o||{},D.each(e,function(e,t){var n=i.cssUnit(t);0r&&0!==r||!1===i.call(e,o))&&jQuery.timer.remove(e,n,i)}a.timerID=i.timerID,s[n][i.timerID]||(s[n][i.timerID]=window.setInterval(a,t)),this.global.push(e)}},remove:function(e,t,n){var i,r=jQuery.data(e,this.dataKey);if(r){if(t){if(r[t]){if(n)n.timerID&&(window.clearInterval(r[t][n.timerID]),delete r[t][n.timerID]);else for(var n in r[t])window.clearInterval(r[t][n]),delete r[t][n];for(i in r[t])break;i||(i=null,delete r[t])}}else for(t in r)this.remove(e,t,n);for(i in r)break;i||jQuery.removeData(e,this.dataKey)}}}}),jQuery(window).bind("unload",function(){jQuery.each(jQuery.timer.global,function(e,t){jQuery.timer.remove(t)})}),function(){"use strict";var a={version:"1.0.1-nanoui",templateSettings:{evaluate:/\{\{([\s\S]+?)\}\}/g,interpolate:/\{\{:([\s\S]+?)\}\}/g,encode:/\{\{>([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,conditional:/\{\{\/?if\s*([\s\S]*?)\s*\}\}/g,conditionalElse:/\{\{else\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{\/?for\s*(?:\}\}|([\s\S]+?)\s*(?:\:\s*([\w$]+))?\s*(?:\:\s*([\w$]+))?\s*\}\})/g,props:/\{\{\/?props\s*(?:\}\}|([\s\S]+?)\s*(?:\:\s*([\w$]+))?\s*(?:\:\s*([\w$]+))?\s*\}\})/g,empty:/\{\{empty\}\}/g,varname:"data, config, helper",strip:!0,append:!0,selfcontained:!1},template:void 0,compile:void 0};function l(){var t={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},e=/&(?!#?\w+;)|<|>|"|'|\//g;return function(){return this?this.replace(e,function(e){return t[e]||e}):this}}"undefined"!=typeof module&&module.exports?module.exports=a:"function"==typeof define&&define.amd?define(function(){return a}):function(){return this||(0,eval)("this")}().doT=a,String.prototype.encodeHTML=l();var u={append:{start:"'+(",end:")+'",endencode:"||'').toString().encodeHTML()+'"},split:{start:"';out+=(",end:");out+='",endencode:"||'').toString().encodeHTML();out+='"}},c=/$^/;function f(e){return e.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}a.template=function(e,t,n){var i,r=(t=t||a.templateSettings).append?u.append:u.split,o=0,s=t.use||t.define?function i(r,e,o){return("string"==typeof e?e:e.toString()).replace(r.define||c,function(e,i,t,n){return 0===i.indexOf("def.")&&(i=i.substring(4)),i in o||(":"===t?(r.defineParams&&n.replace(r.defineParams,function(e,t,n){o[i]={arg:t,text:n}}),i in o||(o[i]=n)):new Function("def","def['"+i+"']="+n)(o)),""}).replace(r.use||c,function(e,t){r.useParams&&(t=t.replace(r.useParams,function(e,t,n,i){if(o[n]&&o[n].arg&&i){var r=(n+":"+i).replace(/'|\\/g,"_");return o.__exp=o.__exp||{},o.__exp[r]=o[n].text.replace(new RegExp("(^|[^\\w$])"+o[n].arg+"([^\\w$])","g"),"$1"+i+"$2"),t+"def.__exp['"+r+"']"}}));var n=new Function("def","return "+t)(o);return n?i(r,n,o):n})}(t,e,n||{}):e;s=("var out='"+(t.strip?s.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):s).replace(/'|\\/g,"\\$&").replace(t.interpolate||c,function(e,t){return r.start+f(t)+r.end}).replace(t.encode||c,function(e,t){return i=!0,r.start+f(t)+r.endencode}).replace(t.conditional||c,function(e,t){return t?"';if("+f(t)+"){out+='":"';}out+='"}).replace(t.conditionalElse||c,function(e,t){return t?"';}else if("+f(t)+"){out+='":"';}else{out+='"}).replace(t.iterate||c,function(e,t,n,i){if(!t)return"';} } out+='";o+=1,n=n||"value",i=i||"index",t=f(t);var r="arr"+o;return"';var "+r+"="+t+";if("+r+" && "+r+".length > 0){var "+n+","+i+"=-1,l"+o+"="+r+".length-1;while("+i+" 0){var "+n+";for( var "+i+" in "+r+"){ if (!"+r+".hasOwnProperty("+i+")) continue; "+n+"="+r+"["+i+"];out+='"}).replace(t.empty||c,function(e){return"';}}else{if(true){out+='"}).replace(t.evaluate||c,function(e,t){return"';"+f(t)+"out+='"})+"';return out;").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/\r/g,"\\r").replace(/(\s|;|\}|^|\{)out\+='';/g,"$1").replace(/\+''/g,"").replace(/(\s|;|\}|^|\{)out\+=''\+/g,"$1out+="),i&&t.selfcontained&&(s="String.prototype.encodeHTML=("+l.toString()+"());"+s);try{return new Function(t.varname,s)}catch(e){throw"undefined"!=typeof console&&console.log("Could not create a template function: "+s),e}},a.compile=function(e,t){return a.template(e,null,t)}}(),function(e,t){"use strict";"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.returnExports=t()}(this,function(){function n(e){try{var t=S.call(e).replace(/\/\/.*\n/g,"").replace(/\/\*[.\s\S]*\*\//g,"").replace(/\n/gm," ").replace(/ {2}/g," ");return N.test(t)}catch(e){return}}function p(e){if(!e)return!1;if("function"!=typeof e&&"object"!=typeof e)return!1;if(E)return function(e){try{return n(e)?!1:(S.call(e),!0)}catch(e){return!1}}(e);if(n(e))return!1;var t=_.call(e);return"[object Function]"===t||"[object GeneratorFunction]"===t}var h,d,l=Array,e=l.prototype,a=Object,t=a.prototype,u=Function,i=u.prototype,v=String,r=v.prototype,y=Number,o=y.prototype,c=e.slice,s=e.splice,g=e.push,f=e.unshift,m=e.concat,b=e.join,x=i.call,w=i.apply,T=Math.max,C=Math.min,_=t.toString,E="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag,S=Function.prototype.toString,N=/^\s*class /,D=RegExp.prototype.exec;h=function(e){return"object"==typeof e&&(E?function(e){try{return D.call(e),!0}catch(e){return!1}}(e):"[object RegExp]"===_.call(e))};var k=String.prototype.valueOf;d=function(e){return"string"==typeof e||"object"==typeof e&&(E?function(e){try{return k.call(e),!0}catch(e){return!1}}(e):"[object String]"===_.call(e))};function j(e){var t=typeof e;return null===e||"object"!=t&&"function"!=t}function A(){}var P,H,M=a.defineProperty&&function(){try{var e={};for(var t in a.defineProperty(e,"x",{enumerable:!1,value:e}),e)return!1;return e.x===e}catch(e){return!1}}(),L=(P=t.hasOwnProperty,H=M?function(e,t,n,i){!i&&t in e||a.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:!0,value:n})}:function(e,t,n,i){!i&&t in e||(e[t]=n)},function(e,t,n){for(var i in t)P.call(t,i)&&H(e,i,t[i],n)}),O=y.isNaN||function(e){return e!=e},I=function(e){var t=+e;return O(t)?t=0:0!==t&&t!==1/0&&t!==-1/0&&(t=(0>>0};L(i,{bind:function(t){var n=this;if(!p(n))throw new TypeError("Function.prototype.bind called on incompatible "+n);for(var i,r=c.call(arguments,1),e=T(0,n.length-r.length),o=[],s=0;s=r)throw new TypeError("reduce of empty array with no initial value")}for(;sError name: "+e.name+"
    Error Message: "+e.message)}t.hasOwnProperty("data")||(a&&a.hasOwnProperty("data")?t.data=a.data:t.data={}),n?l(t):a=t}(e)},addBeforeUpdateCallback:function(e,t){r[e]=t},addBeforeUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addBeforeUpdateCallback(t,e[t])},removeBeforeUpdateCallback:function(e){r.hasOwnProperty(e)&&delete r[e]},executeBeforeUpdateCallbacks:function(e){return t(r,e)},addAfterUpdateCallback:function(e,t){o[e]=t},addAfterUpdateCallbacks:function(e){for(var t in e)e.hasOwnProperty(t)&&NanoStateManager.addAfterUpdateCallback(t,e[t])},removeAfterUpdateCallback:function(e){o.hasOwnProperty(e)&&delete o[e]},executeAfterUpdateCallbacks:function(e){return t(o,e)},addState:function(e){e instanceof NanoStateClass?e.key?i[e.key]=e:reportError("ERROR: Attempted to add a state with an invalid stateKey"):reportError("ERROR: Attempted to add a state which is not instanceof NanoStateClass")},setCurrentState:function(e){if(void 0===e||!e)return reportError("ERROR: No state key was passed!"),!1;if(!i.hasOwnProperty(e))return reportError("ERROR: Attempted to set a current state which does not exist: "+e),!1;var t=s;return s=i[e],null!=t&&t.onRemove(s),s.onAdd(t),!0},getCurrentState:function(){return s},getData:function(){return a}}}(),NanoBaseCallbacks=function(){var a=!0,t={},n={status:function(n){var e;return 2==n.config.status?(e="good",$(".linkActive").removeClass("inactive")):(e=1==n.config.status?"average":"bad",$(".linkActive").addClass("inactive")),$(".statusicon").removeClass("good bad average").addClass(e),$(".linkActive").stopTime("linkPending"),$(".linkActive").removeClass("linkPending"),$(".linkActive").off("click").on("click",function(e){e.preventDefault();var t=$(this).data("href");null!=t&&a&&(a=!1,$("body").oneTime(300,"enableClick",function(){a=!0}),2==n.config.status&&$(this).oneTime(300,"linkPending",function(){$(this).addClass("linkPending")}),window.location.href=t)}),n},nanomap:function(e){return $(".mapIcon").off("mouseenter mouseleave").on("mouseenter",function(e){$("#uiMapTooltip").html($(this).children(".tooltip").html()).show().stopTime().oneTime(5e3,"hideTooltip",function(){$(this).fadeOut(500)})}),$(".zoomLink").off("click").on("click",function(e){e.preventDefault();var t=$(this).data("zoomLevel"),n=$("#uiMap"),a=n.width()*t,r=n.height()*t;n.css({zoom:t,left:"50%",top:"50%",marginLeft:"-"+Math.floor(a/2)+"px",marginTop:"-"+Math.floor(r/2)+"px"})}),$("#uiMapImage").attr("src",e.config.map+"_nanomap_z"+e.config.mapZLevel+".png"),e}};return{addCallbacks:function(){NanoStateManager.addBeforeUpdateCallbacks(t),NanoStateManager.addAfterUpdateCallbacks(n)},removeCallbacks:function(){for(var e in t)t.hasOwnProperty(e)&&NanoStateManager.removeBeforeUpdateCallback(e);for(var e in n)n.hasOwnProperty(e)&&NanoStateManager.removeAfterUpdateCallback(e)}}}(),NanoBaseHelpers=function(){var t={syndicateMode:function(){return $(".mainBG").css("background","url('syndicate.png') no-repeat fixed center/50% 50%, linear-gradient(to bottom, #8f1414 0%, #4B0A0A 100%) no-repeat fixed center;"),$("#uiTitleFluff").css("background-image","url('uiTitleFluff-Syndicate.png')"),$("#uiTitleFluff").css("background-position","50% 50%"),$("#uiTitleFluff").css("background-repeat","no-repeat"),""},combine:function(e,t){return e&&t?e.concat(t):e||t},dump:function(e){return JSON.stringify(e)},link:function(e,t,n,a,r,o){var i="",s="noIcon";void 0!==t&&t&&(i='
    ',s="hasIcon"),void 0!==r&&r||(r="link");var l="";void 0!==o&&o&&(l='id="'+o+'"');var c=NanoTransition.allocID(l+"_"+e.toString().replace(/[^a-z0-9_]/gi,"_")+"_"+t);return void 0!==a&&a?'