diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6c4d6ddcb98..d26dd12beda 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,14 +16,12 @@ # Cyberboss /code/__DATASTRUCTURES/globals.dm @Cyberboss -/code/__DEFINES/components.dm @Cyberboss /code/__DEFINES/server_tools.config.dm @Cyberboss /code/__DEFINES/server_tools.dm @Cyberboss /code/controllers/subsystem/atoms.dm @Cyberboss /code/controllers/subsystem/mapping.dm @Cyberboss /code/controllers/globals.dm @Cyberboss /code/datums/helper_datums/getrev.dm @Cyberboss -/code/datums/components/ @Cyberboss /code/datums/map_config.dm @Cyberboss /code/datums/forced_movement.dm @Cyberboss /code/datums/holocall.dm @Cyberboss @@ -67,4 +65,6 @@ # Multiple Owners +/code/__DEFINES/components.dm @Cyberboss @ninjanomnom /code/controllers/subsystem/air.dm @duncathan @MrStonedOne +/code/datums/components/ @Cyberboss @ninjanomnom \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 7138b233548..f09e4557b9c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: generic +dist: trusty sudo: false +dist: xenial branches: except: - ___TGS3TempBranch @@ -14,6 +16,7 @@ matrix: packages: - python3 - python3-pip + - python3-setuptools cache: directories: - tgui/node_modules @@ -43,7 +46,8 @@ matrix: - gcc-multilib - g++-7 - g++-7-multilib - - libmariadbclient-dev:i386 + - libmariadb-client-lgpl-dev:i386 + - libmariadbd-dev cache: directories: - $HOME/.cargo @@ -67,4 +71,3 @@ script: - tools/travis/build_tools.sh || travis_terminate 1 - tools/travis/build_dependencies.sh || travis_terminate 1 - tools/travis/build_byond.sh - diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index ef386f20de9..b131019c536 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -5239,6 +5239,15 @@ }, /turf/open/floor/plasteel, /area/security/brig) +"aku" = ( +/obj/effect/decal/cleanable/cobweb, +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/radiation, +/obj/effect/turf_decal/bot{ + dir = 2 + }, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "akv" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -5300,6 +5309,55 @@ }, /turf/open/floor/plating, /area/maintenance/solars/port/fore) +"akC" = ( +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/secure_closet/atmospherics, +/obj/effect/turf_decal/bot{ + dir = 2 + }, +/obj/structure/window/reinforced, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) +"akD" = ( +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + name = "output gas connector port" + }, +/obj/machinery/portable_atmospherics/canister, +/obj/effect/decal/cleanable/dirt, +/obj/item/radio/intercom{ + dir = 4; + pixel_x = 27 + }, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) +"akE" = ( +/obj/structure/sign/warning/deathsposal{ + pixel_y = 32 + }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/delivery, +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) +"akF" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/reagent_dispensers/fueltank, +/obj/item/storage/toolbox/emergency, +/obj/structure/sign/warning/nosmoking{ + pixel_x = -28 + }, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "akG" = ( /obj/structure/sign/warning/vacuum/external{ pixel_y = 32 @@ -5573,6 +5631,14 @@ }, /turf/open/floor/plasteel, /area/security/courtroom) +"alf" = ( +/obj/machinery/atmospherics/components/binary/pump{ + dir = 8; + name = "Mix to MiniSat" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "alg" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ @@ -5597,12 +5663,39 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/maintenance/port/fore) +"alj" = ( +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "alk" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ dir = 1 }, /turf/open/floor/plasteel, /area/engine/atmos) +"all" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) +"alm" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "aln" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 @@ -5614,6 +5707,12 @@ }, /turf/open/floor/plating, /area/security/processing) +"alo" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/start/atmospheric_technician, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "alp" = ( /turf/open/floor/plating, /area/security/processing) @@ -5755,6 +5854,14 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plating, /area/security/courtroom) +"alE" = ( +/obj/machinery/atmospherics/pipe/simple/general/visible, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "alF" = ( /obj/machinery/atmospherics/components/unary/tank/air{ dir = 2 @@ -5827,6 +5934,26 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/maintenance/fore/secondary) +"alM" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/decal/cleanable/dirt, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) +"alN" = ( +/obj/structure/reagent_dispensers/watertank, +/obj/item/extinguisher, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "alO" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -5882,6 +6009,20 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /turf/open/floor/plasteel, /area/engine/atmos) +"alY" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/unary/tank/toxins, +/obj/effect/turf_decal/delivery, +/obj/structure/window/reinforced{ + dir = 1; + layer = 2.9 + }, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) +"alZ" = ( +/obj/effect/decal/cleanable/dirt, +/turf/closed/wall, +/area/maintenance/disposal/incinerator) "ama" = ( /mob/living/simple_animal/sloth/paperwork, /turf/open/floor/plasteel, @@ -6032,6 +6173,13 @@ }, /turf/open/floor/plasteel, /area/security/brig) +"amp" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/simple/yellow/visible{ + dir = 10 + }, +/turf/open/space/basic, +/area/space) "amq" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 @@ -36427,13 +36575,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bIH" = ( +/obj/machinery/pipedispenser/disposal, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/space_heater, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, /turf/open/floor/plasteel, /area/engine/atmos) "bII" = ( @@ -36839,14 +36984,10 @@ /turf/closed/wall/r_wall, /area/medical/medbay/central) "bJF" = ( +/obj/machinery/pipedispenser/disposal/transit_tube, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/effect/turf_decal/stripes/line{ - dir = 10 - }, -/obj/machinery/space_heater, -/obj/structure/window/reinforced, /turf/open/floor/plasteel, /area/engine/atmos) "bJG" = ( @@ -38158,10 +38299,7 @@ /turf/open/floor/plating, /area/engine/atmos) "bMR" = ( -/obj/machinery/space_heater, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, +/obj/machinery/pipedispenser, /turf/open/floor/plasteel, /area/engine/atmos) "bMS" = ( @@ -38975,7 +39113,7 @@ }, /obj/machinery/requests_console{ department = "Atmospherics"; - departmentType = 4; + departmentType = 3; name = "Atmos RC"; pixel_x = 30 }, @@ -42385,10 +42523,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bXR" = ( +/obj/structure/closet/secure_closet/atmospherics, /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/obj/structure/closet/radiation, /turf/open/floor/plasteel, /area/engine/atmos) "bXS" = ( @@ -43492,7 +43630,7 @@ "caE" = ( /obj/machinery/requests_console{ department = "Atmospherics"; - departmentType = 4; + departmentType = 3; name = "Atmos RC"; pixel_x = 30 }, @@ -43961,9 +44099,6 @@ /area/maintenance/port/aft) "cbz" = ( /obj/machinery/vending/wardrobe/atmos_wardrobe, -/obj/effect/turf_decal/stripes/line{ - dir = 10 - }, /turf/open/floor/plasteel, /area/engine/atmos) "cbA" = ( @@ -43971,15 +44106,17 @@ /turf/open/floor/plasteel, /area/engine/atmos) "cbB" = ( +/obj/machinery/space_heater, /obj/effect/turf_decal/stripes/line{ dir = 6 }, -/obj/structure/closet/secure_closet/atmospherics, /turf/open/floor/plasteel, /area/engine/atmos) "cbC" = ( -/obj/effect/turf_decal/stripes/line, -/obj/structure/closet/secure_closet/atmospherics, +/obj/machinery/space_heater, +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, /turf/open/floor/plasteel, /area/engine/atmos) "cbD" = ( @@ -44198,7 +44335,7 @@ /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) "ccg" = ( -/obj/machinery/telecomms/message_server, +/obj/machinery/telecomms/message_server/preset, /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) "cch" = ( @@ -45648,21 +45785,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"cgb" = ( -/obj/structure/sign/warning/deathsposal{ - pixel_y = 32 - }, -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/obj/machinery/portable_atmospherics/canister, -/obj/effect/turf_decal/delivery, -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "cgc" = ( /obj/effect/landmark/xeno_spawn, /turf/open/floor/plating{ @@ -46100,13 +46222,6 @@ "chg" = ( /turf/open/floor/plating, /area/engine/atmos) -"chh" = ( -/obj/machinery/atmospherics/components/unary/tank/toxins{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "chi" = ( /obj/machinery/meter, /obj/machinery/atmospherics/pipe/simple/general/visible{ @@ -46115,11 +46230,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"chj" = ( -/obj/structure/disposalpipe/segment, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "chk" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible, /turf/closed/wall, @@ -46149,16 +46259,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"chn" = ( -/obj/structure/cable{ - icon_state = "2-4" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "cho" = ( /obj/machinery/light, /obj/machinery/atmospherics/pipe/simple/general/visible{ @@ -46651,15 +46751,6 @@ /obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/closed/wall/r_wall, /area/engine/atmos) -"ciy" = ( -/obj/structure/sign/warning/nosmoking{ - pixel_x = -28 - }, -/obj/structure/reagent_dispensers/watertank, -/obj/item/extinguisher, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "ciz" = ( /obj/machinery/atmospherics/pipe/manifold/general/visible{ dir = 4 @@ -46667,20 +46758,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"ciA" = ( -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) -"ciB" = ( -/obj/effect/decal/cleanable/cobweb, -/obj/structure/disposalpipe/trunk, -/obj/machinery/disposal/bin, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "ciC" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/simple/yellow/visible{ @@ -46688,17 +46765,6 @@ }, /turf/open/space, /area/space/nearstation) -"ciD" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - name = "output gas connector port" - }, -/obj/machinery/portable_atmospherics/canister, -/obj/structure/sign/warning/nosmoking{ - pixel_x = 28 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "ciF" = ( /obj/structure/table, /obj/item/cartridge/medical, @@ -46915,7 +46981,7 @@ /obj/machinery/requests_console{ announcementConsole = 1; department = "Chief Engineer's Desk"; - departmentType = 3; + departmentType = 4; name = "Chief Engineer RC"; pixel_x = -32 }, @@ -47011,30 +47077,10 @@ /obj/structure/closet/toolcloset, /turf/open/floor/plasteel, /area/construction) -"cjp" = ( -/obj/machinery/atmospherics/pipe/simple/yellow/visible{ - dir = 4 - }, -/obj/structure/reagent_dispensers/fueltank, -/obj/item/storage/toolbox/emergency, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "cjr" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"cjs" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "cju" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 1; @@ -47049,20 +47095,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"cjv" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "cjw" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -47327,11 +47359,6 @@ }, /turf/closed/wall/r_wall, /area/engine/atmos) -"cke" = ( -/obj/structure/chair/stool, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "ckf" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -47344,15 +47371,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"ckh" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 8; - name = "Mix to MiniSat" - }, -/obj/structure/disposalpipe/segment, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "cki" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ @@ -47656,18 +47674,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"clg" = ( -/obj/item/radio/intercom{ - pixel_y = -29 - }, -/obj/structure/table, -/obj/item/paper_bin{ - pixel_x = -3; - pixel_y = 7 - }, -/obj/item/pen, -/turf/open/floor/plating, -/area/maintenance/disposal/incinerator) "clh" = ( /obj/machinery/light/small, /obj/structure/extinguisher_cabinet{ @@ -55190,7 +55196,7 @@ /obj/machinery/requests_console{ announcementConsole = 0; department = "Engineering"; - departmentType = 4; + departmentType = 3; name = "Engineering RC"; pixel_y = 30 }, @@ -55544,14 +55550,6 @@ }, /turf/open/floor/plasteel, /area/vacant_room/commissary) -"eHI" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "eRu" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/closed/wall/r_wall, @@ -55561,10 +55559,6 @@ /obj/structure/grille, /turf/open/space/basic, /area/space/nearstation) -"eTd" = ( -/obj/machinery/pipedispenser/disposal, -/turf/open/floor/plating, -/area/maintenance/disposal) "eUr" = ( /obj/machinery/door/poddoor/preopen{ id = "testlab"; @@ -55779,10 +55773,6 @@ }, /turf/open/floor/plasteel, /area/science/nanite) -"gwp" = ( -/obj/machinery/pipedispenser, -/turf/open/floor/plasteel, -/area/construction) "gwQ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 9 @@ -55800,16 +55790,6 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/vacant_room/commissary) -"gGE" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "gHj" = ( /obj/structure/closet/radiation, /turf/open/floor/plasteel/white/corner{ @@ -72204,7 +72184,7 @@ bgj bgj bjc cAF -eTd +cAF bja aaa aaa @@ -85846,7 +85826,7 @@ bJm bFa bHO bCs -gwp +cCd cCd aYg cjL @@ -94865,8 +94845,8 @@ bVu bVu bVu bVu -bVu caJ +aaf aoV aoV aoV @@ -95119,11 +95099,11 @@ aaf cfj cfU cfj -cfj ckf cfj cfj -bUr +amp +bVu bVu bVu bVu @@ -95374,11 +95354,11 @@ bzs bzs cfj cfj -cjp -chh -ciy -cke -clg +akC +akF +alN +alY +alZ cfj aoV aoV @@ -95630,10 +95610,10 @@ bzs bAw caK cfj -ciB -ckh -chj -ciA +aku +alf +cjr +cjr cjr clh cfj @@ -95890,7 +95870,7 @@ chk chl ciz chi -gGE +alm cjr ckg cmb @@ -96147,7 +96127,7 @@ cfl cfZ cki cld -eHI +alo cjr csq xEu @@ -96404,7 +96384,7 @@ cfk cfY rfW ckj -cjs +alE cle cli uPT @@ -96658,10 +96638,10 @@ cbL cdI ceG cfj -cgb -chn -clj -cjv +akE +alj +all +alM clj ckk cmf @@ -96917,7 +96897,7 @@ ceF cfj cga chm -ciD +akD cju clf csr diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index faad848a397..8d64643adb1 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -64671,7 +64671,7 @@ /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) "cex" = ( -/obj/machinery/telecomms/message_server, +/obj/machinery/telecomms/message_server/preset, /obj/structure/cable/yellow{ icon_state = "4-8" }, diff --git a/_maps/map_files/Donutstation/Donutstation.dmm b/_maps/map_files/Donutstation/Donutstation.dmm index 6ca4bd363a0..9eba5f6a3f9 100644 --- a/_maps/map_files/Donutstation/Donutstation.dmm +++ b/_maps/map_files/Donutstation/Donutstation.dmm @@ -18289,7 +18289,7 @@ }, /obj/machinery/requests_console{ department = "Atmospherics"; - departmentType = 4; + departmentType = 3; name = "Atmos RC"; pixel_x = -30 }, @@ -20075,7 +20075,7 @@ /obj/machinery/requests_console{ announcementConsole = 1; department = "Chief Engineer's Desk"; - departmentType = 3; + departmentType = 4; name = "Chief Engineer RC"; pixel_y = -32 }, @@ -30380,7 +30380,7 @@ /obj/item/multitool, /obj/machinery/requests_console{ department = "Atmospherics"; - departmentType = 4; + departmentType = 3; name = "Atmos RC"; pixel_x = -30 }, @@ -34441,7 +34441,7 @@ }, /obj/machinery/requests_console{ department = "Atmospherics"; - departmentType = 4; + departmentType = 3; name = "Atmos RC"; pixel_x = 30 }, diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 23e7406bd6f..764e2035073 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -331,6 +331,22 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/security/prison) +"aaU" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk, +/obj/structure/sign/warning/deathsposal{ + pixel_y = 32 + }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "aaV" = ( /obj/effect/decal/cleanable/cobweb, /obj/effect/decal/cleanable/dirt, @@ -338,6 +354,11 @@ /area/janitor) "aaW" = ( /obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/delivery, +/obj/structure/sign/warning/nosmoking{ + pixel_x = -28 + }, +/obj/structure/closet/radiation, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) "aaX" = ( @@ -2238,6 +2259,13 @@ }, /turf/open/floor/plating, /area/crew_quarters/fitness/recreation) +"aeD" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/delivery, +/obj/structure/window/reinforced, +/obj/structure/closet/secure_closet/atmospherics, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "aeE" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -4472,7 +4500,7 @@ /turf/open/floor/plating, /area/maintenance/disposal) "aij" = ( -/obj/machinery/pipedispenser/disposal, +/obj/item/vending_refill/coffee, /turf/open/floor/plating{ icon_state = "platingdmg2" }, @@ -4849,6 +4877,11 @@ }, /turf/open/floor/plasteel/dark, /area/crew_quarters/fitness/recreation) +"aiT" = ( +/obj/effect/landmark/start/atmospheric_technician, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "aiU" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on, /obj/effect/turf_decal/tile/neutral{ @@ -6454,7 +6487,6 @@ dir = 9 }, /obj/item/bot_assembly/cleanbot, -/obj/item/vending_refill/coffee, /turf/open/floor/plating, /area/maintenance/port/fore) "alI" = ( @@ -7641,7 +7673,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "anM" = ( -/obj/machinery/pipedispenser, +/obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/starboard) "anN" = ( @@ -8796,6 +8828,13 @@ /obj/item/assembly/flash/handheld, /turf/open/floor/plasteel, /area/security/main) +"apX" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/reagent_dispensers/fueltank, +/obj/item/storage/toolbox/emergency, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/turf/open/floor/plasteel, +/area/maintenance/disposal/incinerator) "apY" = ( /obj/structure/table, /obj/item/folder/red, @@ -11279,6 +11318,17 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"auQ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/obj/machinery/door/airlock/maintenance{ + name = "Incinerator Access"; + req_access_txt = "24" + }, +/turf/open/floor/plating, +/area/maintenance/starboard) "auU" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -24375,7 +24425,7 @@ /obj/machinery/requests_console{ announcementConsole = 0; department = "Engineering"; - departmentType = 4; + departmentType = 3; name = "Engineering RC" }, /turf/closed/wall, @@ -25117,7 +25167,7 @@ /obj/machinery/requests_console{ announcementConsole = 1; department = "Chief Engineer's Desk"; - departmentType = 3; + departmentType = 4; name = "Chief Engineer RC"; pixel_y = 32 }, @@ -40987,7 +41037,7 @@ }, /obj/machinery/requests_console{ department = "Atmospherics"; - departmentType = 4; + departmentType = 3; name = "Atmos RC"; pixel_x = 30 }, @@ -45142,7 +45192,7 @@ /turf/closed/wall/r_wall, /area/space/nearstation) "bJg" = ( -/obj/machinery/telecomms/message_server, +/obj/machinery/telecomms/message_server/preset, /turf/open/floor/circuit/telecomms/mainframe, /area/tcommsat/server) "bJh" = ( @@ -48213,10 +48263,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bPr" = ( +/obj/structure/closet/secure_closet/atmospherics, /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/obj/structure/closet/radiation, /turf/open/floor/plasteel, /area/engine/atmos) "bPs" = ( @@ -50015,7 +50065,7 @@ "bTj" = ( /obj/machinery/requests_console{ department = "Atmospherics"; - departmentType = 4; + departmentType = 3; name = "Atmos RC"; pixel_x = 30 }, @@ -50658,10 +50708,10 @@ /turf/open/floor/plasteel/dark, /area/engine/atmos) "bUA" = ( +/obj/machinery/pipedispenser, /obj/effect/turf_decal/stripes/line{ dir = 10 }, -/obj/structure/closet/secure_closet/atmospherics, /turf/open/floor/plasteel, /area/engine/atmos) "bUB" = ( @@ -50671,19 +50721,19 @@ /obj/machinery/light_switch{ pixel_y = 28 }, +/obj/machinery/pipedispenser/disposal, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/stripes/line, -/obj/structure/closet/secure_closet/atmospherics, /turf/open/floor/plasteel, /area/engine/atmos) "bUC" = ( /obj/item/radio/intercom{ pixel_y = 28 }, +/obj/machinery/pipedispenser/disposal/transit_tube, /obj/effect/turf_decal/stripes/line{ dir = 6 }, -/obj/structure/closet/secure_closet/atmospherics, /turf/open/floor/plasteel, /area/engine/atmos) "bUD" = ( @@ -51137,15 +51187,15 @@ /turf/open/floor/plasteel, /area/hydroponics) "bVx" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 - }, /obj/effect/turf_decal/tile/green{ dir = 1 }, /obj/effect/turf_decal/tile/green{ dir = 4 }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 + }, /turf/open/floor/plasteel, /area/hydroponics) "bVy" = ( @@ -51252,7 +51302,6 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/structure/closet/radiation, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, @@ -52506,6 +52555,7 @@ /obj/effect/turf_decal/tile/green{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, /area/hydroponics) "bYl" = ( @@ -53159,17 +53209,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/maintenance/disposal/incinerator) -"bZD" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Incinerator Access"; - req_access_txt = "12" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, -/turf/open/floor/plating, -/area/maintenance/starboard) "bZE" = ( /turf/closed/wall, /area/maintenance/disposal/incinerator) @@ -53983,18 +54022,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/disposal/incinerator) -"caZ" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk, -/obj/structure/sign/warning/deathsposal{ - pixel_y = 32 - }, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "cba" = ( /obj/machinery/power/smes{ capacity = 9e+006; @@ -54859,6 +54886,9 @@ pixel_y = 2 }, /obj/structure/table, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hydroponics) "ccA" = ( @@ -54874,14 +54904,12 @@ pixel_y = 5 }, /obj/item/watertank, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 - }, /obj/item/grenade/chem_grenade/antiweed, /obj/structure/table/glass, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /turf/open/floor/plasteel, /area/hydroponics) "ccB" = ( @@ -56800,13 +56828,6 @@ icon_state = "platingdmg2" }, /area/maintenance/starboard/aft) -"cgu" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/reagent_dispensers/fueltank, -/obj/item/storage/toolbox/emergency, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "cgv" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/general/visible{ @@ -78107,6 +78128,9 @@ dir = 1 }, /obj/structure/table, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, /turf/open/floor/plasteel, /area/hydroponics) "dbF" = ( @@ -82837,9 +82861,6 @@ }, /turf/open/floor/plasteel, /area/science/misc_lab/range) -"etr" = ( -/turf/open/floor/plasteel, -/area/crew_quarters/fitness/recreation) "eFN" = ( /obj/structure/bodycontainer/crematorium{ id = "crematoriumChapel"; @@ -83155,11 +83176,6 @@ }, /turf/open/floor/plasteel/white, /area/science/research) -"ieW" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "ifN" = ( /obj/effect/turf_decal/stripes/corner{ dir = 1 @@ -83263,6 +83279,12 @@ }, /turf/open/floor/plating, /area/maintenance/solars/port/aft) +"jHw" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/closed/wall, +/area/hydroponics) "jKK" = ( /obj/machinery/door/airlock/external{ req_access_txt = "13" @@ -83420,6 +83442,19 @@ }, /turf/open/floor/plasteel, /area/science/misc_lab/range) +"lkf" = ( +/obj/effect/turf_decal/tile/green{ + dir = 1 + }, +/obj/effect/turf_decal/tile/green, +/obj/effect/turf_decal/tile/green{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, +/turf/open/floor/plasteel, +/area/hydroponics) "lnO" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -83760,6 +83795,18 @@ "pcn" = ( /turf/open/floor/plasteel, /area/science/misc_lab/range) +"pgY" = ( +/obj/effect/turf_decal/tile/green{ + dir = 1 + }, +/obj/effect/turf_decal/tile/green{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/hydroponics) "pmZ" = ( /obj/structure/sign/poster/official/random{ pixel_y = 32 @@ -83885,16 +83932,6 @@ }, /turf/open/floor/plasteel/white, /area/science/misc_lab/range) -"qbK" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/portable_atmospherics/canister, -/obj/effect/turf_decal/delivery, -/obj/structure/window/reinforced, -/obj/structure/sign/warning/nosmoking{ - pixel_x = -28 - }, -/turf/open/floor/plasteel, -/area/maintenance/disposal/incinerator) "qcZ" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable/yellow{ @@ -83927,6 +83964,14 @@ }, /turf/open/floor/plasteel, /area/science/misc_lab/range) +"qkD" = ( +/obj/effect/turf_decal/tile/green, +/obj/effect/turf_decal/tile/green{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/hydroponics) "qom" = ( /obj/structure/cable/yellow{ icon_state = "1-2" @@ -84200,6 +84245,23 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/crew_quarters/locker) +"tQN" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/green, +/obj/effect/turf_decal/tile/green{ + dir = 4 + }, +/obj/effect/turf_decal/tile/green{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/hydroponics) "tVY" = ( /obj/structure/closet/crate, /obj/item/target/alien, @@ -84325,12 +84387,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/department/science) -"vlx" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness/recreation) "vwi" = ( /obj/structure/girder, /obj/structure/grille, @@ -119956,7 +120012,7 @@ bKe bRW bST bUm -bVu +pgY bWT bYj bWT @@ -120213,11 +120269,11 @@ bQI bRX bST bUn -bVt -bWQ +lkf +qkD bYk -bWQ -caL +qkD +tQN dbE bST diB @@ -120732,7 +120788,7 @@ bST bST bST caQ -bST +jHw bST cfg pCp @@ -121692,9 +121748,9 @@ acP afz agz dBY -vlx -vlx -etr +ahl +ahl +ahg alk alk anK @@ -123560,9 +123616,9 @@ bYr avs bZE mKO -qbK -ieW -cgu +aaW +aeD +apX amV bZC arF @@ -124328,11 +124384,11 @@ alq alq bXb bYu -bZD +auQ caY ccI ced -aaW +aiT aju apP ciZ @@ -124586,7 +124642,7 @@ aut bXc apc bZE -caZ +aaU ccJ cee cgx @@ -128180,7 +128236,7 @@ bPu bPu bTl bUF -bKD +bCi bXo bMj bZI diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 43120ec1a6c..635dc97931c 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -2691,7 +2691,7 @@ area_type = /area/lavaland/surface/outdoors; dir = 8; dwidth = 2; - height = 10; + height = 5; id = "laborcamp_away"; name = "labor camp"; width = 9 @@ -4102,7 +4102,7 @@ area_type = /area/lavaland/surface/outdoors; dir = 8; dwidth = 3; - height = 5; + height = 10; id = "mining_away"; name = "lavaland mine"; width = 7 diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index b109ee13e46..7ebfb6721b5 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -6,12 +6,33 @@ /obj/effect/mapping_helpers/dead_body_placer, /turf/open/floor/plasteel/dark, /area/medical/morgue) +"aac" = ( +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/structure/closet/radiation, +/turf/open/floor/plasteel/dark, +/area/maintenance/disposal/incinerator) "aad" = ( /obj/effect/spawner/lootdrop/maintenance, /turf/open/floor/plating{ icon_state = "platingdmg3" }, /area/maintenance/department/science) +"aae" = ( +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow, +/obj/structure/closet/secure_closet/atmospherics, +/turf/open/floor/plasteel/dark, +/area/maintenance/disposal/incinerator) "abf" = ( /obj/structure/bed, /turf/open/floor/plating, @@ -41382,10 +41403,7 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bQH" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/structure/closet/secure_closet/atmospherics, +/obj/machinery/pipedispenser, /turf/open/floor/plasteel, /area/engine/atmos) "bQI" = ( @@ -41393,10 +41411,10 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bQJ" = ( +/obj/structure/closet/secure_closet/atmospherics, /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/obj/structure/closet/radiation, /turf/open/floor/plasteel, /area/engine/atmos) "bQK" = ( @@ -41747,7 +41765,7 @@ "bRu" = ( /obj/machinery/requests_console{ department = "Atmospherics"; - departmentType = 4; + departmentType = 3; name = "Atmos RC"; pixel_x = 30 }, @@ -41764,6 +41782,7 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bRv" = ( +/obj/machinery/pipedispenser/disposal, /obj/machinery/light{ dir = 8 }, @@ -41771,10 +41790,6 @@ c_tag = "Atmospherics Central"; dir = 4 }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/structure/closet/secure_closet/atmospherics, /turf/open/floor/plasteel, /area/engine/atmos) "bRw" = ( @@ -42097,6 +42112,10 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) +"bSe" = ( +/obj/machinery/pipedispenser/disposal/transit_tube, +/turf/open/floor/plasteel, +/area/engine/atmos) "bSf" = ( /obj/machinery/atmospherics/pipe/manifold/general/visible{ dir = 4 @@ -43253,7 +43272,7 @@ /obj/machinery/requests_console{ announcementConsole = 1; department = "Chief Engineer's Desk"; - departmentType = 3; + departmentType = 4; name = "Chief Engineer RC"; pixel_x = -32 }, @@ -43640,7 +43659,6 @@ /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 8 }, -/obj/machinery/pipedispenser, /turf/open/floor/plating, /area/maintenance/department/engine) "bVv" = ( @@ -46149,17 +46167,6 @@ "cby" = ( /turf/open/floor/engine/air, /area/engine/atmos) -"cbz" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/closet/radiation, -/turf/open/floor/plasteel/dark, -/area/maintenance/disposal/incinerator) "cbA" = ( /obj/effect/turf_decal/tile/yellow{ dir = 1 @@ -46563,17 +46570,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"cdg" = ( -/obj/structure/table/glass, -/obj/item/storage/toolbox/emergency, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/disposal/incinerator) "cdk" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 @@ -49228,7 +49224,7 @@ /turf/open/floor/circuit/telecomms/mainframe, /area/tcommsat/server) "cmH" = ( -/obj/machinery/telecomms/message_server, +/obj/machinery/telecomms/message_server/preset, /turf/open/floor/circuit/telecomms/mainframe, /area/tcommsat/server) "cmK" = ( @@ -55869,7 +55865,7 @@ /obj/machinery/requests_console{ announcementConsole = 0; department = "Engineering"; - departmentType = 4; + departmentType = 3; name = "Engineering RC"; pixel_x = -32 }, @@ -59793,7 +59789,9 @@ /turf/open/floor/plating, /area/maintenance/disposal) "srZ" = ( -/obj/machinery/pipedispenser/disposal, +/obj/structure/closet/crate{ + icon_state = "crateopen" + }, /turf/open/floor/plating, /area/maintenance/disposal) "ssx" = ( @@ -97947,7 +97945,7 @@ bOS bPQ bQH bRv -bQH +bSe bPQ bTL uRj @@ -100531,8 +100529,8 @@ bZO caI cbA ccp -cdg -cbz +aac +aae hMa aaa aby diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index cb853d3c590..b011be59bca 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -8316,7 +8316,6 @@ /turf/open/floor/plasteel, /area/syndicate_mothership/control) "si" = ( -/obj/machinery/computer/telecrystals/uplinker, /obj/effect/turf_decal/stripes/line{ dir = 9 }, @@ -8827,7 +8826,6 @@ /turf/open/floor/plasteel, /area/syndicate_mothership/control) "tg" = ( -/obj/machinery/computer/telecrystals/uplinker, /obj/effect/turf_decal/stripes/line{ dir = 8 }, @@ -9522,7 +9520,6 @@ /turf/open/floor/plasteel, /area/syndicate_mothership/control) "uM" = ( -/obj/machinery/computer/telecrystals/uplinker, /obj/effect/turf_decal/stripes/line{ dir = 10 }, @@ -9951,7 +9948,7 @@ name = "Hanger Bay Shutters"; pixel_x = -8; pixel_y = 24; - req_access_txt = "2" + req_access_txt = "101" }, /obj/machinery/button/door/indestructible{ id = "XCCsec3"; @@ -10313,7 +10310,7 @@ id = "XCCFerry"; name = "Hanger Bay Shutters"; pixel_y = 24; - req_access_txt = "2" + req_access_txt = "101" }, /obj/effect/turf_decal/stripes/line{ dir = 5 @@ -10497,9 +10494,6 @@ /turf/open/floor/carpet, /area/wizard_station) "wV" = ( -/obj/machinery/computer/telecrystals/boss{ - dir = 1 - }, /obj/effect/turf_decal/stripes/line{ dir = 5 }, diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index aa04f188601..33d774f22dc 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -93,6 +93,8 @@ #define TR_KEEPSE (1<<5) // changelings shouldn't edit the DNA's SE when turning into a monkey #define TR_DEFAULTMSG (1<<6) #define TR_KEEPORGANS (1<<8) +#define TR_KEEPSTUNS (1<<9) +#define TR_KEEPREAGENTS (1<<10) #define CLONER_FRESH_CLONE "fresh" diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 49147dfe4d3..35257cf9fbe 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -110,6 +110,7 @@ // /atom/movable signals #define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move" //from base of atom/movable/Moved(): (/atom) + #define COMPONENT_MOVABLE_BLOCK_PRE_MOVE 1 #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) @@ -202,6 +203,8 @@ // /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 +#define COMSIG_PDA_CHECK_DETONATE "pda_check_detonate" + #define COMPONENT_PDA_NO_DETONATE 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) @@ -245,6 +248,7 @@ #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_COMM_SIGNAL "nanite_comm_signal" //(comm_code(1-9999), comm_message) Called when sending a nanite comm 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 diff --git a/code/__DEFINES/fantasy_affixes.dm b/code/__DEFINES/fantasy_affixes.dm new file mode 100644 index 00000000000..709d414d117 --- /dev/null +++ b/code/__DEFINES/fantasy_affixes.dm @@ -0,0 +1,5 @@ +#define AFFIX_PREFIX (1 << 0) +#define AFFIX_SUFFIX (1 << 1) + +#define AFFIX_GOOD (1 << 0) +#define AFFIX_EVIL (1 << 1) \ No newline at end of file diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm index 2c7a66ce40c..5e12715aba8 100644 --- a/code/__DEFINES/food.dm +++ b/code/__DEFINES/food.dm @@ -11,6 +11,7 @@ #define GROSS (1<<10) #define TOXIC (1<<11) #define PINEAPPLE (1<<12) +#define CLOTH (1<<14) #define DRINK_NICE 1 #define DRINK_GOOD 2 diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 35a675515a8..3df5f64874a 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -175,6 +175,9 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) //Gets the turf this atom inhabits #define get_turf(A) (get_step(A, 0)) +//Same as above except gets the area instead +#define get_area(A) (isarea(A) ? A : get_step(A, 0)?.loc) + //Ghost orbit types: #define GHOST_ORBIT_CIRCLE "circle" #define GHOST_ORBIT_TRIANGLE "triangle" diff --git a/code/__DEFINES/radio.dm b/code/__DEFINES/radio.dm index 943acdbc7ef..bfba80a80cb 100644 --- a/code/__DEFINES/radio.dm +++ b/code/__DEFINES/radio.dm @@ -103,3 +103,13 @@ #define RADIO_MAGNETS "magnets" #define DEFAULT_SIGNALER_CODE 30 + +//Requests Console +#define REQ_NO_NEW_MESSAGE 0 +#define REQ_NORMAL_MESSAGE_PRIORITY 1 +#define REQ_HIGH_MESSAGE_PRIORITY 2 +#define REQ_EXTREME_MESSAGE_PRIORITY 3 + +#define REQ_DEP_TYPE_ASSISTANCE (1<<0) +#define REQ_DEP_TYPE_SUPPLIES (1<<1) +#define REQ_DEP_TYPE_INFORMATION (1<<2) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index b50423cc80c..47d7a8dff3b 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -122,3 +122,7 @@ #define STATUS_EFFECT_RAINBOWPROTECTION /datum/status_effect/rainbow_protection //Invulnerable and pacifistic #define STATUS_EFFECT_SLIMESKIN /datum/status_effect/slimeskin //Increased armor + +// Stasis helpers + +#define IS_IN_STASIS(mob) (mob.has_status_effect(STATUS_EFFECT_STASIS)) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index cb5187b91a5..f5644114338 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -8,12 +8,6 @@ #define Z_TURFS(ZLEVEL) block(locate(1,1,ZLEVEL), locate(world.maxx, world.maxy, ZLEVEL)) #define CULT_POLL_WAIT 2400 -/proc/get_area(atom/A) - if(isarea(A)) - return A - var/turf/T = get_turf(A) - return T ? T.loc : null - /proc/get_area_name(atom/X, format_text = FALSE) var/area/A = isarea(X) ? X : get_area(X) if(!A) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index ba2474bb872..13a35209420 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1129,6 +1129,27 @@ B --><-- A /proc/get_random_station_turf() return safepick(get_area_turfs(pick(GLOB.the_station_areas))) +/proc/get_safe_random_station_turf() + for (var/i in 1 to 5) + var/list/L = get_area_turfs(pick(GLOB.the_station_areas)) + var/turf/target + while (L.len && !target) + var/I = rand(1, L.len) + var/turf/T = L[I] + if(!T.density) + var/clear = TRUE + for(var/obj/O in T) + if(O.density) + clear = FALSE + break + if(clear) + target = T + if (!target) + L.Cut(I,I+1) + if (target) + return target + + /proc/get_closest_atom(type, list, source) var/closest_atom var/closest_distance diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 3d05d899cf0..5790320af48 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -146,6 +146,11 @@ #define ui_pai_rest "SOUTH:6,WEST+3" #define ui_pai_light "SOUTH:6,WEST+4" #define ui_pai_newscaster "SOUTH:6,WEST+5" +#define ui_pai_host_monitor "SOUTH:6,WEST+6" +#define ui_pai_crew_manifest "SOUTH:6,WEST+7" +#define ui_pai_state_laws "SOUTH:6,WEST+8" +#define ui_pai_pda_send "SOUTH:6,WEST+9" +#define ui_pai_pda_log "SOUTH:6,WEST+10" #define ui_pai_take_picture "SOUTH:6,WEST+12" #define ui_pai_view_images "SOUTH:6,WEST+13" diff --git a/code/_onclick/hud/pai.dm b/code/_onclick/hud/pai.dm index 2da701f217a..c045223d983 100644 --- a/code/_onclick/hud/pai.dm +++ b/code/_onclick/hud/pai.dm @@ -1,17 +1,25 @@ +#define PAI_MISSING_SOFTWARE_MESSAGE "You must download the required software to use this." + /obj/screen/pai icon = 'icons/mob/screen_pai.dmi' + var/required_software /obj/screen/pai/Click() if(isobserver(usr) || usr.incapacitated()) - return TRUE + return FALSE + var/mob/living/silicon/pai/pAI = usr + if(required_software && !pAI.software.Find(required_software)) + to_chat(pAI, PAI_MISSING_SOFTWARE_MESSAGE) + return FALSE + return TRUE /obj/screen/pai/software name = "Software Interface" icon_state = "pai" - /obj/screen/pai/software/Click() - ..() + if(!..()) + return var/mob/living/silicon/pai/pAI = usr pAI.paiInterface() @@ -20,7 +28,8 @@ icon_state = "pai_holoform" /obj/screen/pai/shell/Click() - ..() + if(!..()) + return var/mob/living/silicon/pai/pAI = usr if(pAI.holoform) pAI.fold_in(0) @@ -32,7 +41,8 @@ icon_state = "pai_chassis" /obj/screen/pai/chassis/Click() - ..() + if(!..()) + return var/mob/living/silicon/pai/pAI = usr pAI.choose_chassis() @@ -41,7 +51,8 @@ icon_state = "pai_rest" /obj/screen/pai/rest/Click() - ..() + if(!..()) + return var/mob/living/silicon/pai/pAI = usr pAI.lay_down() @@ -50,41 +61,114 @@ icon_state = "light" /obj/screen/pai/light/Click() - ..() + if(!..()) + return var/mob/living/silicon/pai/pAI = usr pAI.toggle_integrated_light() /obj/screen/pai/newscaster name = "pAI Newscaster" icon_state = "newscaster" + required_software = "newscaster" /obj/screen/pai/newscaster/Click() + if(!..()) + return var/mob/living/silicon/pai/pAI = usr pAI.newscaster.ui_interact(usr) +/obj/screen/pai/host_monitor + name = "Host Health Scan" + icon_state = "host_monitor" + required_software = "host scan" + +/obj/screen/pai/host_monitor/Click() + if(!..()) + return + var/mob/living/silicon/pai/pAI = usr + if(iscarbon(pAI.card.loc)) + pAI.hostscan.attack(pAI.card.loc, pAI) + else + to_chat(src, "You are not being carried by anyone!") + return 0 + +/obj/screen/pai/crew_manifest + name = "Crew Manifest" + icon_state = "manifest" + required_software = "crew manifest" + +/obj/screen/pai/crew_manifest/Click() + if(!..()) + return + var/mob/living/silicon/pai/pAI = usr + pAI.ai_roster() + +/obj/screen/pai/state_laws + name = "State Laws" + icon_state = "state_laws" + +/obj/screen/pai/state_laws/Click() + if(!..()) + return + var/mob/living/silicon/pai/pAI = usr + pAI.checklaws() + +/obj/screen/pai/pda_msg_send + name = "PDA - Send Message" + icon_state = "pda_send" + required_software = "digital messenger" + +/obj/screen/pai/pda_msg_send/Click() + if(!..()) + return + var/mob/living/silicon/pai/pAI = usr + pAI.cmd_send_pdamesg(usr) + +/obj/screen/pai/pda_msg_show + name = "PDA - Show Message Log" + icon_state = "pda_receive" + required_software = "digital messenger" + +/obj/screen/pai/pda_msg_show/Click() + if(!..()) + return + var/mob/living/silicon/pai/pAI = usr + pAI.cmd_show_message_log(usr) + /obj/screen/pai/image_take name = "Take Image" icon_state = "take_picture" + required_software = "photography module" /obj/screen/pai/image_take/Click() - if(..()) + if(!..()) return - if(issilicon(usr)) - var/mob/living/silicon/ai/pAI = usr - pAI.aicamera.toggle_camera_mode(usr) + var/mob/living/silicon/pai/pAI = usr + pAI.aicamera.toggle_camera_mode(usr) /obj/screen/pai/image_view name = "View Images" icon_state = "view_images" + required_software = "photography module" /obj/screen/pai/image_view/Click() - if(..()) + if(!..()) return - if(issilicon(usr)) - var/mob/living/silicon/ai/pAI = usr - pAI.aicamera.viewpictures(usr) + var/mob/living/silicon/pai/pAI = usr + pAI.aicamera.viewpictures(usr) -/datum/hud/pai/New(mob/owner) +/obj/screen/pai/radio + name = "radio" + icon = 'icons/mob/screen_cyborg.dmi' + icon_state = "radio" + +/obj/screen/pai/radio/Click() + if(!..()) + return + var/mob/living/silicon/pai/pAI = usr + pAI.radio.interact(usr) + +/datum/hud/pai/New(mob/living/silicon/pai/owner) ..() var/obj/screen/using @@ -123,12 +207,52 @@ using.screen_loc = ui_borg_language_menu static_inventory += using -//Take image +// Host Monitor + using = new /obj/screen/pai/host_monitor() + using.screen_loc = ui_pai_host_monitor + static_inventory += using + +// Crew Manifest + using = new /obj/screen/pai/crew_manifest() + using.screen_loc = ui_pai_crew_manifest + static_inventory += using + +// Laws + using = new /obj/screen/pai/state_laws() + using.screen_loc = ui_pai_state_laws + static_inventory += using + +// PDA message + using = new /obj/screen/pai/pda_msg_send() + using.screen_loc = ui_pai_pda_send + static_inventory += using + +// PDA log + using = new /obj/screen/pai/pda_msg_show() + using.screen_loc = ui_pai_pda_log + static_inventory += using + +// Take image using = new /obj/screen/pai/image_take() using.screen_loc = ui_pai_take_picture static_inventory += using -//View images +// View images using = new /obj/screen/pai/image_view() using.screen_loc = ui_pai_view_images - static_inventory += using \ No newline at end of file + static_inventory += using + +// Radio + using = new /obj/screen/pai/radio() + using.screen_loc = ui_borg_radio + static_inventory += using + + update_software_buttons() + +/datum/hud/pai/proc/update_software_buttons() + var/mob/living/silicon/pai/owner = mymob + for(var/obj/screen/pai/button in static_inventory) + if(button.required_software) + button.color = owner.software.Find(button.required_software) ? null : "#808080" + +#undef PAI_MISSING_SOFTWARE_MESSAGE diff --git a/code/_onclick/pai.dm b/code/_onclick/pai.dm index 01b6c8421be..06c1d9dfdfe 100644 --- a/code/_onclick/pai.dm +++ b/code/_onclick/pai.dm @@ -2,5 +2,5 @@ ..() if(aicamera.in_camera_mode) //pAI picture taking aicamera.camera_mode_off() - aicamera.captureimage(A, usr) + aicamera.captureimage(A, usr, null, aicamera.picture_size_x, aicamera.picture_size_y) return diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index ed6de7f1683..a6297c4bec4 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -228,7 +228,7 @@ SUBSYSTEM_DEF(job) * fills var "assigned_role" for all ready players. * This proc must not have any side effect besides of modifying "assigned_role". **/ -/datum/controller/subsystem/job/proc/DivideOccupations() +/datum/controller/subsystem/job/proc/DivideOccupations(list/required_jobs) //Setup new player list and get the jobs list JobDebug("Running DO") @@ -241,14 +241,14 @@ SUBSYSTEM_DEF(job) //Get the players who are ready for(var/mob/dead/new_player/player in GLOB.player_list) - if(player.ready == PLAYER_READY_TO_PLAY && player.mind && !player.mind.assigned_role) + if(player.ready == PLAYER_READY_TO_PLAY && player.has_valid_preferences() && player.mind && !player.mind.assigned_role) unassigned += player initial_players_to_assign = unassigned.len JobDebug("DO, Len: [unassigned.len]") if(unassigned.len == 0) - return TRUE + return validate_required_jobs(required_jobs) //Scale number of open security officer slots to population setup_officer_positions() @@ -354,7 +354,26 @@ SUBSYSTEM_DEF(job) if(!GiveRandomJob(player)) if(!AssignRole(player, SSjob.overflow_role)) //If everything is already filled, make them an assistant return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll - return TRUE + + return validate_required_jobs(required_jobs) + +/datum/controller/subsystem/job/proc/validate_required_jobs(list/required_jobs) + if(!required_jobs.len) + return TRUE + for(var/required_group in required_jobs) + var/group_ok = TRUE + for(var/rank in required_group) + var/datum/job/J = GetJob(rank) + if(!J) + SSticker.mode.setup_error = "Invalid job [rank] in gamemode required jobs." + return FALSE + if(J.current_positions < required_group[rank]) + group_ok = FALSE + break + if(group_ok) + return TRUE + SSticker.mode.setup_error = "Required jobs not present." + return FALSE //We couldn't find a job from prefs for this guy. /datum/controller/subsystem/job/proc/HandleUnassigned(mob/dead/new_player/player) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 775bdb0485e..83d1f6f17c6 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -117,9 +117,9 @@ SUBSYSTEM_DEF(ticker) if(!GLOB.syndicate_code_phrase) - GLOB.syndicate_code_phrase = generate_code_phrase() + GLOB.syndicate_code_phrase = generate_code_phrase(return_list=TRUE) if(!GLOB.syndicate_code_response) - GLOB.syndicate_code_response = generate_code_phrase() + GLOB.syndicate_code_response = generate_code_phrase(return_list=TRUE) start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10) if(CONFIG_GET(flag/randomize_shift_time)) @@ -230,7 +230,7 @@ SUBSYSTEM_DEF(ticker) var/can_continue = 0 can_continue = src.mode.pre_setup() //Choose antagonists CHECK_TICK - can_continue = can_continue && SSjob.DivideOccupations() //Distribute jobs + can_continue = can_continue && SSjob.DivideOccupations(mode.required_jobs) //Distribute jobs CHECK_TICK if(!GLOB.Debug2) @@ -412,7 +412,7 @@ SUBSYSTEM_DEF(ticker) queued_players.len = 0 queue_delay = 0 return - + queue_delay++ var/mob/dead/new_player/next_in_line = queued_players[1] diff --git a/code/datums/components/bane.dm b/code/datums/components/bane.dm new file mode 100644 index 00000000000..aac56d099e5 --- /dev/null +++ b/code/datums/components/bane.dm @@ -0,0 +1,45 @@ +/datum/component/bane + dupe_mode = COMPONENT_DUPE_ALLOWED + + var/mobtype + var/speciestype + var/damage_multiplier + +/datum/component/bane/Initialize(mobtype, damage_multiplier=1) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + if(ispath(mobtype, /mob/living)) + src.mobtype = mobtype + else if(ispath(mobtype, /datum/species)) + speciestype = mobtype + else + return COMPONENT_INCOMPATIBLE + + src.damage_multiplier = damage_multiplier + +/datum/component/bane/RegisterWithParent() + if(speciestype) + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/speciesCheck) + else + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/mobCheck) + +/datum/component/bane/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK) + +/datum/component/bane/proc/speciesCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) + if(!is_species(target, speciestype)) + return + activate(source, target, user) + +/datum/component/bane/proc/mobCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) + if(!istype(target, mobtype)) + return + activate(source, target, user) + +/datum/component/bane/proc/activate(obj/item/source, mob/living/target, mob/attacker) + if(attacker.a_intent != INTENT_HARM) + return + + var/extra_damage = max(0, source.force * damage_multiplier) + target.apply_damage(extra_damage, source.damtype, attacker.zone_selected) diff --git a/code/datums/components/fantasy/_fantasy.dm b/code/datums/components/fantasy/_fantasy.dm new file mode 100644 index 00000000000..485ec7432e7 --- /dev/null +++ b/code/datums/components/fantasy/_fantasy.dm @@ -0,0 +1,137 @@ +/datum/component/fantasy + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + + var/quality + + var/canFail + var/announce + + var/originalName + var/list/affixes + var/list/appliedComponents + + var/static/list/affixListing + +/datum/component/fantasy/Initialize(quality, list/affixes = list(), canFail=FALSE, announce=FALSE) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + src.quality = quality || randomQuality() + src.canFail = canFail + src.announce = announce + + src.affixes = affixes + appliedComponents = list() + randomAffixes() + +/datum/component/fantasy/Destroy() + unmodify() + affixes = null + return ..() + +/datum/component/fantasy/RegisterWithParent() + var/obj/item/master = parent + originalName = master.name + modify() + +/datum/component/fantasy/UnregisterFromParent() + unmodify() + +/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, list/arguments) + unmodify() + if(newComp) + quality += newComp.quality + canFail = newComp.canFail + announce = newComp.announce + else + arguments.len = 5 // This is done to replicate what happens when an arglist smaller than the necessary arguments is given + quality += arguments[1] + canFail = arguments[4] || canFail + announce = arguments[5] || announce + modify() + +/datum/component/fantasy/proc/randomQuality() + var/quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0) + if(prob(50)) + quality = -quality + return quality + +/datum/component/fantasy/proc/randomAffixes(force) + if(!affixListing) + affixListing = list() + for(var/T in subtypesof(/datum/fantasy_affix)) + var/datum/fantasy_affix/affix = new T + affixListing[affix] = affix.weight + + var/usedSlots = NONE + for(var/i in affixes) + var/datum/fantasy_affix/affix = i + usedSlots |= affix.placement + + var/alignment + if(quality >= 0) + alignment |= AFFIX_GOOD + if(quality <= 0) + alignment |= AFFIX_EVIL + + for(var/i in 1 to max(1, abs(quality))) // We want at least 1 affix applied + var/datum/fantasy_affix/affix = pickweight(affixListing) + if(affix.placement & usedSlots) + continue + if(!(affix.alignment & alignment)) + continue + affixes += affix + usedSlots |= affix.placement + +/datum/component/fantasy/proc/modify() + var/obj/item/master = parent + + master.force = max(0, master.force + quality) + master.throwforce = max(0, master.throwforce + quality) + master.armor = master.armor.modifyAllRatings(quality) + + var/newName = originalName + for(var/i in affixes) + var/datum/fantasy_affix/affix = i + newName = affix.apply(src, newName) + + if(quality != 0) + newName = "[newName] [quality > 0 ? "+" : ""][quality]" + + if(canFail && prob((quality - 9)*10)) + var/turf/place = get_turf(parent) + place.visible_message("[parent] violently glows blue for a while, then evaporates.") + master.burn() + return + else if(announce) + announce() + + master.name = newName + +/datum/component/fantasy/proc/unmodify() + var/obj/item/master = parent + + for(var/i in affixes) + var/datum/fantasy_affix/affix = i + affix.remove(src) + for(var/i in appliedComponents) + qdel(i) + + master.force = max(0, master.force - quality) + master.throwforce = max(0, master.throwforce - quality) + master.armor = master.armor.modifyAllRatings(-quality) + + master.name = originalName + +/datum/component/fantasy/proc/announce() + var/turf/location = get_turf(parent) + var/span + var/effect_description + if(quality >= 0) + span = "" + effect_description = "shimmering golden glow" + else + span = "" + effect_description = "mottled black glow" + + location.visible_message("[span][originalName] is covered by a [effect_description] and then transforms into [parent]!") diff --git a/code/datums/components/fantasy/affix.dm b/code/datums/components/fantasy/affix.dm new file mode 100644 index 00000000000..b111f1ca8cd --- /dev/null +++ b/code/datums/components/fantasy/affix.dm @@ -0,0 +1,9 @@ +/datum/fantasy_affix + var/placement // A bitflag of "slots" this affix takes up, for example pre/suffix + var/alignment + var/weight = 10 + +/datum/fantasy_affix/proc/apply(datum/component/fantasy/comp, newName) + return newName + +/datum/fantasy_affix/proc/remove(datum/component/fantasy/comp) \ No newline at end of file diff --git a/code/datums/components/fantasy/prefixes.dm b/code/datums/components/fantasy/prefixes.dm new file mode 100644 index 00000000000..9bf54745945 --- /dev/null +++ b/code/datums/components/fantasy/prefixes.dm @@ -0,0 +1,49 @@ +/datum/fantasy_affix/cosmetic_prefixes + placement = AFFIX_PREFIX + alignment = AFFIX_GOOD | AFFIX_EVIL + + var/list/goodPrefixes + var/list/badPrefixes + +/datum/fantasy_affix/cosmetic_prefixes/New() + goodPrefixes = list( + "greater", + "major", + "blessed", + "superior", + "empowered", + "honed", + "true", + "glorious", + "robust", + ) + badPrefixes = list( + "lesser", + "minor", + "blighted", + "inferior", + "enfeebled", + "rusted", + "unsteady", + "tragic", + "gimped", + "cursed", + ) + + weight = (length(goodPrefixes) + length(badPrefixes)) * 10 + +/datum/fantasy_affix/cosmetic_prefixes/apply(datum/component/fantasy/comp, newName) + if(comp.quality > 0 || (comp.quality == 0 && prob(50))) + return "[pick(goodPrefixes)] [newName]" + else + return "[pick(badPrefixes)] [newName]" + +/datum/fantasy_affix/tactical + placement = AFFIX_PREFIX + alignment = AFFIX_GOOD + weight = 1 // Very powerful, no one should have such power + +/datum/fantasy_affix/tactical/apply(datum/component/fantasy/comp, newName) + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/tactical) + return "tactical [newName]" \ No newline at end of file diff --git a/code/datums/components/fantasy/suffixes.dm b/code/datums/components/fantasy/suffixes.dm new file mode 100644 index 00000000000..20d22734efe --- /dev/null +++ b/code/datums/components/fantasy/suffixes.dm @@ -0,0 +1,101 @@ +/datum/fantasy_affix/cosmetic_suffixes + placement = AFFIX_SUFFIX + alignment = AFFIX_GOOD | AFFIX_EVIL + + var/list/goodSuffixes + var/list/badSuffixes + +/datum/fantasy_affix/cosmetic_suffixes/New() + goodSuffixes = list( + "dexterity", + "constitution", + "intelligence", + "wisdom", + "charisma", + "the forest", + "the hills", + "the plains", + "the sea", + "the sun", + "the moon", + "the void", + "the world", + "many secrets", + "many tales", + "many colors", + "rending", + "sundering", + "the night", + "the day", + ) + badSuffixes = list( + "draining", + "burden", + "discomfort", + "awkwardness", + "poor hygiene", + "timidity", + ) + + weight = (length(goodSuffixes) + length(badSuffixes)) * 10 + +/datum/fantasy_affix/cosmetic_suffixes/apply(datum/component/fantasy/comp, newName) + if(comp.quality > 0 || (comp.quality == 0 && prob(50))) + return "[newName] of [pick(goodSuffixes)]" + else + return "[newName] of [pick(badSuffixes)]" + +//////////// Good suffixes +/datum/fantasy_affix/bane + placement = AFFIX_SUFFIX + alignment = AFFIX_GOOD + weight = 20 + +/datum/fantasy_affix/bane/apply(datum/component/fantasy/comp, newName) + . = ..() + // This is set up to be easy to add to these lists as I expect it will need modifications + var/static/list/possible_mobtypes + if(!possible_mobtypes) + // The base list of allowed mob/species types + possible_mobtypes = typecacheof(list( + /mob/living/simple_animal, + /mob/living/carbon, + /datum/species, + )) + // Some particular types to disallow if they're too broad/abstract + possible_mobtypes -= list( + /mob/living/simple_animal/hostile, + ) + // Some types to remove them and their subtypes + possible_mobtypes -= typecacheof(list( + /mob/living/carbon/human/species, + )) + + var/mob/picked_mobtype = pick(possible_mobtypes) + // This works even with the species picks since we're only accessing the name + + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/bane, picked_mobtype) + return "[newName] of [initial(picked_mobtype.name)] slaying" + +/datum/fantasy_affix/strength + placement = AFFIX_SUFFIX + alignment = AFFIX_GOOD + +/datum/fantasy_affix/strength/apply(datum/component/fantasy/comp, newName) + . = ..() + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/knockback, CEILING(comp.quality/2, 1)) + return "[newName] of strength" + +//////////// Bad suffixes + +/datum/fantasy_affix/fool + placement = AFFIX_SUFFIX + alignment = AFFIX_EVIL + +/datum/fantasy_affix/fool/apply(datum/component/fantasy/comp, newName) + . = ..() + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/squeak/bikehorn) + return "[newName] of the fool" \ No newline at end of file diff --git a/code/datums/components/knockback.dm b/code/datums/components/knockback.dm new file mode 100644 index 00000000000..1443a4b905b --- /dev/null +++ b/code/datums/components/knockback.dm @@ -0,0 +1,22 @@ +/datum/component/knockback + var/throw_distance + +/datum/component/knockback/Initialize(throw_distance=1) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + src.throw_distance = throw_distance + +/datum/component/knockback/RegisterWithParent() + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/afterattack_react) + +/datum/component/knockback/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK) + +/datum/component/knockback/proc/afterattack_react(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) + if(!ismovableatom(target) || !proximity_flag) + return + var/obj/item/master = parent + var/atom/movable/throwee = target + var/atom/throw_target = get_edge_target_turf(throwee, get_dir(master, throwee)) + throwee.safe_throw_at(throw_target, throw_distance, 1, user) \ No newline at end of file diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index 172fb236ca6..96b7f70c953 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -249,6 +249,8 @@ /datum/component/mood/proc/add_event(datum/source, category, type, param) //Category will override any events in the same category, should be unique unless the event is based on the same thing like hunger. var/datum/mood_event/the_event + if(!istext(category)) + category = REF(category) if(mood_events[category]) the_event = mood_events[category] if(the_event.type != type) @@ -267,6 +269,8 @@ addtimer(CALLBACK(src, .proc/clear_event, null, category), the_event.timeout, TIMER_UNIQUE|TIMER_OVERRIDE) /datum/component/mood/proc/clear_event(datum/source, category) + if(!istext(category)) + category = REF(category) var/datum/mood_event/event = mood_events[category] if(!event) return 0 diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm index a4c14871e01..767d93f6700 100644 --- a/code/datums/components/nanites.dm +++ b/code/datums/components/nanites.dm @@ -56,6 +56,7 @@ RegisterSignal(parent, COMSIG_MOVABLE_HEAR, .proc/on_hear) RegisterSignal(parent, COMSIG_SPECIES_GAIN, .proc/check_viable_biotype) RegisterSignal(parent, COMSIG_NANITE_SIGNAL, .proc/receive_signal) + RegisterSignal(parent, COMSIG_NANITE_COMM_SIGNAL, .proc/receive_comm_signal) /datum/component/nanites/UnregisterFromParent() UnregisterSignal(parent, list(COMSIG_HAS_NANITES, @@ -77,7 +78,8 @@ COMSIG_LIVING_MINOR_SHOCK, COMSIG_MOVABLE_HEAR, COMSIG_SPECIES_GAIN, - COMSIG_NANITE_SIGNAL)) + COMSIG_NANITE_SIGNAL, + COMSIG_NANITE_COMM_SIGNAL)) /datum/component/nanites/Destroy() STOP_PROCESSING(SSnanites, src) @@ -205,6 +207,12 @@ var/datum/nanite_program/NP = X NP.receive_signal(code, source) +/datum/component/nanites/proc/receive_comm_signal(datum/source, comm_code, comm_message, comm_source = "an unidentified source") + for(var/X in programs) + if(istype(X, /datum/nanite_program/triggered/comm)) + var/datum/nanite_program/triggered/comm/NP = X + NP.receive_comm_signal(comm_code, comm_message, comm_source) + /datum/component/nanites/proc/check_viable_biotype() if(!(MOB_ORGANIC in host_mob.mob_biotypes) && !(MOB_UNDEAD in host_mob.mob_biotypes)) qdel(src) //bodytype no longer sustains nanites diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm index baa9d86b299..6a39c41c424 100644 --- a/code/datums/components/squeak.dm +++ b/code/datums/components/squeak.dm @@ -52,7 +52,7 @@ else steps++ -/datum/component/squeak/proc/play_squeak_crossed(atom/movable/AM) +/datum/component/squeak/proc/play_squeak_crossed(datum/source, atom/movable/AM) if(isitem(AM)) var/obj/item/I = AM if(I.item_flags & ABSTRACT) diff --git a/code/datums/components/tactical.dm b/code/datums/components/tactical.dm new file mode 100644 index 00000000000..d7f035b449d --- /dev/null +++ b/code/datums/components/tactical.dm @@ -0,0 +1,34 @@ +/datum/component/tactical + var/allowed_slot + +/datum/component/tactical/Initialize(allowed_slot) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + src.allowed_slot = allowed_slot + +/datum/component/tactical/RegisterWithParent() + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/modify) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/unmodify) + +/datum/component/tactical/UnregisterFromParent() + unmodify() + +/datum/component/fantasy/Destroy() + unmodify() + return ..() + +/datum/component/tactical/proc/modify(obj/item/source, mob/user, slot) + if(allowed_slot && slot != allowed_slot) + unmodify() + return + + var/obj/item/master = parent + var/image/I = image(icon = master.icon, icon_state = master.icon_state, loc = user) + I.copy_overlays(master) + I.override = TRUE + source.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I) + I.layer = ABOVE_MOB_LAYER + +/datum/component/tactical/proc/unmodify(obj/item/source, mob/user) + user.remove_alt_appearance("sneaking_mission") \ No newline at end of file diff --git a/code/datums/components/tether.dm b/code/datums/components/tether.dm new file mode 100644 index 00000000000..faa6182208a --- /dev/null +++ b/code/datums/components/tether.dm @@ -0,0 +1,37 @@ +/datum/component/tether + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + var/atom/tether_target + var/max_dist + var/tether_name + +/datum/component/tether/Initialize(atom/tether_target, max_dist = 4, tether_name) + if(!isliving(parent) || !istype(tether_target) || !tether_target.loc) + return COMPONENT_INCOMPATIBLE + src.tether_target = tether_target + src.max_dist = max_dist + if (ispath(tether_name, /atom)) + var/atom/tmp = tether_name + src.tether_name = initial(tmp.name) + else + src.tether_name = tether_name + RegisterSignal(parent, list(COMSIG_MOVABLE_PRE_MOVE), .proc/checkTether) + +/datum/component/tether/proc/checkTether(mob/mover, newloc) + if (get_dist(mover,newloc) > max_dist) + to_chat(mover, "The [tether_name] runs out of slack and prevents you from moving!") + return COMPONENT_MOVABLE_BLOCK_PRE_MOVE + + var/atom/blocker + out: + for(var/turf/T in getline(tether_target,newloc)) + if (T.density) + blocker = T + break out + for(var/a in T) + var/atom/A = a + if(A.density && A != mover && A != tether_target) + blocker = A + break out + if (blocker) + to_chat(mover, "The [tether_name] catches on [blocker] and prevents you from moving!") + return COMPONENT_MOVABLE_BLOCK_PRE_MOVE diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index 714b72a85f1..07083b6b29f 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -43,13 +43,14 @@ GLOBAL_LIST_EMPTY(uplinks) RegisterSignal(parent, COMSIG_IMPLANT_EXISTING_UPLINK, .proc/new_implant) else if(istype(parent, /obj/item/pda)) RegisterSignal(parent, COMSIG_PDA_CHANGE_RINGTONE, .proc/new_ringtone) + RegisterSignal(parent, COMSIG_PDA_CHECK_DETONATE, .proc/check_detonate) else if(istype(parent, /obj/item/radio)) RegisterSignal(parent, COMSIG_RADIO_NEW_FREQUENCY, .proc/new_frequency) else if(istype(parent, /obj/item/pen)) RegisterSignal(parent, COMSIG_PEN_ROTATED, .proc/pen_rotation) GLOB.uplinks += src - uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted) + uplink_items = get_uplink_items(_gamemode, TRUE, allow_restricted) if(_owner) owner = _owner @@ -251,6 +252,9 @@ GLOBAL_LIST_EMPTY(uplinks) master.mode = 0 return COMPONENT_STOP_RINGTONE_CHANGE +/datum/component/uplink/proc/check_detonate() + return COMPONENT_PDA_NO_DETONATE + // Radio signal responses /datum/component/uplink/proc/new_frequency(datum/source, list/arguments) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 4fde3987c7b..bb6d271b450 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -105,7 +105,6 @@ .manifest td, th {border:1px solid [monochrome?"black":"#DEF; background-color:white; color:black"]; padding:.25em} .manifest th {height: 2em; [monochrome?"border-top-width: 3px":"background-color: #48C; color:white"]} .manifest tr.head th { [monochrome?"border-top-width: 1px":"background-color: #488;"] } - .manifest td:first-child {text-align:right} .manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: #DEF"]} @@ -255,7 +254,7 @@ M.fields["alg_d"] = "No allergies have been detected in this patient." M.fields["cdi"] = "None" M.fields["cdi_d"] = "No diseases have been diagnosed at the moment." - M.fields["notes"] = "No notes." + M.fields["notes"] = H.get_trait_string(medical) medical += M //Security Record diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 51abd1f47ac..b967b7a5861 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -120,7 +120,7 @@ if(affected_mob.mind && !is_monkey(affected_mob.mind)) add_monkey(affected_mob.mind) if(ishuman(affected_mob)) - var/mob/living/carbon/monkey/M = affected_mob.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) + var/mob/living/carbon/monkey/M = affected_mob.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_KEEPSE) M.ventcrawler = VENTCRAWLER_ALWAYS diff --git a/code/datums/helper_datums/topic_input.dm b/code/datums/helper_datums/topic_input.dm deleted file mode 100644 index 3e43905f1fe..00000000000 --- a/code/datums/helper_datums/topic_input.dm +++ /dev/null @@ -1,62 +0,0 @@ -/datum/topic_input - var/href - var/list/href_list - -/datum/topic_input/New(thref,list/thref_list) - href = thref - href_list = thref_list.Copy() - return - -/datum/topic_input/proc/get(i) - return listgetindex(href_list,i) - -/datum/topic_input/proc/getAndLocate(i) - var/t = get(i) - if(t) - t = locate(t) - if (istext(t)) - t = null - return t || null - -/datum/topic_input/proc/getNum(i) - var/t = get(i) - if(t) - t = text2num(t) - return isnum(t) ? t : null - -/datum/topic_input/proc/getObj(i) - var/t = getAndLocate(i) - return isobj(t) ? t : null - -/datum/topic_input/proc/getMob(i) - var/t = getAndLocate(i) - return ismob(t) ? t : null - -/datum/topic_input/proc/getTurf(i) - var/t = getAndLocate(i) - return isturf(t) ? t : null - -/datum/topic_input/proc/getAtom(i) - return getType(i, /atom) - -/datum/topic_input/proc/getArea(i) - var/t = getAndLocate(i) - return isarea(t) ? t : null - -/datum/topic_input/proc/getStr(i)//params should always be text, but... - var/t = get(i) - return istext(t) ? t : null - -/datum/topic_input/proc/getType(i,type) - var/t = getAndLocate(i) - return istype(t,type) ? t : null - -/datum/topic_input/proc/getPath(i) - var/t = get(i) - if(t) - t = text2path(t) - return ispath(t) ? t : null - -/datum/topic_input/proc/getList(i) - var/t = getAndLocate(i) - return islist(t) ? t : null diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm index 4a1a29fe3ce..f9e7097ace2 100644 --- a/code/datums/mood_events/generic_positive_events.dm +++ b/code/datums/mood_events/generic_positive_events.dm @@ -120,6 +120,7 @@ /datum/mood_event/religiously_comforted description = "You are comforted by the presence of a holy person.\n" mood_change = 3 + timeout = 5 MINUTES /datum/mood_event/clownshoes description = "The shoes are a clown's legacy, I never want to take them off!\n" diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm index 42c3f979011..cc79ec42fc6 100644 --- a/code/datums/mutations.dm +++ b/code/datums/mutations.dm @@ -97,9 +97,6 @@ /datum/mutation/human/proc/on_ranged_attack(atom/target) return -/datum/mutation/human/proc/on_move(new_loc) - return - /datum/mutation/human/proc/on_life() return diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index f37c87ad557..b3cee91681b 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -177,11 +177,11 @@ /datum/mutation/human/race/on_acquiring(mob/living/carbon/human/owner) if(..()) return - . = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) + . = owner.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_KEEPSE) /datum/mutation/human/race/on_losing(mob/living/carbon/monkey/owner) if(owner && istype(owner) && owner.stat != DEAD && (owner.dna.mutations.Remove(src))) - . = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) + . = owner.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_KEEPSE) /datum/mutation/human/glow name = "Glowy" diff --git a/code/datums/mutations/chameleon.dm b/code/datums/mutations/chameleon.dm index d8ee7728a78..a6fd5cab3ec 100644 --- a/code/datums/mutations/chameleon.dm +++ b/code/datums/mutations/chameleon.dm @@ -13,11 +13,12 @@ if(..()) return owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/on_move) /datum/mutation/human/chameleon/on_life() owner.alpha = max(0, owner.alpha - 25) -/datum/mutation/human/chameleon/on_move() +/datum/mutation/human/chameleon/proc/on_move() owner.alpha = CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY /datum/mutation/human/chameleon/on_attack_hand(atom/target, proximity) @@ -29,3 +30,4 @@ if(..()) return owner.alpha = 255 + UnregisterSignal(owner, COMSIG_MOVABLE_MOVED) diff --git a/code/datums/radiation_wave.dm b/code/datums/radiation_wave.dm index 5fb777f9c57..949e63dc6a7 100644 --- a/code/datums/radiation_wave.dm +++ b/code/datums/radiation_wave.dm @@ -9,7 +9,9 @@ var/can_contaminate /datum/radiation_wave/New(atom/_source, dir, _intensity=0, _range_modifier=RAD_DISTANCE_COEFFICIENT, _can_contaminate=TRUE) - source = _source + + source = "[_source] \[[REF(_source)]\]" + master_turf = get_turf(_source) move_dir = dir diff --git a/code/datums/traits/good.dm b/code/datums/traits/good.dm index e73293617f9..ff1ccc15b60 100644 --- a/code/datums/traits/good.dm +++ b/code/datums/traits/good.dm @@ -8,12 +8,14 @@ mob_trait = TRAIT_ALCOHOL_TOLERANCE gain_text = "You feel like you could drink a whole keg!" lose_text = "You don't feel as resistant to alcohol anymore. Somehow." + medical_record_text = "Patient demonstrates a high tolerance for alcohol." /datum/quirk/apathetic name = "Apathetic" desc = "You just don't care as much as other people. That's nice to have in a place like this, I guess." value = 1 mood_quirk = TRUE + medical_record_text = "Patient was administered the Apathy Evaluation Scale but did not bother to complete it." /datum/quirk/apathetic/add() GET_COMPONENT_FROM(mood, /datum/component/mood, quirk_holder) @@ -42,6 +44,7 @@ mob_trait = TRAIT_EMPATH gain_text = "You feel in tune with those around you." lose_text = "You feel isolated from others." + medical_record_text = "Patient is highly perceptive of and sensitive to social cues, or may possibly have ESP. Further testing needed." /datum/quirk/freerunning name = "Freerunning" @@ -50,6 +53,7 @@ mob_trait = TRAIT_FREERUNNING gain_text = "You feel lithe on your feet!" lose_text = "You feel clumsy again." + medical_record_text = "Patient scored highly on cardio tests." /datum/quirk/friendly name = "Friendly" @@ -59,6 +63,7 @@ gain_text = "You want to hug someone." lose_text = "You no longer feel compelled to hug others." mood_quirk = TRUE + medical_record_text = "Patient demonstrates low-inhibitions for physical contact and well-developed arms. Requesting another doctor take over this case." /datum/quirk/jolly name = "Jolly" @@ -66,6 +71,7 @@ value = 1 mob_trait = TRAIT_JOLLY mood_quirk = TRUE + medical_record_text = "Patient demonstrates constant euthymia irregular for environment. It's a bit much, to be honest." /datum/quirk/jolly/on_process() if(prob(0.05)) @@ -78,6 +84,7 @@ mob_trait = TRAIT_LIGHT_STEP gain_text = "You walk with a little more litheness." lose_text = "You start tromping around like a barbarian." + medical_record_text = "Patient's dexterity belies a strong capacity for stealth." /datum/quirk/musician name = "Musician" @@ -86,6 +93,7 @@ mob_trait = TRAIT_MUSICIAN gain_text = "You know everything about musical instruments." lose_text = "You forget how musical instruments work." + medical_record_text = "Patient brain scans show a highly-developed auditory pathway." /datum/quirk/musician/on_spawn() var/mob/living/carbon/human/H = quirk_holder @@ -101,6 +109,7 @@ mob_trait = TRAIT_NIGHT_VISION gain_text = "The shadows seem a little less dark." lose_text = "Everything seems a little darker." + medical_record_text = "Patient's eyes show above-average acclimation to darkness." /datum/quirk/night_vision/on_spawn() var/mob/living/carbon/human/H = quirk_holder @@ -116,6 +125,7 @@ mob_trait = TRAIT_PHOTOGRAPHER gain_text = "You know everything about photography." lose_text = "You forget how photo cameras work." + medical_record_text = "Patient mentions photography as a stress-relieving hobby." /datum/quirk/photographer/on_spawn() var/mob/living/carbon/human/H = quirk_holder @@ -129,12 +139,14 @@ desc = "You know your body well, and can accurately assess the extent of your wounds." value = 2 mob_trait = TRAIT_SELF_AWARE + medical_record_text = "Patient demonstrates an uncanny knack for self-diagnosis." /datum/quirk/skittish name = "Skittish" desc = "You can conceal yourself in danger. Ctrl-shift-click a closed locker to jump into it, as long as you have access." value = 2 mob_trait = TRAIT_SKITTISH + medical_record_text = "Patient demonstrates a high aversion to danger and has described hiding in containers out of fear." /datum/quirk/spiritual name = "Spiritual" @@ -143,23 +155,13 @@ mob_trait = TRAIT_SPIRITUAL gain_text = "You have faith in a higher power." lose_text = "You lose faith!" + medical_record_text = "Patient reports a belief in a higher power." /datum/quirk/spiritual/on_spawn() var/mob/living/carbon/human/H = quirk_holder H.equip_to_slot_or_del(new /obj/item/storage/fancy/candle_box(H), SLOT_IN_BACKPACK) H.equip_to_slot_or_del(new /obj/item/storage/box/matches(H), SLOT_IN_BACKPACK) -/datum/quirk/spiritual/on_process() - var/comforted = FALSE - for(var/mob/living/L in oview(5, quirk_holder)) - if(L.mind && L.mind.isholy && L.stat == CONSCIOUS) - comforted = TRUE - break - if(comforted) - SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "religious_comfort", /datum/mood_event/religiously_comforted) - else - SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "religious_comfort") - /datum/quirk/tagger name = "Tagger" desc = "You're an experienced artist. While drawing graffiti, you can get twice as many uses out of drawing supplies." @@ -167,6 +169,7 @@ mob_trait = TRAIT_TAGGER gain_text = "You know how to tag walls efficiently." lose_text = "You forget how to tag walls properly." + medical_record_text = "Patient was recently seen for possible paint huffing incident." /datum/quirk/tagger/on_spawn() var/mob/living/carbon/human/H = quirk_holder @@ -182,6 +185,7 @@ mob_trait = TRAIT_VORACIOUS gain_text = "You feel HONGRY." lose_text = "You no longer feel HONGRY." + medical_record_text = "Patient demonstrates a disturbing capacity for eating." /datum/quirk/neet name = "NEET" @@ -191,6 +195,7 @@ gain_text = "You feel useless to society." lose_text = "You no longer feel useless to society." mood_quirk = TRUE + medical_record_text = "Patient continues to qualify for welfare and has made no efforts to improve hygiene." /datum/quirk/neet/on_spawn() var/mob/living/carbon/human/H = quirk_holder diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index 1ce0d5c5e7e..d96e567b74a 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -7,6 +7,7 @@ mood_quirk = TRUE gain_text = "Your back REALLY hurts!" lose_text = "Your back feels better." + medical_record_text = "Patient scans indicate severe and chronic back pain." /datum/quirk/badback/on_process() var/mob/living/carbon/human/H = quirk_holder @@ -37,7 +38,7 @@ value = -4 gain_text = "You can't see anything." lose_text = "You miraculously gain back your vision." - medical_record_text = "Subject has permanent blindness." + medical_record_text = "Patient has permanent blindness." /datum/quirk/blindness/add() quirk_holder.become_blind(ROUNDSTART_TRAIT) @@ -67,7 +68,7 @@ mob_trait = TRAIT_DEAF gain_text = "You can't hear anything." lose_text = "You're able to hear again!" - medical_record_text = "Subject's cochlear nerve is incurably damaged." + medical_record_text = "Patient's cochlear nerve is incurably damaged." /datum/quirk/depression name = "Depression" @@ -76,7 +77,7 @@ value = -1 gain_text = "You start feeling depressed." lose_text = "You no longer feel depressed." //if only it were that easy! - medical_record_text = "Patient has a severe mood disorder causing them to experience sudden moments of sadness." + medical_record_text = "Patient has a severe mood disorder, causing them to experience acute episodes of depression." mood_quirk = TRUE /datum/quirk/depression/on_process() @@ -90,6 +91,7 @@ mood_quirk = TRUE var/obj/item/heirloom var/where + medical_record_text = "Patient demonstrates an unnatural attachment to a family heirloom." /datum/quirk/family_heirloom/on_spawn() var/mob/living/carbon/human/H = quirk_holder @@ -214,6 +216,7 @@ value = -1 gain_text = "You seem to make a big deal out of everything." lose_text = "You don't seem to make a big deal out of everything anymore." + medical_record_text = "Patient demonstrates a high level of emotional volatility." /datum/quirk/hypersensitive/add() GET_COMPONENT_FROM(mood, /datum/component/mood, quirk_holder) @@ -233,6 +236,7 @@ mob_trait = TRAIT_LIGHT_DRINKER gain_text = "Just the thought of drinking alcohol makes your head spin." lose_text = "You're no longer severely affected by alcohol." + medical_record_text = "Patient demonstrates a low tolerance for alcohol. (Wimp)" /datum/quirk/nearsighted //t. errorage name = "Nearsighted" @@ -256,6 +260,7 @@ name = "Nyctophobia" desc = "As far as you can remember, you've always been afraid of the dark. While in the dark without a light source, you instinctually act careful, and constantly feel a sense of dread." value = -1 + medical_record_text = "Patient demonstrates a fear of the dark. (Seriously?)" /datum/quirk/nyctophobia/on_process() var/mob/living/carbon/human/H = quirk_holder @@ -333,6 +338,7 @@ desc = "An accident caused you to lose one of your limbs. Because of this, you now have a random prosthetic!" value = -1 var/slot_string = "limb" + medical_record_text = "During physical examination, patient was found to have a prosthetic limb." /datum/quirk/prosthetic_limb/on_spawn() var/limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index f16f2b37417..66ac13905bb 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -16,6 +16,7 @@ value = 0 gain_text = "You feel repulsion at the idea of eating meat." lose_text = "You feel like eating meat isn't that bad." + medical_record_text = "Patient reports a vegetarian diet." /datum/quirk/vegetarian/add() var/mob/living/carbon/human/H = quirk_holder @@ -38,6 +39,7 @@ value = 0 gain_text = "You feel an intense craving for pineapple." lose_text = "Your feelings towards pineapples seem to return to a lukewarm state." + medical_record_text = "Patient demonstrates a pathological love of pineapple." /datum/quirk/pineapple_liker/add() var/mob/living/carbon/human/H = quirk_holder @@ -56,6 +58,7 @@ value = 0 gain_text = "You find yourself pondering what kind of idiot actually enjoys pineapples..." lose_text = "Your feelings towards pineapples seem to return to a lukewarm state." + medical_record_text = "Patient is correct to think that pineapple is disgusting." /datum/quirk/pineapple_hater/add() var/mob/living/carbon/human/H = quirk_holder @@ -74,6 +77,7 @@ value = 0 gain_text = "You start craving something that tastes strange." lose_text = "You feel like eating normal food again." + medical_record_text = "Patient demonstrates irregular nutrition preferences." /datum/quirk/deviant_tastes/add() var/mob/living/carbon/human/H = quirk_holder @@ -96,6 +100,7 @@ gain_text = "You feel like you have to stay clean." lose_text = "You no longer feel the need to always be clean." mood_quirk = TRUE + medical_record_text = "While waiting for the exam to begin, patient cleaned the examination room." /datum/quirk/neat/on_process() var/mob/living/carbon/human/H = quirk_holder diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm index 92cc1770b36..2fcccf26631 100644 --- a/code/datums/wires/syndicatebomb.dm +++ b/code/datums/wires/syndicatebomb.dm @@ -22,16 +22,19 @@ holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-") B.explode_now = TRUE tell_admins(B) + else + holder.visible_message("[icon2html(B, viewers(holder))] Nothing happens.") if(WIRE_UNBOLT) holder.visible_message("[icon2html(B, viewers(holder))] The bolts spin in place for a moment.") if(WIRE_DELAY) if(B.delayedbig) - holder.visible_message("[icon2html(B, viewers(holder))] The bomb has already been delayed.") + holder.visible_message("[icon2html(B, viewers(holder))] Nothing happens.") else holder.visible_message("[icon2html(B, viewers(holder))] The bomb chirps.") playsound(B, 'sound/machines/chime.ogg', 30, 1) B.detonation_timer += 300 - B.delayedbig = TRUE + if(B.active) + B.delayedbig = TRUE if(WIRE_PROCEED) holder.visible_message("[icon2html(B, viewers(holder))] The bomb buzzes ominously!") playsound(B, 'sound/machines/buzz-sigh.ogg', 30, 1) @@ -43,7 +46,7 @@ else if(seconds >= 11) // Both to prevent negative timers and to have a little mercy. B.detonation_timer = world.time + 100 if(WIRE_ACTIVATE) - if(!B.active && !B.defused) + if(!B.active) holder.visible_message("[icon2html(B, viewers(holder))] You hear the bomb start ticking!") B.activate() B.update_icon() @@ -58,15 +61,10 @@ var/obj/machinery/syndicatebomb/B = holder switch(wire) if(WIRE_BOOM) - if(mend) - B.defused = FALSE // Cutting and mending all the wires of an inactive bomb will thus cure any sabotage. - else - if(B.active) - holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-") - B.explode_now = TRUE - tell_admins(B) - else - B.defused = TRUE + if(!mend && B.active) + holder.visible_message("[icon2html(B, viewers(holder))] An alarm sounds! It's go-") + B.explode_now = TRUE + tell_admins(B) if(WIRE_UNBOLT) if(!mend && B.anchored) holder.visible_message("[icon2html(B, viewers(holder))] The bolts lift out of the ground!") @@ -81,7 +79,8 @@ if(!mend && B.active) holder.visible_message("[icon2html(B, viewers(holder))] The timer stops! The bomb has been defused!") B.active = FALSE - B.defused = TRUE + B.delayedlittle = FALSE + B.delayedbig = FALSE B.update_icon() /datum/wires/syndicatebomb/proc/tell_admins(obj/machinery/syndicatebomb/B) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index e9c370154cb..bed96e11d9d 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -223,8 +223,10 @@ if(!newloc.Enter(src, src.loc)) return + if (SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, newloc) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE) + return + // Past this is the point of no return - SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, newloc) var/atom/oldloc = loc var/area/oldarea = get_area(oldloc) var/area/newarea = get_area(newloc) diff --git a/code/game/gamemodes/changeling/traitor_chan.dm b/code/game/gamemodes/changeling/traitor_chan.dm index 70c04cb008f..ef9b710d7b0 100644 --- a/code/game/gamemodes/changeling/traitor_chan.dm +++ b/code/game/gamemodes/changeling/traitor_chan.dm @@ -9,15 +9,13 @@ required_enemies = 1 // how many of each type are required recommended_enemies = 3 reroll_friendly = 1 + announce_span = "Traitors and Changelings" + announce_text = "There are alien creatures on the station along with some syndicate operatives out for their own gain! Do not let the changelings or the traitors succeed!" var/list/possible_changelings = list() var/list/changelings = list() var/const/changeling_amount = 1 //hard limit on changelings if scaling is turned off -/datum/game_mode/traitor/changeling/announce() - to_chat(world, "The current game mode is - Traitor+Changeling!") - to_chat(world, "There are alien creatures on the station along with some syndicate operatives out for their own gain! Do not let the changelings or the traitors succeed!") - /datum/game_mode/traitor/changeling/can_start() if(!..()) return 0 diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 87132f7df37..affc7c4f2e6 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -25,6 +25,7 @@ var/list/datum/mind/antag_candidates = list() // List of possible starting antags goes here var/list/restricted_jobs = list() // Jobs it doesn't make sense to be. I.E chaplain or AI cultist var/list/protected_jobs = list() // Jobs that can't be traitors because + var/list/required_jobs = list() // alternative required job groups eg list(list(cap=1),list(hos=1,sec=2)) translates to one captain OR one hos and two secmans var/required_players = 0 var/maximum_players = -1 // -1 is no maximum, positive numbers limit the selection of a mode on overstaffed stations var/required_enemies = 0 @@ -359,7 +360,7 @@ // Ultimate randomizing code right here for(var/mob/dead/new_player/player in GLOB.player_list) - if(player.client && player.ready == PLAYER_READY_TO_PLAY) + if(player.client && player.ready == PLAYER_READY_TO_PLAY && player.has_valid_preferences()) players += player // Shuffling, the players list is now ping-independent!!! @@ -394,24 +395,6 @@ drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie - while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates - if(drafted.len > 0) - applicant = pick(drafted) - if(applicant) - candidates += applicant - drafted.Remove(applicant) - - else // Not enough scrubs, ABORT ABORT ABORT - break - - if(restricted_jobs) - for(var/datum/mind/player in drafted) // Remove people who can't be an antagonist - for(var/job in restricted_jobs) - if(player.assigned_role == job) - drafted -= player - - drafted = shuffle(drafted) // Will hopefully increase randomness, Donkie - while(candidates.len < recommended_enemies) // Pick randomlly just the number of people we need and add them to our list of candidates if(drafted.len > 0) applicant = pick(drafted) diff --git a/code/game/gamemodes/monkey/monkey.dm b/code/game/gamemodes/monkey/monkey.dm index 5b87693ef32..45cbe960e0c 100644 --- a/code/game/gamemodes/monkey/monkey.dm +++ b/code/game/gamemodes/monkey/monkey.dm @@ -15,6 +15,9 @@ restricted_jobs = list("Cyborg", "AI") + announce_span = "Monkey" + announce_text = "One or more crewmembers have been infected with Jungle Fever! Crew: Contain the outbreak. None of the infected monkeys may escape alive to CentCom. Monkeys: Ensure that your kind lives on! Rise up against your captors!" + var/carriers_to_make = 1 var/list/carriers = list() @@ -45,11 +48,6 @@ return FALSE return TRUE - -/datum/game_mode/monkey/announce() - to_chat(world, "The current game mode is - Monkey!") - to_chat(world, "One or more crewmembers have been infected with Jungle Fever! Crew: Contain the outbreak. None of the infected monkeys may escape alive to CentCom. Monkeys: Ensure that your kind lives on! Rise up against your captors!") - /datum/game_mode/monkey/post_setup() for(var/datum/mind/carriermind in carriers) var/datum/antagonist/monkey/M = add_monkey_leader(carriermind, monkey_team) diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm index 5b6b2778892..4b1cc2cd443 100644 --- a/code/game/gamemodes/nuclear/nuclear.dm +++ b/code/game/gamemodes/nuclear/nuclear.dm @@ -137,6 +137,7 @@ command_radio = TRUE /datum/outfit/syndicate/no_crystals + name = "Syndicate Operative - Reinforcement" tc = 0 /datum/outfit/syndicate/post_equip(mob/living/carbon/human/H) @@ -146,7 +147,7 @@ if(command_radio) R.command = TRUE - if(tc) + if(ispath(uplink_type, /obj/item/uplink/nuclear) || tc) // /obj/item/uplink/nuclear understands 0 tc var/obj/item/U = new uplink_type(H, H.key, tc) H.equip_to_slot_or_del(U, SLOT_IN_BACKPACK) diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm index 4f0c1df5a20..23924107fa9 100644 --- a/code/game/gamemodes/revolution/revolution.dm +++ b/code/game/gamemodes/revolution/revolution.dm @@ -14,12 +14,13 @@ antag_flag = ROLE_REV false_report_weight = 10 restricted_jobs = list("Security Officer", "Warden", "Detective", "AI", "Cyborg","Captain", "Head of Personnel", "Head of Security", "Chief Engineer", "Research Director", "Chief Medical Officer") + required_jobs = list(list("Captain"=1),list("Head of Personnel"=1),list("Head of Security"=1),list("Chief Engineer"=1),list("Research Director"=1),list("Chief Medical Officer"=1)) //Any head present required_players = 30 required_enemies = 2 recommended_enemies = 3 enemy_minimum_age = 14 - announce_span = "danger" + announce_span = "Revolution" announce_text = "Some crewmembers are attempting a coup!\n\ Revolutionaries: Expand your cause and overthrow the heads of staff by execution or otherwise.\n\ Crew: Prevent the revolutionaries from taking over the station." @@ -31,14 +32,6 @@ var/list/datum/mind/headrev_candidates = list() var/end_when_heads_dead = TRUE -/////////////////////////// -//Announces the game type// -/////////////////////////// -/datum/game_mode/revolution/announce() - to_chat(world, "The current game mode is - Revolution!") - to_chat(world, "Some crewmembers are attempting to start a revolution!
\nRevolutionaries - Kill the Captain, HoP, HoS, CE, RD and CMO. Convert other crewmembers (excluding the heads of staff, and security officers) to your cause by flashing them. Protect your leaders.
\nPersonnel - Protect the heads of staff. Kill the leaders of the revolution, and brainwash the other revolutionaries (by beating them in the head).
") - - /////////////////////////////////////////////////////////////////////////////// //Gets the round setup, cancelling if there's not enough players at the start// /////////////////////////////////////////////////////////////////////////////// diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 276992860db..d5b41a02371 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -142,6 +142,8 @@ ui.open() /obj/machinery/sleeper/AltClick(mob/user) + if(!user.canUseTopic(src, !issilicon(user))) + return if(state_open) close_machine() else diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index c537150ec59..ebe68f10e92 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -147,6 +147,10 @@ Class Procs: else STOP_PROCESSING(SSfastprocess, src) dropContents() + if(length(component_parts)) + for(var/atom/A in component_parts) + qdel(A) + component_parts.Cut() return ..() /obj/machinery/proc/locate_machinery() @@ -348,6 +352,7 @@ Class Procs: spawn_frame(disassembled) for(var/obj/item/I in component_parts) I.forceMove(loc) + component_parts.Cut() qdel(src) /obj/machinery/proc/spawn_frame(disassembled) diff --git a/code/game/machinery/aug_manipulator.dm b/code/game/machinery/aug_manipulator.dm index ce4aa0c5920..35aa8f7746f 100644 --- a/code/game/machinery/aug_manipulator.dm +++ b/code/game/machinery/aug_manipulator.dm @@ -130,7 +130,7 @@ /obj/machinery/aug_manipulator/AltClick(mob/living/user) ..() - if(!user.canUseTopic(src)) + if(!user.canUseTopic(src, !issilicon(user))) return else eject_part(user) diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm index b2324d0cae6..36393fb2e6b 100644 --- a/code/game/machinery/computer/apc_control.dm +++ b/code/game/machinery/computer/apc_control.dm @@ -90,7 +90,7 @@ /obj/machinery/computer/apc_control/Topic(href, href_list) if(..()) return - if(!usr || !usr.canUseTopic(src) || stat || QDELETED(src)) + if(!usr || !usr.canUseTopic(src, !issilicon(usr)) || stat || QDELETED(src)) return if(href_list["authenticate"]) var/obj/item/card/id/ID = usr.get_idcard(TRUE) @@ -139,7 +139,7 @@ if(href_list["name_filter"]) playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) var/new_filter = stripped_input(usr, "What name are you looking for?", name) - if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src)) + if(!src || !usr || !usr.canUseTopic(src, !issilicon(usr)) || stat || QDELETED(src)) return log_activity("changed name filter to \"[new_filter]\"") playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) @@ -147,7 +147,7 @@ if(href_list["above_filter"]) playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (greater than).", name) as null|num - if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src)) + if(!src || !usr || !usr.canUseTopic(src, !issilicon(usr)) || stat || QDELETED(src)) return log_activity("changed greater than charge filter to \"[new_filter]\"") if(new_filter) @@ -157,7 +157,7 @@ if(href_list["below_filter"]) playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (lesser than).", name) as null|num - if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src)) + if(!src || !usr || !usr.canUseTopic(src, !issilicon(usr)) || stat || QDELETED(src)) return log_activity("changed lesser than charge filter to \"[new_filter]\"") if(new_filter) diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index db2192789c4..22dd25037e7 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -52,7 +52,7 @@ /obj/machinery/computer/communications/Topic(href, href_list) if(..()) return - if(!usr.canUseTopic(src)) + if(!usr.canUseTopic(src, !issilicon(usr))) return if(!is_station_level(z) && !is_reserved_level(z)) //Can only use in transit and on SS13 to_chat(usr, "Unable to establish a connection: \black You're too far away from the station!") @@ -708,7 +708,7 @@ to_chat(user, "Intercomms recharging. Please stand by.") return var/input = stripped_input(user, "Please choose a message to announce to the station crew.", "What?") - if(!input || !user.canUseTopic(src)) + if(!input || !user.canUseTopic(src, !issilicon(usr))) return SScommunications.make_announcement(user, is_silicon, input) deadchat_broadcast("[user.real_name] made a priority announcement from [get_area_name(usr, TRUE)].", user) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index d65fb491610..5389a579961 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -583,7 +583,7 @@ if(user) if(message) if(authenticated) - if(user.canUseTopic(src)) + if(user.canUseTopic(src, BE_CLOSE)) if(!record1 || record1 == active1) if(!record2 || record2 == active2) return 1 diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 9d0ba743405..0335572ef0b 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -816,7 +816,7 @@ What a mess.*/ /obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2) if(user) if(authenticated) - if(user.canUseTopic(src)) + if(user.canUseTopic(src, BE_CLOSE)) if(!trim(message1)) return 0 if(!record1 || record1 == active1) @@ -825,7 +825,7 @@ What a mess.*/ return 0 /obj/machinery/computer/secure_data/AltClick(mob/user) - if(user.canUseTopic(src)) + if(user.canUseTopic(src, !issilicon(user))) eject_id(user) /obj/machinery/computer/secure_data/proc/eject_id(mob/user) diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm deleted file mode 100644 index 84b178f64c8..00000000000 --- a/code/game/machinery/computer/telecrystalconsoles.dm +++ /dev/null @@ -1,215 +0,0 @@ -#define NUKESCALINGMODIFIER 1 - -GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","Echo","Foxtrot","Zero", "Niner")) - -/obj/machinery/computer/telecrystals - name = "\improper telecrystal assignment station" - desc = "A device used to manage telecrystals during group operations. You shouldn't be looking at this particular one..." - icon_state = "tcstation" - icon_keyboard = "tcstation_key" - icon_screen = "syndie" - clockwork = TRUE //it'd look weird, at least if ratvar ever got there - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - - light_color = LIGHT_COLOR_RED - -///////////////////////////////////////////// -/obj/machinery/computer/telecrystals/uplinker - name = "\improper telecrystal upload/receive station" - desc = "A device used to manage telecrystals during group operations. To use, simply insert your uplink. With your uplink installed \ - you can upload your telecrystals to the group's pool using the console, or be assigned additional telecrystals by your lieutenant." - var/obj/item/uplinkholder = null - var/obj/machinery/computer/telecrystals/boss/linkedboss = null - -/obj/machinery/computer/telecrystals/uplinker/Initialize() - . = ..() - - var/ID = pick_n_take(GLOB.possible_uplinker_IDs) - if(!ID) - ID = rand(1,999) - name = "[name] [ID]" - -/obj/machinery/computer/telecrystals/uplinker/attackby(obj/item/I, mob/user, params) - if(uplinkholder) - to_chat(user, "[src] already has an uplink in it.") - return - GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I) - if(hidden_uplink) - if(!user.transferItemToLoc(I, src)) - return - uplinkholder = I - I.add_fingerprint(user) - update_icon() - updateUsrDialog() - else - to_chat(user, "[I] doesn't appear to be an uplink...") - -/obj/machinery/computer/telecrystals/uplinker/update_icon() - ..() - if(uplinkholder) - add_overlay("[initial(icon_state)]-closed") - -/obj/machinery/computer/telecrystals/uplinker/proc/ejectuplink() - if(uplinkholder) - uplinkholder.forceMove(drop_location()) - uplinkholder = null - update_icon() - -/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1) - if(uplinkholder && linkedboss) - GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder) - if(amt < 0) - linkedboss.storedcrystals += hidden_uplink.telecrystals - if(addLog) - linkedboss.logTransfer("[src] donated [hidden_uplink.telecrystals] telecrystals to [linkedboss].") - hidden_uplink.telecrystals = 0 - else if(amt <= hidden_uplink.telecrystals) - hidden_uplink.telecrystals -= amt - linkedboss.storedcrystals += amt - if(addLog) - linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].") - -/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1) - if(uplinkholder && linkedboss) - GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder) - if(amt < 0) - hidden_uplink.telecrystals += linkedboss.storedcrystals - if(addLog) - linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].") - linkedboss.storedcrystals = 0 - else if(amt <= linkedboss.storedcrystals) - hidden_uplink.telecrystals += amt - linkedboss.storedcrystals -= amt - if(addLog) - linkedboss.logTransfer("[src] received [amt] telecrystals from [linkedboss].") - -/////// - -/obj/machinery/computer/telecrystals/uplinker/ui_interact(mob/user) - . = ..() - var/dat = "" - if(linkedboss) - dat += "[linkedboss] has [linkedboss.storedcrystals] telecrystals available for distribution.

" - else - dat += "No linked management consoles detected. Scan for uplink stations using the management console.

" - - if(uplinkholder) - GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder) - dat += "[hidden_uplink.telecrystals] telecrystals remain in this uplink.
" - if(linkedboss) - dat += "Donate TC: 1 | 5 | All" - dat += "
Eject Uplink" - - - var/datum/browser/popup = new(user, "computer", "Telecrystal Upload/Receive Station", 700, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/telecrystals/uplinker/Topic(href, href_list) - if(..()) - return - - if(href_list["donate"]) - var/tcamt = text2num(href_list["donate"]) - donateTC(tcamt) - - if(href_list["eject"]) - ejectuplink() - - src.updateUsrDialog() - - -///////////////////////////////////////// -/obj/machinery/computer/telecrystals/boss - name = "team telecrystal management console" - desc = "A device used to manage telecrystals during group operations. To use, simply initialize the machine by scanning for nearby uplink stations. \ - Once the consoles are linked up, you can assign any telecrystals amongst your operatives; be they donated by your agents or rationed to the squad \ - based on the danger rating of the mission." - icon_state = "computer" - icon_screen = "tcboss" - icon_keyboard = "syndie_key" - var/virgin = 1 - var/scanrange = 10 - var/storedcrystals = 0 - var/list/TCstations = list() - var/list/transferlog = list() - -/obj/machinery/computer/telecrystals/boss/proc/logTransfer(logmessage) - transferlog += ("[station_time_timestamp()] [logmessage]") - -/obj/machinery/computer/telecrystals/boss/proc/scanUplinkers() - for(var/obj/machinery/computer/telecrystals/uplinker/A in urange(scanrange, src.loc)) - if(!A.linkedboss) - TCstations += A - A.linkedboss = src - if(virgin) - getDangerous() - virgin = 0 - -/obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population. - var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop) - var/danger = GLOB.joined_player_list.len - nukeops.len - danger = CEILING(danger, 10) - scaleTC(danger) - -/obj/machinery/computer/telecrystals/boss/proc/scaleTC(amt)//Its own proc, since it'll probably need a lot of tweaks for balance, use a fancier algorhithm, etc. - storedcrystals += amt * NUKESCALINGMODIFIER - -///////// - -/obj/machinery/computer/telecrystals/boss/ui_interact(mob/user) - . = ..() - var/dat = "" - dat += "Scan for TC stations.
" - dat += "[storedcrystals] telecrystals are available for distribution.
" - dat += "

" - - - for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations) - dat += "[A.name] | " - if(A.uplinkholder) - GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, A.uplinkholder) - dat += "[hidden_uplink.telecrystals] telecrystals." - if(storedcrystals) - dat+= "
Add TC: 1 | 5 | 10 | All" - dat += "
" - - if(TCstations.len && storedcrystals) - dat += "

Evenly distribute remaining TC.

" - - - for(var/entry in transferlog) - dat += "[entry]
" - - - var/datum/browser/popup = new(user, "computer", "Team Telecrystal Management Console", 700, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/telecrystals/boss/Topic(href, href_list) - if(..()) - return - - if(href_list["scan"]) - scanUplinkers() - - if(href_list["give"]) - var/tcamt = text2num(href_list["give"]) - if(TCstations.len) // sanity - var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations - A.giveTC(tcamt) - - if(href_list["distrib"]) - var/sanity = 0 - while(storedcrystals && sanity < 100) - for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations) - A.giveTC(1,0) - sanity++ - logTransfer("[src] evenly distributed telecrystals.") - - src.updateUsrDialog() - return - -#undef NUKESCALINGMODIFIER diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index 3fb0b04d8b7..4cee76a9ca5 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -5,11 +5,24 @@ GLOBAL_LIST_EMPTY(req_console_assistance) GLOBAL_LIST_EMPTY(req_console_supplies) GLOBAL_LIST_EMPTY(req_console_information) GLOBAL_LIST_EMPTY(allConsoles) +GLOBAL_LIST_EMPTY(req_console_ckey_departments) -#define NO_NEW_MESSAGE 0 -#define NORMAL_MESSAGE_PRIORITY 1 -#define HIGH_MESSAGE_PRIORITY 2 -#define EXTREME_MESSAGE_PRIORITY 3 // not implemented, will probably require some hacking... everything needs to have a hidden feature in this game. + +#define REQ_SCREEN_MAIN 0 +#define REQ_SCREEN_REQ_ASSISTANCE 1 +#define REQ_SCREEN_REQ_SUPPLIES 2 +#define REQ_SCREEN_RELAY 3 +#define REQ_SCREEN_WRITE 4 +#define REQ_SCREEN_CHOOSE 5 +#define REQ_SCREEN_SENT 6 +#define REQ_SCREEN_ERR 7 +#define REQ_SCREEN_VIEW_MSGS 8 +#define REQ_SCREEN_AUTHENTICATE 9 +#define REQ_SCREEN_ANNOUNCE 10 + +#define REQ_EMERGENCY_SECURITY 1 +#define REQ_EMERGENCY_ENGINEERING 2 +#define REQ_EMERGENCY_MEDICAL 3 /obj/machinery/requests_console name = "requests console" @@ -18,17 +31,17 @@ GLOBAL_LIST_EMPTY(allConsoles) icon_state = "req_comp0" var/department = "Unknown" //The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department var/list/messages = list() //List of all messages - var/departmentType = 0 + var/departmentType = 0 //bitflag // 0 = none (not listed, can only replied to) - // 1 = assistance - // 2 = supplies - // 3 = info - // 4 = ass + sup //Erro goddamn you just HAD to shorten "assistance" down to "ass" - // 5 = ass + info - // 6 = sup + info - // 7 = ass + sup + info - var/newmessagepriority = NO_NEW_MESSAGE - var/screen = 0 + // assistance = 1 + // supplies = 2 + // info = 4 + // assistance + supplies = 3 + // assistance + info = 5 + // supplies + info = 6 + // assistance + supplies + info = 7 + var/newmessagepriority = REQ_NO_NEW_MESSAGE + var/screen = REQ_SCREEN_MAIN // 0 = main menu, // 1 = req. assistance, // 2 = req. supplies @@ -47,9 +60,9 @@ GLOBAL_LIST_EMPTY(allConsoles) var/announceAuth = FALSE //Will be set to 1 when you authenticate yourself for announcements var/msgVerified = "" //Will contain the name of the person who verified it var/msgStamped = "" //If a message is stamped, this will contain the stamp name - var/message = ""; - var/dpt = ""; //the department which will be receiving the message - var/priority = -1 ; //Priority of the message being sent + var/message = "" + var/to_department = "" //the department which will be receiving the message + var/priority = REQ_NO_NEW_MESSAGE //Priority of the message being sent var/obj/item/radio/Radio var/emergency //If an emergency has been called by this device. Acts as both a cooldown and lets the responder know where it the emergency was triggered from var/receive_ore_updates = FALSE //If ore redemption machines will send an update when it receives new ores. @@ -74,11 +87,11 @@ GLOBAL_LIST_EMPTY(allConsoles) if(icon_state != "req_comp_off") icon_state = "req_comp_off" else - if(emergency || (newmessagepriority == EXTREME_MESSAGE_PRIORITY)) + if(emergency || (newmessagepriority == REQ_EXTREME_MESSAGE_PRIORITY)) icon_state = "req_comp3" - else if(newmessagepriority == HIGH_MESSAGE_PRIORITY) + else if(newmessagepriority == REQ_HIGH_MESSAGE_PRIORITY) icon_state = "req_comp2" - else if(newmessagepriority == NORMAL_MESSAGE_PRIORITY) + else if(newmessagepriority == REQ_NORMAL_MESSAGE_PRIORITY) icon_state = "req_comp1" else icon_state = "req_comp0" @@ -87,38 +100,19 @@ GLOBAL_LIST_EMPTY(allConsoles) . = ..() name = "\improper [department] requests console" GLOB.allConsoles += src - switch(departmentType) - if(1) - if(!("[department]" in GLOB.req_console_assistance)) - GLOB.req_console_assistance += department - if(2) - if(!("[department]" in GLOB.req_console_supplies)) - GLOB.req_console_supplies += department - if(3) - if(!("[department]" in GLOB.req_console_information)) - GLOB.req_console_information += department - if(4) - if(!("[department]" in GLOB.req_console_assistance)) - GLOB.req_console_assistance += department - if(!("[department]" in GLOB.req_console_supplies)) - GLOB.req_console_supplies += department - if(5) - if(!("[department]" in GLOB.req_console_assistance)) - GLOB.req_console_assistance += department - if(!("[department]" in GLOB.req_console_information)) - GLOB.req_console_information += department - if(6) - if(!("[department]" in GLOB.req_console_supplies)) - GLOB.req_console_supplies += department - if(!("[department]" in GLOB.req_console_information)) - GLOB.req_console_information += department - if(7) - if(!("[department]" in GLOB.req_console_assistance)) - GLOB.req_console_assistance += department - if(!("[department]" in GLOB.req_console_supplies)) - GLOB.req_console_supplies += department - if(!("[department]" in GLOB.req_console_information)) - GLOB.req_console_information += department + + if(departmentType) + + if((departmentType & REQ_DEP_TYPE_ASSISTANCE) && !(department in GLOB.req_console_assistance)) + GLOB.req_console_assistance += department + + if((departmentType & REQ_DEP_TYPE_SUPPLIES) && !(department in GLOB.req_console_supplies)) + GLOB.req_console_supplies += department + + if((departmentType & REQ_DEP_TYPE_INFORMATION) && !(department in GLOB.req_console_information)) + GLOB.req_console_information += department + + GLOB.req_console_ckey_departments[ckey(department)] = department Radio = new /obj/item/radio(src) Radio.listening = 0 @@ -133,83 +127,77 @@ GLOBAL_LIST_EMPTY(allConsoles) var/dat = "" if(!open) switch(screen) - if(1) //req. assistance + if(REQ_SCREEN_MAIN) + announceAuth = FALSE + if (newmessagepriority == REQ_NORMAL_MESSAGE_PRIORITY) + dat += "
There are new messages

" + else if (newmessagepriority == REQ_HIGH_MESSAGE_PRIORITY) + dat += "
There are new PRIORITY messages

" + else if (newmessagepriority == REQ_EXTREME_MESSAGE_PRIORITY) + dat += "
There are new EXTREME PRIORITY messages

" + dat += "View Messages

" + + dat += "Request Assistance
" + dat += "Request Supplies
" + dat += "Relay Anonymous Information

" + + if(!emergency) + dat += "Emergency: Security
" + dat += "Emergency: Engineering
" + dat += "Emergency: Medical

" + else + dat += "[emergency] has been dispatched to this location.

" + + if(announcementConsole) + dat += "Send Station-wide Announcement

" + if (silent) + dat += "Speaker OFF" + else + dat += "Speaker ON" + if(REQ_SCREEN_REQ_ASSISTANCE) dat += "Which department do you need assistance from?

" - dat += "
" - for(var/dpt in GLOB.req_console_assistance) - if (dpt != department) - dat += "" - dat += "" - dat += "" - dat += "" - dat += "
[dpt]Normal High" - if(hackState) - dat += "EXTREME" - dat += "
" - dat += "
<< Back
" + dat += departments_table(GLOB.req_console_assistance) - if(2) //req. supplies + if(REQ_SCREEN_REQ_SUPPLIES) dat += "Which department do you need supplies from?

" - dat += "" - for(var/dpt in GLOB.req_console_supplies) - if (dpt != department) - dat += "" - dat += "" - dat += "" - dat += "" - dat += "
[dpt]Normal High" - if(hackState) - dat += "EXTREME" - dat += "
" - dat += "
<< Back
" + dat += departments_table(GLOB.req_console_supplies) - if(3) //relay information + if(REQ_SCREEN_RELAY) dat += "Which department would you like to send information to?

" - dat += "" - for(var/dpt in GLOB.req_console_information) - if (dpt != department) - dat += "" - dat += "" - dat += "" - dat += "" - dat += "
[dpt]Normal High" - if(hackState) - dat += "EXTREME" - dat += "
" - dat += "
<< Back
" + dat += departments_table(GLOB.req_console_information) - if(6) //sent successfully + if(REQ_SCREEN_SENT) dat += "Message sent.

" - dat += "Continue
" + dat += "<< Back
" - if(7) //unsuccessful; not sent + if(REQ_SCREEN_ERR) dat += "An error occurred.

" - dat += "Continue
" + dat += "<< Back
" - if(8) //view messages + if(REQ_SCREEN_VIEW_MSGS) for (var/obj/machinery/requests_console/Console in GLOB.allConsoles) if (Console.department == department) - Console.newmessagepriority = NO_NEW_MESSAGE + Console.newmessagepriority = REQ_NO_NEW_MESSAGE Console.update_icon() - newmessagepriority = NO_NEW_MESSAGE + newmessagepriority = REQ_NO_NEW_MESSAGE update_icon() var/messageComposite = "" for(var/msg in messages) // This puts more recent messages at the *top*, where they belong. messageComposite = "
[msg]
" + messageComposite dat += messageComposite - dat += "
<< Back to Main Menu
" + dat += "
<< Back to Main Menu
" - if(9) //authentication before sending + if(REQ_SCREEN_AUTHENTICATE) dat += "Message Authentication

" - dat += "Message for [dpt]: [message]

" + dat += "Message for [to_department]: [message]

" dat += "
You may authenticate your message now by scanning your ID or your stamp

" dat += "Validated by: [msgVerified ? msgVerified : "Not Validated"]
" dat += "Stamped by: [msgStamped ? msgStamped : "Not Stamped"]

" - dat += "Send Message
" - dat += "
<< Discard Message
" + dat += "Send Message
" + dat += "
<< Discard Message
" - if(10) //send announcement + if(REQ_SCREEN_ANNOUNCE) dat += "

Station-wide Announcement

" if(announceAuth) dat += "
Authentication accepted

" @@ -221,42 +209,32 @@ GLOBAL_LIST_EMPTY(allConsoles) dat += "Announce Message
" else dat += "Announce Message
" - dat += "
<< Back
" + dat += "
<< Back
" - else //main menu - screen = 0 - announceAuth = FALSE - if (newmessagepriority == NORMAL_MESSAGE_PRIORITY) - dat += "
There are new messages

" - if (newmessagepriority == HIGH_MESSAGE_PRIORITY) - dat += "
There are new PRIORITY messages

" - if (newmessagepriority == EXTREME_MESSAGE_PRIORITY) - dat += "
There are new EXTREME PRIORITY messages

" - dat += "View Messages

" - - dat += "Request Assistance
" - dat += "Request Supplies
" - dat += "Relay Anonymous Information

" - - if(!emergency) - dat += "Emergency: Security
" - dat += "Emergency: Engineering
" - dat += "Emergency: Medical

" - else - dat += "[emergency] has been dispatched to this location.

" - - if(announcementConsole) - dat += "Send Station-wide Announcement

" - if (silent) - dat += "Speaker OFF" - else - dat += "Speaker ON" + if(!dat) + CRASH("No UI for src. Screen var is: [screen]") var/datum/browser/popup = new(user, "req_console", "[department] Requests Console", 450, 440) popup.set_content(dat) popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) popup.open() return +/obj/machinery/requests_console/proc/departments_table(list/req_consoles) + var/dat = "" + dat += "" + for(var/req_dpt in req_consoles) + if (req_dpt != department) + dat += "" + dat += "" + dat += "" + dat += "" + dat += "
[req_dpt]Normal High" + if(hackState) + dat += "EXTREME" + dat += "
" + dat += "
<< Back
" + return dat + /obj/machinery/requests_console/Topic(href, href_list) if(..()) return @@ -264,35 +242,24 @@ GLOBAL_LIST_EMPTY(allConsoles) add_fingerprint(usr) if(reject_bad_text(href_list["write"])) - dpt = ckey(href_list["write"]) //write contains the string of the receiving department's name + to_department = ckey(href_list["write"]) //write contains the string of the receiving department's name - var/new_message = copytext(reject_bad_text(input(usr, "Write your message:", "Awaiting Input", "")),1,MAX_MESSAGE_LEN) + var/new_message = (to_department in GLOB.req_console_ckey_departments) && copytext(reject_bad_text(input(usr, "Write your message:", "Awaiting Input", "")),1,MAX_MESSAGE_LEN) if(new_message) + to_department = GLOB.req_console_ckey_departments[to_department] message = new_message - screen = 9 - if (text2num(href_list["priority"]) < 2) - priority = -1 - else - priority = text2num(href_list["priority"]) - else - dpt = ""; - msgVerified = "" - msgStamped = "" - screen = 0 - priority = -1 + screen = REQ_SCREEN_AUTHENTICATE + priority = CLAMP(text2num(href_list["priority"]), REQ_NORMAL_MESSAGE_PRIORITY, REQ_EXTREME_MESSAGE_PRIORITY) if(href_list["writeAnnouncement"]) var/new_message = copytext(reject_bad_text(input(usr, "Write your message:", "Awaiting Input", "")),1,MAX_MESSAGE_LEN) if(new_message) message = new_message - if (text2num(href_list["priority"]) < 2) - priority = -1 - else - priority = text2num(href_list["priority"]) + priority = CLAMP(text2num(href_list["priority"]) || REQ_NORMAL_MESSAGE_PRIORITY, REQ_NORMAL_MESSAGE_PRIORITY, REQ_EXTREME_MESSAGE_PRIORITY) else message = "" announceAuth = FALSE - screen = 0 + screen = REQ_SCREEN_MAIN if(href_list["sendAnnouncement"]) if(!announcementConsole) @@ -306,136 +273,78 @@ GLOBAL_LIST_EMPTY(allConsoles) message_admins("[ADMIN_LOOKUPFLW(usr)] has made a station announcement from [src] at [AREACOORD(usr)].") announceAuth = FALSE message = "" - screen = 0 + screen = REQ_SCREEN_MAIN if(href_list["emergency"]) if(!emergency) var/radio_freq switch(text2num(href_list["emergency"])) - if(1) //Security + if(REQ_EMERGENCY_SECURITY) //Security radio_freq = FREQ_SECURITY emergency = "Security" - if(2) //Engineering + if(REQ_EMERGENCY_ENGINEERING) //Engineering radio_freq = FREQ_ENGINEERING emergency = "Engineering" - if(3) //Medical + if(REQ_EMERGENCY_MEDICAL) //Medical radio_freq = FREQ_MEDICAL emergency = "Medical" if(radio_freq) Radio.set_frequency(radio_freq) Radio.talk_into(src,"[emergency] emergency in [department]!!",radio_freq,get_spans(),get_default_language()) update_icon() - addtimer(CALLBACK(src, .proc/clear_emergency), 3000) + addtimer(CALLBACK(src, .proc/clear_emergency), 5 MINUTES) - if( href_list["department"] && message ) - var/log_msg = message - var/sending = message - sending += "
" - if (msgVerified) - sending += msgVerified - sending += "
" - if (msgStamped) - sending += msgStamped - sending += "
" - screen = 7 //if it's successful, this will get overrwritten (7 = unsufccessfull, 6 = successfull) - if (sending) - var/pass = FALSE - var/datum/data_rc_msg/log = new(href_list["department"], department, log_msg, msgStamped, msgVerified, priority) - for (var/obj/machinery/telecomms/message_server/MS in GLOB.telecomms_list) - if (MS.toggled) - MS.rc_msgs += log - pass = TRUE + if(href_list["send"] && message && to_department && priority) - if(pass) - var/radio_freq = 0 - switch(href_list["department"]) - if("bridge") - radio_freq = FREQ_COMMAND - if("medbay") - radio_freq = FREQ_MEDICAL - if("science") - radio_freq = FREQ_SCIENCE - if("engineering") - radio_freq = FREQ_ENGINEERING - if("security") - radio_freq = FREQ_SECURITY - if("cargobay" || "mining") - radio_freq = FREQ_SUPPLY - Radio.set_frequency(radio_freq) - var/authentic - if(msgVerified || msgStamped) - authentic = " (Authenticated)" + var/radio_freq + switch(ckey(to_department)) + if("bridge") + radio_freq = FREQ_COMMAND + if("medbay") + radio_freq = FREQ_MEDICAL + if("science") + radio_freq = FREQ_SCIENCE + if("engineering") + radio_freq = FREQ_ENGINEERING + if("security") + radio_freq = FREQ_SECURITY + if("cargobay" || "mining") + radio_freq = FREQ_SUPPLY - var/alert = "" - for (var/obj/machinery/requests_console/Console in GLOB.allConsoles) - if (ckey(Console.department) == ckey(href_list["department"])) - switch(priority) - if(2) //High priority - alert = "PRIORITY Alert in [department][authentic]" - Console.createmessage(src, alert, sending, 2, 1) - if(3) // Extreme Priority - alert = "EXTREME PRIORITY Alert from [department][authentic]" - Console.createmessage(src, alert , sending, 3, 1) - else // Normal priority - alert = "Message from [department][authentic]" - Console.createmessage(src, alert , sending, 1, 1) - screen = 6 - - if(radio_freq) - Radio.talk_into(src,"[alert]: [message]",radio_freq,get_spans(),get_default_language()) - - switch(priority) - if(2) - messages += "High Priority
To: [dpt]
[sending]" - else - messages += "To: [dpt]
[sending]" - else - say("NOTICE: No server detected!") + var/datum/signal/subspace/messaging/rc/signal = new(src, list( + "sender" = department, + "rec_dpt" = to_department, + "send_dpt" = department, + "message" = message, + "verified" = msgVerified, + "stamped" = msgStamped, + "priority" = priority, + "notify_freq" = radio_freq + )) + signal.send_to_receivers() + screen = signal.data["done"] ? REQ_SCREEN_SENT : REQ_SCREEN_ERR //Handle screen switching - switch(text2num(href_list["setScreen"])) - if(null) //skip - if(1) //req. assistance - screen = 1 - if(2) //req. supplies - screen = 2 - if(3) //relay information - screen = 3 -// if(4) //write message -// screen = 4 - if(5) //choose priority - screen = 5 - if(6) //sent successfully - screen = 6 - if(7) //unsuccessfull; not sent - screen = 7 - if(8) //view messages - screen = 8 - if(9) //authentication - screen = 9 - if(10) //send announcement - if(!announcementConsole) - return - screen = 10 - else //main menu - dpt = "" - msgVerified = "" - msgStamped = "" - message = "" - priority = -1 - screen = 0 + if(href_list["setScreen"]) + var/set_screen = CLAMP(text2num(href_list["setScreen"]) || 0, REQ_SCREEN_MAIN, REQ_SCREEN_ANNOUNCE) + switch(set_screen) + if(REQ_SCREEN_MAIN) + to_department = "" + msgVerified = "" + msgStamped = "" + message = "" + priority = -1 + if(REQ_SCREEN_ANNOUNCE) + if(!announcementConsole) + return + screen = set_screen //Handle silencing the console - switch( href_list["setSilent"] ) - if(null) //skip - if("1") - silent = TRUE - else - silent = FALSE + if(href_list["setSilent"]) + silent = text2num(href_list["setSilent"]) ? TRUE : FALSE updateUsrDialog() - return /obj/machinery/requests_console/say_mod(input, message_mode) var/ending = copytext(input, length(input) - 2) @@ -448,42 +357,53 @@ GLOBAL_LIST_EMPTY(allConsoles) emergency = null update_icon() -/obj/machinery/requests_console/proc/createmessage(source, title, message, priority) +//from message_server.dm: Console.createmessage(data["sender"], data["send_dpt"], data["message"], data["verified"], data["stamped"], data["priority"], data["notify_freq"]) +/obj/machinery/requests_console/proc/createmessage(source, source_department, message, msgVerified, msgStamped, priority, radio_freq) var/linkedsender - if(istype(source, /obj/machinery/requests_console)) - var/obj/machinery/requests_console/sender = source - linkedsender = "[sender.department]" - else - capitalize(source) - linkedsender = source - capitalize(title) + + var/sending = "[message]
" + if(msgVerified) + sending = "[sending][msgVerified]
" + if(msgStamped) + sending = "[sending][msgStamped]
" + + linkedsender = source_department ? "[source_department]" : (source || "unknown") + + var/authentic = (msgVerified || msgStamped) && " (Authenticated)" + var/alert = "Message from [source][authentic]" + var/silenced = silent + var/header = "From: [linkedsender] Received: [station_time_timestamp()]
" + switch(priority) - if(2) //High priority - if(newmessagepriority < HIGH_MESSAGE_PRIORITY) - newmessagepriority = HIGH_MESSAGE_PRIORITY + if(REQ_NORMAL_MESSAGE_PRIORITY) + if(newmessagepriority < REQ_NORMAL_MESSAGE_PRIORITY) + newmessagepriority = REQ_NORMAL_MESSAGE_PRIORITY update_icon() - if(!silent) - playsound(src, 'sound/machines/twobeep_high.ogg', 50, 1) - say(title) - messages += "High Priority
From: [linkedsender]
[message]" - if(3) // Extreme Priority - if(newmessagepriority < EXTREME_MESSAGE_PRIORITY) - newmessagepriority = EXTREME_MESSAGE_PRIORITY + if(REQ_HIGH_MESSAGE_PRIORITY) + header = "High Priority
[header]" + alert = "PRIORITY Alert from [source][authentic]" + if(newmessagepriority < REQ_HIGH_MESSAGE_PRIORITY) + newmessagepriority = REQ_HIGH_MESSAGE_PRIORITY update_icon() - if(1) - playsound(src, 'sound/machines/twobeep_high.ogg', 50, 1) - say(title) - messages += "!!!Extreme Priority!!!
From: [linkedsender]
[message]" - else // Normal priority - if(newmessagepriority < NORMAL_MESSAGE_PRIORITY) - newmessagepriority = NORMAL_MESSAGE_PRIORITY + if(REQ_EXTREME_MESSAGE_PRIORITY) + header = "!!!Extreme Priority!!!
[header]" + alert = "EXTREME PRIORITY Alert from [source][authentic]" + silenced = FALSE + if(newmessagepriority < REQ_EXTREME_MESSAGE_PRIORITY) + newmessagepriority = REQ_EXTREME_MESSAGE_PRIORITY update_icon() - if(!src.silent) - playsound(src, 'sound/machines/twobeep_high.ogg', 50, 1) - say(title) - messages += "From: [linkedsender]
[message]" + + messages += "[header][sending]" + + if(!silenced) + playsound(src, 'sound/machines/twobeep_high.ogg', 50, 1) + say(alert) + + if(radio_freq) + Radio.set_frequency(radio_freq) + Radio.talk_into(src, "[alert]: [message]", radio_freq, get_spans(), get_default_language()) /obj/machinery/requests_console/attackby(obj/item/O, mob/user, params) if(O.tool_behaviour == TOOL_CROWBAR) @@ -509,10 +429,10 @@ GLOBAL_LIST_EMPTY(allConsoles) var/obj/item/card/id/ID = O.GetID() if(ID) - if(screen == 9) + if(screen == REQ_SCREEN_AUTHENTICATE) msgVerified = "Verified by [ID.registered_name] ([ID.assignment])" updateUsrDialog() - if(screen == 10) + if(screen == REQ_SCREEN_ANNOUNCE) if (ACCESS_RC_ANNOUNCE in ID.access) announceAuth = TRUE else @@ -521,14 +441,25 @@ GLOBAL_LIST_EMPTY(allConsoles) updateUsrDialog() return if (istype(O, /obj/item/stamp)) - if(screen == 9) + if(screen == REQ_SCREEN_AUTHENTICATE) var/obj/item/stamp/T = O msgStamped = "Stamped with the [T.name]" updateUsrDialog() return return ..() -#undef NO_NEW_MESSAGE -#undef NORMAL_MESSAGE_PRIORITY -#undef HIGH_MESSAGE_PRIORITY -#undef EXTREME_MESSAGE_PRIORITY +#undef REQ_EMERGENCY_SECURITY +#undef REQ_EMERGENCY_ENGINEERING +#undef REQ_EMERGENCY_MEDICAL + +#undef REQ_SCREEN_MAIN +#undef REQ_SCREEN_REQ_ASSISTANCE +#undef REQ_SCREEN_REQ_SUPPLIES +#undef REQ_SCREEN_RELAY +#undef REQ_SCREEN_WRITE +#undef REQ_SCREEN_CHOOSE +#undef REQ_SCREEN_SENT +#undef REQ_SCREEN_ERR +#undef REQ_SCREEN_VIEW_MSGS +#undef REQ_SCREEN_AUTHENTICATE +#undef REQ_SCREEN_ANNOUNCE diff --git a/code/game/machinery/stasis.dm b/code/game/machinery/stasis.dm index 5f7f0263dbb..2069b012001 100644 --- a/code/game/machinery/stasis.dm +++ b/code/game/machinery/stasis.dm @@ -34,7 +34,7 @@ last_stasis_sound = _running /obj/machinery/stasis/AltClick(mob/user) - if(world.time >= stasis_can_toggle && user.canUseTopic(src)) + if(world.time >= stasis_can_toggle && user.canUseTopic(src, !issilicon(user))) stasis_enabled = !stasis_enabled stasis_can_toggle = world.time + STASIS_TOGGLE_COOLDOWN playsound(src, 'sound/machines/click.ogg', 60, TRUE) @@ -44,7 +44,7 @@ /obj/machinery/stasis/Exited(atom/movable/AM, atom/newloc) if(AM == occupant) var/mob/living/L = AM - if(L.IsInStasis()) + if(IS_IN_STASIS(L)) thaw_them(L) . = ..() @@ -95,12 +95,12 @@ return var/freq = rand(24750, 26550) playsound(src, 'sound/effects/spray.ogg', 5, TRUE, 2, frequency = freq) - target.SetStasis(TRUE) + target.apply_status_effect(STATUS_EFFECT_STASIS, null, TRUE) target.ExtinguishMob() use_power = ACTIVE_POWER_USE /obj/machinery/stasis/proc/thaw_them(mob/living/target) - target.SetStasis(FALSE) + target.remove_status_effect(STATUS_EFFECT_STASIS) if(target == occupant) use_power = IDLE_POWER_USE @@ -124,9 +124,9 @@ return var/mob/living/L_occupant = occupant if(stasis_running()) - if(!L_occupant.IsInStasis()) + if(!IS_IN_STASIS(L_occupant)) chill_out(L_occupant) - else if(L_occupant.IsInStasis()) + else if(IS_IN_STASIS(L_occupant)) thaw_them(L_occupant) /obj/machinery/stasis/screwdriver_act(mob/living/user, obj/item/I) @@ -138,4 +138,10 @@ /obj/machinery/stasis/nap_violation(mob/violator) unbuckle_mob(violator, TRUE) + +/obj/machinery/stasis/attack_robot(mob/user) + if(Adjacent(user) && occupant) + unbuckle_mob(occupant) + else + ..() #undef STASIS_TOGGLE_COOLDOWN diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index 50569a17979..5e4e2bdc59e 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -11,6 +11,7 @@ density = FALSE layer = BELOW_MOB_LAYER //so people can't hide it and it's REALLY OBVIOUS resistance_flags = FIRE_PROOF | ACID_PROOF + speed_process = TRUE interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_OFFLINE @@ -22,7 +23,6 @@ var/open_panel = FALSE //are the wires exposed? var/active = FALSE //is the bomb counting down? - var/defused = FALSE //is the bomb capable of exploding? var/obj/item/bombcore/payload = /obj/item/bombcore var/beepsound = 'sound/items/timer.ogg' var/delayedbig = FALSE //delay wire pulsed? @@ -34,7 +34,7 @@ var/explode_now = FALSE /obj/machinery/syndicatebomb/proc/try_detonate(ignore_active = FALSE) - . = (payload in src) && (active || ignore_active) && !defused + . = (payload in src) && (active || ignore_active) if(.) payload.detonate() @@ -52,6 +52,8 @@ detonation_timer = null next_beep = null countdown.stop() + if(payload in src) + payload.defuse() return if(!isnull(next_beep) && (next_beep <= world.time)) @@ -72,17 +74,11 @@ playsound(loc, beepsound, volume, 0) next_beep = world.time + 10 - if(active && !defused && ((detonation_timer <= world.time) || explode_now)) + if(active && ((detonation_timer <= world.time) || explode_now)) active = FALSE timer_set = initial(timer_set) update_icon() try_detonate(TRUE) - //Counter terrorists win - else if(!active || defused) - if(defused && payload in src) - payload.defuse() - countdown.stop() - STOP_PROCESSING(SSfastprocess, src) /obj/machinery/syndicatebomb/Initialize() . = ..() @@ -91,6 +87,7 @@ payload = new payload(src) update_icon() countdown = new(src) + STOP_PROCESSING(SSfastprocess, src) /obj/machinery/syndicatebomb/Destroy() QDEL_NULL(wires) @@ -173,7 +170,7 @@ else var/old_integ = obj_integrity . = ..() - if((old_integ > obj_integrity) && active && !defused && (payload in src)) + if((old_integ > obj_integrity) && active && (payload in src)) to_chat(user, "That seems like a really bad idea...") /obj/machinery/syndicatebomb/interact(mob/user) @@ -199,11 +196,7 @@ timer_set = CLAMP(new_timer, minimum_timer, maximum_timer) loc.visible_message("[icon2html(src, viewers(src))] timer set for [timer_set] seconds.") if(alert(user,"Would you like to start the countdown now?",,"Yes","No") == "Yes" && in_range(src, user) && isliving(user)) - if(defused || active) - if(defused) - visible_message("[icon2html(src, viewers(src))] Device error: User intervention required.") - return - else + if(!active) visible_message("[icon2html(src, viewers(loc))] [timer_set] seconds until detonation, please clear the area.") activate() update_icon() @@ -287,8 +280,7 @@ qdel(src) /obj/item/bombcore/proc/defuse() -//Note: Because of how var/defused is used you shouldn't override this UNLESS you intend to set the var to 0 or -// otherwise remove the core/reset the wires before the end of defuse(). It will repeatedly be called otherwise. +//Note: the machine's defusal is mostly done from the wires code, this is here if you want the core itself to do anything. ///Bomb Core Subtypes/// @@ -304,12 +296,12 @@ if(holder.wires) holder.wires.repair() holder.wires.shuffle_wires() - holder.defused = 0 - holder.open_panel = 0 holder.delayedbig = FALSE holder.delayedlittle = FALSE + holder.explode_now = FALSE holder.update_icon() holder.updateDialog() + STOP_PROCESSING(SSfastprocess, holder) /obj/item/bombcore/training/detonate() var/obj/machinery/syndicatebomb/holder = loc diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm index b1daa1eb85b..2070a69e386 100644 --- a/code/game/machinery/telecomms/computers/message.dm +++ b/code/game/machinery/telecomms/computers/message.dm @@ -5,6 +5,12 @@ #define LINKED_SERVER_NONRESPONSIVE (!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) +#define MSG_MON_SCREEN_MAIN 0 +#define MSG_MON_SCREEN_LOGS 1 +#define MSG_MON_SCREEN_HACKED 2 +#define MSG_MON_SCREEN_CUSTOM_MSG 3 +#define MSG_MON_SCREEN_REQUEST_LOGS 4 + // The monitor itself. /obj/machinery/computer/message_monitor name = "message monitor console" @@ -21,7 +27,7 @@ var/defaultmsg = "Welcome. Please select an option." 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/screen = MSG_MON_SCREEN_MAIN // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message var/hacking = FALSE // Is it being hacked into by the AI/Cyborg var/message = "System bootup complete. Please select an option." // The message that shows on the main menu. var/auth = FALSE // Are they authenticated? @@ -46,7 +52,7 @@ return if(!isnull(linkedServer)) obj_flags |= EMAGGED - screen = 2 + screen = MSG_MON_SCREEN_HACKED spark_system.set_up(5, 0, src) spark_system.start() var/obj/item/paper/monitorkey/MK = new(loc, linkedServer) @@ -86,21 +92,21 @@ if(auth) dat += "

\[Authenticated\] /" - dat += " Server Power: [linkedServer && linkedServer.toggled ? "\[On\]":"\[Off\]"]

" + dat += " Server Power: [linkedServer && linkedServer.on ? "\[On\]":"\[Off\]"]" else dat += "

\[Unauthenticated\] /" - dat += " Server Power: [linkedServer && linkedServer.toggled ? "\[On\]":"\[Off\]"]

" + dat += " Server Power: [linkedServer && linkedServer.on ? "\[On\]":"\[Off\]"]" if(hacking || (obj_flags & EMAGGED)) - screen = 2 + screen = MSG_MON_SCREEN_HACKED else if(!auth || LINKED_SERVER_NONRESPONSIVE) if(LINKED_SERVER_NONRESPONSIVE) message = noserver - screen = 0 + screen = MSG_MON_SCREEN_MAIN switch(screen) //Main menu - if(0) + if(MSG_MON_SCREEN_MAIN) // = TAB var/i = 0 dat += "
[++i]. Link To A Server
" @@ -131,7 +137,7 @@ dat += "

Reg, #514 forbids sending messages to a Head of Staff containing Erotic Rendering Properties." //Message Logs - if(1) + if(MSG_MON_SCREEN_LOGS) var/index = 0 dat += "
Back - Refresh

" dat += "" @@ -144,7 +150,7 @@ dat += "" dat += "
XSenderRecipientMessage
X
[pda.sender][pda.recipient][pda.message][pda.picture ? " (Photo)":""]
" //Hacking screen. - if(2) + if(MSG_MON_SCREEN_HACKED) if(isAI(user) || iscyborg(user)) dat += "Brute-forcing for server key.
It will take 20 seconds for every character that the password has." dat += "In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time." @@ -187,7 +193,7 @@ 001101001011011010110010100101110"} //Fake messages - if(3) + if(MSG_MON_SCREEN_CUSTOM_MSG) dat += "
Back - Reset

" dat += {" @@ -205,7 +211,7 @@ dat += "

Send" //Request Console Logs - if(4) + if(MSG_MON_SCREEN_REQUEST_LOGS) var/index = 0 /* data_rc_msg @@ -243,7 +249,7 @@ var/currentKey = linkedServer.decryptkey to_chat(user, "Brute-force completed! The key is '[currentKey]'.") hacking = FALSE - screen = 0 // Return the screen back to normal + screen = MSG_MON_SCREEN_MAIN // Return the screen back to normal /obj/machinery/computer/message_monitor/proc/UnmagConsole() obj_flags &= ~EMAGGED @@ -265,7 +271,7 @@ message = noserver else if(auth) auth = FALSE - screen = 0 + screen = MSG_MON_SCREEN_MAIN else var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null) if(dkey && dkey != "") @@ -300,7 +306,7 @@ if(LINKED_SERVER_NONRESPONSIVE) message = noserver else if(auth) - screen = 1 + screen = MSG_MON_SCREEN_LOGS //Clears the logs - KEY REQUIRED if (href_list["clear_logs"]) @@ -340,7 +346,7 @@ var/mob/living/silicon/S = usr if(istype(S) && S.hack_software) hacking = TRUE - screen = 2 + screen = MSG_MON_SCREEN_HACKED //Time it takes to bruteforce is dependant on the password length. spawn(100*length(linkedServer.decryptkey)) if(src && linkedServer && usr) @@ -348,7 +354,7 @@ //Delete the log. if (href_list["delete_logs"]) //Are they on the view logs screen? - if(screen == 1) + if(screen == MSG_MON_SCREEN_LOGS) if(LINKED_SERVER_NONRESPONSIVE) message = noserver else //if(istype(href_list["delete_logs"], /datum/data_pda_msg)) @@ -357,7 +363,7 @@ //Delete the request console log. if (href_list["delete_requests"]) //Are they on the view logs screen? - if(screen == 4) + if(screen == MSG_MON_SCREEN_REQUEST_LOGS) if(LINKED_SERVER_NONRESPONSIVE) message = noserver else //if(istype(href_list["delete_logs"], /datum/data_pda_msg)) @@ -368,12 +374,12 @@ if(LINKED_SERVER_NONRESPONSIVE) message = noserver else if(auth) - screen = 3 + screen = MSG_MON_SCREEN_CUSTOM_MSG //Fake messaging selection - KEY REQUIRED if (href_list["select"]) if(LINKED_SERVER_NONRESPONSIVE) message = noserver - screen = 0 + screen = MSG_MON_SCREEN_MAIN else switch(href_list["select"]) @@ -415,7 +421,7 @@ message = "NOTICE: No message entered!" return attack_hand(usr) - var/datum/signal/subspace/pda/signal = new(src, list( + var/datum/signal/subspace/messaging/pda/signal = new(src, list( "name" = "[customsender]", "job" = "[customjob]", "message" = custommessage, @@ -431,13 +437,19 @@ if(LINKED_SERVER_NONRESPONSIVE) message = noserver else if(auth) - screen = 4 + screen = MSG_MON_SCREEN_REQUEST_LOGS if (href_list["back"]) - screen = 0 + screen = MSG_MON_SCREEN_MAIN return attack_hand(usr) +#undef MSG_MON_SCREEN_MAIN +#undef MSG_MON_SCREEN_LOGS +#undef MSG_MON_SCREEN_HACKED +#undef MSG_MON_SCREEN_CUSTOM_MSG +#undef MSG_MON_SCREEN_REQUEST_LOGS + #undef LINKED_SERVER_NONRESPONSIVE /obj/item/paper/monitorkey @@ -457,7 +469,7 @@ add_overlay("paper_words") /obj/item/paper/monitorkey/LateInitialize() - for (var/obj/machinery/telecomms/message_server/server in GLOB.telecomms_list) + for (var/obj/machinery/telecomms/message_server/preset/server in GLOB.telecomms_list) if (server.decryptkey) print(server) break diff --git a/code/game/machinery/telecomms/machines/bus.dm b/code/game/machinery/telecomms/machines/bus.dm index 8638d22450d..9b73692b626 100644 --- a/code/game/machinery/telecomms/machines/bus.dm +++ b/code/game/machinery/telecomms/machines/bus.dm @@ -69,7 +69,7 @@ id = "Bus 4" network = "tcommsat" freq_listening = list(FREQ_ENGINEERING) - autolinkers = list("processor4", "engineering", "common") + autolinkers = list("processor4", "engineering", "common", "messaging") /obj/machinery/telecomms/bus/preset_four/Initialize() . = ..() @@ -78,5 +78,5 @@ /obj/machinery/telecomms/bus/preset_one/birdstation name = "Bus" - autolinkers = list("processor1", "common") + autolinkers = list("processor1", "common", "messaging") freq_listening = list() diff --git a/code/game/machinery/telecomms/machines/hub.dm b/code/game/machinery/telecomms/machines/hub.dm index e7e37887745..dedf7c7f3a7 100644 --- a/code/game/machinery/telecomms/machines/hub.dm +++ b/code/game/machinery/telecomms/machines/hub.dm @@ -39,5 +39,5 @@ network = "tcommsat" autolinkers = list("hub", "relay", "s_relay", "m_relay", "r_relay", "h_relay", "science", "medical", "supply", "service", "common", "command", "engineering", "security", - "receiverA", "receiverB", "broadcasterA", "broadcasterB", "autorelay") + "receiverA", "receiverB", "broadcasterA", "broadcasterB", "autorelay", "messaging") diff --git a/code/game/machinery/telecomms/machines/message_server.dm b/code/game/machinery/telecomms/machines/message_server.dm index cc390e1fc04..9b6d2430f1c 100644 --- a/code/game/machinery/telecomms/machines/message_server.dm +++ b/code/game/machinery/telecomms/machines/message_server.dm @@ -17,30 +17,35 @@ armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70) +#define MESSAGE_SERVER_FUNCTIONING_MESSAGE "This is an automated message. The messaging system is functioning correctly." + // The message server itself. /obj/machinery/telecomms/message_server - icon = 'icons/obj/machines/research.dmi' - icon_state = "server" + icon_state = "message_server" name = "Messaging Server" - desc = "A machine that attempts to gather the secret knowledge of the universe." + desc = "A machine that processes and routes PDA and request console messages." density = TRUE use_power = IDLE_POWER_USE idle_power_usage = 10 active_power_usage = 100 - - id = "Messaging Server" - network = "tcommsat" - autolinkers = list("common") + circuit = /obj/item/circuitboard/machine/telecomms/message_server var/list/datum/data_pda_msg/pda_msgs = list() var/list/datum/data_rc_msg/rc_msgs = list() - var/decryptkey + var/decryptkey = "password" + var/calibrating = 15 MINUTES //Init reads this and adds world.time, then becomes 0 when that time has passed and the machine works -/obj/machinery/telecomms/message_server/Initialize() +/obj/machinery/telecomms/message_server/Initialize(mapload) . = ..() if (!decryptkey) decryptkey = GenerateKey() - pda_msgs += new /datum/data_pda_msg("System Administrator", "system", "This is an automated message. The messaging system is functioning correctly.") + + if (calibrating) + calibrating += world.time + say("Calibrating... Estimated wait time: [rand(3, 9)] minutes.") + pda_msgs += new /datum/data_pda_msg("System Administrator", "system", "This is an automated message. System calibration started at [station_time_timestamp()]") + else + pda_msgs += new /datum/data_pda_msg("System Administrator", "system", MESSAGE_SERVER_FUNCTIONING_MESSAGE) /obj/machinery/telecomms/message_server/Destroy() for(var/obj/machinery/computer/message_monitor/monitor in GLOB.telecomms_list) @@ -48,6 +53,11 @@ monitor.linkedServer = null . = ..() +/obj/machinery/telecomms/message_server/examine(mob/user) + ..() + if(calibrating) + to_chat(user, "It's still calibrating.") + /obj/machinery/telecomms/message_server/proc/GenerateKey() var/newKey newKey += pick("the", "if", "of", "as", "in", "a", "you", "from", "to", "an", "too", "little", "snow", "dead", "drunk", "rosebud", "duck", "al", "le") @@ -56,68 +66,86 @@ return newKey /obj/machinery/telecomms/message_server/process() - if(toggled && (stat & (BROKEN|NOPOWER))) - toggled = FALSE - update_icon() + . = ..() + if(calibrating && calibrating <= world.time) + calibrating = 0 + pda_msgs += new /datum/data_pda_msg("System Administrator", "system", MESSAGE_SERVER_FUNCTIONING_MESSAGE) -/obj/machinery/telecomms/message_server/receive_information(datum/signal/subspace/pda/signal, obj/machinery/telecomms/machine_from) - // can't log non-PDA signals - if(!istype(signal) || !signal.data["message"] || !toggled) +/obj/machinery/telecomms/message_server/receive_information(datum/signal/subspace/messaging/signal, obj/machinery/telecomms/machine_from) + // can't log non-message signals + if(!istype(signal) || !signal.data["message"] || !on || calibrating) return // log the signal - var/datum/data_pda_msg/M = new(signal.format_target(), "[signal.data["name"]] ([signal.data["job"]])", signal.data["message"], signal.data["photo"]) - pda_msgs += M - signal.logged = M + if(istype(signal, /datum/signal/subspace/messaging/pda)) + var/datum/signal/subspace/messaging/pda/PDAsignal = signal + var/datum/data_pda_msg/M = new(PDAsignal.format_target(), "[PDAsignal.data["name"]] ([PDAsignal.data["job"]])", PDAsignal.data["message"], PDAsignal.data["photo"]) + pda_msgs += M + signal.logged = M + else if(istype(signal, /datum/signal/subspace/messaging/rc)) + var/datum/data_rc_msg/M = new(signal.data["rec_dpt"], signal.data["send_dpt"], signal.data["message"], signal.data["stamped"], signal.data["verified"], signal.data["priority"]) + signal.logged = M + if(signal.data["send_dpt"]) // don't log messages not from a department but allow them to work + rc_msgs += M + signal.data["reject"] = FALSE // pass it along to either the hub or the broadcaster if(!relay_information(signal, /obj/machinery/telecomms/hub)) relay_information(signal, /obj/machinery/telecomms/broadcaster) /obj/machinery/telecomms/message_server/update_icon() - if((stat & (BROKEN|NOPOWER))) - icon_state = "server-nopower" - else if (!toggled) - icon_state = "server-off" - else - icon_state = "server-on" + ..() + cut_overlays() + if(calibrating) + add_overlay("message_server_calibrate") -// PDA signal datum -/datum/signal/subspace/pda +// Root messaging signal datum +/datum/signal/subspace/messaging frequency = FREQ_COMMON server_type = /obj/machinery/telecomms/message_server - var/datum/data_pda_msg/logged + var/datum/logged -/datum/signal/subspace/pda/New(source, data) - src.source = source - src.data = data +/datum/signal/subspace/messaging/New(init_source, init_data) + source = init_source + data = init_data var/turf/T = get_turf(source) levels = list(T.z) + if(!("reject" in data)) + data["reject"] = TRUE -/datum/signal/subspace/pda/copy() - var/datum/signal/subspace/pda/copy = new(source, data.Copy()) +/datum/signal/subspace/messaging/copy() + var/datum/signal/subspace/messaging/copy = new type(source, data.Copy()) copy.original = src copy.levels = levels return copy -/datum/signal/subspace/pda/proc/format_target() +// PDA signal datum +/datum/signal/subspace/messaging/pda/proc/format_target() if (length(data["targets"]) > 1) return "Everyone" return data["targets"][1] -/datum/signal/subspace/pda/proc/format_message() +/datum/signal/subspace/messaging/pda/proc/format_message() if (logged && data["photo"]) return "\"[data["message"]]\" (Photo)" return "\"[data["message"]]\"" -/datum/signal/subspace/pda/broadcast() +/datum/signal/subspace/messaging/pda/broadcast() if (!logged) // Can only go through if a message server logs it return for (var/obj/item/pda/P in GLOB.PDAs) if ("[P.owner] ([P.ownjob])" in data["targets"]) P.receive_message(src) +// Request Console signal datum +/datum/signal/subspace/messaging/rc/broadcast() + if (!logged) // Like /pda, only if logged + return + var/rec_dpt = ckey(data["rec_dpt"]) + for (var/obj/machinery/requests_console/Console in GLOB.allConsoles) + if(ckey(Console.department) == rec_dpt || (data["ore_update"] && Console.receive_ore_updates)) + Console.createmessage(data["sender"], data["send_dpt"], data["message"], data["verified"], data["stamped"], data["priority"], data["notify_freq"]) // Log datums stored by the message server. /datum/data_pda_msg @@ -168,12 +196,20 @@ id_auth = param_id_auth if(param_priority) switch(param_priority) - if(1) + if(REQ_NORMAL_MESSAGE_PRIORITY) priority = "Normal" - if(2) + if(REQ_HIGH_MESSAGE_PRIORITY) priority = "High" - if(3) + if(REQ_EXTREME_MESSAGE_PRIORITY) priority = "Extreme" else priority = "Undetermined" +#undef MESSAGE_SERVER_FUNCTIONING_MESSAGE + +/obj/machinery/telecomms/message_server/preset + id = "Messaging Server" + network = "tcommsat" + autolinkers = list("messaging") + decryptkey = null //random + calibrating = 0 diff --git a/code/game/machinery/telecomms/telecomunications.dm b/code/game/machinery/telecomms/telecomunications.dm index bb514b761b5..2395dcc9562 100644 --- a/code/game/machinery/telecomms/telecomunications.dm +++ b/code/game/machinery/telecomms/telecomunications.dm @@ -145,9 +145,10 @@ GLOBAL_LIST_EMPTY(telecomms_list) . = ..() if(. & EMP_PROTECT_SELF) return - 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 + if(prob(100/severity) && !(stat & EMPED)) + stat |= EMPED + var/duration = (300 * 10)/severity + addtimer(CALLBACK(src, .proc/de_emp), rand(duration - 20, duration + 20)) + +/obj/machinery/telecomms/proc/de_emp() + stat &= ~EMPED diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index a44a643e967..ebfc2f506f9 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -19,7 +19,7 @@ to_chat(user, "Alt-click it to start a wash cycle.") /obj/machinery/washing_machine/AltClick(mob/user) - if(!user.canUseTopic(src)) + if(!user.canUseTopic(src, !issilicon(user))) return if(busy) diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index ea3b2d8b777..21db291f39e 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -108,15 +108,17 @@ /obj/item/mecha_parts/mecha_equipment/medical/sleeper/Topic(href,href_list) ..() - var/datum/topic_input/afilter = new /datum/topic_input(href,href_list) - if(afilter.get("eject")) + if(href_list["eject"]) go_out() - if(afilter.get("view_stats")) + if(href_list["view_stats"]) chassis.occupant << browse(get_patient_stats(),"window=msleeper") onclose(chassis.occupant, "msleeper") return - if(afilter.get("inject")) - inject_reagent(afilter.getType("inject", /datum/reagent),afilter.getObj("source")) + if(href_list["inject"]) + var/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/SG = locate() in chassis + var/datum/reagent/R = locate(href_list["inject"]) in SG.reagents.reagent_list + if (istype(R)) + inject_reagent(R, SG) return /obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/get_patient_stats() @@ -183,7 +185,7 @@ if(SG && SG.reagents && islist(SG.reagents.reagent_list)) for(var/datum/reagent/R in SG.reagents.reagent_list) if(R.volume > 0) - output += "Inject [R.name]
" + output += "Inject [R.name]
" return output @@ -352,19 +354,18 @@ /obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Topic(href,href_list) ..() - var/datum/topic_input/afilter = new (href,href_list) - if(afilter.get("toggle_mode")) + if (href_list["toggle_mode"]) mode = !mode update_equip_info() return - if(afilter.get("select_reagents")) + if (href_list["select_reagents"]) processed_reagents.len = 0 var/m = 0 var/message for(var/i=1 to known_reagents.len) if(m>=synth_speed) break - var/reagent = afilter.get("reagent_[i]") + var/reagent = href_list["reagent_[i]"] if(reagent && (reagent in known_reagents)) message = "[m ? ", " : null][known_reagents[reagent]]" processed_reagents += reagent @@ -376,14 +377,14 @@ occupant_message("Reagent processing started.") log_message("Reagent processing started.", LOG_MECHA) return - if(afilter.get("show_reagents")) + if (href_list["show_reagents"]) chassis.occupant << browse(get_reagents_page(),"window=msyringegun") - if(afilter.get("purge_reagent")) - var/reagent = afilter.get("purge_reagent") + if (href_list["purge_reagent"]) + var/reagent = href_list["purge_reagent"] if(reagent) reagents.del_reagent(reagent) return - if(afilter.get("purge_all")) + if (href_list["purge_all"]) reagents.clear_reagents() return return diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index 6bc35958e39..5919df1a119 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -29,6 +29,11 @@ . = ..() recharging_turf = get_step(loc, dir) +/obj/machinery/mech_bay_recharge_port/Destroy() + if (recharge_console && recharge_console.recharge_port == src) + recharge_console.recharge_port = null + return ..() + /obj/machinery/mech_bay_recharge_port/RefreshParts() var/MC for(var/obj/item/stock_parts/capacitor/C in component_parts) @@ -135,3 +140,8 @@ /obj/machinery/computer/mech_bay_power_console/Initialize() . = ..() reconnect() + +/obj/machinery/computer/mech_bay_power_console/Destroy() + if (recharge_port && recharge_port.recharge_console == src) + recharge_port.recharge_console = null + return ..() diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index a97c0e3a683..3c99cd1a15d 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -312,9 +312,8 @@ /obj/machinery/mecha_part_fabricator/Topic(href, href_list) if(..()) return - var/datum/topic_input/afilter = new /datum/topic_input(href,href_list) if(href_list["part_set"]) - var/tpart_set = afilter.getStr("part_set") + var/tpart_set = href_list["part_set"] if(tpart_set) if(tpart_set=="clear") part_set = null @@ -322,7 +321,7 @@ part_set = tpart_set screen = "parts" if(href_list["part"]) - var/T = afilter.getStr("part") + var/T = href_list["part"] for(var/v in stored_research.researched_designs) var/datum/design/D = SSresearch.techweb_design_by_id(v) if(D.build_type & MECHFAB) @@ -333,7 +332,7 @@ add_to_queue(D) break if(href_list["add_to_queue"]) - var/T = afilter.getStr("add_to_queue") + var/T = href_list["add_to_queue"] for(var/v in stored_research.researched_designs) var/datum/design/D = SSresearch.techweb_design_by_id(v) if(D.build_type & MECHFAB) @@ -342,10 +341,10 @@ break return update_queue_on_page() if(href_list["remove_from_queue"]) - remove_from_queue(afilter.getNum("remove_from_queue")) + remove_from_queue(text2num(href_list["remove_from_queue"])) return update_queue_on_page() if(href_list["partset_to_queue"]) - add_part_set_to_queue(afilter.get("partset_to_queue")) + add_part_set_to_queue(href_list["partset_to_queue"]) return update_queue_on_page() if(href_list["process_queue"]) spawn(0) @@ -359,8 +358,8 @@ if(href_list["screen"]) screen = href_list["screen"] if(href_list["queue_move"] && href_list["index"]) - var/index = afilter.getNum("index") - var/new_index = index + afilter.getNum("queue_move") + var/index = text2num(href_list["index"]) + var/new_index = index + text2num(href_list["queue_move"]) if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index)) if(ISINRANGE(new_index,1,queue.len)) queue.Swap(index,new_index) @@ -371,7 +370,7 @@ if(href_list["sync"]) sync() if(href_list["part_desc"]) - var/T = afilter.getStr("part_desc") + var/T = href_list["part_desc"] for(var/v in stored_research.researched_designs) var/datum/design/D = SSresearch.techweb_design_by_id(v) if(D.build_type & MECHFAB) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 2ecb6f717e0..0fb1c3370db 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -851,10 +851,6 @@ . = t_air.return_temperature() return -/obj/mecha/portableConnectorReturnAir() - return internal_tank.return_air() - - /obj/mecha/MouseDrop_T(mob/M, mob/user) if((user != M) || user.incapacitated() || !Adjacent(user)) return diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index 07b9290240e..053660b50b6 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -30,17 +30,19 @@ /obj/machinery/computer/mecha/Topic(href, href_list) if(..()) return - var/datum/topic_input/afilter = new /datum/topic_input(href,href_list) if(href_list["send_message"]) - var/obj/item/mecha_parts/mecha_tracking/MT = afilter.getObj("send_message") + var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["send_message"]) + if (!istype(MT)) + return var/message = stripped_input(usr,"Input message","Transmit message") var/obj/mecha/M = MT.in_mecha() if(trim(message) && M) M.occupant_message(message) return if(href_list["shock"]) - var/obj/item/mecha_parts/mecha_tracking/MT = afilter.getObj("shock") - MT.shock() + var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["shock"]) + if (istype(MT)) + MT.shock() updateUsrDialog() return diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index 77862a4d9c8..e7d53db45c1 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -216,73 +216,71 @@ if(usr.incapacitated()) return - var/datum/topic_input/afilter = new /datum/topic_input(href,href_list) - if(in_range(src, usr)) + var/obj/item/card/id/id_card + if (href_list["id_card"]) + id_card = locate(href_list["id_card"]) + if (!istype(id_card)) + return - if(href_list["req_access"] && add_req_access) - output_access_dialog(afilter.getObj("id_card"),afilter.getMob("user")) + if(href_list["req_access"] && add_req_access && id_card) + output_access_dialog(id_card,usr) - if(href_list["maint_access"] && maint_access) - var/mob/user = afilter.getMob("user") - if(user) - if(state==0) - state = 1 - to_chat(user, "The securing bolts are now exposed.") - else if(state==1) - state = 0 - to_chat(user, "The securing bolts are now hidden.") - output_maintenance_dialog(afilter.getObj("id_card"),user) + if(href_list["maint_access"] && maint_access && id_card) + if(state==0) + state = 1 + to_chat(usr, "The securing bolts are now exposed.") + else if(state==1) + state = 0 + to_chat(usr, "The securing bolts are now hidden.") + output_maintenance_dialog(id_card,usr) if(href_list["set_internal_tank_valve"] && state >=1) - var/mob/user = afilter.getMob("user") - if(user) - var/new_pressure = input(user,"Input new output pressure","Pressure setting",internal_tank_valve) as num - if(new_pressure) - internal_tank_valve = new_pressure - to_chat(user, "The internal pressure valve has been set to [internal_tank_valve]kPa.") + var/new_pressure = input(usr,"Input new output pressure","Pressure setting",internal_tank_valve) as num + if(new_pressure) + internal_tank_valve = new_pressure + to_chat(usr, "The internal pressure valve has been set to [internal_tank_valve]kPa.") - if(href_list["add_req_access"] && add_req_access && afilter.getObj("id_card")) - operation_req_access += afilter.getNum("add_req_access") - output_access_dialog(afilter.getObj("id_card"),afilter.getMob("user")) + if(href_list["add_req_access"] && add_req_access && id_card) + operation_req_access += text2num(href_list["add_req_access"]) + output_access_dialog(id_card,usr) - if(href_list["del_req_access"] && add_req_access && afilter.getObj("id_card")) - operation_req_access -= afilter.getNum("del_req_access") - output_access_dialog(afilter.getObj("id_card"),afilter.getMob("user")) + if(href_list["del_req_access"] && add_req_access && id_card) + operation_req_access -= text2num(href_list["add_req_access"]) + output_access_dialog(id_card, usr) if(href_list["finish_req_access"]) add_req_access = 0 - var/mob/user = afilter.getMob("user") - user << browse(null,"window=exosuit_add_access") + usr << browse(null,"window=exosuit_add_access") if(usr != occupant) return if(href_list["update_content"]) - send_byjax(src.occupant,"exosuit.browser","content",src.get_stats_part()) + send_byjax(usr,"exosuit.browser","content",src.get_stats_part()) if(href_list["select_equip"]) - var/obj/item/mecha_parts/mecha_equipment/equip = afilter.getObj("select_equip") + var/obj/item/mecha_parts/mecha_equipment/equip = locate(href_list["select_equip"]) in src if(equip && equip.selectable) - src.selected = equip - src.occupant_message("You switch to [equip]") - src.visible_message("[src] raises [equip]") - send_byjax(src.occupant,"exosuit.browser","eq_list",src.get_equipment_list()) + selected = equip + occupant_message("You switch to [equip]") + visible_message("[src] raises [equip]") + send_byjax(usr,"exosuit.browser","eq_list",src.get_equipment_list()) if(href_list["rmictoggle"]) radio.broadcasting = !radio.broadcasting - send_byjax(src.occupant,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged")) + send_byjax(usr,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged")) if(href_list["rspktoggle"]) radio.listening = !radio.listening - send_byjax(src.occupant,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged")) + send_byjax(usr,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged")) if(href_list["rfreq"]) - var/new_frequency = (radio.frequency + afilter.getNum("rfreq")) + var/new_frequency = (radio.frequency + text2num(href_list["rfreq"])) if (!radio.freerange || (radio.frequency < MIN_FREE_FREQ || radio.frequency > MAX_FREE_FREQ)) new_frequency = sanitize_frequency(new_frequency) radio.set_frequency(new_frequency) - send_byjax(src.occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]") + send_byjax(usr,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]") if (href_list["change_name"]) var/userinput = input(occupant, "Choose new exosuit name", "Rename exosuit", "") as null|text @@ -292,14 +290,14 @@ if (href_list["toggle_id_upload"]) add_req_access = !add_req_access - send_byjax(src.occupant,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel") + send_byjax(usr,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel") if(href_list["toggle_maint_access"]) if(state) occupant_message("Maintenance protocols in effect") return maint_access = !maint_access - send_byjax(src.occupant,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols") + send_byjax(usr,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols") if (href_list["toggle_port_connection"]) if(internal_tank.connected_port) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 7e404b4769b..aa7d0a2f137 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -38,7 +38,6 @@ /obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose name = "blood" icon = 'icons/effects/blood.dmi' - icon_state = "ltrails_1" desc = "Your instincts say you shouldn't be following these." var/list/existing_dirs = list() diff --git a/code/game/objects/effects/effect_system/effect_system.dm b/code/game/objects/effects/effect_system/effect_system.dm index eb4c562c369..e2bc6f54ec1 100644 --- a/code/game/objects/effects/effect_system/effect_system.dm +++ b/code/game/objects/effects/effect_system/effect_system.dm @@ -20,6 +20,9 @@ would spawn and follow the beaker, even if it is carried or thrown. GLOB.cameranet.updateVisibility(src) return ..() +/obj/effect/particle_effect/newtonian_move() // Prevents effects from getting registered for SSspacedrift + return TRUE + /datum/effect_system var/number = 3 var/cardinals = FALSE diff --git a/code/game/objects/effects/effect_system/effects_explosion.dm b/code/game/objects/effects/effect_system/effects_explosion.dm index d208510e860..c91df696e6c 100644 --- a/code/game/objects/effects/effect_system/effects_explosion.dm +++ b/code/game/objects/effects/effect_system/effects_explosion.dm @@ -5,19 +5,23 @@ anchored = TRUE /obj/effect/particle_effect/expl_particles/Initialize() - . = ..() - QDEL_IN(src, 15) + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/effect/particle_effect/expl_particles/LateInitialize() + var/direct = pick(GLOB.alldirs) + var/steps_amt = pick(1;25,2;50,3,4;200) + for(var/j in 1 to steps_amt) + step(src, direct) + sleep(1) + qdel(src) /datum/effect_system/expl_particles number = 10 /datum/effect_system/expl_particles/start() for(var/i in 1 to number) - var/obj/effect/particle_effect/expl_particles/expl = new /obj/effect/particle_effect/expl_particles(location) - var/direct = pick(GLOB.alldirs) - var/steps_amt = pick(1;25,2;50,3,4;200) - for(var/j in 1 to steps_amt) - addtimer(CALLBACK(GLOBAL_PROC, .proc/_step, expl, direct), j) + new /obj/effect/particle_effect/expl_particles(location) /obj/effect/explosion name = "fire" diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index 6da00041048..2912cffccd9 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -25,13 +25,17 @@ light_color = LIGHT_COLOR_FIRE /obj/effect/particle_effect/sparks/Initialize() - . = ..() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/effect/particle_effect/sparks/LateInitialize() flick("sparks", src) // replay the animation playsound(src, "sparks", 100, TRUE) var/turf/T = loc if(isturf(T)) T.hotspot_expose(1000,100) - QDEL_IN(src, 20) + sleep(20) + qdel(src) /obj/effect/particle_effect/sparks/Destroy() var/turf/T = loc diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm index 98d456d5f19..3a29b72ca34 100644 --- a/code/game/objects/effects/spawners/gibspawner.dm +++ b/code/game/objects/effects/spawners/gibspawner.dm @@ -46,9 +46,6 @@ for(var/j = 1, j<= gibamounts[i], j++) var/gibType = gibtypes[i] gib = new gibType(loc, diseases) - if(iscarbon(loc)) - var/mob/living/carbon/digester = loc - digester.stomach_contents += gib gib.add_blood_DNA(dna_to_add) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index e6e18e76835..681eb0cc93d 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -94,9 +94,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) // non-clothing items var/datum/dog_fashion/dog_fashion = null - var/datum/rpg_loot/rpg_loot = null - - //Tooltip vars var/force_string //string form of an item's force. Edit this var only to set a custom force string var/last_force_string_check = 0 @@ -121,7 +118,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) actions_types = null if(GLOB.rpg_loot_items) - rpg_loot = new(src) + AddComponent(/datum/component/fantasy) if(force_string) item_flags |= FORCE_STRING_OVERRIDE @@ -146,7 +143,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) m.temporarilyRemoveItemFromInventory(src, TRUE) for(var/X in actions) qdel(X) - QDEL_NULL(rpg_loot) return ..() /obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm index cb20bc36d4e..f4a41dae23f 100644 --- a/code/game/objects/items/RPD.dm +++ b/code/game/objects/items/RPD.dm @@ -278,7 +278,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( /obj/item/pipe_dispenser/ui_act(action, params) if(..()) return - if(!usr.canUseTopic(src)) + if(!usr.canUseTopic(src, BE_CLOSE)) return var/playeffect = TRUE switch(action) diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm index 6df370ef780..416a20dd647 100644 --- a/code/game/objects/items/RSF.dm +++ b/code/game/objects/items/RSF.dm @@ -173,7 +173,7 @@ RSF to_chat(user, "Fabricating Cookie..") var/obj/item/reagent_containers/food/snacks/cookie/S = new /obj/item/reagent_containers/food/snacks/cookie(T) if(toxin) - S.reagents.add_reagent("chloralhydratedelayed", 10) + S.reagents.add_reagent("chloralhydrate", 10) if (iscyborg(user)) var/mob/living/silicon/robot/R = user R.cell.charge -= 100 diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index 0d4ea67d2f8..e5b0617c63c 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -59,7 +59,7 @@ /obj/item/areaeditor/blueprints/attack_self(mob/user) . = ..() if(!legend) - var/area/A = get_area() + var/area/A = get_area(user) if(get_area_type() == AREA_STATION) . += "

According to \the [src], you are now in \"[html_encode(A.name)]\".

" . += "

Change area name

" @@ -140,12 +140,9 @@ legend = FALSE -/obj/item/areaeditor/proc/get_area() - var/turf/T = get_turf(usr) - var/area/A = T.loc - return A - -/obj/item/areaeditor/proc/get_area_type(area/A = get_area()) +/obj/item/areaeditor/proc/get_area_type(area/A) + if (!A) + A = get_area(usr) if(A.outdoors) return AREA_SPACE var/list/SPECIALS = list( @@ -183,7 +180,7 @@ return "" /obj/item/areaeditor/proc/edit_area() - var/area/A = get_area() + var/area/A = get_area(usr) var/prevname = "[A.name]" var/str = stripped_input(usr,"New area name:", "Area Creation", "", MAX_NAME_LEN) if(!str || !length(str) || str==prevname) //cancel diff --git a/code/game/objects/items/cardboard_cutouts.dm b/code/game/objects/items/cardboard_cutouts.dm index fe51b0fc0ad..768c7ac2137 100644 --- a/code/game/objects/items/cardboard_cutouts.dm +++ b/code/game/objects/items/cardboard_cutouts.dm @@ -88,7 +88,7 @@ to_chat(user, "Take the cap off first!") return var/new_appearance = input(user, "Choose a new appearance for [src].", "26th Century Deception") as null|anything in possible_appearances - if(!new_appearance || !crayon || !user.canUseTopic(src)) + if(!new_appearance || !crayon || !user.canUseTopic(src, BE_CLOSE)) return if(!do_after(user, 10, FALSE, src, TRUE)) return diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 5f24b69ab46..384965149af 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -125,6 +125,13 @@ if(mapload && access_txt) access = text2access(access_txt) +/obj/item/card/id/Destroy() + if (registered_account) + registered_account.bank_cards -= src + if (my_store && my_store.my_card == src) + my_store.my_card = null + return ..() + /obj/item/card/id/attack_self(mob/user) if(Adjacent(user)) user.visible_message("[user] shows you: [icon2html(src, viewers(user))] [src.name].", "You show \the [src.name].") @@ -175,7 +182,7 @@ return if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return - + return TRUE /obj/item/card/id/AltClick(mob/living/user) @@ -199,7 +206,7 @@ return if (world.time < registered_account.withdrawDelay) - registered_account.bank_card_talk("ERROR: UNABLE TO LOGIN DUE TO SCHEDULED MAINTENANCE. MAINTENANCE IS SCHEDULED TO COMPLETE IN [(registered_account.withdrawDelay - world.time)/10] SECONDS.", TRUE) + registered_account.bank_card_talk("ERROR: UNABLE TO LOGIN DUE TO SCHEDULED MAINTENANCE. MAINTENANCE IS SCHEDULED TO COMPLETE IN [(registered_account.withdrawDelay - world.time)/10] SECONDS.", TRUE) return var/amount_to_remove = FLOOR(input(user, "How much do you want to withdraw? Current Balance: [registered_account.account_balance]", "Withdraw Funds", 5) as num, 1) @@ -216,7 +223,7 @@ return else var/difference = amount_to_remove - registered_account.account_balance - registered_account.bank_card_talk("ERROR: The linked account requires [difference] more credit\s to perform that withdrawal.", TRUE) + registered_account.bank_card_talk("ERROR: The linked account requires [difference] more credit\s to perform that withdrawal.", TRUE) /obj/item/card/id/examine(mob/user) ..() diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index 3ef0f2751c4..1a4cd7a02ef 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -185,6 +185,14 @@ /obj/item/stack/cable_coil = 1, /obj/item/stock_parts/subspace/filter = 1) +/obj/item/circuitboard/machine/telecomms/message_server + name = "Messaging Server (Machine Board)" + build_path = /obj/machinery/telecomms/message_server + req_components = list( + /obj/item/stock_parts/manipulator = 2, + /obj/item/stack/cable_coil = 1, + /obj/item/stock_parts/subspace/filter = 3) + /obj/item/circuitboard/machine/teleporter_hub name = "Teleporter Hub (Machine Board)" build_path = /obj/machinery/teleport/hub diff --git a/code/game/objects/items/crab17.dm b/code/game/objects/items/crab17.dm index 29d03305cc5..8a065e732ec 100644 --- a/code/game/objects/items/crab17.dm +++ b/code/game/objects/items/crab17.dm @@ -17,7 +17,9 @@ if(alert(user, "Are you sure you want to crash this market with no survivors?", "Protocol CRAB-17", "Yes", "No") == "Yes") if(dumped || QDELETED(src)) //Prevents fuckers from cheesing alert return FALSE - var/turf/targetturf = get_random_station_turf() + var/turf/targetturf = get_safe_random_station_turf() + if (!targetturf) + return FALSE new /obj/effect/dumpeetTarget(targetturf, user) dumped = TRUE @@ -31,7 +33,7 @@ density = TRUE pixel_z = -8 layer = LARGE_MOB_LAYER - max_integrity = 3000 + max_integrity = 600 var/list/accounts_to_rob var/mob/living/carbon/human/bogdanoff var/canwalk = FALSE @@ -78,7 +80,7 @@ add_overlay("hatch") add_overlay("legs_retracted") addtimer(CALLBACK(src, .proc/startUp), 50) - START_PROCESSING(SSfastprocess, src) + /obj/structure/checkoutmachine/proc/startUp() //very VERY snowflake code that adds a neat animation when the pod lands. start_dumping() //The machine doesnt move during this time, giving people close by a small window to grab their funds before it starts running around @@ -141,11 +143,12 @@ cut_overlay("text") add_overlay("text") canwalk = TRUE + START_PROCESSING(SSfastprocess, src) /obj/structure/checkoutmachine/Destroy() stop_dumping() STOP_PROCESSING(SSfastprocess, src) - priority_announce("The credit deposit machine at [get_area(src).name] has been destroyed. Station funds have stopped draining!", sender_override = "CRAB-17 Protocol") + priority_announce("The credit deposit machine at [get_area(src)] has been destroyed. Station funds have stopped draining!", sender_override = "CRAB-17 Protocol") explosion(src, 0,0,1, flame_range = 2) return ..() @@ -167,12 +170,10 @@ var/datum/bank_account/account = bogdanoff.get_bank_account() if (account) // get_bank_account() may return FALSE account.transfer_money(B, amount) - B.bank_card_talk("You have lost [percentage_lost * 100]% of your funds! A spacecoin credit deposit machine is located at: [get_area(src).name].") + B.bank_card_talk("You have lost [percentage_lost * 100]% of your funds! A spacecoin credit deposit machine is located at: [get_area(src)].") addtimer(CALLBACK(src, .proc/dump), 150) //Drain every 15 seconds /obj/structure/checkoutmachine/process() - if(!canwalk) - return var/anydir = pick(GLOB.cardinals) if(Process_Spacemove(anydir)) Move(get_step(src, anydir), anydir) @@ -208,13 +209,13 @@ . = ..() bogdanoff = user addtimer(CALLBACK(src, .proc/startLaunch), 100) - sound_to_playing_players('sound/items/dump_it.ogg', 50) + sound_to_playing_players('sound/items/dump_it.ogg', 20) deadchat_broadcast("Protocol CRAB-17 has been activated. A space-coin market has been launched at the station!", turf_target = get_turf(src)) /obj/effect/dumpeetTarget/proc/startLaunch() DF = new /obj/effect/dumpeetFall(drop_location()) dump = new /obj/structure/checkoutmachine(null, bogdanoff) - priority_announce("The spacecoin bubble has popped! Get to the credit deposit machine at [get_area(src).name] and cash out before you lose all of your funds!", sender_override = "CRAB-17 Protocol") + priority_announce("The spacecoin bubble has popped! Get to the credit deposit machine at [get_area(src)] and cash out before you lose all of your funds!", sender_override = "CRAB-17 Protocol") animate(DF, pixel_z = -8, time = 5, , easing = LINEAR_EASING) playsound(src, 'sound/weapons/mortar_whistle.ogg', 70, 1, 6) addtimer(CALLBACK(src, .proc/endLaunch), 5, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 510e6b0d43c..162dddf3a63 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -61,7 +61,6 @@ GLOBAL_LIST_EMPTY(PDAs) var/note = "Congratulations, your station has chosen the Thinktronic 5230 Personal Data Assistant!" //Current note in the notepad function var/notehtml = "" var/notescanned = FALSE // True if what is in the notekeeper was from a paper. - var/detonatable = TRUE // Can the PDA be blown up? var/hidden = FALSE // Is the PDA hidden from the PDA list? var/emped = FALSE var/equipped = FALSE //used here to determine if this is the first time its been picked up @@ -631,7 +630,7 @@ GLOBAL_LIST_EMPTY(PDAs) if (!string_targets.len) return - var/datum/signal/subspace/pda/signal = new(src, list( + var/datum/signal/subspace/messaging/pda/signal = new(src, list( "name" = "[owner]", "job" = "[ownjob]", "message" = message, @@ -663,7 +662,7 @@ GLOBAL_LIST_EMPTY(PDAs) if (everyone) last_everyone = world.time -/obj/item/pda/proc/receive_message(datum/signal/subspace/pda/signal) +/obj/item/pda/proc/receive_message(datum/signal/subspace/messaging/pda/signal) tnote += "← From [signal.data["name"]] ([signal.data["job"]]):
[signal.format_message()]
" if (!silent) @@ -892,8 +891,6 @@ GLOBAL_LIST_EMPTY(PDAs) /obj/item/pda/proc/explode() //This needs tuning. - if(!detonatable) - return var/turf/T = get_turf(src) if (ismob(loc)) @@ -925,7 +922,7 @@ GLOBAL_LIST_EMPTY(PDAs) //AI verb and proc for sending PDA messages. -/mob/living/silicon/ai/proc/cmd_send_pdamesg(mob/user) +/mob/living/silicon/proc/cmd_send_pdamesg(mob/user) var/list/plist = list() var/list/namecounts = list() @@ -960,7 +957,7 @@ GLOBAL_LIST_EMPTY(PDAs) aiPDA.create_message(src, selected) -/mob/living/silicon/ai/verb/cmd_toggle_pda_receiver() +/mob/living/silicon/verb/cmd_toggle_pda_receiver() set category = "AI Commands" set name = "PDA - Toggle Sender/Receiver" if(usr.stat == DEAD) @@ -971,7 +968,7 @@ GLOBAL_LIST_EMPTY(PDAs) else to_chat(usr, "You do not have a PDA. You should make an issue report about this.") -/mob/living/silicon/ai/verb/cmd_toggle_pda_silent() +/mob/living/silicon/verb/cmd_toggle_pda_silent() set category = "AI Commands" set name = "PDA - Toggle Ringer" if(usr.stat == DEAD) @@ -983,7 +980,7 @@ GLOBAL_LIST_EMPTY(PDAs) else to_chat(usr, "You do not have a PDA. You should make an issue report about this.") -/mob/living/silicon/ai/proc/cmd_show_message_log(mob/user) +/mob/living/silicon/proc/cmd_show_message_log(mob/user) if(incapacitated()) return if(!isnull(aiPDA)) @@ -1012,6 +1009,9 @@ GLOBAL_LIST_EMPTY(PDAs) continue . += P +/obj/item/pda/proc/pda_no_detonate() + return COMPONENT_PDA_NO_DETONATE + #undef PDA_SCANNER_NONE #undef PDA_SCANNER_MEDICAL #undef PDA_SCANNER_FORENSICS diff --git a/code/game/objects/items/devices/PDA/PDA_types.dm b/code/game/objects/items/devices/PDA/PDA_types.dm index 102dd6e13f4..299b07f08ba 100644 --- a/code/game/objects/items/devices/PDA/PDA_types.dm +++ b/code/game/objects/items/devices/PDA/PDA_types.dm @@ -22,7 +22,6 @@ icon = null ttone = "data" fon = FALSE - detonatable = FALSE /obj/item/pda/ai/attack_self(mob/user) if ((honkamt > 0) && (prob(60)))//For clown virus. @@ -33,7 +32,9 @@ /obj/item/pda/ai/pai ttone = "assist" - +/obj/item/pda/ai/Initialize() + . = ..() + RegisterSignal(src, COMSIG_PDA_CHECK_DETONATE, .proc/pda_no_detonate) /obj/item/pda/medical name = "medical PDA" @@ -120,7 +121,10 @@ default_cartridge = /obj/item/cartridge/captain inserted_item = /obj/item/pen/fountain/captain icon_state = "pda-captain" - detonatable = FALSE + +/obj/item/pda/captain/Initialize() + . = ..() + RegisterSignal(src, COMSIG_PDA_CHECK_DETONATE, .proc/pda_no_detonate) /obj/item/pda/cargo name = "cargo technician PDA" diff --git a/code/game/objects/items/devices/PDA/virus_cart.dm b/code/game/objects/items/devices/PDA/virus_cart.dm index ecd51b6b227..80a5aceae1d 100644 --- a/code/game/objects/items/devices/PDA/virus_cart.dm +++ b/code/game/objects/items/devices/PDA/virus_cart.dm @@ -71,8 +71,7 @@ difficulty++ //if cartridge has manifest access it has extra snowflake difficulty else difficulty += 2 - GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, target) - if(!target.detonatable || prob(difficulty * 15) || (hidden_uplink)) + if(SEND_SIGNAL(target, COMSIG_PDA_CHECK_DETONATE) & COMPONENT_PDA_NO_DETONATE || prob(difficulty * 15)) U.show_message("An error flashes on your [src].", 1) else log_bomber(U, "triggered a PDA explosion on", target, "[!is_special_character(U) ? "(TRIGGED BY NON-ANTAG)" : ""]") diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 33a341788b5..798bfe47804 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -472,7 +472,7 @@ GENE SCANNER /obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens ..() - if(user.canUseTopic(src)) + if(user.canUseTopic(src, BE_CLOSE)) if(cooldown) to_chat(user, "[src]'s barometer function is preparing itself.") diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index 1c48dea1a15..0981469eb6a 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -99,7 +99,7 @@ /obj/item/transfer_valve/Topic(href, href_list) ..() - if(!usr.canUseTopic(src)) + if(!usr.canUseTopic(src, BE_CLOSE)) return if(tank_one && href_list["tankone"]) split_gases() diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index 8e744cfb93f..8e3ce9b75d8 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -194,6 +194,7 @@ O.forceMove(drop_location()) beakers = list() stage_change(EMPTY) + active = FALSE return if(nadeassembly) diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index 1565d3adb87..9b71dcb8959 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -165,6 +165,10 @@ attack_verb = list("shanked", "shivved") armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) +/obj/item/kitchen/knife/carrotshiv/suicide_act(mob/living/carbon/user) + user.visible_message("[user] forcefully drives \the [src] into [user.p_their()] eye! It looks like [user.p_theyre()] trying to commit suicide!") + return BRUTELOSS + /obj/item/kitchen/rollingpin name = "rolling pin" desc = "Used to knock out the Bartender." diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index 73bb8a86408..b24a6dfde4d 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -66,7 +66,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "burning", H << browse(dat, "window=editicon;can_close=0;can_minimize=0;size=250x650") /obj/item/storage/book/bible/Topic(href, href_list) - if(!usr.canUseTopic(src)) + if(!usr.canUseTopic(src, BE_CLOSE)) return if(href_list["seticon"] && SSreligion && !SSreligion.bible_icon_state) var/iconi = text2num(href_list["seticon"]) diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index 1de02f46cf4..531ac28eeab 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -324,7 +324,7 @@ /obj/item/storage/pill_bottle/penacid name = "bottle of pentetic acid pills" - desc = "Contains pills to expunge radioation and toxins" + desc = "Contains pills to expunge radiation and toxins." /obj/item/storage/pill_bottle/penacid/PopulateContents() for(var/i in 1 to 3) diff --git a/code/game/objects/structures/ai_core.dm b/code/game/objects/structures/ai_core.dm index e46e06db33c..e0681b76178 100644 --- a/code/game/objects/structures/ai_core.dm +++ b/code/game/objects/structures/ai_core.dm @@ -333,9 +333,11 @@ That prevents a few funky behaviors. to_chat(AI, "You have been uploaded to a stationary terminal. Remote device connection restored.") to_chat(user, "Transfer successful: [AI.name] ([rand(1000,9999)].exe) installed and executed successfully. Local copy has been removed.") card.AI = null + AI.battery = circuit.battery qdel(src) else //If for some reason you use an empty card on an empty AI terminal. to_chat(user, "There is no AI loaded on this terminal!") /obj/item/circuitboard/aicore name = "AI core (AI Core Board)" //Well, duh, but best to be consistent + var/battery = 200 //backup battery for when the AI loses power. Copied to/from AI mobs when carding, and placed here to avoid recharge via deconning the core diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 0a5862711db..f26efcaa328 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -417,7 +417,7 @@ /obj/structure/closet/CtrlShiftClick(mob/living/user) if(!HAS_TRAIT(user, TRAIT_SKITTISH)) return ..() - if(!user.canUseTopic(src) || !isturf(user.loc)) + if(!user.canUseTopic(src, BE_CLOSE) || !isturf(user.loc)) return dive_into(user) diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 0b7d3e0bd49..f786ed3074a 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -313,18 +313,9 @@ throw_speed = 2 throw_range = 4 - -/obj/item/twohanded/required/kirbyplants/equipped(mob/living/user) - var/image/I = image(icon = 'icons/obj/flora/plants.dmi' , icon_state = src.icon_state, loc = user) - I.copy_overlays(src) - I.override = 1 - add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I) - I.layer = ABOVE_MOB_LAYER - ..() - -/obj/item/twohanded/required/kirbyplants/dropped(mob/living/user) - ..() - user.remove_alt_appearance("sneaking_mission") +/obj/item/twohanded/required/kirbyplants/Initialize() + . = ..() + AddComponent(/datum/component/tactical) /obj/item/twohanded/required/kirbyplants/random icon = 'icons/obj/flora/_flora.dmi' diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm index 9f5d6035afb..9fd097f6ad2 100644 --- a/code/game/objects/structures/safe.dm +++ b/code/game/objects/structures/safe.dm @@ -96,7 +96,7 @@ FLOOR SAFES return var/mob/living/carbon/human/user = usr - if(!user.canUseTopic(src)) + if(!user.canUseTopic(src, BE_CLOSE)) return var/canhear = FALSE diff --git a/code/modules/antagonists/blob/blob_mobs.dm b/code/modules/antagonists/blob/blob_mobs.dm index 37b409a5f1c..92599e90441 100644 --- a/code/modules/antagonists/blob/blob_mobs.dm +++ b/code/modules/antagonists/blob/blob_mobs.dm @@ -271,7 +271,7 @@ /mob/living/simple_animal/hostile/blob/blobbernaut/AttackingTarget() . = ..() if(. && isliving(target) && overmind) - overmind.blobstrain.blobbernaut_attack(target) + overmind.blobstrain.blobbernaut_attack(target, src) /mob/living/simple_animal/hostile/blob/blobbernaut/update_icons() ..() diff --git a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm index e592be0c5e8..aff1b56da55 100644 --- a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm +++ b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm @@ -37,10 +37,10 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ overmind.add_points(point_rate) overmind.blob_core.obj_integrity = min(overmind.blob_core.max_integrity, overmind.blob_core.obj_integrity+core_regen) -/datum/blobstrain/proc/attack_living(var/mob/living/L) // When the blob attacks people +/datum/blobstrain/proc/attack_living(var/mob/living/L, var/list/nearby_blobs) // When the blob attacks people send_message(L) -/datum/blobstrain/proc/blobbernaut_attack(mob/living/L) // When this blob's blobbernaut attacks people +/datum/blobstrain/proc/blobbernaut_attack(mob/living/L, blobbernaut) // When this blob's blobbernaut attacks people /datum/blobstrain/proc/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag, coefficient = 1) //when the blob takes damage, do this return coefficient*damage diff --git a/code/modules/antagonists/blob/blobstrains/debris_devourer.dm b/code/modules/antagonists/blob/blobstrains/debris_devourer.dm new file mode 100644 index 00000000000..f06c880ce44 --- /dev/null +++ b/code/modules/antagonists/blob/blobstrains/debris_devourer.dm @@ -0,0 +1,46 @@ +#define DEBRIS_DENSITY (length(core.contents) / length(overmind.blobs_legit)) // items per blob + +// Accumulates junk liberally +/datum/blobstrain/debris_devourer + name = "Debris Devourer" + description = "will launch accumulated debris into targets." + analyzerdescdamage = "Does medium brute damage and may grab onto melee weapons." + analyzerdesceffect = "Devours loose items left on the station, and releases them when attacking or attacked." + color = "#8B1000" + complementary_color = "#00558B" + blobbernaut_message = "blasts" + message = "The blob blasts you" + + +/datum/blobstrain/debris_devourer/attack_living(var/mob/living/L, var/list/nearby_blobs) + send_message(L) + for (var/obj/structure/blob/blob in nearby_blobs) + debris_attack(L, blob) + +/datum/blobstrain/debris_devourer/on_sporedeath(mob/living/spore) + for(var/i in 1 to 3) + var/obj/item/I = locate() in overmind.blob_core + if (I && !QDELETED(I)) + I.forceMove(get_turf(spore)) + I.throw_at(get_edge_target_turf(spore,pick(GLOB.alldirs)), 3, 5) + +/datum/blobstrain/debris_devourer/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O, coefficient = 1) //when the blob expands, do this + for (var/obj/item/I in T) + I.forceMove(overmind.blob_core) + +/datum/blobstrain/debris_devourer/proc/debris_attack(mob/living/L, source) + var/obj/structure/blob/core/core = overmind.blob_core + if (prob(20 * DEBRIS_DENSITY)) // Pretend the items are spread through the blob and its mobs and not in the core. + var/obj/item/I = locate() in core + if (I && !QDELETED(I)) + I.forceMove(get_turf(source)) + I.throw_at(L, 2, 5) + +/datum/blobstrain/debris_devourer/blobbernaut_attack(mob/living/L, mob/living/blobbernaut) // When this blob's blobbernaut attacks people + debris_attack(L,blobbernaut) + +/datum/blobstrain/debris_devourer/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag, coefficient = 1) //when the blob takes damage, do this + var/obj/structure/blob/core/core = overmind.blob_core + return round(max((coefficient*damage)-min(coefficient*DEBRIS_DENSITY, 10), 0)) // reduce damage taken by items per blob, up to 10 + +#undef DEBRIS_DENSITY diff --git a/code/modules/antagonists/blob/powers.dm b/code/modules/antagonists/blob/powers.dm index 878701a90e6..46cf18e6ed3 100644 --- a/code/modules/antagonists/blob/powers.dm +++ b/code/modules/antagonists/blob/powers.dm @@ -269,7 +269,7 @@ continue if(L.stat != DEAD) attacksuccess = TRUE - blobstrain.attack_living(L) + blobstrain.attack_living(L, possibleblobs) var/obj/structure/blob/B = locate() in T if(B) if(attacksuccess) //if we successfully attacked a turf with a blob on it, only give an attack refund diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm index 9fcb9dac10b..bf897892c9d 100644 --- a/code/modules/antagonists/brother/brother.dm +++ b/code/modules/antagonists/brother/brother.dm @@ -31,15 +31,12 @@ owner.special_role = null return ..() -/datum/antagonist/brother/proc/give_meeting_area() - if(!owner.current || !team || !team.meeting_area) - return - to_chat(owner.current, "Your designated meeting area: [team.meeting_area]") - antag_memory += "Meeting Area: [team.meeting_area]
" +/datum/antagonist/brother/antag_panel_data() + return "Conspirators : [get_brother_names()]]" -/datum/antagonist/brother/greet() - var/brother_text = "" +/datum/antagonist/brother/proc/get_brother_names() var/list/brothers = team.members - owner + var/brother_text = "" for(var/i = 1 to brothers.len) var/datum/mind/M = brothers[i] brother_text += M.name @@ -47,6 +44,16 @@ brother_text += " and " else if(i != brothers.len) brother_text += ", " + return brother_text + +/datum/antagonist/brother/proc/give_meeting_area() + if(!owner.current || !team || !team.meeting_area) + return + to_chat(owner.current, "Your designated meeting area: [team.meeting_area]") + antag_memory += "Meeting Area: [team.meeting_area]
" + +/datum/antagonist/brother/greet() + var/brother_text = get_brother_names() to_chat(owner.current, "You are the [owner.special_role] of [brother_text].") to_chat(owner.current, "The Syndicate only accepts those that have proven themselves. Prove yourself and prove your [team.member_name]s by completing your objectives together!") owner.announce_objectives() diff --git a/code/modules/antagonists/changeling/powers/augmented_eyesight.dm b/code/modules/antagonists/changeling/powers/augmented_eyesight.dm index 6943ad5bdb1..04922a25c8b 100644 --- a/code/modules/antagonists/changeling/powers/augmented_eyesight.dm +++ b/code/modules/antagonists/changeling/powers/augmented_eyesight.dm @@ -19,7 +19,7 @@ else to_chat(user, "We can't adjust our eyes if we don't have any!") -/datum/action/changeling/augmented_eyesight/sting_action(mob/living/carbon/human/user) +/datum/action/changeling/augmented_eyesight/sting_action(mob/living/carbon/user) if(!istype(user)) return ..() diff --git a/code/modules/antagonists/changeling/powers/humanform.dm b/code/modules/antagonists/changeling/powers/humanform.dm index c285cadc8db..588fdcccb22 100644 --- a/code/modules/antagonists/changeling/powers/humanform.dm +++ b/code/modules/antagonists/changeling/powers/humanform.dm @@ -7,6 +7,9 @@ //Transform into a human. /datum/action/changeling/humanform/sting_action(mob/living/carbon/user) + if(user.movement_type & VENTCRAWLING) + to_chat(user, "We must exit the pipes before we can transform back!") + return FALSE var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) var/list/names = list() for(var/datum/changelingprofile/prof in changeling.stored_profiles) @@ -20,12 +23,12 @@ if(!chosen_prof) return if(!user || user.notransform) - return 0 + return FALSE to_chat(user, "We transform our appearance.") ..() changeling.purchasedpowers -= src - var/newmob = user.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) + var/newmob = user.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_KEEPSE) changeling_transform(newmob, chosen_prof) return TRUE diff --git a/code/modules/antagonists/changeling/powers/lesserform.dm b/code/modules/antagonists/changeling/powers/lesserform.dm index 476410ac973..03ea226e9e5 100644 --- a/code/modules/antagonists/changeling/powers/lesserform.dm +++ b/code/modules/antagonists/changeling/powers/lesserform.dm @@ -13,5 +13,5 @@ return FALSE to_chat(user, "Our genes cry out!") ..() - user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) + user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_KEEPSE) return TRUE diff --git a/code/modules/antagonists/changeling/powers/strained_muscles.dm b/code/modules/antagonists/changeling/powers/strained_muscles.dm index 13c68ebe0ee..20956107e42 100644 --- a/code/modules/antagonists/changeling/powers/strained_muscles.dm +++ b/code/modules/antagonists/changeling/powers/strained_muscles.dm @@ -18,7 +18,7 @@ if(active) to_chat(user, "Our muscles tense and strengthen.") else - user.add_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING)) + user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES) to_chat(user, "Our muscles relax.") if(stacks >= 10) to_chat(user, "We collapse in exhaustion.") diff --git a/code/modules/antagonists/changeling/powers/tiny_prick.dm b/code/modules/antagonists/changeling/powers/tiny_prick.dm index 199d394c1ac..dc848b92fdc 100644 --- a/code/modules/antagonists/changeling/powers/tiny_prick.dm +++ b/code/modules/antagonists/changeling/powers/tiny_prick.dm @@ -108,7 +108,7 @@ C.real_name = NewDNA.real_name NewDNA.transfer_identity(C) if(ismonkey(C)) - C.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG) + C.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG) C.updateappearance(mutcolor_update=1) diff --git a/code/modules/antagonists/creep/creep.dm b/code/modules/antagonists/creep/creep.dm index cde02e79a2d..b1ec9db398e 100644 --- a/code/modules/antagonists/creep/creep.dm +++ b/code/modules/antagonists/creep/creep.dm @@ -117,7 +117,7 @@ if(trauma.total_time_creeping > 0) report += "The [name] spent a total of [DisplayTimeText(trauma.total_time_creeping)] being near [trauma.obsession]!" else - report += "The [name] did not go near their obsession the entire round! That's extremely impressive, but you are a shit [name]!" + report += "The [name] did not go near their obsession the entire round! That's extremely impressive!" else report += "The [name] had no trauma attached to their antagonist ways! Either it bugged out or an admin incorrectly gave this good samaritan antag and it broke! You might as well show yourself!!" diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm index ad850d6aec4..480bf4f06ef 100644 --- a/code/modules/antagonists/disease/disease_mob.dm +++ b/code/modules/antagonists/disease/disease_mob.dm @@ -138,6 +138,8 @@ the new instance inside the host to be updated to the template's stats. . = ..() if(!mind.has_antag_datum(/datum/antagonist/disease)) mind.add_antag_datum(/datum/antagonist/disease) + var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + medsensor.add_hud_to(src) /mob/camera/disease/proc/pick_name() var/static/list/taken_names diff --git a/code/modules/antagonists/monkey/monkey.dm b/code/modules/antagonists/monkey/monkey.dm index dff5090c72e..a776d5707a0 100644 --- a/code/modules/antagonists/monkey/monkey.dm +++ b/code/modules/antagonists/monkey/monkey.dm @@ -70,9 +70,9 @@ switch(alert(admin, "Humanize?", "Humanize", "Yes", "No")) if("Yes") if(admin == M) - admin = M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG) + admin = M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG) else - M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG) + M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG) if("No") //nothing else diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm index df04059f998..9a355aac564 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm @@ -61,7 +61,39 @@ GLOBAL_LIST_EMPTY(jam_on_wardec) for(var/obj/machinery/computer/camera_advanced/shuttle_docker/D in GLOB.jam_on_wardec) D.jammed = TRUE - new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS) + var/list/orphans = list() + var/list/uplinks = list() + + for (var/datum/mind/M in get_antag_minds(/datum/antagonist/nukeop)) + if (iscyborg(M.current)) + continue + var/datum/component/uplink/uplink = M.find_syndicate_uplink() + if (!uplink) + orphans += M.current + continue + uplinks += uplink + + + var/tc_to_distribute = CHALLENGE_TELECRYSTALS + var/tc_per_nukie = round(tc_to_distribute / (length(orphans)+length(uplinks))) + + for (var/datum/component/uplink/uplink in uplinks) + uplink.telecrystals += tc_per_nukie + tc_to_distribute -= tc_per_nukie + + for (var/mob/living/L in orphans) + var/TC = new /obj/item/stack/telecrystal(user.drop_location(), tc_per_nukie) + to_chat(L, "Your uplink could not be found so your share of the team's bonus telecrystals has been bluespaced to your [L.put_in_hands(TC) ? "hands" : "feet"].") + tc_to_distribute -= tc_per_nukie + + if (tc_to_distribute > 0) // What shall we do with the remainder... + for (var/mob/living/simple_animal/hostile/carp/cayenne/C in GLOB.mob_living_list) + if (C.stat != DEAD) + var/obj/item/stack/telecrystal/TC = new(C.drop_location(), tc_to_distribute) + TC.throw_at(get_step(C, C.dir), 3, 3) + C.visible_message("[C] coughs up a half-digested telecrystal","You cough up a half-digested telecrystal!") + break + CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY)) SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1) diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index 78f9e39c789..79363f32b50 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -53,6 +53,13 @@ memorize_code() if(send_to_spawnpoint) move_to_spawnpoint() + // grant extra TC for the people who start in the nukie base ie. not the lone op + var/extra_tc = CEILING(GLOB.joined_player_list.len/5, 5) + var/datum/component/uplink/U = owner.find_syndicate_uplink() + if (U) + U.telecrystals += extra_tc + + /datum/antagonist/nukeop/get_team() return nuke_team @@ -75,9 +82,16 @@ /datum/antagonist/nukeop/proc/give_alias() if(nuke_team && nuke_team.syndicate_name) - var/number = 1 - number = nuke_team.members.Find(owner) - owner.current.real_name = "[nuke_team.syndicate_name] Operative #[number]" + var/mob/living/carbon/human/H = owner.current + if(istype(H)) // Reinforcements get a real name + var/chosen_name = H.dna.species.random_name(H.gender,0,nuke_team.syndicate_name) + H.fully_replace_character_name(H.real_name,chosen_name) + else + var/number = 1 + number = nuke_team.members.Find(owner) + owner.current.real_name = "[nuke_team.syndicate_name] Operative #[number]" + + /datum/antagonist/nukeop/proc/memorize_code() if(nuke_team && nuke_team.tracked_nuke && nuke_team.memorized_code) @@ -234,6 +248,7 @@ var/obj/machinery/nuclearbomb/tracked_nuke var/core_objective = /datum/objective/nuclear var/memorized_code + var/list/team_discounts /datum/team/nuclear/New() ..() diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 6708a956eab..c47cfc75787 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -242,14 +242,18 @@ return var/mob/traitor_mob=owner.current - to_chat(traitor_mob, "The Syndicate provided you with the following information on how to identify their agents:") - to_chat(traitor_mob, "Code Phrase: [GLOB.syndicate_code_phrase]") - to_chat(traitor_mob, "Code Response: [GLOB.syndicate_code_response]") + var/phrases = jointext(GLOB.syndicate_code_phrase, ", ") + var/responses = jointext(GLOB.syndicate_code_response, ", ") - antag_memory += "Code Phrase: [GLOB.syndicate_code_phrase]
" - antag_memory += "Code Response: [GLOB.syndicate_code_response]
" + to_chat(traitor_mob, "The Syndicate have provided you with the following codewords to identify fellow agents:") + to_chat(traitor_mob, "Code Phrase: [phrases]") + to_chat(traitor_mob, "Code Response: [responses]") - to_chat(traitor_mob, "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe.") + antag_memory += "Code Phrase: [phrases]
" + antag_memory += "Code Response: [responses]
" + + to_chat(traitor_mob, "Use the codewords during regular conversation to identify other agents. Proceed with caution, however, as everyone is a potential foe.") + to_chat(traitor_mob, "You memorize the codewords, allowing you to recognise them when heard.") /datum/antagonist/traitor/proc/add_law_zero() var/mob/living/silicon/ai/killer = owner.current diff --git a/code/modules/assembly/health.dm b/code/modules/assembly/health.dm index 782d729ce4a..55ca5b61932 100644 --- a/code/modules/assembly/health.dm +++ b/code/modules/assembly/health.dm @@ -90,7 +90,7 @@ var/mob/user = usr - if(!user.canUseTopic(src)) + if(!user.canUseTopic(src, BE_CLOSE)) usr << browse(null, "window=hscan") onclose(usr, "hscan") return diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index d33fac81bb0..e56a5584a2d 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -96,9 +96,30 @@ /////////////////////////GAS OVERLAYS////////////////////////////// + /turf/open/proc/update_visuals() - var/list/new_overlay_types = tile_graphic() + var/list/atmos_overlay_types = src.atmos_overlay_types // Cache for free performance + var/list/new_overlay_types = list() + var/static/list/nonoverlaying_gases = typecache_of_gases_with_no_overlays() + + if(!air) // 2019-05-14: was not able to get this path to fire in testing. Consider removing/looking at callers -Naksu + if (atmos_overlay_types) + for(var/overlay in atmos_overlay_types) + vis_contents -= overlay + src.atmos_overlay_types = null + return + + var/list/gases = air.gases + + for(var/id in gases) + if (nonoverlaying_gases[id]) + continue + var/gas = gases[id] + var/gas_meta = gas[GAS_META] + var/gas_overlay = gas_meta[META_GAS_OVERLAY] + if(gas_overlay && gas[MOLES] > gas_meta[META_GAS_MOLES_VISIBLE]) + new_overlay_types += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(gas[MOLES] / MOLES_GAS_VISIBLE_STEP, 1))] if (atmos_overlay_types) for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added @@ -113,21 +134,6 @@ UNSETEMPTY(new_overlay_types) src.atmos_overlay_types = new_overlay_types -/turf/open/proc/tile_graphic() - var/static/list/nonoverlaying_gases = typecache_of_gases_with_no_overlays() - if(!air) - return - . = new /list - var/list/gases = air.gases - for(var/id in gases) - if (nonoverlaying_gases[id]) - continue - var/gas = gases[id] - var/gas_meta = gas[GAS_META] - var/gas_overlay = gas_meta[META_GAS_OVERLAY] - if(gas_overlay && gas[MOLES] > gas_meta[META_GAS_MOLES_VISIBLE]) - . += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(gas[MOLES] / MOLES_GAS_VISIBLE_STEP, 1))] - /proc/typecache_of_gases_with_no_overlays() . = list() for (var/gastype in subtypesof(/datum/gas)) diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index ebbbca809ca..48e507d4599 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -428,23 +428,9 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) continue if(!cached_gases[id] || cached_gases[id][MOLES] < min_reqs[id]) continue reaction_loop - //at this point, all minimum requirements for the reaction are satisfied. - /* currently no reactions have maximum requirements, so we can leave the checks commented out for a slight performance boost - PLEASE DO NOT REMOVE THIS CODE. the commenting is here only for a performance increase. - enabling these checks should be as easy as possible and the fact that they are disabled should be as clear as possible - - var/list/max_reqs = reaction.max_requirements - if((max_reqs["TEMP"] && temp > max_reqs["TEMP"]) \ - || (max_reqs["ENER"] && ener > max_reqs["ENER"])) - continue - for(var/id in max_reqs) - if(id == "TEMP" || id == "ENER") - continue - if(cached_gases[id] && cached_gases[id][MOLES] > max_reqs[id]) - continue reaction_loop //at this point, all requirements for the reaction are satisfied. we can now react() - */ + . |= reaction.react(src, holder) if (. & STOP_REACTIONS) break diff --git a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm index c3004fb6fad..7acd8625d45 100644 --- a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm +++ b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm @@ -43,7 +43,6 @@ . = ..() temperature = initial_temperature - //used by space tiles /datum/gas_mixture/immutable/space initial_temperature = TCMB diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index bc9721ccb67..9b49eee1537 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -36,7 +36,6 @@ //regarding the requirements lists: the minimum or maximum requirements must be non-zero. //when in doubt, use MINIMUM_MOLE_COUNT. var/list/min_requirements - var/list/max_requirements var/exclude = FALSE //do it this way to allow for addition/removal of reactions midmatch in the future var/priority = 100 //lower numbers are checked/react later than higher numbers. if two reactions have the same priority they may happen in either order var/name = "reaction" @@ -534,4 +533,4 @@ var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) air.temperature = CLAMP((air.temperature*old_heat_capacity + energy_released)/new_heat_capacity,TCMB,INFINITY) - return REACTING \ No newline at end of file + return REACTING diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index d660be433fe..d19e6bbcf8d 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -48,6 +48,12 @@ radio.canhear_range = 0 radio.recalculateChannels() +/obj/machinery/atmospherics/components/unary/cryo_cell/Exited(atom/movable/AM, atom/newloc) + var/oldoccupant = occupant + . = ..() // Parent proc takes care of removing occupant if necessary + if (AM == oldoccupant) + update_icon() + /obj/machinery/atmospherics/components/unary/cryo_cell/on_construction() ..(dir, dir) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm index 851085b0437..03ae98bb6a6 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm @@ -42,13 +42,6 @@ to_chat(user, "You cannot unwrench [src], detach [connected_device] first!") return FALSE -/obj/machinery/atmospherics/components/unary/portables_connector/portableConnectorReturnAir() - return connected_device.portableConnectorReturnAir() - -/obj/proc/portableConnectorReturnAir() - return - - /obj/machinery/atmospherics/components/unary/portables_connector/layer1 piping_layer = 1 icon_state = "connector_map-1" diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 3ef4f62ac6c..e5612d67589 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -218,7 +218,8 @@ var/datum/pipeline/P = PL[i] if(!P) continue - GL += P.return_air() + GL += P.other_airs + GL += P.air for(var/atmosmch in P.other_atmosmch) if (istype(atmosmch, /obj/machinery/atmospherics/components/binary/valve)) var/obj/machinery/atmospherics/components/binary/valve/V = atmosmch @@ -228,20 +229,29 @@ else if (istype(atmosmch, /obj/machinery/atmospherics/components/unary/portables_connector)) var/obj/machinery/atmospherics/components/unary/portables_connector/C = atmosmch if(C.connected_device) - GL += C.portableConnectorReturnAir() + GL += C.connected_device.air_contents var/total_thermal_energy = 0 var/total_heat_capacity = 0 var/datum/gas_mixture/total_gas_mixture = new(0) + var/list/total_gases = total_gas_mixture.gases + for(var/i in GL) var/datum/gas_mixture/G = i total_gas_mixture.volume += G.volume - total_gas_mixture.merge(G) + // This is sort of a combined merge + heat_capacity calculation + + var/list/giver_gases = G.gases + //gas transfer + for(var/giver_id in giver_gases) + var/giver_gas_data = giver_gases[giver_id] + ASSERT_GAS(giver_id, total_gas_mixture) + total_gases[giver_id][MOLES] += giver_gas_data[MOLES] + total_heat_capacity += giver_gas_data[MOLES] * giver_gas_data[GAS_META][META_GAS_SPECIFIC_HEAT] total_thermal_energy += THERMAL_ENERGY(G) - total_heat_capacity += G.heat_capacity() total_gas_mixture.temperature = total_heat_capacity ? total_thermal_energy/total_heat_capacity : 0 diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 94b6ac58473..b8bf2fb6eed 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -92,9 +92,6 @@ update_icon() return TRUE -/obj/machinery/portable_atmospherics/portableConnectorReturnAir() - return air_contents - /obj/machinery/portable_atmospherics/AltClick(mob/living/user) if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, !ismonkey(user))) return diff --git a/code/modules/cargo/bounties/chef.dm b/code/modules/cargo/bounties/chef.dm index b9d9ebc184a..a66d6cfd381 100644 --- a/code/modules/cargo/bounties/chef.dm +++ b/code/modules/cargo/bounties/chef.dm @@ -36,7 +36,7 @@ name = "Bread" description = "Problems with central planning have led to bread prices skyrocketing. Ship some bread to ease tensions." reward = 1000 - wanted_types = list(/obj/item/reagent_containers/food/snacks/store/bread, /obj/item/reagent_containers/food/snacks/breadslice, /obj/item/reagent_containers/food/snacks/bun, /obj/item/reagent_containers/food/snacks/pizzabread, /obj/item/reagent_containers/food/snacks/rawpastrybase) + wanted_types = list(/obj/item/reagent_containers/food/snacks/store/bread, /obj/item/reagent_containers/food/snacks/breadslice, /obj/item/reagent_containers/food/snacks/bun, /obj/item/reagent_containers/food/snacks/pizzabread, /obj/item/reagent_containers/food/snacks/rawpastrybase) /datum/bounty/item/chef/pie name = "Pie" @@ -120,7 +120,7 @@ description = "Here at Nanotrasen we consider employees to be family. And you know what families love? Pancakes. Ship a baker's dozen." reward = 5000 required_count = 13 - wanted_types = list(/datum/crafting_recipe/food/pancakes) + wanted_types = list(/obj/item/reagent_containers/food/snacks/pancakes) /datum/bounty/item/chef/nuggies name = "Chicken Nuggets" diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index 82a9d54184b..f3c366a4987 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -684,6 +684,9 @@ GLOBAL_LIST_EMPTY(asset_datums) if(icon_state in icon_states(icon_file)) I = icon(icon_file, icon_state, SOUTH) + var/c = initial(item.color) + if (!isnull(c) && c != "#FFFFFF") + I.Blend(initial(c), ICON_MULTIPLY) else item = new item() I = icon(item.icon, item.icon_state, SOUTH) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index da066e08409..94eec80ed05 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -665,8 +665,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) //The job before the current job. I only use this to get the previous jobs color when I'm filling in blank rows. var/datum/job/lastJob - var/datum/job/overflow = SSjob.GetJob(SSjob.overflow_role) - for(var/datum/job/job in sortList(SSjob.occupations, /proc/cmp_job_display_asc)) index += 1 @@ -694,7 +692,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/available_in_days = job.available_in_days(user.client) HTML += "[rank] \[IN [(available_in_days)] DAYS\]" continue - if((job_preferences[overflow] == JP_LOW) && (rank != SSjob.overflow_role) && !is_banned_from(user.ckey, SSjob.overflow_role)) + if((job_preferences[SSjob.overflow_role] == JP_LOW) && (rank != SSjob.overflow_role) && !is_banned_from(user.ckey, SSjob.overflow_role)) HTML += "[rank]" continue if((rank in GLOB.command_positions) || (rank == "AI"))//Bold head jobs @@ -734,7 +732,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) HTML += "" if(rank == SSjob.overflow_role)//Overflow is special - if(job_preferences[overflow.title] == JP_LOW) + if(job_preferences[SSjob.overflow_role] == JP_LOW) HTML += "Yes" else HTML += "No" diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 32cfa27c4aa..609a49718c6 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -64,6 +64,7 @@ desc = "If you're reading this it means I messed up. This is related to moths eating clothes and I didn't know a better way to do it than making a new food object." list_reagents = list("nutriment" = 1) tastes = list("dust" = 1, "lint" = 1) + foodtype = CLOTH /obj/item/clothing/attack(mob/M, mob/user, def_zone) if(user.a_intent != INTENT_HARM && ismoth(M)) diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 5565cf4a5f9..eddee8115e3 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -47,7 +47,7 @@ armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) brightness_on = 2 //luminosity when on flags_cover = HEADCOVERSEYES - heat = 1000 + heat = 999 /obj/item/clothing/head/hardhat/cakehat/process() var/turf/location = src.loc @@ -64,7 +64,7 @@ force = 15 throwforce = 15 damtype = BURN - hitsound = 'sound/items/welder.ogg' + hitsound = 'sound/weapons/sear.ogg' START_PROCESSING(SSobj, src) /obj/item/clothing/head/hardhat/cakehat/turn_off() diff --git a/code/modules/clothing/suits/chaplainsuits.dm b/code/modules/clothing/suits/chaplainsuits.dm index ebc6b9aaaba..20409af040f 100644 --- a/code/modules/clothing/suits/chaplainsuits.dm +++ b/code/modules/clothing/suits/chaplainsuits.dm @@ -51,13 +51,13 @@ icon_state = "monkfrock" item_state = "monkfrock" body_parts_covered = CHEST|GROIN|LEGS|ARMS - flags_inv = HIDEJUMPSUIT hoodtype = /obj/item/clothing/head/hooded/monkfrock /obj/item/clothing/head/hooded/monkfrock name = "monk's hood" desc = "For when a man wants to cover up his tonsure." icon_state = "monkhood" + item_state = "monkhood" body_parts_covered = HEAD flags_inv = HIDEHAIR|HIDEEARS diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm index 70d75c8077c..756b9fac4b1 100644 --- a/code/modules/events/pirates.dm +++ b/code/modules/events/pirates.dm @@ -132,7 +132,7 @@ if(!active) if(alert(user, "Turning the scrambler on will make the shuttle trackable by GPS. Are you sure you want to do it?", "Scrambler", "Yes", "Cancel") == "Cancel") return - if(active || !user.canUseTopic(src)) + if(active || !user.canUseTopic(src, BE_CLOSE)) return toggle_on(user) update_icon() @@ -447,4 +447,4 @@ /datum/export/pirate/holochip/get_cost(atom/movable/AM) var/obj/item/holochip/H = AM - return H.credits \ No newline at end of file + return H.credits diff --git a/code/modules/events/wizard/rpgloot.dm b/code/modules/events/wizard/rpgloot.dm index 3fc3acec632..0bc626ddf43 100644 --- a/code/modules/events/wizard/rpgloot.dm +++ b/code/modules/events/wizard/rpgloot.dm @@ -8,11 +8,12 @@ /datum/round_event/wizard/rpgloot/start() var/upgrade_scroll_chance = 0 for(var/obj/item/I in world) + CHECK_TICK + if(!(I.flags_1 & INITIALIZED_1)) continue - if(!istype(I.rpg_loot)) - I.rpg_loot = new(I) + I.AddComponent(/datum/component/fantasy) if(istype(I, /obj/item/storage)) var/obj/item/storage/S = I @@ -44,33 +45,7 @@ if(!proximity || !istype(target)) return - var/datum/rpg_loot/rpg_loot_datum = target.rpg_loot - var/turf/T = get_turf(target) - - if(!istype(rpg_loot_datum)) - var/original_name = "[target]" - target.rpg_loot = rpg_loot_datum = new /datum/rpg_loot(target) - - var/span - var/effect_description - if(target.rpg_loot.quality >= 0) - span = "" - effect_description = "shimmering golden shield" - else - span = "" - effect_description = "mottled black glow" - - T.visible_message("[span][original_name] is covered by a [effect_description] and then transforms into [target]!") - - else - var/quality = rpg_loot_datum.quality - - if(can_backfire && quality > 9 && prob((quality - 9)*10)) - T.visible_message("[target] violently glows blue for a while, then evaporates.") - target.burn() - else - T.visible_message("[target] glows blue and seems vaguely \"better\"!") - rpg_loot_datum.modify(upgrade_amount) + target.AddComponent(/datum/component/fantasy, upgrade_amount, null, null, can_backfire, TRUE) if(--uses <= 0) qdel(src) @@ -80,58 +55,3 @@ desc = "Somehow, this piece of paper can be applied to items to make them \"better\". This scroll is made from the tongues of dead paper wizards, and can be used an unlimited number of times, with no drawbacks." uses = INFINITY can_backfire = FALSE - -/datum/rpg_loot - var/positive_prefix = "okay" - var/negative_prefix = "weak" - var/suffix = "something profound" - var/quality = 0 - - var/obj/item/attached - var/original_name - -/datum/rpg_loot/New(attached_item=null) - attached = attached_item - - randomise() - -/datum/rpg_loot/Destroy() - attached = null - -/datum/rpg_loot/proc/randomise() - var/static/list/prefixespositive = list("greater", "major", "blessed", "superior", "empowered", "honed", "true", "glorious", "robust") - var/static/list/prefixesnegative = list("lesser", "minor", "blighted", "inferior", "enfeebled", "rusted", "unsteady", "tragic", "gimped") - var/static/list/suffixes = list("orc slaying", "elf slaying", "corgi slaying", "strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma", "the forest", "the hills", "the plains", "the sea", "the sun", "the moon", "the void", "the world", "the fool", "many secrets", "many tales", "many colors", "rending", "sundering", "the night", "the day") - - var/new_quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0) - - suffix = pick(suffixes) - positive_prefix = pick(prefixespositive) - negative_prefix = pick(prefixesnegative) - - if(prob(50)) - new_quality = -new_quality - - modify(new_quality) - -/datum/rpg_loot/proc/rename() - var/obj/item/I = attached - if(!original_name) - original_name = I.name - if(quality < 0) - I.name = "[negative_prefix] [original_name] of [suffix] [quality]" - else if(quality == 0) - I.name = "[original_name] of [suffix]" - else if(quality > 0) - I.name = "[positive_prefix] [original_name] of [suffix] +[quality]" - -/datum/rpg_loot/proc/modify(quality_mod) - var/obj/item/I = attached - quality += quality_mod - - I.force = max(0,I.force + quality_mod) - I.throwforce = max(0,I.throwforce + quality_mod) - - I.armor = I.armor.modifyAllRatings(quality) - - rename() diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm index ea6a0f06a08..ed38b73771e 100644 --- a/code/modules/fields/timestop.dm +++ b/code/modules/fields/timestop.dm @@ -73,6 +73,11 @@ /datum/proximity_monitor/advanced/timestop/proc/freeze_atom(atom/movable/A) if(immune[A] || global_frozen_atoms[A] || !istype(A)) return FALSE + if(ismob(A)) + var/mob/M = A + if(M.anti_magic_check(check_anti_magic, check_holy)) + immune[A] = TRUE + return var/frozen = TRUE if(isliving(A)) freeze_mob(A) @@ -154,9 +159,6 @@ /datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L) frozen_mobs += L - if(L.anti_magic_check(check_anti_magic, check_holy)) - immune += L - return L.Stun(20, 1, 1) walk(L, 0) //stops them mid pathing even if they're stunimmune if(isanimal(L)) diff --git a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm index 500d3c228a3..c364722e115 100644 --- a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm +++ b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm @@ -24,6 +24,7 @@ icon_state = R.glass_icon_state else var/mutable_appearance/reagent_overlay = mutable_appearance(icon, "glassoverlay") + icon_state = "glass_empty" reagent_overlay.color = mix_color_from_reagents(reagents.reagent_list) add_overlay(reagent_overlay) else diff --git a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm index c91d0e77ab6..91014587180 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/microwave.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/microwave.dm @@ -188,13 +188,13 @@ ..() /obj/machinery/microwave/AltClick(mob/user) - if(user.canUseTopic(src, BE_CLOSE)) + if(user.canUseTopic(src, !issilicon(usr))) cook() /obj/machinery/microwave/ui_interact(mob/user) . = ..() - if(operating || panel_open || !anchored || !user.canUseTopic(src)) + if(operating || panel_open || !anchored || !user.canUseTopic(src, !issilicon(user))) return if(isAI(user) && (stat & NOPOWER)) return @@ -209,7 +209,7 @@ var/choice = show_radial_menu(user, src, isAI(user) ? ai_radial_options : radial_options, require_near = !issilicon(user)) // post choice verification - if(operating || panel_open || !anchored || !user.canUseTopic(src)) + if(operating || panel_open || !anchored || !user.canUseTopic(src, !issilicon(user))) return if(isAI(user) && (stat & NOPOWER)) return diff --git a/code/modules/food_and_drinks/recipes/drinks_recipes.dm b/code/modules/food_and_drinks/recipes/drinks_recipes.dm index 511cc7fe7ef..fdd32766748 100644 --- a/code/modules/food_and_drinks/recipes/drinks_recipes.dm +++ b/code/modules/food_and_drinks/recipes/drinks_recipes.dm @@ -533,11 +533,18 @@ required_reagents = list("hooch" = 1, "absinthe" = 1, "manlydorf" = 1, "syndicatebomb" = 1) mix_message = "The mixture turns to a sickening froth." +/datum/chemical_reaction/lemonade + name = "Lemonade" + id = "lemonade" + results = list("lemonade" = 5) + required_reagents = list("lemonjuice" = 2, "water" = 2, "sugar" = 1, "ice" = 1) + mix_message = "You're suddenly reminded of home." + /datum/chemical_reaction/arnold_palmer name = "Arnold Palmer" id = "arnold_palmer" results = list("arnold_palmer" = 2) - required_reagents = list("tea" = 1, "lemonjuice" = 1) + required_reagents = list("tea" = 1, "lemonade" = 1) mix_message = "The smells of fresh green grass and sand traps waft through the air as the mixture turns a friendly yellow-orange." /datum/chemical_reaction/chocolate_milk diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css index f79bf982af9..0eab0aea60c 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ b/code/modules/goonchat/browserassets/css/browserOutput.css @@ -17,7 +17,7 @@ body { line-height: 1.2; overflow-x: hidden; overflow-y: scroll; - word-wrap: break-word; + word-wrap: break-word; scrollbar-face-color:#1A1A1A; scrollbar-track-color:#171717; scrollbar-highlight-color:#171717; @@ -305,6 +305,7 @@ em {font-style: normal; font-weight: bold;} .userdanger {color: #c51e1e; font-weight: bold; font-size: 24px;} .danger {color: #c51e1e;} .warning {color: #c51e1e; font-style: italic;} +.alertwarning {color: #FF0000; font-weight: bold} .boldwarning {color: #c51e1e; font-style: italic; font-weight: bold} .announce {color: #c51e1e; font-weight: bold;} .boldannounce {color: #c51e1e; font-weight: bold;} @@ -318,6 +319,8 @@ em {font-style: normal; font-weight: bold;} .unconscious {color: #a4bad6; font-weight: bold;} .suicide {color: #ff5050; font-style: italic;} .green {color: #059223;} +.red {color: #FF0000} +.blue {color: #215cff} .nicegreen {color: #059223;} .shadowling {color: #8e8a99;} .cult {color: #aa1c1c;} diff --git a/code/modules/goonchat/browserassets/css/browserOutput_white.css b/code/modules/goonchat/browserassets/css/browserOutput_white.css index cbf1daad751..09d2539039c 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput_white.css +++ b/code/modules/goonchat/browserassets/css/browserOutput_white.css @@ -303,6 +303,7 @@ h1.alert, h2.alert {color: #000000;} .userdanger {color: #ff0000; font-weight: bold; font-size: 24px;} .danger {color: #ff0000;} .warning {color: #ff0000; font-style: italic;} +.alertwarning {color: #FF0000; font-weight: bold} .boldwarning {color: #ff0000; font-style: italic; font-weight: bold} .announce {color: #228b22; font-weight: bold;} .boldannounce {color: #ff0000; font-weight: bold;} @@ -316,7 +317,9 @@ h1.alert, h2.alert {color: #000000;} .unconscious {color: #0000ff; font-weight: bold;} .suicide {color: #ff5050; font-style: italic;} .green {color: #03ff39;} -.nicegreen {color: #14a833;} +.red {color: #FF0000} +.blue {color: #0000FF} +.nicegreen {color: #14a833;} .shadowling {color: #3b2769;} .cult {color: #960000;} diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm index 7a847032d9f..6864de381a6 100644 --- a/code/modules/hydroponics/grown/citrus.dm +++ b/code/modules/hydroponics/grown/citrus.dm @@ -178,7 +178,7 @@ /obj/item/reagent_containers/food/snacks/grown/citrus/orange_3d seed = /obj/item/seeds/orange - name = "extradminesional orange" + name = "extradimensional orange" desc = "You can hardly wrap your head around this thing." icon_state = "orang" filling_color = "#FFA500" diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index 1db1ba9bbd8..cfe73c63824 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -41,7 +41,7 @@ blood_type = B.data["blood_type"] features = B.data["features"] factions = B.data["factions"] - factions = B.data["quirks"] + quirks = B.data["quirks"] contains_sample = TRUE visible_message("The [src] is injected with a fresh blood sample.") log_cloning("[key_name(mind)]'s cloning record was added to [src] at [AREACOORD(src)].") diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 5f9a1a7ceba..5c032413b90 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -424,6 +424,7 @@ plant_health = 0 harvest = 0 pestlevel = 0 // Pests die + lastproduce = 0 if(!dead) update_icon() dead = 1 @@ -812,6 +813,7 @@ if(myseed) //Could be that they're just using it as a de-weeder age = 0 plant_health = 0 + lastproduce = 0 if(harvest) harvest = FALSE //To make sure they can't just put in another seed and insta-harvest it qdel(myseed) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 398954acc2b..92d776fc7d9 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -1051,6 +1051,11 @@ /obj/structure/closet/crate/necropolis/colossus name = "colossus chest" +/obj/structure/closet/crate/necropolis/colossus/bullet_act(obj/item/projectile/P) + if(istype(P, /obj/item/projectile/colossus)) + return BULLET_ACT_FORCE_PIERCE + return ..() + /obj/structure/closet/crate/necropolis/colossus/PopulateContents() var/list/choices = subtypesof(/obj/machinery/anomalous_crystal) var/random_crystal = pick(choices) diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index 8183cff25b2..f2aaa7bb574 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -138,9 +138,14 @@ if(!has_minerals) return - for(var/obj/machinery/requests_console/D in GLOB.allConsoles) - if(D.receive_ore_updates) - D.createmessage("Ore Redemption Machine", "New minerals available!", msg, 1, 0) + var/datum/signal/subspace/messaging/rc/signal = new(src, list( + "ore_update" = TRUE, + "sender" = "Ore Redemption Machine", + "message" = msg, + "verified" = "Verified by Ore Redemption Machine", + "priority" = REQ_NORMAL_MESSAGE_PRIORITY + )) + signal.send_to_receivers() /obj/machinery/mineral/ore_redemption/process() if(!materials.mat_container || panel_open || !powered()) diff --git a/code/modules/mob/dead/new_player/sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories.dm index c50f05ad0f9..71106b1927e 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories.dm @@ -262,11 +262,11 @@ /datum/sprite_accessory/hair/cornrowbraid name = "Cornrow Braid" - icon_state = "hair_rowbraid" + icon_state = "hair_cornrowbraid" /datum/sprite_accessory/hair/cornrowdualtail - name = "Cornrow Dual Tail" - icon_state = "hair_rowdualtail" + name = "Cornrow Tail" + icon_state = "hair_cornrowtail" /datum/sprite_accessory/hair/crew name = "Crewcut" @@ -284,10 +284,6 @@ name = "Dandy Pompadour" icon_state = "hair_dandypompadour" -/datum/sprite_accessory/hair/dave - name = "Dave" - icon_state = "hair_dave" - /datum/sprite_accessory/hair/devillock name = "Devil Lock" icon_state = "hair_devilock" @@ -490,7 +486,7 @@ /datum/sprite_accessory/hair/shavedmohawk name = "Mohawk (Unshaven)" - icon_state = "hair_unshavenmohawk" + icon_state = "hair_unshaven_mohawk" /datum/sprite_accessory/hair/mulder name = "Mulder" @@ -616,10 +612,6 @@ name = "Ponytail (Spiky)" icon_state = "hair_spikyponytail" -/datum/sprite_accessory/hair/ziegler - name = "Ponytail (Ziegler)" - icon_state = "hair_ziegler" - /datum/sprite_accessory/hair/poofy name = "Poofy" icon_state = "hair_poofy" @@ -632,10 +624,6 @@ name = "Ronin" icon_state = "hair_ronin" -/datum/sprite_accessory/hair/scully - name = "Scully" - icon_state = "hair_scully" - /datum/sprite_accessory/hair/shaved name = "Shaved" icon_state = "hair_shaved" @@ -870,10 +858,6 @@ name = "Beard (Moonshiner)" icon_state = "facial_moonshiner" -/datum/sprite_accessory/facial_hair/tribearder - name = "Beard (Tribearder)" - icon_state = "facial_tribearder" - /datum/sprite_accessory/facial_hair/longbeard name = "Beard (Long)" icon_state = "facial_longbeard" diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index be7402d3b3e..c1dd9bf251e 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -279,23 +279,6 @@ Doesn't work on other aliens/AI.*/ new choice(user.loc) return TRUE -/obj/effect/proc_holder/alien/regurgitate - name = "Regurgitate" - desc = "Empties the contents of your stomach." - plasma_cost = 0 - action_icon_state = "alien_barf" - -/obj/effect/proc_holder/alien/regurgitate/fire(mob/living/carbon/user) - if(user.stomach_contents.len) - for(var/atom/movable/A in user.stomach_contents) - user.stomach_contents.Remove(A) - A.forceMove(user.drop_location()) - if(isliving(A)) - var/mob/M = A - M.reset_perspective() - user.visible_message("[user] hurls out the contents of their stomach!") - return - /obj/effect/proc_holder/alien/sneak name = "Sneak" desc = "Blend into the shadows to stalk your prey." diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index 48c29737108..7382e747ac3 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -22,11 +22,6 @@ /obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien) -//This is fine right now, if we're adding organ specific damage this needs to be updated -/mob/living/carbon/alien/humanoid/Initialize() - AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null)) - . = ..() - /mob/living/carbon/alien/humanoid/restrained(ignore_grab) return handcuffed @@ -98,10 +93,6 @@ /mob/living/carbon/alien/humanoid/alien_evolve(mob/living/carbon/alien/humanoid/new_xeno) drop_all_held_items() - for(var/atom/movable/A in stomach_contents) - stomach_contents.Remove(A) - new_xeno.stomach_contents.Add(A) - A.forceMove(new_xeno) ..() //For alien evolution/promotion/queen finder procs. Checks for an active alien of that type diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm index 4d2a7d68ad1..95a1cd8b991 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm @@ -1,9 +1,4 @@ -/mob/living/carbon/alien/humanoid/grabbedby(mob/living/carbon/user, supress_message = 0) - if(user == src && pulling && grab_state >= GRAB_AGGRESSIVE && !pulling.anchored && iscarbon(pulling)) - devour_mob(pulling, devour_time = 60) - else - ..() /mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) if(user.a_intent == INTENT_HARM) diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 51fe5e2e100..acfe3f6fafb 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -4,7 +4,7 @@ set invisibility = 0 if (notransform) return - if(..() && !IsInStasis()) //not dead and not in stasis + if(..() && !IS_IN_STASIS(src)) //not dead and not in stasis // GROW! if(amount_grown < max_grown) amount_grown++ diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 89188d61a1c..99b5b64d3f0 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -11,8 +11,8 @@ //This must be done first, so the mob ghosts correctly before DNA etc is nulled . = ..() + QDEL_LIST(hand_bodyparts) QDEL_LIST(internal_organs) - QDEL_LIST(stomach_contents) QDEL_LIST(bodyparts) QDEL_LIST(implants) remove_from_all_data_huds() @@ -22,30 +22,6 @@ /mob/living/carbon/initialize_footstep() AddComponent(/datum/component/footstep, 1, 2) -/mob/living/carbon/relaymove(mob/user, direction) - if(user in src.stomach_contents) - if(prob(40)) - if(prob(25)) - audible_message("You hear something rumbling inside [src]'s stomach...", \ - "You hear something rumbling.", 4,\ - "Something is rumbling inside your stomach!") - var/obj/item/I = user.get_active_held_item() - if(I && I.force) - var/d = rand(round(I.force / 4), I.force) - var/obj/item/bodypart/BP = get_bodypart(BODY_ZONE_CHEST) - if(BP.receive_damage(d, 0)) - update_damage_overlays() - visible_message("[user] attacks [src]'s stomach wall with the [I.name]!", \ - "[user] attacks your stomach wall with the [I.name]!") - playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1) - - if(prob(src.getBruteLoss() - 50)) - for(var/atom/movable/A in stomach_contents) - A.forceMove(drop_location()) - stomach_contents.Remove(A) - src.gib() - - /mob/living/carbon/swap_hand(held_index) if(!held_index) held_index = (active_hand_index % held_items.len)+1 @@ -741,7 +717,7 @@ if(hud_used.healths) if(stat != DEAD) . = 1 - if(!shown_health_amount) + if(shown_health_amount == null) shown_health_amount = health if(shown_health_amount >= maxHealth) hud_used.healths.icon_state = "health0" @@ -868,19 +844,6 @@ /mob/living/carbon/fakefireextinguish() remove_overlay(FIRE_LAYER) - -/mob/living/carbon/proc/devour_mob(mob/living/carbon/C, devour_time = 130) - C.visible_message("[src] is attempting to devour [C]!", \ - "[src] is attempting to devour you!") - if(!do_mob(src, C, devour_time)) - return - if(pulling && pulling == C && grab_state >= GRAB_AGGRESSIVE && a_intent == INTENT_GRAB) - C.visible_message("[src] devours [C]!", \ - "[src] devours you!") - C.forceMove(src) - stomach_contents.Add(C) - log_combat(src, C, "devoured") - /mob/living/carbon/proc/create_bodyparts() var/l_arm_index_next = -1 var/r_arm_index_next = 0 diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index d00cf21de6f..10389b32103 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -5,7 +5,6 @@ hud_possible = list(HEALTH_HUD,STATUS_HUD,ANTAG_HUD,GLAND_HUD,NANITE_HUD,DIAG_NANITE_FULL_HUD) has_limbs = 1 held_items = list(null, null) - var/list/stomach_contents = list() var/list/internal_organs = list() //List of /obj/item/organ in the mob. They don't go in the contents for some reason I don't want to know. var/list/internal_organs_slot= list() //Same as above, but stores "slot ID" - "organ" pairs for easy access. var/silent = FALSE //Can't talk. Value goes down every life proc. //NOTE TO FUTURE CODERS: DO NOT INITIALIZE NUMERICAL VARS AS NULL OR I WILL MURDER YOU. diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 9307e21c4d8..babd0ec041c 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -241,12 +241,13 @@ else gain_trauma_type(BRAIN_TRAUMA_SEVERE) - if(prev_brainloss < BRAIN_DAMAGE_MILD && brainloss >= BRAIN_DAMAGE_MILD) - to_chat(src, "You feel lightheaded.") - else if(prev_brainloss < BRAIN_DAMAGE_SEVERE && brainloss >= BRAIN_DAMAGE_SEVERE) - to_chat(src, "You feel less in control of your thoughts.") - else if(prev_brainloss < (BRAIN_DAMAGE_DEATH - 20) && brainloss >= (BRAIN_DAMAGE_DEATH - 20)) - to_chat(src, "You can feel your mind flickering on and off...") + if (stat < UNCONSCIOUS) // conscious or soft-crit + if(prev_brainloss < BRAIN_DAMAGE_MILD && brainloss >= BRAIN_DAMAGE_MILD) + to_chat(src, "You feel lightheaded.") + else if(prev_brainloss < BRAIN_DAMAGE_SEVERE && brainloss >= BRAIN_DAMAGE_SEVERE) + to_chat(src, "You feel less in control of your thoughts.") + else if(prev_brainloss < (BRAIN_DAMAGE_DEATH - 20) && brainloss >= (BRAIN_DAMAGE_DEATH - 20)) + to_chat(src, "You can feel your mind flickering on and off...") /mob/living/carbon/setBrainLoss(amount) var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index ae0e223e085..88cc5efe31d 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -9,19 +9,17 @@ emote("deathgasp") . = ..() - + for(var/T in get_traumas()) var/datum/brain_trauma/BT = T BT.on_death() - + if(SSticker.mode) SSticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now /mob/living/carbon/gib(no_brain, no_organs, no_bodyparts) var/atom/Tsec = drop_location() for(var/mob/M in src) - if(M in stomach_contents) - stomach_contents.Remove(M) M.forceMove(Tsec) visible_message("[M] bursts out of [src]!") ..() diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 0e6dc2819a5..68a2f65dc92 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -237,40 +237,45 @@ if(stun_absorption[i]["end_time"] > world.time && stun_absorption[i]["examine_message"]) msg += "[t_He] [t_is][stun_absorption[i]["examine_message"]]\n" - if(drunkenness && !skipface && !appears_dead) //Drunkenness - switch(drunkenness) - if(11 to 21) - msg += "[t_He] [t_is] slightly flushed.\n" - if(21.01 to 41) //.01s are used in case drunkenness ends up to be a small decimal - msg += "[t_He] [t_is] flushed.\n" - if(41.01 to 51) - msg += "[t_He] [t_is] quite flushed and [t_his] breath smells of alcohol.\n" - if(51.01 to 61) - msg += "[t_He] [t_is] very flushed and [t_his] movements jerky, with breath reeking of alcohol.\n" - if(61.01 to 91) - msg += "[t_He] look[p_s()] like a drunken mess.\n" - if(91.01 to INFINITY) - msg += "[t_He] [t_is] a shitfaced, slobbering wreck.\n" - - if(HAS_TRAIT(user, TRAIT_EMPATH) && !appears_dead && (src != user)) - if (a_intent != INTENT_HELP) - msg += "[t_He] seem[p_s()] to be on guard.\n" - if (getOxyLoss() >= 10) - msg += "[t_He] seem[p_s()] winded.\n" - if (getToxLoss() >= 10) - msg += "[t_He] seem[p_s()] sickly.\n" - GET_COMPONENT_FROM(mood, /datum/component/mood, src) - if(mood.sanity <= SANITY_DISTURBED) - msg += "[t_He] seem[p_s()] distressed.\n" - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empath", /datum/mood_event/sad_empath, src) - if (HAS_TRAIT(src, TRAIT_BLIND)) - msg += "[t_He] appear[p_s()] to be staring off into space.\n" - if (HAS_TRAIT(src, TRAIT_DEAF)) - msg += "[t_He] appear[p_s()] to not be responding to noises.\n" - - msg += "" - if(!appears_dead) + if(drunkenness && !skipface) //Drunkenness + switch(drunkenness) + if(11 to 21) + msg += "[t_He] [t_is] slightly flushed.\n" + if(21.01 to 41) //.01s are used in case drunkenness ends up to be a small decimal + msg += "[t_He] [t_is] flushed.\n" + if(41.01 to 51) + msg += "[t_He] [t_is] quite flushed and [t_his] breath smells of alcohol.\n" + if(51.01 to 61) + msg += "[t_He] [t_is] very flushed and [t_his] movements jerky, with breath reeking of alcohol.\n" + if(61.01 to 91) + msg += "[t_He] look[p_s()] like a drunken mess.\n" + if(91.01 to INFINITY) + msg += "[t_He] [t_is] a shitfaced, slobbering wreck.\n" + + if(src != user) + if(HAS_TRAIT(user, TRAIT_EMPATH)) + if (a_intent != INTENT_HELP) + msg += "[t_He] seem[p_s()] to be on guard.\n" + if (getOxyLoss() >= 10) + msg += "[t_He] seem[p_s()] winded.\n" + if (getToxLoss() >= 10) + msg += "[t_He] seem[p_s()] sickly.\n" + GET_COMPONENT_FROM(mood, /datum/component/mood, src) + if(mood.sanity <= SANITY_DISTURBED) + msg += "[t_He] seem[p_s()] distressed.\n" + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empath", /datum/mood_event/sad_empath, src) + if (HAS_TRAIT(src, TRAIT_BLIND)) + msg += "[t_He] appear[p_s()] to be staring off into space.\n" + if (HAS_TRAIT(src, TRAIT_DEAF)) + msg += "[t_He] appear[p_s()] to not be responding to noises.\n" + + msg += "" + + if(HAS_TRAIT(user, TRAIT_SPIRITUAL) && mind?.isholy) + msg += "[t_He] [t_has] a holy aura about [t_him].\n" + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "religious_comfort", /datum/mood_event/religiously_comforted) + if(stat == UNCONSCIOUS) msg += "[t_He] [t_is]n't responding to anything around [t_him] and seem[p_s()] to be asleep.\n" else diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 2c86eaf6c75..be172bcf0fb 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -700,7 +700,7 @@ to_chat(src, "You can't do that right now!") return FALSE if(!Adjacent(M) && (M.loc != src)) - if((be_close == 0) || (!no_tk && (dna.check_mutation(TK) && tkMaxRangeCheck(src, M)))) + if((be_close == FALSE) || (!no_tk && (dna.check_mutation(TK) && tkMaxRangeCheck(src, M)))) return TRUE to_chat(src, "You are too far away!") return FALSE diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 90fb37f44fc..f8d3e525ce1 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -169,12 +169,6 @@ return ..() -/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0) - if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (HAS_TRAIT(src, TRAIT_FAT)) && ismonkey(pulling)) - devour_mob(pulling) - else - ..() - /mob/living/carbon/human/grippedby(mob/living/user, instant = FALSE) if(w_uniform) w_uniform.add_fingerprint(user) @@ -238,7 +232,7 @@ "[M] disarmed [src]!") else if(!M.client || prob(5)) // only natural monkeys get to stun reliably, (they only do it occasionaly) playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) - if (src.IsKnockdown() && !src.IsParalyzed()) + if (src.IsKnockdown() && !src.IsParalyzed()) Paralyze(40) log_combat(M, src, "pinned") visible_message("[M] has pinned down [src]!", \ diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 94ca3443da3..698d76a8800 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -43,8 +43,6 @@ /mob/living/carbon/human/Move(NewLoc, direct) . = ..() - for(var/datum/mutation/human/HM in dna.mutations) - HM.on_move(NewLoc) if(shoes) if(mobility_flags & MOBILITY_STAND) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index ca3e63f38d4..761c01d9977 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -28,9 +28,11 @@ if (QDELETED(src)) return 0 - if(!IsInStasis()) + if(!IS_IN_STASIS(src)) if(.) //not dead - handle_active_genes() + + for(var/datum/mutation/human/HM in dna.mutations) // Handle active genes + HM.on_life() if(stat != DEAD) //heart attack stuff @@ -310,10 +312,6 @@ clear_alert("embeddedobject") SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "embedded") -/mob/living/carbon/human/proc/handle_active_genes() - for(var/datum/mutation/human/HM in dna.mutations) - HM.on_life() - /mob/living/carbon/human/proc/handle_heart() var/we_breath = !HAS_TRAIT_FROM(src, TRAIT_NOBREATH, SPECIES_TRAIT) diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 3171b92139a..23ae58c3daf 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -403,9 +403,9 @@ if(P.starting) var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) - var/turf/target = get_turf(P.starting) // redirect the projectile - P.preparePixelProjectile(locate(CLAMP(target.x + new_x, 1, world.maxx), CLAMP(target.y + new_y, 1, world.maxy), H.z), H) + P.firer = H + P.preparePixelProjectile(locate(CLAMP(new_x, 1, world.maxx), CLAMP(new_y, 1, world.maxy), H.z), H) return BULLET_ACT_FORCE_PIERCE return ..() diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index ad0a7733c43..8a7f775a489 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -11,7 +11,7 @@ attack_sound = 'sound/weapons/slash.ogg' miss_sound = 'sound/weapons/slashmiss.ogg' meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/moth - liked_food = VEGETABLES | DAIRY + liked_food = VEGETABLES | DAIRY | CLOTH disliked_food = FRUIT | GROSS toxic_food = MEAT | RAW mutanteyes = /obj/item/organ/eyes/moth diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index ae8c0e6802f..7130a8b352c 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -14,7 +14,7 @@ var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg') disliked_food = NONE liked_food = GROSS | MEAT | RAW - changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | ERT_SPAWN + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | ERT_SPAWN /datum/species/zombie/check_roundstart_eligible() if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 8d8a939762f..dc051b0ad1b 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -8,7 +8,7 @@ damageoverlaytemp = 0 update_damage_hud() - if(!IsInStasis()) + if(!IS_IN_STASIS(src)) if(stat != DEAD) //Reagent processing needs to come before breathing, to prevent edge cases. handle_organs() @@ -375,23 +375,6 @@ if(radiation > RAD_MOB_SAFE) adjustToxLoss(log(radiation-RAD_MOB_SAFE)*RAD_TOX_COEFFICIENT) -/mob/living/carbon/handle_stomach() - set waitfor = 0 - for(var/mob/living/M in stomach_contents) - if(M.loc != src) - stomach_contents.Remove(M) - continue - if(iscarbon(M) && stat != DEAD) - if(M.stat == DEAD) - M.death(1) - stomach_contents.Remove(M) - qdel(M) - continue - if(SSmobs.times_fired%3==1) - if(!(M.status_flags & GODMODE)) - M.adjustBruteLoss(5) - adjust_nutrition(10) - /* Alcohol Poisoning Chart diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 624ed6d0160..9f7fdbe96e4 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -9,7 +9,7 @@ if (notransform) return - if(..() && !IsInStasis()) + if(..() && !IS_IN_STASIS(src)) if(!client) if(stat == CONSCIOUS) diff --git a/code/modules/mob/living/carbon/say.dm b/code/modules/mob/living/carbon/say.dm index c4751434f17..bbb65518d70 100644 --- a/code/modules/mob/living/carbon/say.dm +++ b/code/modules/mob/living/carbon/say.dm @@ -46,4 +46,14 @@ for(var/T in get_traumas()) var/datum/brain_trauma/trauma = T message = trauma.on_hear(message, speaker, message_language, raw_message, radio_freq) + + if (src.mind.has_antag_datum(/datum/antagonist/traitor)) + for (var/codeword in GLOB.syndicate_code_phrase) + var/regex/codeword_match = new("([codeword])", "ig") + message = codeword_match.Replace(message, "$1") + + for (var/codeword in GLOB.syndicate_code_response) + var/regex/codeword_match = new("([codeword])", "ig") + message = codeword_match.Replace(message, "$1") + return message diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 7c2b3a0f51d..0d40c75d80b 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -35,7 +35,7 @@ if(!loc) return - if(!IsInStasis()) + if(!IS_IN_STASIS(src)) if(stat != DEAD) //Mutations and radiation @@ -59,9 +59,6 @@ if(environment) handle_environment(environment) - //stuff in the stomach - handle_stomach() - handle_gravity() if(stat != DEAD) @@ -117,9 +114,6 @@ var/turf/location = get_turf(src) location.hotspot_expose(700, 50, 1) -/mob/living/proc/handle_stomach() - return - //this updates all special effects: knockdown, druggy, stuttering, etc.. /mob/living/proc/handle_status_effects() if(confused) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 9f6616d96fd..15c6e1ac38f 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -383,7 +383,7 @@ death() /mob/living/incapacitated(ignore_restraints = FALSE, ignore_grab = FALSE, check_immobilized = FALSE, ignore_stasis = FALSE) - if(stat || IsUnconscious() || IsStun() || IsParalyzed() || (check_immobilized && IsImmobilized()) || (!ignore_restraints && restrained(ignore_grab)) || (!ignore_stasis && IsInStasis())) + if(stat || IsUnconscious() || IsStun() || IsParalyzed() || (check_immobilized && IsImmobilized()) || (!ignore_restraints && restrained(ignore_grab)) || (!ignore_stasis && IS_IN_STASIS(src))) return TRUE /mob/living/canUseStorage() @@ -1097,8 +1097,7 @@ var/stun = IsStun() var/knockdown = IsKnockdown() var/ignore_legs = get_leg_ignore() - var/in_stasis = IsInStasis() - var/canmove = !IsImmobilized() && !stun && conscious && !paralyzed && !buckled && (!stat_softcrit || !pulledby) && !chokehold && !IsFrozen() && !in_stasis && (has_arms || ignore_legs || has_legs) + var/canmove = !IsImmobilized() && !stun && conscious && !paralyzed && !buckled && (!stat_softcrit || !pulledby) && !chokehold && !IsFrozen() && !IS_IN_STASIS(src) && (has_arms || ignore_legs || has_legs) if(canmove) mobility_flags |= MOBILITY_MOVE else diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 2215d6d5980..70fea44ed1d 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -229,6 +229,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list( // Recompose message for AI hrefs, language incomprehension. message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode) message = hear_intercept(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) + show_message(message, 2, deaf_message, deaf_type) return message diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index f1e2d1ee47d..15ed13269a5 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -29,6 +29,7 @@ sec_hud = DATA_HUD_SECURITY_BASIC d_hud = DATA_HUD_DIAGNOSTIC_ADVANCED mob_size = MOB_SIZE_LARGE + var/battery = 200 //emergency power if the AI's APC is off var/list/network = list("ss13") var/obj/machinery/camera/current var/list/connected_robots = list() @@ -41,7 +42,6 @@ var/obj/mecha/controlled_mech //For controlled_mech a mech, to determine whether to relaymove or use the AI eye. var/radio_enabled = TRUE //Determins if a carded AI can speak with its built in radio or not. radiomod = ";" //AIs will, by default, state their laws on the internal radio. - var/obj/item/pda/ai/aiPDA var/obj/item/multitool/aiMulti var/mob/living/simple_animal/bot/Bot var/tracking = FALSE //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed. @@ -233,6 +233,8 @@ if(statpanel("Status")) if(!stat) stat(null, text("System integrity: [(health+100)/2]%")) + if(isturf(loc)) //only show if we're "in" a core + stat(null, text("Backup Power: [battery/2]%")) stat(null, text("Connected cyborgs: [connected_robots.len]")) for(var/mob/living/silicon/robot/R in connected_robots) var/robot_status = "Nominal" @@ -282,15 +284,6 @@ viewalerts = 1 src << browse(dat, "window=aialerts&can_close=0") -/mob/living/silicon/ai/proc/ai_roster() - var/dat = "Crew RosterCrew Roster:

" - - dat += GLOB.data_core.get_manifest() - dat += "" - - src << browse(dat, "window=airoster") - onclose(src, "airoster") - /mob/living/silicon/ai/proc/ai_call_shuttle() if(control_disabled) to_chat(usr, "Wireless control is disabled!") @@ -338,8 +331,14 @@ set name = "Toggle Floor Bolts" if(!isturf(loc)) // if their location isn't a turf return // stop - if(incapacitated()) + if(stat == DEAD) return + if(incapacitated()) + if(battery < 50) + to_chat(src, "Insufficient backup power!") + return + battery = battery - 50 + to_chat(src, "You route power from your backup battery to move the bolts.") var/is_anchored = FALSE if(move_resist == MOVE_FORCE_VERY_STRONG) move_resist = MOVE_FORCE_NORMAL @@ -813,7 +812,8 @@ to_chat(user, "No intelligence patterns detected." ) return ShutOffDoomsdayDevice() - new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location. + var/obj/structure/AIcore/new_core = new /obj/structure/AIcore/deactivated(loc)//Spawns a deactivated terminal at AI location. + new_core.circuit.battery = battery ai_restore_power()//So the AI initially has power. control_disabled = TRUE //Can't control things remotely if you're stuck in a card! radio_enabled = FALSE //No talking on the built-in radio for you either! diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 15a04235cc0..fb7aa030e09 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -28,11 +28,15 @@ // Handle power damage (oxy) if(aiRestorePowerRoutine) // Lost power - adjustOxyLoss(1) + if (!battery) + to_chat(src, "Your backup battery's output drops below usable levels. It takes only a moment longer for your systems to fail, corrupted and unusable.") + adjustOxyLoss(200) + else + battery -- else // Gain Power - if(getOxyLoss()) - adjustOxyLoss(-1) + if (battery < 200) + battery ++ if(!lacks_power()) var/area/home = get_area(src) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index b09358bb487..c2bf28280d8 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -27,7 +27,6 @@ var/speakDoubleExclamation = "alarms" var/speakQuery = "queries" - var/obj/item/radio/headset // The pAI's headset var/obj/item/pai_cable/cable // The cable we produce and use when door or camera jacking var/master // Name of the one who commands us @@ -39,10 +38,6 @@ var/screen // Which screen our main window displays var/subscreen // Which specific function of the main screen is being displayed - var/obj/item/pda/ai/pai/pda = null - - var/obj/machinery/newscaster //pAI Newscaster - var/secHUD = 0 // Toggles whether the Security HUD is active or not var/medHUD = 0 // Toggles whether the Medical HUD is active or not @@ -58,6 +53,8 @@ var/obj/item/integrated_signaler/signaler // AI's signaller var/obj/item/instrument/piano_synth/internal_instrument + var/obj/machinery/newscaster //pAI Newscaster + var/obj/item/healthanalyzer/hostscan //pAI healthanalyzer var/encryptmod = FALSE var/holoform = FALSE @@ -111,20 +108,21 @@ P.setPersonality(src) forceMove(P) card = P - job = "personal AI" + job = "Personal AI" signaler = new(src) + hostscan = new /obj/item/healthanalyzer(src) if(!radio) radio = new /obj/item/radio/headset/silicon/pai(src) newscaster = new /obj/machinery/newscaster(src) if(!aicamera) aicamera = new /obj/item/camera/siliconcam/ai_camera(src) + aicamera.flash_enabled = TRUE //PDA - pda = new(src) - spawn(5) - pda.ownjob = "pAI Messenger" - pda.owner = text("[]", src) - pda.name = pda.owner + " (" + pda.ownjob + ")" + aiPDA = new/obj/item/pda/ai(src) + aiPDA.owner = real_name + aiPDA.ownjob = "pAI Messenger" + aiPDA.name = real_name + " (" + aiPDA.ownjob + ")" . = ..() diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 00bca64322c..0a4f20096a9 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -6,21 +6,30 @@ /mob/living/silicon/pai/var/list/available_software = list( + //Nightvision + //T-Ray + //radiation eyes + //chem goggs + //mesons "crew manifest" = 5, "digital messenger" = 5, - "medical records" = 15, - "security records" = 15, - //"camera jack" = 10, - "door jack" = 30, "atmosphere sensor" = 5, + "photography module" = 5, + "remote signaller" = 10, + "medical records" = 10, + "security records" = 10, + "camera zoom" = 10, + "host scan" = 10, + //"camera jack" = 10, //"heartbeat sensor" = 10, - "security HUD" = 20, + //"projection array" = 15, "medical HUD" = 20, - "universal translator" = 35, - //"projection array" = 15 - "remote signaller" = 5, - "loudness booster" = 25, - "encryption keys" = 20 + "security HUD" = 20, + "loudness booster" = 20, + "newscaster" = 20, + "door jack" = 25, + "encryption keys" = 25, + "universal translator" = 35 ) /mob/living/silicon/pai/proc/paiInterface() @@ -69,6 +78,9 @@ left_part = softwareSignal() if("loudness") left_part = softwareLoudness() + if("hostscan") + left_part = softwareHostScan() + //usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc @@ -114,176 +126,180 @@ onclose(src, "pai") temp = null - - /mob/living/silicon/pai/Topic(href, href_list) - ..() + if(..()) + return var/soft = href_list["software"] var/sub = href_list["sub"] if(soft) screen = soft - if(sub) - subscreen = text2num(sub) - switch(soft) - // Purchasing new software - if("buy") - if(subscreen == 1) - var/target = href_list["buy"] - if(available_software.Find(target) && !software.Find(target)) - var/cost = available_software[target] - if(ram >= cost) - software.Add(target) - ram -= cost + if(sub) + subscreen = text2num(sub) + switch(soft) + if("buy") // Purchasing new software + if(subscreen == 1) + var/target = href_list["buy"] + if(available_software.Find(target) && !software.Find(target)) + var/cost = available_software[target] + if(ram >= cost) + software.Add(target) + ram -= cost + var/datum/hud/pai/pAIhud = hud_used + pAIhud?.update_software_buttons() + else + temp = "Insufficient RAM available." else - temp = "Insufficient RAM available." - else - temp = "Trunk \"[target]\" not found." - - // Configuring onboard radio - if("radio") - radio.attack_self(src) - - if("image") - var/newImage = input("Select your new display image.", "Display Image", "Happy") in list("Happy", "Cat", "Extremely Happy", "Face", "Laugh", "Off", "Sad", "Angry", "What") - var/pID = 1 - - switch(newImage) - if("Happy") - pID = 1 - if("Cat") - pID = 2 - if("Extremely Happy") - pID = 3 - if("Face") - pID = 4 - if("Laugh") - pID = 5 - if("Off") - pID = 6 - if("Sad") - pID = 7 - if("Angry") - pID = 8 - if("What") - pID = 9 - if("Null") - pID = 10 - card.setEmotion(pID) - - if("news") - newscaster.ui_interact(src) - - if("signaller") - - if(href_list["send"]) - signaler.send_activation() - audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*") - playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE) - - if(href_list["freq"]) - var/new_frequency = (signaler.frequency + text2num(href_list["freq"])) - if(new_frequency < MIN_FREE_FREQ || new_frequency > MAX_FREE_FREQ) - new_frequency = sanitize_frequency(new_frequency) - signaler.set_frequency(new_frequency) - - if(href_list["code"]) - signaler.code += text2num(href_list["code"]) - signaler.code = round(signaler.code) - signaler.code = min(100, signaler.code) - signaler.code = max(1, signaler.code) + temp = "Trunk \"[target]\" not found." + if("radio") // Configuring onboard radio + radio.attack_self(src) - if("directive") - if(href_list["getdna"]) - var/mob/living/M = card.loc - var/count = 0 - while(!isliving(M)) - if(!M || !M.loc) - return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful) - M = M.loc - count++ - if(count >= 6) + if("image") // Set pAI card display face + var/newImage = input("Select your new display image.", "Display Image", "Happy") in list("Happy", "Cat", "Extremely Happy", "Face", "Laugh", "Off", "Sad", "Angry", "What") + var/pID = 1 + + switch(newImage) + if("Happy") + pID = 1 + if("Cat") + pID = 2 + if("Extremely Happy") + pID = 3 + if("Face") + pID = 4 + if("Laugh") + pID = 5 + if("Off") + pID = 6 + if("Sad") + pID = 7 + if("Angry") + pID = 8 + if("What") + pID = 9 + if("Null") + pID = 10 + card.setEmotion(pID) + + if("news") + newscaster.ui_interact(src) + + if("camzoom") + aicamera.adjust_zoom(usr) + + if("signaller") + if(href_list["send"]) + signaler.send_activation() + audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*") + playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE) + + if(href_list["freq"]) + var/new_frequency = (signaler.frequency + text2num(href_list["freq"])) + if(new_frequency < MIN_FREE_FREQ || new_frequency > MAX_FREE_FREQ) + new_frequency = sanitize_frequency(new_frequency) + signaler.set_frequency(new_frequency) + + if(href_list["code"]) + signaler.code += text2num(href_list["code"]) + signaler.code = round(signaler.code) + signaler.code = min(100, signaler.code) + signaler.code = max(1, signaler.code) + + if("directive") + if(href_list["getdna"]) + if(iscarbon(card.loc)) + CheckDNA(card.loc, src) //you should only be able to check when directly in hand, muh immersions? + else to_chat(src, "You are not being carried by anyone!") - return 0 - spawn CheckDNA(M, src) + return 0 // FALSE ? If you return here you won't call paiinterface() below - if("pdamessage") - if(!isnull(pda)) - if(href_list["toggler"]) - pda.toff = !pda.toff - else if(href_list["ringer"]) - pda.silent = !pda.silent - else if(href_list["target"]) - if(silent) - return alert("Communications circuits remain uninitialized.") + if("pdamessage") + if(!isnull(aiPDA)) + if(href_list["toggler"]) + aiPDA.toff = !aiPDA.toff + else if(href_list["ringer"]) + aiPDA.silent = !aiPDA.silent + else if(href_list["target"]) + if(silent) + return alert("Communications circuits remain uninitialized.") + var/target = locate(href_list["target"]) in GLOB.PDAs + aiPDA.create_message(src, target) - var/target = locate(href_list["target"]) in GLOB.PDAs - pda.create_message(src, target) + if("medicalrecord") // Accessing medical records + if(subscreen == 1) + medicalActive1 = find_record("id", href_list["med_rec"], GLOB.data_core.general) + if(medicalActive1) + medicalActive2 = find_record("id", href_list["med_rec"], GLOB.data_core.medical) + if(!medicalActive2) + medicalActive1 = null + temp = "Unable to locate requested security record. Record may have been deleted, or never have existed." - // Accessing medical records - if("medicalrecord") - if(subscreen == 1) - medicalActive1 = find_record("id", href_list["med_rec"], GLOB.data_core.general) - if(medicalActive1) - medicalActive2 = find_record("id", href_list["med_rec"], GLOB.data_core.medical) - if(!medicalActive2) - medicalActive1 = null - temp = "Unable to locate requested security record. Record may have been deleted, or never have existed." + if("securityrecord") + if(subscreen == 1) + securityActive1 = find_record("id", href_list["sec_rec"], GLOB.data_core.general) + if(securityActive1) + securityActive2 = find_record("id", href_list["sec_rec"], GLOB.data_core.security) + if(!securityActive2) + securityActive1 = null + temp = "Unable to locate requested security record. Record may have been deleted, or never have existed." - if("securityrecord") - if(subscreen == 1) - securityActive1 = find_record("id", href_list["sec_rec"], GLOB.data_core.general) - if(securityActive1) - securityActive2 = find_record("id", href_list["sec_rec"], GLOB.data_core.security) - if(!securityActive2) - securityActive1 = null - temp = "Unable to locate requested security record. Record may have been deleted, or never have existed." - if("securityhud") - if(href_list["toggle"]) - secHUD = !secHUD - if(secHUD) - var/datum/atom_hud/sec = GLOB.huds[sec_hud] - sec.add_hud_to(src) - else - var/datum/atom_hud/sec = GLOB.huds[sec_hud] - sec.remove_hud_from(src) - if("medicalhud") - if(href_list["toggle"]) - medHUD = !medHUD - if(medHUD) - var/datum/atom_hud/med = GLOB.huds[med_hud] - med.add_hud_to(src) - else - var/datum/atom_hud/med = GLOB.huds[med_hud] - med.remove_hud_from(src) - if("encryptionkeys") - if(href_list["toggle"]) - encryptmod = TRUE - if("translator") - if(href_list["toggle"]) - grant_all_languages(TRUE) - // this is PERMAMENT. - if("doorjack") - if(href_list["jack"]) - if(cable && cable.machine) - hackdoor = cable.machine - hackloop() - if(href_list["cancel"]) - hackdoor = null - if(href_list["cable"]) - var/turf/T = get_turf(loc) - cable = new /obj/item/pai_cable(T) - T.visible_message("A port on [src] opens to reveal [cable], which promptly falls to the floor.", "You hear the soft click of something light and hard falling to the ground.") - if("loudness") - if(subscreen == 1) // Open Instrument - internal_instrument.interact(src) - if(subscreen == 2) // Change Instrument type - internal_instrument.selectInstrument() + if("securityhud") + if(href_list["toggle"]) + secHUD = !secHUD + if(secHUD) + var/datum/atom_hud/sec = GLOB.huds[sec_hud] + sec.add_hud_to(src) + else + var/datum/atom_hud/sec = GLOB.huds[sec_hud] + sec.remove_hud_from(src) - //updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window - paiInterface() // So we'll just call the update directly rather than doing some default checks - return + if("medicalhud") + if(href_list["toggle"]) + medHUD = !medHUD + if(medHUD) + var/datum/atom_hud/med = GLOB.huds[med_hud] + med.add_hud_to(src) + else + var/datum/atom_hud/med = GLOB.huds[med_hud] + med.remove_hud_from(src) + + if("hostscan") + if(href_list["toggle"]) + var/mob/living/silicon/pai/pAI = usr + pAI.hostscan.attack_self(usr) + if(href_list["toggle2"]) + var/mob/living/silicon/pai/pAI = usr + pAI.hostscan.toggle_mode() + + if("encryptionkeys") + if(href_list["toggle"]) + encryptmod = TRUE + + if("translator") + if(href_list["toggle"]) + grant_all_languages(TRUE) + // this is PERMAMENT. + + if("doorjack") + if(href_list["jack"]) + if(cable && cable.machine) + hackdoor = cable.machine + hackloop() + if(href_list["cancel"]) + hackdoor = null + if(href_list["cable"]) + var/turf/T = get_turf(loc) + cable = new /obj/item/pai_cable(T) + T.visible_message("A port on [src] opens to reveal [cable], which promptly falls to the floor.", "You hear the soft click of something light and hard falling to the ground.") + + if("loudness") + if(subscreen == 1) // Open Instrument + internal_instrument.interact(src) + if(subscreen == 2) // Change Instrument type + internal_instrument.selectInstrument() + + paiInterface() // MENUS @@ -295,7 +311,6 @@ dat += "
Directives
" dat += "Radio Configuration
" dat += "Screen Display
" - dat += "Newscaster
" //dat += "Text Messaging
" dat += "
" @@ -306,6 +321,8 @@ dat += "Digital Messenger
" if(s == "crew manifest") dat += "Crew Manifest
" + if(s == "host scan") + dat += "Host Health Scan" if(s == "medical records") dat += "Medical Records
" if(s == "security records") @@ -321,6 +338,8 @@ // Advanced dat += "Advanced
" for(var/s in software) + if(s == "camera zoom") + dat += "Adjust Camera Zoom
" if(s == "atmosphere sensor") dat += "Atmospheric Sensor
" if(s == "heartbeat sensor") @@ -390,6 +409,8 @@ return dat /mob/living/silicon/pai/proc/CheckDNA(mob/living/carbon/M, mob/living/silicon/pai/P) + if(!istype(M)) + return var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No") if(answer == "Yes") M.visible_message("[M] presses [M.p_their()] thumb against [P].",\ @@ -482,7 +503,7 @@ . += "
\nBack
" return . -// Encryption kets +// Encryption Keys /mob/living/silicon/pai/proc/softwareEncryptionKeys() var/dat = {"

Encryption Key Firmware


When enabled, this device will be able to use up to two (2) encryption keys for departmental channel access.

@@ -500,7 +521,7 @@ // Security HUD /mob/living/silicon/pai/proc/facialRecognition() - var/dat = {"

Facial Recognition Suite


+ var/dat = {"

Facial Recognition Overlay


When enabled, this package will scan all viewable faces and compare them against the known criminal database, providing real-time graphical data about any detected persons of interest.

The package is currently [ (secHUD) ? "en" : "dis" ]abled.
Toggle Package
@@ -510,47 +531,24 @@ // Medical HUD /mob/living/silicon/pai/proc/medicalAnalysis() var/dat = "" - if(subscreen == 0) - dat += {"

Medical Analysis Suite


-

Visual Status Overlay


- When enabled, this package will scan all nearby crewmembers' vitals and provide real-time graphical data about their state of health.

- The suite is currently [ (medHUD) ? "en" : "dis" ]abled.
- Toggle Suite
-
- Host Bioscan
- "} - if(subscreen == 1) - dat += {"

Medical Analysis Suite


-

Host Bioscan


- "} - var/mob/living/M = card.loc - if(!isliving(M)) - while(!isliving(M)) - if(isturf(M)) - temp = "Error: No biological host found.
" - subscreen = 0 - return dat - M = M.loc - dat += {"Bioscan Results for [M]:
" - Overall Status: [M.stat > 1 ? "dead" : "[M.health]% healthy"]
- Scan Breakdown:
- Respiratory: [M.getOxyLoss() > 50 ? "" : ""][M.getOxyLoss()]
- Toxicology: [M.getToxLoss() > 50 ? "" : ""][M.getToxLoss()]
- Burns: [M.getFireLoss() > 50 ? "" : ""][M.getFireLoss()]
- Structural Integrity: [M.getBruteLoss() > 50 ? "" : ""][M.getBruteLoss()]
- Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)
- "} - for(var/thing in M.diseases) - var/datum/disease/D = thing - dat += {"

Infection Detected.


- Name: [D.name]
- Type: [D.spread_text]
- Stage: [D.stage]/[D.max_stages]
- Possible Cure: [D.cure_text]
- "} - dat += "Visual Status Overlay
" + dat += {"

Medical Analysis Overlay


+ When enabled, this package will scan all nearby crewmembers' vitals and provide real-time graphical data about their state of health.

+ The suite is currently [ (medHUD) ? "en" : "dis" ]abled.
+ Toggle Suite
+ "} return dat +//Health Scanner +/mob/living/silicon/pai/proc/softwareHostScan() + + var/dat = "" + dat += {"

Host Bisoscan Settings


+ + Change Scan Type
+ + Toggle Verbosity
+ "} + return dat // Atmospheric Scanner /mob/living/silicon/pai/proc/softwareAtmo() var/dat = "

Atmospheric Sensor

" @@ -636,19 +634,19 @@ var/dat = "

Digital Messenger

" dat += {"Signal/Receiver Status: - [(pda.toff) ? "\[Off\]" : "\[On\]"]
+ [(aiPDA.toff) ? "\[Off\]" : "\[On\]"]
Ringer Status: - [(pda.silent) ? "\[Off\]" : "\[On\]"]

"} + [(aiPDA.silent) ? "\[Off\]" : "\[On\]"]

"} dat += "
    " - if(!pda.toff) + if(!aiPDA.toff) for (var/obj/item/pda/P in sortNames(get_viewable_pdas())) - if (P == pda) + if (P == aiPDA) continue dat += "
  • [P]" dat += "
  • " dat += "
" dat += "

" - dat += "Messages:
[pda.tnote]" + dat += "Messages:
[aiPDA.tnote]" return dat // Loudness Booster diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 25fa70b061d..228d17af971 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -23,7 +23,7 @@ var/obj/item/camera/siliconcam/aicamera = null //photography hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_TRACK_HUD) - var/obj/item/radio/borg/radio = null //AIs dont use this but this is at the silicon level to advoid copypasta in say() + var/obj/item/radio/borg/radio = null //All silicons make use of this, with (p)AI's creating headsets var/list/alarm_types_show = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0) var/list/alarm_types_clear = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0) @@ -44,6 +44,7 @@ var/hack_software = FALSE //Will be able to use hacking actions var/interaction_range = 7 //wireless control range + var/obj/item/pda/aiPDA /mob/living/silicon/Initialize() . = ..() @@ -321,6 +322,11 @@ usr << browse(list, "window=laws") +/mob/living/silicon/proc/ai_roster() + var/datum/browser/popup = new(src, "airoster", "Crew Manifest", 387, 420) + popup.set_content(GLOB.data_core.get_manifest()) + popup.open() + /mob/living/silicon/proc/set_autosay() //For allowing the AI and borgs to set the radio behavior of auto announcements (state laws, arrivals). if(!radio) to_chat(src, "Radio not detected.") diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 4f31bd06976..617963b8dcb 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -237,7 +237,7 @@ Auto Patrol[]"}, targets += C if(targets.len>0) var/mob/living/carbon/t = pick(targets) - if((t.stat!=2) && (!(t.mobility_flags & MOBILITY_STAND)) && (!t.handcuffed)) //we don't shoot people who are dead, cuffed or lying down. + if(t.stat != DEAD && (t.mobility_flags & MOBILITY_STAND) && !t.handcuffed) //we don't shoot people who are dead, cuffed or lying down. shootAt(t) switch(mode) @@ -435,7 +435,7 @@ Auto Patrol[]"}, projectile = /obj/item/projectile/beam/lasertag/redtag /mob/living/simple_animal/bot/ed209/proc/shootAt(mob/target) - if(lastfired && world.time - lastfired < shot_delay) + if(world.time <= lastfired + shot_delay) return lastfired = world.time var/turf/T = loc diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 0a4ad713c08..6076ba4de3e 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -472,7 +472,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians var/used_message = "All the cards seem to be blank now." var/failure_message = "..And draw a card! It's...blank? Maybe you should try again later." var/ling_failure = "The deck refuses to respond to a souless creature such as you." - var/list/possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support") + var/list/possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support", "Gravitokinetic") var/random = TRUE var/allowmultiple = FALSE var/allowling = TRUE @@ -547,6 +547,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians if("Dextrous") pickedtype = /mob/living/simple_animal/hostile/guardian/dextrous + if("Gravitokinetic") + pickedtype = /mob/living/simple_animal/hostile/guardian/gravitokinetic + var/list/guardians = user.hasparasites() if(guardians.len && !allowmultiple) to_chat(user, "You already have a [mob_name]!" ) @@ -575,10 +578,10 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians random = FALSE /obj/item/guardiancreator/choose/dextrous - possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support") + possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support", "Gravitokinetic") /obj/item/guardiancreator/choose/wizard - possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard") + possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Gravitokinetic") allowmultiple = TRUE /obj/item/guardiancreator/tech @@ -594,13 +597,13 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians ling_failure = "The holoparasites recoil in horror. They want nothing to do with a creature like you." /obj/item/guardiancreator/tech/choose/traitor - possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support") + possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support", "Gravitokinetic") /obj/item/guardiancreator/tech/choose random = FALSE /obj/item/guardiancreator/tech/choose/dextrous - possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support") + possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support", "Gravitokinetic") /obj/item/paper/guides/antag/guardian name = "Holoparasite Guide" @@ -624,6 +627,8 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
Standard: Devastating close combat attacks and high damage resist. Can smash through weak walls.

+ Gravitokinetic: Attacks will apply crushing gravity to the target. Can target the ground as well to slow targets advancing on you, but this will affect the user.
+
"} /obj/item/paper/guides/antag/guardian/update_icon() @@ -652,6 +657,8 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
Standard: Devastating close combat attacks and high damage resist. Can smash through weak walls.

+ Gravitokinetic: Attacks will apply crushing gravity to the target. Can target the ground as well to slow targets advancing on you, but this will affect the user.
+
"} diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm index 55bbea98eef..4078f4b041c 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm @@ -81,7 +81,7 @@ else to_chat(user, "[src] glows with a strange light, and you don't touch it.") -/obj/guardian_bomb/Bump(atom/A) +/obj/guardian_bomb/Bumped(atom/A) detonate(A) ..() diff --git a/code/modules/mob/living/simple_animal/guardian/types/gravitokinetic.dm b/code/modules/mob/living/simple_animal/guardian/types/gravitokinetic.dm new file mode 100644 index 00000000000..f7305975968 --- /dev/null +++ b/code/modules/mob/living/simple_animal/guardian/types/gravitokinetic.dm @@ -0,0 +1,62 @@ +//gravitokinetic +/mob/living/simple_animal/hostile/guardian/gravitokinetic + melee_damage_lower = 15 + melee_damage_upper = 15 + damage_coeff = list(BRUTE = 0.75, BURN = 0.75, TOX = 0.75, CLONE = 0.75, STAMINA = 0, OXY = 0.75) + playstyle_string = "As a gravitokinetic type, you can alt click to make the gravity on the ground stronger, and punching applies this effect to a target." + magic_fluff_string = "..And draw the Singularity, an anomalous force of terror." + tech_fluff_string = "Boot sequence complete. Gravitokinetic modules loaded. Holoparasite swarm online." + carp_fluff_string = "CARP CARP CARP! Caught one! It's a gravitokinetic carp! Now do you understand the gravity of the situation?" + var/list/gravito_targets = list() + var/gravity_power_range = 10 //how close the stand must stay to the target to keep the heavy gravity + var/datum/callback/distance_check + +/mob/living/simple_animal/hostile/guardian/gravitokinetic/Initialize() + . = ..() + distance_check = CALLBACK(src, .proc/__distance_check) + +/mob/living/simple_animal/hostile/guardian/gravitokinetic/AttackingTarget() + . = ..() + if(isliving(target) && target != src) + to_chat(src, "Your punch has applied heavy gravity to [target]!") + add_gravity(target, 2) + to_chat(target, "Everything feels really heavy!") + +/mob/living/simple_animal/hostile/guardian/gravitokinetic/AltClickOn(atom/A) + if(isopenturf(A) && is_deployed() && stat != DEAD && in_range(src, A) && !incapacitated()) + var/turf/T = A + if(isspaceturf(T)) + to_chat(src, "You cannot add gravity to space!") + return + visible_message("[src] slams their fist into the [T]!", "You modify the gravity of the [T].") + do_attack_animation(T) + add_gravity(T, 4) + return + return ..() + +/mob/living/simple_animal/hostile/guardian/gravitokinetic/Recall(forced) + . = ..() + to_chat(src, "You have released your gravitokinetic powers!") + for(var/datum/component/C in gravito_targets) + remove_gravity(C) + +/mob/living/simple_animal/hostile/guardian/gravitokinetic/Moved(oldLoc, dir) + . = ..() + for(var/datum/component/C in gravito_targets) + if(get_dist(src, C.parent) > gravity_power_range) + remove_gravity(C) + +/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/add_gravity(atom/A, new_gravity = 2) + var/datum/component/C = A.AddComponent(/datum/component/forced_gravity,new_gravity) + RegisterSignal(A, COMSIG_MOVABLE_MOVED, distance_check) + gravito_targets.Add(C) + playsound(src, 'sound/effects/gravhit.ogg', 100, 1) + +/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/remove_gravity(datum/component/C) + UnregisterSignal(C.parent, COMSIG_MOVABLE_MOVED) + gravito_targets.Remove(C) + qdel(C) + +/mob/living/simple_animal/hostile/guardian/gravitokinetic/proc/__distance_check(atom/movable/AM, OldLoc, Dir, Forced) + if(get_dist(src, AM) > gravity_power_range) + remove_gravity(AM.GetComponent(/datum/component/forced_gravity)) diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index 74e3b0b35f9..9600141c1b5 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -65,7 +65,6 @@ /obj/item/organ/body_egg/changeling_egg/proc/Pop() var/mob/living/carbon/monkey/M = new(owner) - owner.stomach_contents += M for(var/obj/item/organ/I in src) I.Insert(M, 1) 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 5c28b07b34e..27e736bafcc 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -1,3 +1,4 @@ +#define COLOSSUS_SLEEP(X) sleep(X); if(QDELETED(src)) return; /* COLOSSUS @@ -73,7 +74,7 @@ Difficulty: Very Hard telegraph() if(health < maxHealth/3) - double_spiral() + INVOKE_ASYNC(src, .proc/double_spiral) else visible_message("\"Judgement.\"") INVOKE_ASYNC(src, .proc/spiral_shoot, pick(TRUE, FALSE)) @@ -123,17 +124,17 @@ Difficulty: Very Hard /mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots() dir_shots(GLOB.diagonals) - sleep(10) + COLOSSUS_SLEEP(10) dir_shots(GLOB.cardinals) - sleep(10) + COLOSSUS_SLEEP(10) dir_shots(GLOB.diagonals) - sleep(10) + COLOSSUS_SLEEP(10) dir_shots(GLOB.cardinals) /mob/living/simple_animal/hostile/megafauna/colossus/proc/double_spiral() visible_message("\"Die.\"") - sleep(10) + COLOSSUS_SLEEP(10) INVOKE_ASYNC(src, .proc/spiral_shoot) INVOKE_ASYNC(src, .proc/spiral_shoot, TRUE) @@ -151,7 +152,7 @@ Difficulty: Very Hard counter = 16 shoot_projectile(start_turf, counter * 22.5) playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, 1) - sleep(1) + COLOSSUS_SLEEP(1) /mob/living/simple_animal/hostile/megafauna/colossus/proc/shoot_projectile(turf/marker, set_angle) if(!isnum(set_angle) && (!marker || marker == loc)) 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 6724b62e469..ea7b8849793 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -3,6 +3,7 @@ #define SWOOP_DAMAGEABLE 1 #define SWOOP_INVULNERABLE 2 +#define DRAKE_SLEEP(X) sleep(X); if(QDELETED(src) || stat == DEAD) return; /* @@ -137,20 +138,24 @@ Difficulty: Medium var/turf/T = pick(RANGE_TURFS(1, target)) new /obj/effect/temp_visual/lava_warning(T, 60) // longer reset time for the lava amount-- - sleep(delay) + DRAKE_SLEEP(delay) /mob/living/simple_animal/hostile/megafauna/dragon/proc/lava_swoop(var/amount = 30) INVOKE_ASYNC(src, .proc/lava_pools, amount) swoop_attack(FALSE, target, 1000) // longer cooldown until it gets reset below + if(QDELETED(src) || stat == DEAD) + return fire_cone() if(health < maxHealth*0.5) - sleep(10) + DRAKE_SLEEP(10) fire_cone() - sleep(10) + DRAKE_SLEEP(10) fire_cone() SetRecoveryTime(40) /mob/living/simple_animal/hostile/megafauna/dragon/proc/mass_fire(var/spiral_count = 12, var/range = 15, var/times = 3) + if(QDELETED(src) || stat == DEAD) + return for(var/i = 1 to times) SetRecoveryTime(50) playsound(get_turf(src),'sound/magic/fireball.ogg', 200, 1) @@ -158,7 +163,7 @@ Difficulty: Medium for(var/j = 1 to spiral_count) var/list/turfs = line_target(j * increment + i * increment / 2, range, src) INVOKE_ASYNC(src, .proc/fire_line, turfs) - sleep(25) + DRAKE_SLEEP(25) SetRecoveryTime(30) /mob/living/simple_animal/hostile/megafauna/dragon/proc/lava_arena() @@ -179,7 +184,7 @@ Difficulty: Medium T.ChangeTurf(/turf/open/floor/plating/asteroid/basalt/lava_land_surface) else indestructible_turfs += T - sleep(10) // give them a bit of time to realize what attack is actually happening + DRAKE_SLEEP(10) // give them a bit of time to realize what attack is actually happening var/list/turfs = RANGE_TURFS(2, center) while(amount > 0) @@ -203,10 +208,12 @@ Difficulty: Medium else if(!istype(T, /turf/closed/indestructible)) new /obj/effect/temp_visual/lava_safe(T) amount-- - sleep(24) + DRAKE_SLEEP(24) return 1 // attack finished completely /mob/living/simple_animal/hostile/megafauna/dragon/proc/arena_escape_enrage() // you ran somehow / teleported away from my arena attack now i'm mad fucker + if(QDELETED(src) || stat == DEAD) + return //angry but helpless SetRecoveryTime(80) visible_message("[src] starts to glow vibrantly as its wounds close up!") adjustBruteLoss(-250) // yeah you're gonna pay for that, don't run nerd @@ -214,10 +221,12 @@ Difficulty: Medium move_to_delay = move_to_delay / 2 light_range = 10 sleep(10) // run. - mass_fire(20, 15, 3) - remove_atom_colour(TEMPORARY_COLOUR_PRIORITY) - move_to_delay = initial(move_to_delay) - light_range = initial(light_range) + if(!QDELETED(src)) + if(stat != DEAD) + mass_fire(20, 15, 3) + move_to_delay = initial(move_to_delay) + remove_atom_colour(TEMPORARY_COLOUR_PRIORITY) + light_range = initial(light_range) /mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_cone(var/atom/at = target) playsound(get_turf(src),'sound/magic/fireball.ogg', 200, 1) @@ -245,6 +254,10 @@ Difficulty: Medium return (getline(src, T) - get_turf(src)) /mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_line(var/list/turfs) + dragon_fire_line(src, turfs) + +//fire line keeps going even if dragon is deleted +/proc/dragon_fire_line(var/source, var/list/turfs) var/list/hit_list = list() for(var/turf/T in turfs) if(istype(T, /turf/closed)) @@ -252,11 +265,11 @@ Difficulty: Medium new /obj/effect/hotspot(T) T.hotspot_expose(700,50,1) for(var/mob/living/L in T.contents) - if(L in hit_list || L == src) + if(L in hit_list || L == source) continue hit_list += L L.adjustFireLoss(20) - to_chat(L, "You're hit by [src]'s fire breath!") + to_chat(L, "You're hit by [source]'s fire breath!") // deals damage to mechs for(var/obj/mecha/M in T.contents) @@ -306,6 +319,7 @@ Difficulty: Medium swooping |= SWOOP_INVULNERABLE mouse_opacity = MOUSE_OPACITY_TRANSPARENT sleep(7) + //badmins please don't kill it while it's invulnerable while(target && loc != get_turf(target)) forceMove(get_step(src, get_dir(src, target))) @@ -354,6 +368,8 @@ Difficulty: Medium density = TRUE sleep(1) + if(QDELETED(src)) + return swooping &= ~SWOOP_DAMAGEABLE SetRecoveryTime(swoop_cooldown) if(!lava_success) diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 2f07a61e9ca..497a0c3310f 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -64,6 +64,7 @@ unsuitable_atmos_damage = 0 faction = list("hostile","vines","plants") var/list/grasping = list() + var/list/tethers = list() var/max_grasps = 4 var/grasp_chance = 20 var/grasp_pull_chance = 85 @@ -75,6 +76,8 @@ var/datum/beam/B = grasping[L] if(B) qdel(B) + for(var/datum/component/tether in tethers) + tether.RemoveComponent() grasping = null return ..() @@ -96,24 +99,31 @@ step(L,get_dir(L,src)) //reel them in L.Paralyze(60) //you can't get away now~ - if(grasping.len < max_grasps) + if(length(grasping) < max_grasps) grasping: for(var/mob/living/L in view(grasp_range, src)) - if(L == src || faction_check_mob(L) || (L in grasping) || L == target) + if(L == src || faction_check_mob(L) || L in grasping || L == target) continue - for(var/t in getline(src,L)) - for(var/a in t) - var/atom/A = a - if(A.density && A != L) + for(var/turf/T in getline(src,L)) + if (T.density) + continue grasping + for(var/obj/O in T) + if(O.density) continue grasping if(prob(grasp_chance)) to_chat(L, "\The [src] has you entangled!") grasping[L] = Beam(L, "vine", time=INFINITY, maxdistance=5, beam_type=/obj/effect/ebeam/vine) - + tethers += list(L.AddComponent(/datum/component/tether, src, grasp_range+1, /obj/effect/ebeam/vine), AddComponent(/datum/component/tether, L, grasp_range+1, /obj/effect/ebeam/vine)) break //only take 1 new victim per cycle /mob/living/simple_animal/hostile/venus_human_trap/OpenFire(atom/the_target) + for(var/turf/T in getline(src,target)) + if (T.density) + return + for(var/obj/O in T) + if(O.density) + return var/dist = get_dist(src,the_target) Beam(the_target, "vine", time=dist*2, maxdistance=dist+2, beam_type=/obj/effect/ebeam/vine) the_target.attack_animal(src) diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 1d41e25a334..b5747b1f65e 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -374,14 +374,6 @@ priority_absorb_key["stuns_absorbed"] += amount return TRUE -/////////////////////////////////// STASIS /////////////////////////////////// - -/mob/living/proc/IsInStasis() - . = has_status_effect(STATUS_EFFECT_STASIS) - -/mob/living/proc/SetStasis(apply, updating = TRUE) - . = apply ? apply_status_effect(STATUS_EFFECT_STASIS, null, updating) : remove_status_effect(STATUS_EFFECT_STASIS) - /////////////////////////////////// DISABILITIES //////////////////////////////////// /mob/living/proc/add_quirk(quirktype, spawn_effects) //separate proc due to the way these ones are handled if(HAS_TRAIT(src, quirktype)) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 04cd056e58a..cac9ec1f3d3 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -1,4 +1,3 @@ - // see _DEFINES/is_helpers.dm for mob type checks /mob/proc/lowest_buckled_mob() @@ -54,14 +53,14 @@ var/te = n var/t = "" n = length(n) - var/p = null - p = 1 - while(p <= n) + + for(var/p = 1 to min(n,MAX_BROADCAST_LEN)) if ((copytext(te, p, p + 1) == " " || prob(pr))) t = text("[][]", t, copytext(te, p, p + 1)) else t = text("[]*", t) - p++ + if(n > MAX_BROADCAST_LEN) + t += "..." //signals missing text return sanitize(t) /proc/slur(n) @@ -499,3 +498,25 @@ It's fairly easy to fix if dealing with single letters but not so much with comp if(HAS_TRAIT(src, TRAIT_DISSECTED)) . += "This body has been dissected and analyzed. It is no longer worth experimenting on.
" + +// Used to make sure that a player has a valid job preference setup, used to knock players out of eligibility for anything if their prefs don't make sense. +// A "valid job preference setup" in this situation means at least having one job set to low, or not having "return to lobby" enabled +// Prevents "antag rolling" by setting antag prefs on, all jobs to never, and "return to lobby if preferences not availible" +// Doing so would previously allow you to roll for antag, then send you back to lobby if you didn't get an antag role +// This also does some admin notification and logging as well +/mob/proc/has_valid_preferences() + if(!client) + return FALSE //Not sure how this would get run without the mob having a client, but let's just be safe. + if(client.prefs.joblessrole != RETURNTOLOBBY) + return TRUE + // If they have antags enabled, they're potentially doing this on purpose instead of by accident. Notify admins if so. + var/has_antags = FALSE + if(client.prefs.be_special.len > 0) + has_antags = TRUE + if(client.prefs.job_preferences.len == 0) + to_chat(src, "You have no jobs enabled, along with return to lobby if job is unavailable. This makes you ineligible for any round start role, please update your job preferences.") + if(has_antags) + log_admin("[src.ckey] just got booted back to lobby with no jobs, but antags enabled.") + message_admins("[src.ckey] just got booted back to lobby with no jobs enabled, but antag rolling enabled. Likely antag rolling abuse.") + return FALSE //This is the only case someone should actually be completely blocked from antag rolling as well + return TRUE diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 959abea8cdf..af538cac605 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG)) +/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG)) if (notransform) return //Handle items on mob @@ -123,6 +123,19 @@ qdel(G) //we lose the organs in the missing limbs qdel(BP) + //transfer stuns + if(tr_flags & TR_KEEPSTUNS) + O.Stun(AmountStun(), ignore_canstun = TRUE) + O.Knockdown(AmountKnockdown(), ignore_canstun = TRUE) + O.Immobilize(AmountImmobilized(), ignore_canstun = TRUE) + O.Paralyze(AmountParalyzed(), ignore_canstun = TRUE) + O.Unconscious(AmountUnconscious(), ignore_canstun = TRUE) + O.Sleeping(AmountSleeping(), ignore_canstun = TRUE) + + //transfer reagents + if(tr_flags & TR_KEEPREAGENTS) + reagents.trans_to(O, reagents.total_volume) + //transfer mind if we didn't yet if(mind) mind.transfer_to(O) @@ -149,7 +162,7 @@ ////////////////////////// Humanize ////////////////////////////// //Could probably be merged with monkeyize but other transformations got their own procs, too -/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG)) +/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG)) if (notransform) return //Handle items on mob @@ -283,6 +296,19 @@ qdel(G) //we lose the organs in the missing limbs qdel(BP) + //transfer stuns + if(tr_flags & TR_KEEPSTUNS) + O.Stun(AmountStun(), ignore_canstun = TRUE) + O.Knockdown(AmountKnockdown(), ignore_canstun = TRUE) + O.Immobilize(AmountImmobilized(), ignore_canstun = TRUE) + O.Paralyze(AmountParalyzed(), ignore_canstun = TRUE) + O.Unconscious(AmountUnconscious(), ignore_canstun = TRUE) + O.Sleeping(AmountSleeping(), ignore_canstun = TRUE) + + //transfer reagents + if(tr_flags & TR_KEEPREAGENTS) + reagents.trans_to(O, reagents.total_volume) + if(mind) mind.transfer_to(O) var/datum/antagonist/changeling/changeling = O.mind.has_antag_datum(/datum/antagonist/changeling) diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index b4f567158c2..c58ecca5727 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -97,7 +97,7 @@ if(issilicon(usr)) return var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] - if(usr.canUseTopic(src)) + if(usr.canUseTopic(src, BE_CLOSE)) card_slot.try_eject(null, usr) // Eject ID card from computer, if it has ID slot with card inside. @@ -108,7 +108,7 @@ if(issilicon(usr)) return var/obj/item/computer_hardware/ai_slot/ai_slot = all_components[MC_AI] - if(usr.canUseTopic(src)) + if(usr.canUseTopic(src, BE_CLOSE)) ai_slot.try_eject(null, usr,1) @@ -120,7 +120,7 @@ if(issilicon(usr)) return - if(usr.canUseTopic(src)) + if(usr.canUseTopic(src, BE_CLOSE)) var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD] if(uninstall_component(portable_drive, usr)) portable_drive.verb_pickup() @@ -130,7 +130,7 @@ if(issilicon(user)) return - if(user.canUseTopic(src)) + if(user.canUseTopic(src, BE_CLOSE)) var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] var/obj/item/computer_hardware/ai_slot/ai_slot = all_components[MC_AI] var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD] @@ -159,7 +159,7 @@ /obj/item/modular_computer/MouseDrop(obj/over_object, src_location, over_location) var/mob/M = usr - if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src)) + if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src, BE_CLOSE)) return attack_self(M) return ..() diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm index 3106a9e5105..07f762353f4 100644 --- a/code/modules/modular_computers/computers/item/laptop.dm +++ b/code/modules/modular_computers/computers/item/laptop.dm @@ -77,7 +77,7 @@ return if(!isturf(loc) && !ismob(loc)) // No opening it in backpack. return - if(!user.canUseTopic(src)) + if(!user.canUseTopic(src, BE_CLOSE)) return toggle_open(user) diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm index 7a192c427c6..be51588423c 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_sword_recall.dm @@ -23,9 +23,6 @@ var/mob/living/carbon/C = energyKatana.loc C.transferItemToLoc(energyKatana, get_turf(energyKatana), TRUE) - //Somebody swollowed my sword, probably the clown doing a circus act. - if(energyKatana in C.stomach_contents) - C.stomach_contents -= energyKatana else energyKatana.forceMove(get_turf(energyKatana)) diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 98ce25de3cb..22452ea0106 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -165,7 +165,7 @@ /obj/item/pen/sleepy/Initialize() . = ..() create_reagents(45, OPENCONTAINER) - reagents.add_reagent("chloralhydratedelayed", 20) + reagents.add_reagent("chloralhydrate", 20) reagents.add_reagent("mutetoxin", 15) reagents.add_reagent("tirizene", 10) @@ -179,6 +179,14 @@ /obj/item/pen/edagger/Initialize() . = ..() AddComponent(/datum/component/butchering, 60, 100, 0, 'sound/weapons/blade1.ogg', TRUE) + +/obj/item/pen/edagger/suicide_act(mob/user) + . = BRUTELOSS + if(on) + user.visible_message("[user] forcefully rams the pen into their mouth!") + else + user.visible_message("[user] is holding a pen up to their mouth! It looks like [user.p_theyre()] trying to commit suicide!") + attack_self(user) /obj/item/pen/edagger/attack_self(mob/living/user) if(on) diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index 87b8d8f00f6..34dfdd13e97 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -47,14 +47,16 @@ . = ..() to_chat(user, "Alt-click to change its focusing, allowing you to set how big of an area it will capture.") -/obj/item/camera/AltClick(mob/user) - if(!user.canUseTopic(src, BE_CLOSE)) - return +/obj/item/camera/proc/adjust_zoom(mob/user) var/desired_x = input(user, "How high do you want the camera to shoot, between [picture_size_x_min] and [picture_size_x_max]?", "Zoom", picture_size_x) as num var/desired_y = input(user, "How wide do you want the camera to shoot, between [picture_size_y_min] and [picture_size_y_max]?", "Zoom", picture_size_y) as num picture_size_x = min(CLAMP(desired_x, picture_size_x_min, picture_size_x_max), CAMERA_PICTURE_SIZE_HARD_LIMIT) picture_size_y = min(CLAMP(desired_y, picture_size_y_min, picture_size_y_max), CAMERA_PICTURE_SIZE_HARD_LIMIT) +/obj/item/camera/AltClick(mob/user) + if(!user.canUseTopic(src, BE_CLOSE)) + return + adjust_zoom(user) /obj/item/camera/attack(mob/living/carbon/human/M, mob/user) return @@ -221,7 +223,7 @@ else if(default_picture_name) picture.picture_name = default_picture_name - + p.set_picture(picture, TRUE, TRUE) if(CONFIG_GET(flag/picture_logging_camera)) picture.log_to_file() diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 81f82c890a2..71d0aecce99 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -345,6 +345,8 @@ var/BR = brightness var/PO = bulb_power var/CO = bulb_colour + if(color) + CO = color var/area/A = get_area(src) if (A && A.fire) CO = bulb_emergency_colour @@ -383,6 +385,10 @@ removeStaticPower(static_power_used, STATIC_LIGHT) broken_sparks(start_only=TRUE) + +/obj/machinery/light/update_atom_colour() + ..() + update() /obj/machinery/light/proc/broken_sparks(start_only=FALSE) if(status == LIGHT_BROKEN && has_power()) diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 92e7c7e6b5d..b4cca3bc4b9 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -304,6 +304,12 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(!istype(T)) //We are in a crate or somewhere that isn't turf, if we return to turf resume processing but for now. return //Yeah just stop. + if(isclosedturf(T)) + var/turf/did_it_melt = T.Melt() + if(!isclosedturf(did_it_melt)) //In case some joker finds way to place these on indestructible walls + visible_message("[src] melts through [T]!") + return + if(power) soundloop.volume = min(40, (round(power/100)/50)+1) // 5 +1 volume per 20 power. 2500 power is max @@ -649,6 +655,13 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) else L.show_message("You hear an unearthly ringing and notice your skin is covered in fresh radiation burns.", 2) +//Do not blow up our internal radio +/obj/machinery/power/supermatter_crystal/contents_explosion(severity, target) + return + +/obj/machinery/power/supermatter_crystal/prevent_content_explosion() + return TRUE + /obj/machinery/power/supermatter_crystal/engine is_main_engine = TRUE diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 994216e584a..21d7d2ccc01 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -41,6 +41,11 @@ var/comp_id = 0 var/efficiency +/obj/machinery/power/compressor/Destroy() + if (turbine && turbine.compressor == src) + turbine.compressor = null + turbine = null + return ..() /obj/machinery/power/turbine name = "gas turbine generator" @@ -57,6 +62,12 @@ var/lastgen var/productivity = 1 +/obj/machinery/power/turbine/Destroy() + if (compressor && compressor.turbine == src) + compressor.turbine = null + compressor = null + return ..() + /obj/machinery/computer/turbine_computer name = "gas turbine control computer" desc = "A computer to remotely control a gas turbine." diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm index db5c0ded73a..67222a1931e 100644 --- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm +++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm @@ -166,7 +166,7 @@ /obj/machinery/reagentgrinder/ui_interact(mob/user) // The microwave Menu //I am reasonably certain that this is not a microwave . = ..() - if(operating || !user.canUseTopic(src)) + if(operating || !user.canUseTopic(src, !issilicon(user))) return var/list/options = list() @@ -197,7 +197,7 @@ choice = show_radial_menu(user, src, options, require_near = !issilicon(user)) // post choice verification - if(operating || (isAI(user) && stat & NOPOWER) || !user.canUseTopic(src)) + if(operating || (isAI(user) && stat & NOPOWER) || !user.canUseTopic(src, !issilicon(user))) return switch(choice) diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index d954194fdc6..75cc72cb315 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -1764,14 +1764,14 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/between_the_sheets/on_mob_life(mob/living/L) ..() if(L.IsSleeping()) - if(L.bruteloss && L.fireloss) //If you are damaged by both types, slightly increased healing but it only heals one. The more the merrier wink wink. + if(L.getBruteLoss() && L.getFireLoss()) //If you are damaged by both types, slightly increased healing but it only heals one. The more the merrier wink wink. if(prob(50)) L.adjustBruteLoss(-0.25) else L.adjustFireLoss(-0.25) - else if(L.bruteloss && !L.fireloss) //If you have only one, it still heals but not as well. + else if(L.getBruteLoss()) //If you have only one, it still heals but not as well. L.adjustBruteLoss(-0.2) - else if(!L.bruteloss && L.fireloss) + else if(L.getFireLoss()) L.adjustFireLoss(-0.2) /datum/reagent/consumable/ethanol/kamikaze diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index d5c4423e62f..86fb1dc48ea 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -308,6 +308,17 @@ ..() . = 1 +/datum/reagent/consumable/lemonade + name = "Lemonade" + id = "lemonade" + description = "Sweet, tangy lemonade. Good for the soul." + quality = DRINK_NICE + taste_description = "sunshine and summertime" + glass_icon_state = "lemonpitcher" + glass_name = "pitcher of lemonade" + glass_desc = "This drink leaves you feeling nostalgic for some reason." + + /datum/reagent/consumable/tea/arnold_palmer name = "Arnold Palmer" id = "arnold_palmer" diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 3b545902e58..42ad24c7367 100755 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -573,7 +573,7 @@ ..() /datum/reagent/consumable/honey - name = "honey" + name = "Honey" id = "honey" description = "Sweet sweet honey that decays into sugar. Has antibacterial and natural healing properties." color = "#d3a308" diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index c0379de1490..c7a517d45ae 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1,5 +1,5 @@ /datum/reagent/blood - data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null) + data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null,"quirks"=null) name = "Blood" id = "blood" color = "#C80000" // rgb: 200, 0, 0 diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 8e77f5fdcd2..32440405f18 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -301,25 +301,6 @@ . = 1 ..() -/datum/reagent/toxin/chloralhydratedelayed //sedates half as quickly and does not cause toxloss. same name/desc so it doesn't give away sleepypens - name = "Chloral Hydrate" - id = "chloralhydratedelayed" - description = "A powerful sedative that induces confusion and drowsiness before putting its target to sleep." - silent_toxin = TRUE - reagent_state = SOLID - color = "#000067" // rgb: 0, 0, 103 - toxpwr = 0 - metabolization_rate = 1.5 * REAGENTS_METABOLISM - -/datum/reagent/toxin/chloralhydratedelayed/on_mob_life(mob/living/carbon/M) - switch(current_cycle) - if(10 to 20) - M.confused += 1 - M.drowsyness += 1 - if(20 to INFINITY) - M.Sleeping(40, 0) - ..() - /datum/reagent/toxin/fakebeer //disguised as normal beer for use by emagged brobots name = "Beer" id = "fakebeer" diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index f82c37bacf6..7783c7849e3 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -173,7 +173,7 @@ /obj/item/reagent_containers/pill/penacid name = "pentetic acid pill" - desc = "Used to expunge radioation and toxins." + desc = "Used to expunge radiation and toxins." list_reagents = list("pen_acid" = 10) icon_state = "pill22" rename_with_volume = TRUE diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm index a5fe1297553..d7dc52b2487 100644 --- a/code/modules/research/designs/autolathe_designs.dm +++ b/code/modules/research/designs/autolathe_designs.dm @@ -10,6 +10,15 @@ build_path = /obj/item/reagent_containers/glass/bucket category = list("initial","Tools","Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_SERVICE + +/datum/design/mop + name = "Mop" + id = "mop" + build_type = AUTOLATHE | PROTOLATHE + materials = list(MAT_METAL = 1000) + build_path = /obj/item/mop + category = list("initial","Tools","Tool Designs") + departmental_flags = DEPARTMENTAL_FLAG_SERVICE /datum/design/crowbar name = "Pocket Crowbar" diff --git a/code/modules/research/designs/electronics_designs.dm b/code/modules/research/designs/electronics_designs.dm index 7df285c9adf..96d797650d1 100644 --- a/code/modules/research/designs/electronics_designs.dm +++ b/code/modules/research/designs/electronics_designs.dm @@ -46,6 +46,16 @@ category = list("Electronics") departmental_flags = DEPARTMENTAL_FLAG_SCIENCE +/datum/design/nanite_comm_remote + name = "Nanite Communication Remote" + desc = "Allows for the construction of a nanite communication remote." + id = "nanite_comm_remote" + build_type = PROTOLATHE + materials = list(MAT_GLASS = 500, MAT_METAL = 500) + build_path = /obj/item/nanite_remote/comm + category = list("Electronics") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE + /datum/design/nanite_scanner name = "Nanite Scanner" desc = "Allows for the construction of a nanite scanner." diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 44c2742cbd7..2cd31ed67d1 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -260,6 +260,16 @@ ////////////Janitor Designs////////////// ///////////////////////////////////////// +/datum/design/mop + name = "Mop" + desc = "It mops." + id = "mop" + build_type = PROTOLATHE + materials = list(MAT_METAL = 1000) + build_path = /obj/item/mop + category = list("Equipment") + departmental_flags = DEPARTMENTAL_FLAG_SERVICE + /datum/design/advmop name = "Advanced Mop" desc = "An upgraded mop with a large internal capacity for holding water or other cleaning chemicals." diff --git a/code/modules/research/designs/nanite_designs.dm b/code/modules/research/designs/nanite_designs.dm index 177d7073a10..6a4b8686635 100644 --- a/code/modules/research/designs/nanite_designs.dm +++ b/code/modules/research/designs/nanite_designs.dm @@ -415,21 +415,21 @@ name = "Skull Echo" desc = "The nanites echo a synthesized message inside the host's skull." id = "voice_nanites" - program_type = /datum/nanite_program/triggered/voice + program_type = /datum/nanite_program/triggered/comm/voice category = list("Suppression Nanites") /datum/design/nanites/speech name = "Forced Speech" desc = "The nanites force the host to say a pre-programmed sentence when triggered." id = "speech_nanites" - program_type = /datum/nanite_program/triggered/speech + program_type = /datum/nanite_program/triggered/comm/speech category = list("Suppression Nanites") /datum/design/nanites/hallucination name = "Hallucination" desc = "The nanites make the host see and hear things that aren't real." id = "hallucination_nanites" - program_type = /datum/nanite_program/triggered/hallucination + program_type = /datum/nanite_program/triggered/comm/hallucination category = list("Suppression Nanites") ////////////////////SENSOR NANITES////////////////////////////////////// diff --git a/code/modules/research/designs/power_designs.dm b/code/modules/research/designs/power_designs.dm index 7ed2b6b6b9c..9def198276c 100644 --- a/code/modules/research/designs/power_designs.dm +++ b/code/modules/research/designs/power_designs.dm @@ -11,7 +11,7 @@ construction_time=100 build_path = /obj/item/stock_parts/cell/empty category = list("Misc","Power Designs","Machinery","initial") - departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING + departmental_flags = DEPARTMENTAL_FLAG_ALL /datum/design/high_cell name = "High-Capacity Power Cell" diff --git a/code/modules/research/designs/telecomms_designs.dm b/code/modules/research/designs/telecomms_designs.dm index b1da302290c..eb4b404db4d 100644 --- a/code/modules/research/designs/telecomms_designs.dm +++ b/code/modules/research/designs/telecomms_designs.dm @@ -49,6 +49,15 @@ build_path = /obj/item/circuitboard/machine/telecomms/server category = list("Subspace Telecomms") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/board/telecomms_messaging + name = "Machine Design (Messaging Server)" + desc = "Allows for the construction of Telecommunications Messaging Servers." + id = "s-messaging" + build_path = /obj/item/circuitboard/machine/telecomms/message_server + category = list("Subspace Telecomms") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE /datum/design/board/subspace_broadcaster name = "Machine Design (Subspace Broadcaster)" diff --git a/code/modules/research/nanites/nanite_programs/buffing.dm b/code/modules/research/nanites/nanite_programs/buffing.dm index 734e1082c2c..0f0814fab94 100644 --- a/code/modules/research/nanites/nanite_programs/buffing.dm +++ b/code/modules/research/nanites/nanite_programs/buffing.dm @@ -118,11 +118,11 @@ /datum/nanite_program/mindshield/enable_passive_effect() . = ..() - if(!host_mob.mind.has_antag_datum(/datum/antagonist/rev) && !is_hivemember(host_mob)) //won't work if on a rev, to avoid having implanted revs. same applies for hivemind members. + if(!host_mob.mind.has_antag_datum(/datum/antagonist/rev, TRUE) && !is_hivemember(host_mob) && !host_mob.is_wokevessel()) //won't work if on a rev, to avoid having implanted revs. same applies for hivemind members. ADD_TRAIT(host_mob, TRAIT_MINDSHIELD, "nanites") host_mob.sec_hud_set_implants() /datum/nanite_program/mindshield/disable_passive_effect() . = ..() REMOVE_TRAIT(host_mob, TRAIT_MINDSHIELD, "nanites") - host_mob.sec_hud_set_implants() \ No newline at end of file + host_mob.sec_hud_set_implants() diff --git a/code/modules/research/nanites/nanite_programs/suppression.dm b/code/modules/research/nanites/nanite_programs/suppression.dm index 57d497288e4..e91fc0fb125 100644 --- a/code/modules/research/nanites/nanite_programs/suppression.dm +++ b/code/modules/research/nanites/nanite_programs/suppression.dm @@ -114,7 +114,19 @@ . = ..() host_mob.cure_fakedeath("nanites") -/datum/nanite_program/triggered/speech +//Can receive transmissions from a nanite communication remote for customized messages +/datum/nanite_program/triggered/comm + var/comm_code = 0 + var/comm_message = "" + +/datum/nanite_program/triggered/comm/proc/receive_comm_signal(signal_comm_code, comm_message, comm_source) + if(!activated || !comm_code) + return + if(signal_comm_code == comm_code) + host_mob.investigate_log("'s [name] nanite program was messaged by [comm_source] with comm code [signal_comm_code] and message '[comm_message]'.", INVESTIGATE_NANITES) + trigger(comm_message) + +/datum/nanite_program/triggered/comm/speech name = "Forced Speech" desc = "The nanites force the host to say a pre-programmed sentence when triggered." unique = FALSE @@ -122,10 +134,10 @@ trigger_cooldown = 20 rogue_types = list(/datum/nanite_program/brain_misfire, /datum/nanite_program/brain_decay) - extra_settings = list("Sentence") + extra_settings = list("Sentence","Comm Code") var/sentence = "" -/datum/nanite_program/triggered/speech/set_extra_setting(user, setting) +/datum/nanite_program/triggered/comm/speech/set_extra_setting(user, setting) if(setting == "Sentence") var/new_sentence = stripped_input(user, "Choose the sentence that the host will be forced to say.", "Sentence", sentence, MAX_MESSAGE_LEN) if(!new_sentence) @@ -133,23 +145,34 @@ if(copytext(new_sentence, 1, 2) == "*") //emotes are abusable, like surrender return sentence = new_sentence + if(setting == "Comm Code") + var/new_code = input(user, "Set the communication code (1-9999) or set to 0 to disable external signals.", name, null) as null|num + if(isnull(new_code)) + return + comm_code = CLAMP(round(new_code, 1), 0, 9999) -/datum/nanite_program/triggered/speech/get_extra_setting(setting) +/datum/nanite_program/triggered/comm/speech/get_extra_setting(setting) if(setting == "Sentence") return sentence + if(setting == "Comm Code") + return comm_code -/datum/nanite_program/triggered/speech/copy_extra_settings_to(datum/nanite_program/triggered/speech/target) +/datum/nanite_program/triggered/comm/speech/copy_extra_settings_to(datum/nanite_program/triggered/comm/speech/target) target.sentence = sentence + target.comm_code = comm_code -/datum/nanite_program/triggered/speech/trigger() +/datum/nanite_program/triggered/comm/speech/trigger(comm_message) if(!..()) return + var/sent_message = comm_message + if(!comm_message) + sent_message = sentence if(host_mob.stat == DEAD) return to_chat(host_mob, "You feel compelled to speak...") - host_mob.say(sentence, forced = "nanite speech") + host_mob.say(sent_message, forced = "nanite speech") -/datum/nanite_program/triggered/voice +/datum/nanite_program/triggered/comm/voice name = "Skull Echo" desc = "The nanites echo a synthesized message inside the host's skull." unique = FALSE @@ -157,44 +180,62 @@ trigger_cooldown = 20 rogue_types = list(/datum/nanite_program/brain_misfire, /datum/nanite_program/brain_decay) - extra_settings = list("Message") + extra_settings = list("Message","Comm Code") var/message = "" -/datum/nanite_program/triggered/voice/set_extra_setting(user, setting) +/datum/nanite_program/triggered/comm/voice/set_extra_setting(user, setting) if(setting == "Message") var/new_message = stripped_input(user, "Choose the message sent to the host.", "Message", message, MAX_MESSAGE_LEN) if(!new_message) return message = new_message + if(setting == "Comm Code") + var/new_code = input(user, "Set the communication code (1-9999) or set to 0 to disable external signals.", name, null) as null|num + if(isnull(new_code)) + return + comm_code = CLAMP(round(new_code, 1), 0, 9999) -/datum/nanite_program/triggered/voice/get_extra_setting(setting) +/datum/nanite_program/triggered/comm/voice/get_extra_setting(setting) if(setting == "Message") return message + if(setting == "Comm Code") + return comm_code -/datum/nanite_program/triggered/voice/copy_extra_settings_to(datum/nanite_program/triggered/voice/target) +/datum/nanite_program/triggered/comm/voice/copy_extra_settings_to(datum/nanite_program/triggered/comm/voice/target) target.message = message + target.comm_code = comm_code -/datum/nanite_program/triggered/voice/trigger() +/datum/nanite_program/triggered/comm/voice/trigger(comm_message) if(!..()) return + var/sent_message = comm_message + if(!comm_message) + sent_message = message if(host_mob.stat == DEAD) return - to_chat(host_mob, "You hear a strange, robotic voice in your head... \"[message]\"") + to_chat(host_mob, "You hear a strange, robotic voice in your head... \"[sent_message]\"") -/datum/nanite_program/triggered/hallucination +/datum/nanite_program/triggered/comm/hallucination name = "Hallucination" desc = "The nanites make the host hallucinate something when triggered." trigger_cost = 4 trigger_cooldown = 80 unique = FALSE rogue_types = list(/datum/nanite_program/brain_misfire) - extra_settings = list("Hallucination Type") + extra_settings = list("Hallucination Type", "Comm Code") var/hal_type var/hal_details -/datum/nanite_program/triggered/hallucination/trigger() +/datum/nanite_program/triggered/comm/hallucination/trigger(comm_message) if(!..()) return + + if(comm_message && (hal_type != "Message")) //Triggered via comm remote, but not set to a message hallucination + return + var/sent_message = comm_message //Comm remotes can send custom hallucination messages for the chat hallucination + if(!sent_message) + sent_message = hal_details + if(!iscarbon(host_mob)) return var/mob/living/carbon/C = host_mob @@ -203,7 +244,7 @@ else switch(hal_type) if("Message") - new /datum/hallucination/chat(C, TRUE, null, hal_details) + new /datum/hallucination/chat(C, TRUE, null, sent_message) if("Battle") new /datum/hallucination/battle(C, TRUE, hal_details) if("Sound") @@ -223,7 +264,13 @@ if("Plasma Flood") new /datum/hallucination/fake_flood(C, TRUE) -/datum/nanite_program/triggered/hallucination/set_extra_setting(user, setting) +/datum/nanite_program/triggered/comm/hallucination/set_extra_setting(user, setting) + if(setting == "Comm Code") + var/new_code = input(user, "(Only for Message) Set the communication code (1-9999) or set to 0 to disable external signals.", name, null) as null|num + if(isnull(new_code)) + return + comm_code = CLAMP(round(new_code, 1), 0, 9999) + if(setting == "Hallucination Type") var/list/possible_hallucinations = list("Random","Message","Battle","Sound","Weird Sound","Station Message","Health","Alert","Fire","Shock","Plasma Flood") var/hal_type_choice = input("Choose the hallucination type", name) as null|anything in possible_hallucinations @@ -299,13 +346,16 @@ if("Plasma Flood") hal_type = "Plasma Flood" -/datum/nanite_program/triggered/hallucination/get_extra_setting(setting) +/datum/nanite_program/triggered/comm/hallucination/get_extra_setting(setting) if(setting == "Hallucination Type") if(!hal_type) return "Random" else return hal_type + if(setting == "Comm Code") + return comm_code -/datum/nanite_program/triggered/hallucination/copy_extra_settings_to(datum/nanite_program/triggered/hallucination/target) +/datum/nanite_program/triggered/comm/hallucination/copy_extra_settings_to(datum/nanite_program/triggered/comm/hallucination/target) target.hal_type = hal_type - target.hal_details = hal_details \ No newline at end of file + target.hal_details = hal_details + target.comm_code = comm_code \ No newline at end of file diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm index ee92a5c555c..6525c339918 100644 --- a/code/modules/research/nanites/nanite_programs/utility.dm +++ b/code/modules/research/nanites/nanite_programs/utility.dm @@ -181,6 +181,15 @@ return SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, code, source) +/datum/nanite_program/relay/proc/relay_comm_signal(comm_code, relay_code, comm_message) + if(!activated) + return + if(!host_mob) + return + if(relay_code != relay_channel) + return + SEND_SIGNAL(host_mob, COMSIG_NANITE_COMM_SIGNAL, comm_code, comm_message) + /datum/nanite_program/metabolic_synthesis name = "Metabolic Synthesis" desc = "The nanites use the metabolic cycle of the host to speed up their replication rate, using their extra nutrition as fuel." diff --git a/code/modules/research/nanites/nanite_remote.dm b/code/modules/research/nanites/nanite_remote.dm index 60dd78cf949..9ae5a2df7c1 100644 --- a/code/modules/research/nanites/nanite_remote.dm +++ b/code/modules/research/nanites/nanite_remote.dm @@ -165,6 +165,109 @@ . = TRUE +/obj/item/nanite_remote/comm + name = "nanite communication remote" + desc = "A device that can send text messages to specific programs." + icon_state = "nanite_comm_remote" + var/comm_code = 0 + var/comm_message = "" + +/obj/item/nanite_remote/comm/afterattack(atom/target, mob/user, etc) + switch(mode) + if(REMOTE_MODE_OFF) + return + if(REMOTE_MODE_SELF) + to_chat(user, "You activate [src], signaling the nanites in your bloodstream.") + signal_mob(user, comm_code, comm_message) + if(REMOTE_MODE_TARGET) + if(isliving(target) && (get_dist(target, get_turf(src)) <= 7)) + to_chat(user, "You activate [src], signaling the nanites inside [target].") + signal_mob(target, code, comm_message, key_name(user)) + if(REMOTE_MODE_AOE) + to_chat(user, "You activate [src], signaling the nanites inside every host around you.") + for(var/mob/living/L in view(user, 7)) + signal_mob(L, code, comm_message, key_name(user)) + if(REMOTE_MODE_RELAY) + to_chat(user, "You activate [src], signaling all connected relay nanites.") + signal_relay(code, relay_code, comm_message, key_name(user)) + +/obj/item/nanite_remote/comm/signal_mob(mob/living/M, code, source) + SEND_SIGNAL(M, COMSIG_NANITE_COMM_SIGNAL, comm_code, comm_message) + +/obj/item/nanite_remote/comm/signal_relay(code, relay_code, source) + for(var/X in SSnanites.nanite_relays) + var/datum/nanite_program/relay/N = X + N.relay_comm_signal(comm_code, relay_code, comm_message) + +/obj/item/nanite_remote/comm/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) + SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "nanite_comm_remote", name, 420, 800, master_ui, state) + ui.open() + +/obj/item/nanite_remote/comm/ui_data() + var/list/data = list() + data["comm_code"] = comm_code + data["relay_code"] = relay_code + data["comm_message"] = comm_message + data["mode"] = mode + data["locked"] = locked + data["saved_settings"] = saved_settings + + return data + +/obj/item/nanite_remote/comm/ui_act(action, params) + if(..()) + return + switch(action) + if("set_comm_code") + if(locked) + return + var/new_code = input("Set comm code (0000-9999):", name, code) as null|num + if(!isnull(new_code)) + new_code = CLAMP(round(new_code, 1),0,9999) + comm_code = new_code + . = TRUE + if("set_message") + if(locked) + return + var/new_message = stripped_input(usr, "Set the message (Max 300 characters):", "Set Message", null , 300) + if(!new_message) + return + comm_message = new_message + . = TRUE + if("comm_save") + if(locked) + return + var/code_name = stripped_input(usr, "Set the setting name", "Set Name", null , 15) + if(!code_name) + return + var/new_save = list() + new_save["id"] = last_id + 1 + last_id++ + new_save["name"] = code_name + new_save["code"] = comm_code + new_save["mode"] = mode + new_save["relay_code"] = relay_code + new_save["message"] = comm_message + + saved_settings += list(new_save) + . = TRUE + if("comm_load") + var/code_id = params["save_id"] + var/list/setting + for(var/list/X in saved_settings) + if(X["id"] == text2num(code_id)) + setting = X + break + if(setting) + comm_code = setting["code"] + mode = setting["mode"] + relay_code = setting["relay_code"] + comm_message = setting["message"] + . = TRUE + + #undef REMOTE_MODE_OFF #undef REMOTE_MODE_SELF #undef REMOTE_MODE_TARGET diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 0587c7f6077..3dd98081433 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -48,7 +48,7 @@ starting_node = TRUE display_name = "Basic Tools" description = "Basic mechanical, electronic, surgical and botanical tools." - design_ids = list("screwdriver", "wrench", "wirecutters", "crowbar", "multitool", "welding_tool", "tscanner", "analyzer", "cable_coil", "pipe_painter", "airlock_painter", "scalpel", "circular_saw", "surgicaldrill", "retractor", "cautery", "hemostat", "cultivator", "plant_analyzer", "shovel", "spade", "hatchet") + design_ids = list("screwdriver", "wrench", "wirecutters", "crowbar", "multitool", "welding_tool", "tscanner", "analyzer", "cable_coil", "pipe_painter", "airlock_painter", "scalpel", "circular_saw", "surgicaldrill", "retractor", "cautery", "hemostat", "cultivator", "plant_analyzer", "shovel", "spade", "hatchet", "mop") /////////////////////////Biotech///////////////////////// /datum/techweb_node/biotech @@ -56,7 +56,7 @@ display_name = "Biological Technology" description = "What makes us tick." //the MC, silly! prereq_ids = list("base") - design_ids = list("chem_heater", "chem_master", "chem_dispenser", "vr_sleeper", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "medspray","genescanner") + design_ids = list("chem_heater", "chem_master", "chem_dispenser", "pandemic", "defibrillator", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "medspray","genescanner") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 @@ -400,7 +400,7 @@ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server", - "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter") + "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter", "s-messaging") /datum/techweb_node/integrated_HUDs id = "integrated_HUDs" @@ -867,7 +867,7 @@ display_name = "Basic Nanite Programming" description = "The basics of nanite construction and programming." prereq_ids = list("datatheory","robotics") - design_ids = list("nanite_disk","nanite_remote","nanite_scanner",\ + design_ids = list("nanite_disk","nanite_remote","nanite_comm_remote","nanite_scanner",\ "nanite_chamber","public_nanite_chamber","nanite_chamber_control","nanite_programmer","nanite_program_hub","nanite_cloud_control",\ "relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm index 77aff44c317..eb055cbf669 100644 --- a/code/modules/research/xenobiology/crossbreeding/_misc.dm +++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm @@ -16,39 +16,114 @@ Slimecrossing Items default_picture_name = "A nostalgic picture" var/used = FALSE +/datum/saved_bodypart + var/obj/item/bodypart/old_part + var/bodypart_type + var/brute_dam + var/burn_dam + var/stamina_dam + +/datum/saved_bodypart/New(obj/item/bodypart/part) + old_part = part + bodypart_type = part.type + brute_dam = part.brute_dam + burn_dam = part.burn_dam + stamina_dam = part.stamina_dam + +/mob/living/carbon/proc/apply_saved_bodyparts(list/datum/saved_bodypart/parts) + var/list/dont_chop = list() + for(var/zone in parts) + var/datum/saved_bodypart/saved_part = parts[zone] + var/obj/item/bodypart/already = get_bodypart(zone) + if(QDELETED(saved_part.old_part)) + saved_part.old_part = new saved_part.bodypart_type + if(!already || already != saved_part.old_part) + saved_part.old_part.replace_limb(src, TRUE) + saved_part.old_part.heal_damage(INFINITY, INFINITY, INFINITY, null, FALSE) + saved_part.old_part.receive_damage(saved_part.brute_dam, saved_part.burn_dam, saved_part.stamina_dam) + dont_chop[zone] = TRUE + for(var/_part in bodyparts) + var/obj/item/bodypart/part = _part + if(dont_chop[part.body_zone]) + continue + part.drop_limb(TRUE) + +/mob/living/carbon/proc/save_bodyparts() + var/list/datum/saved_bodypart/ret = list() + for(var/_part in bodyparts) + var/obj/item/bodypart/part = _part + var/datum/saved_bodypart/saved_part = new(part) + + ret[part.body_zone] = saved_part + return ret + + + /datum/component/dejavu - var/health //health for simple animals, and integrity for objects + var/integrity //for objects + var/brute_loss //for simple animals + var/list/datum/saved_bodypart/saved_bodyparts //maps bodypart slots to health + var/clone_loss = 0 + var/tox_loss = 0 + var/oxy_loss = 0 + var/brain_loss = 0 var/x var/y var/z - var/rewinds_remaining = 1 + var/rewinds_remaining -/datum/component/dejavu/Initialize() +/datum/component/dejavu/Initialize(rewinds = 1) + rewinds_remaining = rewinds var/turf/T = get_turf(parent) if(T) x = T.x y = T.y z = T.z - if(istype(parent, /mob/living/simple_animal)) + if(isliving(parent)) + var/mob/living/L = parent + clone_loss = L.getCloneLoss() + tox_loss = L.getToxLoss() + oxy_loss = L.getOxyLoss() + brain_loss = L.getBrainLoss() + if(iscarbon(parent)) + var/mob/living/carbon/C = parent + saved_bodyparts = C.save_bodyparts() + else if(isanimal(parent)) var/mob/living/simple_animal/M = parent - health = M.health - else if(istype(parent, /obj)) + brute_loss = M.bruteloss + else if(isobj(parent)) var/obj/O = parent - health = O.obj_integrity + integrity = O.obj_integrity addtimer(CALLBACK(src, .proc/rewind), DEJAVU_REWIND_INTERVAL) /datum/component/dejavu/proc/rewind() to_chat(parent, "You remember a time not so long ago...") + + if(isliving(parent)) + var/mob/living/L = parent + L.setCloneLoss(clone_loss) + L.setToxLoss(tox_loss) + L.setOxyLoss(oxy_loss) + L.setBrainLoss(brain_loss) + + if(iscarbon(parent)) + if(saved_bodyparts) + var/mob/living/carbon/C = parent + C.apply_saved_bodyparts(saved_bodyparts) + else if(isanimal(parent)) + var/mob/living/simple_animal/M = parent + M.bruteloss = brute_loss + M.updatehealth() + else if(isobj(parent)) + var/obj/O = parent + O.obj_integrity = integrity + + //comes after healing so new limbs comically drop to the floor if(!isnull(x) && istype(parent, /atom/movable)) var/atom/movable/AM = parent var/turf/T = locate(x,y,z) AM.forceMove(T) - if(istype(parent, /mob/living/simple_animal)) - var/mob/living/simple_animal/M = parent - M.adjustHealth(health) - else if(istype(parent, /obj)) - var/obj/O = parent - O.obj_integrity = health + rewinds_remaining -- if(rewinds_remaining) addtimer(CALLBACK(src, .proc/rewind), DEJAVU_REWIND_INTERVAL) @@ -69,7 +144,7 @@ Slimecrossing Items to_chat(target, "You'll remember this moment forever!") used = TRUE - target.AddComponent(/datum/component/dejavu) + target.AddComponent(/datum/component/dejavu, 2) .=..() diff --git a/code/modules/research/xenobiology/crossbreeding/regenerative.dm b/code/modules/research/xenobiology/crossbreeding/regenerative.dm index a0a069d70a8..6074f645300 100644 --- a/code/modules/research/xenobiology/crossbreeding/regenerative.dm +++ b/code/modules/research/xenobiology/crossbreeding/regenerative.dm @@ -148,8 +148,9 @@ Regenerative extracts: /obj/item/slimecross/regenerative/sepia colour = "sepia" -/obj/item/slimecross/regenerative/sepia/core_effect(mob/living/target, mob/user) - new /obj/effect/timestop(get_turf(target), 2, 50, list(user,target)) +/obj/item/slimecross/regenerative/sepia/core_effect_before(mob/living/target, mob/user) + to_chat(target, "You try to forget how you feel.") + target.AddComponent(/datum/component/dejavu) /obj/item/slimecross/regenerative/cerulean colour = "cerulean" @@ -252,4 +253,4 @@ Regenerative extracts: colour = "rainbow" /obj/item/slimecross/regenerative/rainbow/core_effect(mob/living/target, mob/user) - target.apply_status_effect(STATUS_EFFECT_RAINBOWPROTECTION) \ No newline at end of file + target.apply_status_effect(STATUS_EFFECT_RAINBOWPROTECTION) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index d706fc4d18e..ff0122f60e6 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -262,6 +262,7 @@ var/engine_coeff = 1 //current engine coeff var/current_engines = 0 //current engine power var/initial_engines = 0 //initial engine power + var/list/engine_list = list() var/can_move_docking_ports = FALSE //if this shuttle can move docking ports other than the one it is docked at var/list/hidden_turfs = list() @@ -725,19 +726,47 @@ return null /obj/docking_port/mobile/proc/hyperspace_sound(phase, list/areas) - var/s + var/selected_sound switch(phase) if(HYPERSPACE_WARMUP) - s = 'sound/effects/hyperspace_begin.ogg' + selected_sound = "hyperspace_begin" if(HYPERSPACE_LAUNCH) - s = 'sound/effects/hyperspace_progress.ogg' + selected_sound = "hyperspace_progress" if(HYPERSPACE_END) - s = 'sound/effects/hyperspace_end.ogg' + selected_sound = "hyperspace_end" else CRASH("Invalid hyperspace sound phase: [phase]") - for(var/A in areas) - for(var/obj/machinery/door/E in A) //dumb, I know, but playing it on the engines doesn't do it justice - playsound(E, s, 100, FALSE, max(width, height) - world.view) + // This previously was played from each door at max volume, and was one of the worst things I had ever seen. + // Now it's instead played from the nearest engine if close, or the first engine in the list if far since it doesn't really matter. + // Or a door if for some reason the shuttle has no engine, fuck oh hi daniel fuck it + var/range = (engine_coeff * max(width, height)) + var/long_range = range * 2.5 + var/atom/distant_source + if(engine_list[1]) + distant_source = engine_list[1] + else + for(var/A in areas) + distant_source = locate(/obj/machinery/door) in A + if(distant_source) + break + + if(distant_source) + for(var/mob/M in SSmobs.clients_by_zlevel[z]) + var/dist_far = get_dist(M, distant_source) + if(dist_far <= long_range && dist_far > range) + M.playsound_local(distant_source, "sound/effects/[selected_sound]_distance.ogg", 100, falloff = 20) + else if(dist_far <= range) + var/source + if(engine_list.len == 0) + source = distant_source + else + var/closest_dist = 10000 + for(var/obj/O in engine_list) + var/dist_near = get_dist(M, O) + if(dist_near < closest_dist) + source = O + closest_dist = dist_near + M.playsound_local(source, "sound/effects/[selected_sound].ogg", 100, falloff = range / 2) // Losing all initial engines should get you 2 // Adding another set of engines at 0.5 time @@ -749,14 +778,15 @@ current_engines = max(0,current_engines + mod) if(in_flight()) var/delta_coeff = engine_coeff / old_coeff - modTimer(delta_coeff) - + modTimer(delta_coeff) + /obj/docking_port/mobile/proc/count_engines() . = 0 for(var/thing in shuttle_areas) var/area/shuttle/areaInstance = thing for(var/obj/structure/shuttle/engine/E in areaInstance.contents) if(!QDELETED(E)) + engine_list += E . += E.engine_power // Double initial engines to get to 0.5 minimum diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index 46afae0a2d7..b2d00e1a8e1 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -76,7 +76,7 @@ break if(!our_statue) - name = "inert [name]" + name = "inert [initial(name)]" return else name = initial(name) diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index cb2af17e1e4..652ef3badf1 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -35,6 +35,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for the badmin verb for now /obj/effect/proc_holder/Destroy() + if (action) + qdel(action) if(ranged_ability_user) remove_ranged_ability() return ..() diff --git a/code/modules/spells/spell_types/inflict_handler.dm b/code/modules/spells/spell_types/inflict_handler.dm index 94d5ed7a36c..f5ce493b4a2 100644 --- a/code/modules/spells/spell_types/inflict_handler.dm +++ b/code/modules/spells/spell_types/inflict_handler.dm @@ -2,7 +2,7 @@ name = "Inflict Handler" desc = "This spell blinds and/or destroys/damages/heals and/or knockdowns/stuns the target." - var/amt_knockdown = 0 + var/amt_paralyze = 0 var/amt_unconscious = 0 var/amt_stun = 0 @@ -44,7 +44,7 @@ target.adjustToxLoss(amt_dam_tox) target.adjustOxyLoss(amt_dam_oxy) //disabling - target.Paralyze(amt_knockdown) + target.Paralyze(amt_paralyze) target.Unconscious(amt_unconscious) target.Stun(amt_stun) diff --git a/code/modules/spells/spell_types/summonitem.dm b/code/modules/spells/spell_types/summonitem.dm index c6b95d183c9..bf8332c95eb 100644 --- a/code/modules/spells/spell_types/summonitem.dm +++ b/code/modules/spells/spell_types/summonitem.dm @@ -80,8 +80,6 @@ if(iscarbon(M)) //Edge case housekeeping var/mob/living/carbon/C = M - 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/bodypart/part = X if(item_to_retrieve in part.embedded_objects) diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index dc327474e5f..dccad5b0ee2 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -21,7 +21,7 @@ speed = 5 trigger_range = 0 linger = TRUE - knockdown = 60 + paralyze = 60 hitsound = 'sound/magic/mm_hit.ogg' trail = TRUE diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 840b59c1466..5c20ede1815 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -29,27 +29,50 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) if(I.limited_stock < 0 && !I.cant_discount && I.item && I.cost > 1) sale_items += I if(allow_sales) - for(var/i in 1 to 3) - var/datum/uplink_item/I = pick_n_take(sale_items) - var/datum/uplink_item/A = new I.type - var/discount = A.get_discount() - var/list/disclaimer = list("Void where prohibited.", "Not recommended for children.", "Contains small parts.", "Check local laws for legality in region.", "Do not taunt.", "Not responsible for direct, indirect, incidental or consequential damages resulting from any defect, error or failure to perform.", "Keep away from fire or flames.", "Product is provided \"as is\" without any implied or expressed warranties.", "As seen on TV.", "For recreational use only.", "Use only as directed.", "16% sales tax will be charged for orders originating within Space Nebraska.") - A.limited_stock = 1 - I.refundable = FALSE //THIS MAN USES ONE WEIRD TRICK TO GAIN FREE TC, CODERS HATES HIM! - A.refundable = FALSE - if(A.cost >= 20) //Tough love for nuke ops - discount *= 0.5 - A.cost = max(round(A.cost * discount),1) - A.category = "Discounted Gear" - A.name += " ([round(((initial(A.cost)-A.cost)/initial(A.cost))*100)]% off!)" - A.desc += " Normally costs [initial(A.cost)] TC. All sales final. [pick(disclaimer)]" - A.item = I.item + var/datum/team/nuclear/nuclear_team + if (gamemode == /datum/game_mode/nuclear) // uplink code kind of needs a redesign + nuclear_team = locate() in GLOB.antagonist_teams // the team discounts could be a in a GLOB with this design but it would make sense for them to be team specific... + if (!nuclear_team) + create_uplink_sales(3, "Discounted Gear", 1, sale_items, filtered_uplink_items) + else + if (!nuclear_team.team_discounts) + // create 5 unlimited stock discounts + create_uplink_sales(5, "Discounted Team Gear", -1, sale_items, filtered_uplink_items) + // Create 10 limited stock discounts + create_uplink_sales(10, "Limited Stock Team Gear", 1, sale_items, filtered_uplink_items) + nuclear_team.team_discounts = list("Discounted Team Gear" = filtered_uplink_items["Discounted Team Gear"], "Limited Stock Team Gear" = filtered_uplink_items["Limited Stock Team Gear"]) + else + filtered_uplink_items["Discounted Team Gear"] = nuclear_team.team_discounts["Discounted Team Gear"] + filtered_uplink_items["Limited Stock Team Gear"] = nuclear_team.team_discounts["Limited Stock Team Gear"] + - if(!filtered_uplink_items[A.category]) - filtered_uplink_items[A.category] = list() - filtered_uplink_items[A.category][A.name] = A return filtered_uplink_items +/proc/create_uplink_sales(num, category_name, limited_stock, sale_items, uplink_items) + if (num <= 0) + return + + if(!uplink_items[category_name]) + uplink_items[category_name] = list() + + for (var/i in 1 to num) + var/datum/uplink_item/I = pick_n_take(sale_items) + var/datum/uplink_item/A = new I.type + var/discount = A.get_discount() + var/list/disclaimer = list("Void where prohibited.", "Not recommended for children.", "Contains small parts.", "Check local laws for legality in region.", "Do not taunt.", "Not responsible for direct, indirect, incidental or consequential damages resulting from any defect, error or failure to perform.", "Keep away from fire or flames.", "Product is provided \"as is\" without any implied or expressed warranties.", "As seen on TV.", "For recreational use only.", "Use only as directed.", "16% sales tax will be charged for orders originating within Space Nebraska.") + A.limited_stock = limited_stock + I.refundable = FALSE //THIS MAN USES ONE WEIRD TRICK TO GAIN FREE TC, CODERS HATES HIM! + A.refundable = FALSE + if(A.cost >= 20) //Tough love for nuke ops + discount *= 0.5 + A.category = category_name + A.cost = max(round(A.cost * discount),1) + A.name += " ([round(((initial(A.cost)-A.cost)/initial(A.cost))*100)]% off!)" + A.desc += " Normally costs [initial(A.cost)] TC. All sales final. [pick(disclaimer)]" + A.item = I.item + + uplink_items[category_name][A.name] = A + /** * Uplink Items @@ -1424,6 +1447,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item)) item = /obj/item/suspiciousphone restricted = TRUE cost = 7 + limited_stock = 1 // Implants /datum/uplink_item/implants diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm index f124bc76a0f..c25c0627af7 100644 --- a/code/modules/vehicles/ridden.dm +++ b/code/modules/vehicles/ridden.dm @@ -7,6 +7,7 @@ var/legs_required = 2 var/arms_required = 1 //why not? var/fall_off_if_missing_arms = FALSE //heh... + var/message_cooldown = 0 /obj/vehicle/ridden/Initialize() . = ..() @@ -64,7 +65,9 @@ if(legs_required) var/how_many_legs = user.get_num_legs() if(how_many_legs < legs_required) - to_chat(user, "You can't seem to manage that with[how_many_legs ? " your leg[how_many_legs > 1 ? "s" : null]" : "out legs"]...") + if(message_cooldown < world.time) + to_chat(user, "You can't seem to manage that with[how_many_legs ? " your leg[how_many_legs > 1 ? "s" : null]" : "out legs"]...") + message_cooldown = world.time + 5 SECONDS return FALSE if(arms_required) var/how_many_arms = user.get_num_arms() @@ -78,7 +81,9 @@ L.Stun(30) return FALSE - to_chat(user, "You can't seem to manage that with[how_many_arms ? " your arm[how_many_arms > 1 ? "s" : null]" : "out arms"]...") + if(message_cooldown < world.time) + to_chat(user, "You can't seem to manage that with[how_many_arms ? " your arm[how_many_arms > 1 ? "s" : null]" : "out arms"]...") + message_cooldown = world.time + 5 SECONDS return FALSE var/datum/component/riding/R = GetComponent(/datum/component/riding) R.handle_ride(user, direction) diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index 6b2aeaadc82..397627075ae 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -16,6 +16,8 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY CANISTER CHARGES in vending_items.dm */ +#define MAX_VENDING_INPUT_AMOUNT 30 + /datum/data/vending_product name = "generic" var/product_path = null @@ -74,8 +76,10 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C var/default_price = 25 var/extra_price = 50 var/onstation = TRUE //if it doesn't originate from off-station during mapload, everything is free + var/list/canload_access_list - var/dish_quants = list() //used by the snack machine's custom compartment to count dishes. + var/list/vending_machine_input = list() + var/input_display_header = "Custom Compartment" var/obj/item/vending_refill/refill_canister = null //The type of refill canisters used by this machine. @@ -274,8 +278,42 @@ GLOBAL_LIST_EMPTY(vending_products) else to_chat(user, "There's nothing to restock!") return + if(compartmentLoadAccessCheck(user)) + if(canLoadItem(I)) + loadingAttempt(I,user) + updateUsrDialog() //can't put this on the proc above because we spam it below + + if(istype(I, /obj/item/storage/bag)) //trays USUALLY + var/obj/item/storage/T = I + var/loaded = 0 + var/denied_items = 0 + for(var/obj/item/the_item in T.contents) + if(contents.len >= MAX_VENDING_INPUT_AMOUNT) // no more than 30 item can fit inside, legacy from snack vending although not sure why it exists + to_chat(user, "[src]'s chef compartment is full.") + break + if(loadingAttempt(the_item,user)) + SEND_SIGNAL(T, COMSIG_TRY_STORAGE_TAKE, the_item, src, TRUE) + loaded++ + else + denied_items++ + if(denied_items) + to_chat(user, "[src] refuses some items.") + if(loaded) + to_chat(user, "You insert [loaded] dishes into [src]'s chef compartment.") + updateUsrDialog() else - return ..() + ..() + +/obj/machinery/vending/proc/loadingAttempt(obj/item/I,mob/user) + . = TRUE + if(!user.transferItemToLoc(I, src)) + return FALSE + if(vending_machine_input[I.name]) + vending_machine_input[I.name]++ + else + vending_machine_input[I.name] = 1 + to_chat(user, "You insert [I] into [src]'s input compartment.") + /obj/machinery/vending/exchange_parts(mob/user, obj/item/storage/part_replacer/W) if(!istype(W)) @@ -361,12 +399,12 @@ GLOBAL_LIST_EMPTY(vending_products) dat += "" if(onstation && C && C.registered_account) dat += "Balance: $[account.account_balance]" - if(istype(src, /obj/machinery/vending/snack)) - dat += "

Chef's Food Selection

" + if(vending_machine_input.len) + dat += "

[input_display_header]

" dat += "
" - for (var/O in dish_quants) - if(dish_quants[O] > 0) - var/N = dish_quants[O] + for (var/O in vending_machine_input) + if(vending_machine_input[O] > 0) + var/N = vending_machine_input[O] dat += "Dispense " dat += "[capitalize(O)] ($[default_price]): [N]
" dat += "
" @@ -385,7 +423,7 @@ GLOBAL_LIST_EMPTY(vending_products) if((href_list["dispense"]) && (vend_ready)) var/N = href_list["dispense"] - if(dish_quants[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. + if(vending_machine_input[N] <= 0) // Sanity check, there are probably ways to press the button when it shouldn't be possible. return vend_ready = 0 if(ishuman(usr) && onstation) @@ -410,7 +448,7 @@ GLOBAL_LIST_EMPTY(vending_products) D.adjust_money(chef_price) use_power(5) - dish_quants[N] = max(dish_quants[N] - 1, 0) + vending_machine_input[N] = max(vending_machine_input[N] - 1, 0) for(var/obj/O in contents) if(O.name == N) say("Thank you for supporting your local kitchen and purchasing [O]!") @@ -575,5 +613,28 @@ GLOBAL_LIST_EMPTY(vending_products) else return FALSE +/obj/machinery/vending/proc/canLoadItem(obj/item/I,mob/user) + return FALSE + +/obj/machinery/vending/proc/compartmentLoadAccessCheck(mob/user) + if(!canload_access_list) + return TRUE + else + var/do_you_have_access = FALSE + var/req_access_txt_holder = req_access_txt + for(var/i in canload_access_list) + req_access_txt = i + if(!allowed(user) && !(obj_flags & EMAGGED) && scan_id) + continue + else + do_you_have_access = TRUE + break //you passed don't bother looping anymore + req_access_txt = req_access_txt_holder // revert to normal (before the proc ran) + if(do_you_have_access) + return TRUE + else + to_chat(user, "[src]'s input compartment blinks red: Access denied.") + return FALSE + /obj/machinery/vending/onTransitZ() return diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm index 600e6e855de..bd88395279b 100644 --- a/code/modules/vending/autodrobe.dm +++ b/code/modules/vending/autodrobe.dm @@ -132,6 +132,9 @@ /obj/item/clothing/head/clownmitre = 1, /obj/item/skub = 1,) +/obj/machinery/vending/autodrobe/canLoadItem(obj/item/I,mob/user) + return (I.type in products) + refill_canister = /obj/item/vending_refill/autodrobe default_price = 50 extra_price = 75 diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm index f0db03002b9..d73e61c28a0 100644 --- a/code/modules/vending/clothesmate.dm +++ b/code/modules/vending/clothesmate.dm @@ -123,6 +123,9 @@ extra_price = 75 payment_department = NO_FREEBIES +/obj/machinery/vending/clothing/canLoadItem(obj/item/I,mob/user) + return (I.type in products) + /obj/item/vending_refill/clothing machine_name = "ClothesMate" icon_state = "refill_clothes" diff --git a/code/modules/vending/medical.dm b/code/modules/vending/medical.dm index 866b07a6e65..ad7341cc29e 100644 --- a/code/modules/vending/medical.dm +++ b/code/modules/vending/medical.dm @@ -14,9 +14,10 @@ /obj/item/reagent_containers/pill/salbutamol = 2, /obj/item/reagent_containers/pill/insulin = 5, /obj/item/reagent_containers/glass/bottle/charcoal = 4, - /obj/item/reagent_containers/glass/bottle/epinephrine = 4, - /obj/item/reagent_containers/glass/bottle/salglu_solution = 3, + /obj/item/reagent_containers/glass/bottle/epinephrine = 3, /obj/item/reagent_containers/glass/bottle/morphine = 4, + /obj/item/reagent_containers/glass/bottle/potass_iodide = 1, + /obj/item/reagent_containers/glass/bottle/salglu_solution = 3, /obj/item/reagent_containers/glass/bottle/toxin = 3, /obj/item/reagent_containers/syringe/antiviral = 6, /obj/item/reagent_containers/medspray/styptic = 2, diff --git a/code/modules/vending/snack.dm b/code/modules/vending/snack.dm index 00f7897a298..c80b2457656 100644 --- a/code/modules/vending/snack.dm +++ b/code/modules/vending/snack.dm @@ -14,79 +14,34 @@ /obj/item/reagent_containers/food/snacks/energybar = 6) contraband = list(/obj/item/reagent_containers/food/snacks/syndicake = 6) refill_canister = /obj/item/vending_refill/snack - var/chef_compartment_access = "28" //ACCESS_KITCHEN + canload_access_list = list(ACCESS_KITCHEN) default_price = 20 extra_price = 30 payment_department = ACCOUNT_SRV + input_display_header = "Chef's Food Selection" /obj/item/vending_refill/snack machine_name = "Getmore Chocolate Corp" -/obj/machinery/vending/snack/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/reagent_containers/food/snacks)) - if(!compartment_access_check(user)) - return - var/obj/item/reagent_containers/food/snacks/S = W - if(!S.junkiness) - if(!iscompartmentfull(user)) - if(!user.transferItemToLoc(W, src)) - return - food_load(W) - to_chat(user, "You insert [W] into [src]'s chef compartment.") - else - to_chat(user, "[src]'s chef compartment does not accept junk food.") - - else if(istype(W, /obj/item/storage/bag/tray)) - if(!compartment_access_check(user)) - return - var/obj/item/storage/T = W - var/loaded = 0 - var/denied_items = 0 - for(var/obj/item/reagent_containers/food/snacks/S in T.contents) - if(iscompartmentfull(user)) - break - if(!S.junkiness) - SEND_SIGNAL(T, COMSIG_TRY_STORAGE_TAKE, S, src, TRUE) - food_load(S) - loaded++ - else - denied_items++ - if(denied_items) - to_chat(user, "[src] refuses some items.") - if(loaded) - to_chat(user, "You insert [loaded] dishes into [src]'s chef compartment.") - updateUsrDialog() - return - - else - return ..() +/obj/machinery/vending/snack/canLoadItem(obj/item/I,mob/user) + . = FALSE + if(istype(I,/obj/item/reagent_containers/food/snacks)) + var/obj/item/reagent_containers/food/snacks/snacki = I + if(snacki.junkiness) + return FALSE + return TRUE /obj/machinery/vending/snack/Destroy() for(var/obj/item/reagent_containers/food/snacks/S in contents) S.forceMove(get_turf(src)) return ..() -/obj/machinery/vending/snack/proc/compartment_access_check(user) - req_access_txt = chef_compartment_access - if(!allowed(user) && !(obj_flags & EMAGGED) && scan_id) - to_chat(user, "[src]'s chef compartment blinks red: Access denied.") - req_access_txt = "0" - return 0 - req_access_txt = "0" - return 1 - -/obj/machinery/vending/snack/proc/iscompartmentfull(mob/user) - if(contents.len >= 30) // no more than 30 dishes can fit inside - to_chat(user, "[src]'s chef compartment is full.") - return 1 - return 0 - /obj/machinery/vending/snack/proc/food_load(obj/item/reagent_containers/food/snacks/S) - if(dish_quants[S.name]) - dish_quants[S.name]++ + if(vending_machine_input[S.name]) + vending_machine_input[S.name]++ else - dish_quants[S.name] = 1 - sortList(dish_quants) + vending_machine_input[S.name] = 1 + sortList(vending_machine_input) /obj/machinery/vending/snack/random name = "\improper Random Snackies" diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index b81a4582455..45b380fbf6c 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -5,6 +5,10 @@ default_price = 50 extra_price = 75 payment_department = NO_FREEBIES + input_display_header = "Returned Clothing" + +/obj/machinery/vending/wardrobe/canLoadItem(obj/item/I,mob/user) + return (I.type in products) /obj/machinery/vending/wardrobe/sec_wardrobe name = "\improper SecDrobe" @@ -320,7 +324,7 @@ /obj/item/toy/plush/narplush = 1, /obj/item/clothing/head/medievaljewhat = 3, /obj/item/clothing/suit/chaplainsuit/clownpriest = 1, - /obj/item/clothing/head/clownmitre = 1) + /obj/item/clothing/head/clownmitre = 1) premium = list(/obj/item/clothing/suit/chaplainsuit/bishoprobe = 1, /obj/item/clothing/head/bishopmitre = 1) refill_canister = /obj/item/vending_refill/wardrobe/chap_wardrobe diff --git a/html/changelog.html b/html/changelog.html index 08628bc3ea9..37c5aaaf480 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,259 @@ -->
+

27 May 2019

+

4dplanner updated:

+
    +
  • The deja vu effect (previously only used by rewind camera) now resets all your limbs and damage to the point it was added after 10 seconds (as well as the original position reset)
  • +
  • The deja vu effect cannot resurrect the dead, but will heal their corpse
  • +
  • New limbs fall off, old ones re-attach
  • +
  • Regenerative sepia cores add a deja vu effect before healing instead of a timestop
  • +
  • The rewind camera rewinds 2 times to distinguish it from the regenerative core
  • +
  • colossus and drake can no longer attack from the afterlife
  • +
  • timestop is properly defeated by antimagic.
  • +
  • timestop only checks antimagic once
  • +
+

Akrilla updated:

+
    +
  • Traitors now recognize codewords automatically in spoken conversation. Phrases in blue, responses in red.
  • +
  • Changed traitor greet text slightly.
  • +
+

ExcessiveUseOfVending updated:

+
    +
  • Wardrobe Vendors will now accept clothing types they sell. Now you can clean up after getting that cool alternate uniform!
  • +
  • see PR #43964 on how to easily setup a vending machine to accept items!
  • +
+

Farquaar updated:

+
    +
  • The monk's frock has been sanctified and will no longer reveal your naked body when the hood is pulled up.
  • +
+

Fire Chance updated:

+
    +
  • Fixed the drink sprites overlapping when you are mixing beer with other drinks.
  • +
+

Garen7 updated:

+
    +
  • Lesser form lings can now toggle augmented vision
  • +
  • You can no longer turn back into human form as a lesser form ling while ventcrawling
  • +
  • Stuns and Reagents are now passed when transforming into a monkey or human
  • +
+

Irafas updated:

+
    +
  • Connected the incinerator/janitor's/botany backroom/service rooms to the scrubber network
  • +
+

JJRcop updated:

+
    +
  • You can now build a new PDA messaging server if you lose it.
  • +
  • Requests console messages no longer work if the messaging server is offline. Emergency alerts will still function in that case as long as the rest of telecomms is online.
  • +
+

Naksu updated:

+
    +
  • pipeline gas reconciliation is now faster
  • +
+

OnlineGirlfriend updated:

+
    +
  • Lemonade
  • +
  • Arnold Palmer recipe
  • +
  • lemonade sprite
  • +
+

Putnam3145 updated:

+
    +
  • All departments can now print basic power cells from their respective techfab.
  • +
+

RaveRadbury updated:

+
    +
  • Quirks have flavor text in medical records
  • +
  • All quirks have medical record entries
  • +
  • All quirk medical records refer to "Patient", removing a few instances of "Subject"
  • +
+

Tlaltecuhtli updated:

+
    +
  • fixes message spam from riding a vehicle without enough legs/arms
  • +
+

XDTM updated:

+
    +
  • Added a new device, the nanite communication remote, which can be used to send custom messages to message-based nanite programs.
  • +
  • Comm remotes use separate Comm Codes: for a message to be received, the signal's comm code must be the same as the program's.
  • +
+

actioninja updated:

+
    +
  • Shuttle sounds should no longer ass blast your ears as they no longer play PER DOOR and instead from the nearest engine, or door if none are available.
  • +
  • Distant shuttle sounds.
  • +
+

bgobandit updated:

+
    +
  • TP now shows the names of blood brothers' brothers.
  • +
+

hey there uwu updated:

+
    +
  • You can no longer choose the zombie race from the magic mirror, as intended.
  • +
+

nemvar updated:

+
    +
  • Colored lights now shine in different colours.
  • +
  • Mops can now be printed at the autolathe and protolathe.
  • +
+

tralezab updated:

+
    +
  • Gravitokinetic stands are now available!
  • +
+ +

23 May 2019

+

4dplanner updated:

+
    +
  • between the sheets heals carbons
  • +
  • colossus chest is intangible to colossus bolts
  • +
+

Naksu updated:

+
    +
  • removed some unnecessary wrappers in Life() code.
  • +
  • get_area() is now a define rather than a proc.
  • +
+

TheSilverNuke updated:

+
    +
  • edaggers have a special suicide!
  • +
+

nemvar updated:

+
    +
  • You can now reuse chemical grenade casings if they fail to react.
  • +
+

ninjanomnom updated:

+
    +
  • Some rpg affixes now have special effects
  • +
+

weeweesoda updated:

+
    +
  • The CRAB protocol traitor item now has a maximum stock of 1 each round
  • +
+ +

22 May 2019

+

Incoming5643 updated:

+
    +
  • After a very long period of being broken, the training bomb in security finally works properly again.
  • +
  • Syndicate bomb cores have become a little more robust in their operation. Defused but still cored bombs are no longer inert and can be set again. Would be heroes are advised to cut out and dispose of bomb cores, and dismantle unneeded bomb shells to be absolutely sure.
  • +
+

MrFluffster updated:

+
    +
  • CLOTH foodtype
  • +
+

Naksu updated:

+
    +
  • Added a new blob strain that grows inside the station and eats garbage
  • +
  • Several fixes for stuff harddeling
  • +
  • Cryotubes no longer display a double of a person that was once in but teleported out by having ingested bluespace or other such nonsense
  • +
  • pda.detonatable and uplink component checks removed in favor of a signal in detomatix cart handling
  • +
  • nukeop uplinks now have 5 unlimited discounts and 10 limited discounts shared between the team, rather than 3 individual discounts like traitor uplinks
  • +
  • corpses no longer feel, light-headed or otherwise
  • +
  • removed /datum/mutation/human/proc/on_move in favor of having the chameleon mutation register for a signal
  • +
+

RaveRadbury updated:

+
    +
  • "Religiously Comforted" from Spiritual Quirk occurs on examine and lasts for 5 minutes
  • +
+

kriskog updated:

+
    +
  • Added a bunch of previously missing adjacency checks to ui window actions and alt clicks.
  • +
+

loserXD updated:

+
    +
  • Hangar Bay Shutters need only general CentCom access to open now
  • +
+

nemvar updated:

+
    +
  • Podcloning now lets you keep your quirks.
  • +
+

vuonojenmustaturska updated:

+
    +
  • Removed the ability of fat people to vore monkeys, and the ability of aliens to vore humans.
  • +
  • Removed stubbed out would-be functionality related to stomach contents
  • +
  • Nuclear Operative reinforcements now get uplinks with 0 TC and a real name.
  • +
+ +

19 May 2019

+

CrazyClown12 updated:

+
    +
  • The chloral hydrate inside of the sleepy pen is no longer slower acting than chloral hydrate made in chemistry.
  • +
  • The chloral hydrate inside of cookies synthesised by emagged borgs is no longer slower acting than chloral hydrate made in chemistry.
  • +
  • Delayed chloral hydrate
  • +
+

Erwgd updated:

+
    +
  • Swapped out an epinephrine bottle for potassium iodide in NanoMed Plus vending machines.
  • +
+

Naksu updated:

+
    +
  • Items using atom colors for coloring now show up properly colored in vending machines, rather than snow-white
  • +
+

Partheo updated:

+
    +
  • Scrubbers have updated design and animation
  • +
+

Rave Radbury, Art by Navi.OS updated:

+
    +
  • pAI's have a bunch of HUD stuff now
  • +
  • pAI's now have an AI style PDA
  • +
  • pAI cameras can now download a zoom feature! Bigger and smaller pictures!
  • +
  • Split the pAI medhud module into seperate medhud and health analyzer modules
  • +
  • Journalism modules now have RAM costs
  • +
  • RAM prices have changed on a number of modules
  • +
  • added more pAI HUD icons
  • +
+

Zxaber updated:

+
    +
  • AI power backup is now separate from the health, and is tied to their core. Carding an AI on battery backup will leave the core at partial charge. AIs no longer slowly lose integrity while on backups (but will instantly die as before once the backup runs out). As such, whacking an AI with a wrench will no longer magically lower their backup battery capacity.
  • +
  • AIs on backup battery can now unbolt at the cost of a quarter of their battery's max charge. This cannot be done while at under 25% power.
  • +
+

imsxz updated:

+
    +
  • cakehat has been nerfed
  • +
  • cakehat sounds cooler
  • +
+ +

17 May 2019

+

4dplanner updated:

+
    +
  • health hud will no longer show full health at 0 hp
  • +
  • glass golems properly redirect projectiles
  • +
  • glass golem reflected projectiles can damage the original firer
  • +
+

ExcessiveUseOfCobblestone updated:

+
    +
  • borgs can now unbuckle people from stasis beds
  • +
+

Garen7 updated:

+
    +
  • fixes lings being able to infinitely use their strained muscles
  • +
+

Naksu updated:

+
    +
  • The crabphone will no longer deafen everyone who didn't have the foreknowledge that it was coming.
  • +
  • The crabphone has 80% less HP, as befits something that costs 7 TC and is not two bubblegums stacked on top of eachother.
  • +
  • Nuclear operative TC now comes pre-distributed, the telecrystal assignment stations have been removed.
  • +
  • mindshield nanites no longer give mindshields to revheads and one mind awoken hiveminds.
  • +
  • Fixed several issues with venus human traps and their vines going through walls
  • +
  • Made atmos update_visuals() proc a bit faster
  • +
+

jegub updated:

+
    +
  • Lets the grass grow under your feet.
  • +
+

nemvar updated:

+
    +
  • Explosive holoparasite bombs now explode if you bump into them, instead of the other way around.
  • +
+

pireamaineach updated:

+
    +
  • Added a 3rd atmos tech locker and rad locker to the incinerators on Meta and Box, and an atmos tech locker to the incinerator on Pubby since it already had a rad-suit.
  • +
  • Reverts https://github.com/tgstation/tgstation/pull/43557
  • +
  • Makes the doors to the incinerator on meta require atmos access.
  • +
  • Axes some hairstyles that didn't make the final cut but never got fully removed, removes an unused sprite.
  • +
  • Also fixes the cornrows because they were bRoek
  • +
+

zeroisthebiggay updated:

+
    +
  • Gives Sentient Diseases a medical hud to observe their victims further with.
  • +
+

14 May 2019

Flatgub updated:

    @@ -78,6 +331,10 @@
  • An extra tile to the Box chapel's width
  • One barely noticeable tile of width from escape(one escape brig chair dead [*] )
+

RaveRadbury updated:

+
    +
  • mood_event timeouts are now in MINUTES and SECONDS
  • +

Skoglol updated:

  • You no longer get shocked by shock touching someone you are pulling.
  • @@ -780,394 +1037,6 @@
    • -Mechs no longer explode on death -Mechs and syndicate combat mechs sleep the pilot for 2s when destroyed, other combat mechs for 4s. -Mechs now have exit times. 1s for basic ripley, 2s for other mechs, 4s for all combat mechs. You cannot punch or use equipment when exiting, and moving cancels.
    - -

    25 March 2019

    -

    ShizCalev updated:

    -
      -
    • Added a chair to pubby's cloning room.
    • -
    • Fixed a minor runtime caused by admins clicking a follow link while in the lobby.
    • -
    -

    actioninja updated:

    -
      -
    • Lot of small darkmode fixes
    • -
    - -

    24 March 2019

    -

    Mickyan updated:

    -
      -
    • Strong alcoholic beverages in excessive quantity are now far more dangerous. Drink responsibly.
    • -
    - -

    23 March 2019

    -

    Borisvanmemes updated:

    -
      -
    • ED 209s now drop DRAGNets and not tasers
    • -
    -

    MrStonedOne updated:

    -
      -
    • Fixed the connection cap being silly about what connections it counted towards the limit.
    • -
    -

    SpaceManiac updated:

    -
      -
    • Heirloom bodybags no longer lose their heirloom status when deployed.
    • -
    -

    actioninja updated:

    -
      -
    • Goonchat properly loads the white theme by default.
    • -
    • The input bar no longer has weirdness with color when swapping themes.
    • -
    - -

    22 March 2019

    -

    Atlanta Ned updated:

    -
      -
    • If you've got Head of Staff access, you can now message Central Command. Central Command is not responsible for any executions sustained as a result of mutinous behavior.
    • -
    -

    Fikou updated:

    -
      -
    • added an ezmk pulse rifle to the seraph mech
    • -
    • removed the buckshot gun from the seraph mech
    • -
    -

    MMMiracles updated:

    -
      -
    • The engine on Donutstation has been changed to the Supermatter.
    • -
    -

    MrStonedOne updated:

    -
      -
    • Exempted byond accounts already in the round from the connected players cap, allowing them to reconnect even if the server is full. This exemption applies even if you are dead or are a ghost, but does not apply if you hit "observe" from the lobby.
    • -
    -

    ShizCalev updated:

    -
      -
    • ED-209 tablecrafting recipe has been corrected to use a DRAGNet
    • -
    • Fixed an exploit allowing you to grab people from anywhere with a clowncar.
    • -
    • Simple mobs can now only damage clown cars from the inside if they're able to smash through walls.
    • -
    • Mech disablers are no longer invisible.
    • -
    • Improved some cloning logging.
    • -
    • Emagging a cloning pod will now leave fingerprints.
    • -
    • Ejecting someone while they're being cloned will now leave fingerprints.
    • -
    -

    SpaceManiac updated:

    -
      -
    • Logs for certain kinds of errors will now include better debugging information.
    • -
    • Renamed the "any color" paint bucket to "adaptive paint".
    • -
    -

    Tlaltecuhtli updated:

    -
      -
    • ai/borg uploads now have a gps signal when built which will be active until its monitor gets decostructed
    • -
    • ai/borg uploads take slighty longer to deconstruct
    • -
    -

    anconfuzedrock updated:

    -
      -
    • New negative quirk - back pain causes very bad mood from wearing uneven storage items on your back, but other back items like air tanks and shotguns are okay.
    • -
    -

    plapatin updated:

    -
      -
    • Watch the Tip of the Round messages, there's a few extra ones out there now, along with outdated ones being revised!
    • -
    - -

    21 March 2019

    -

    Militaires updated:

    -
      -
    • Snails now utilize glasses offset system
    • -
    -

    ShizCalev updated:

    -
      -
    • Repairing robotic limbs attached to yourself will no longer refer to you in the third person.
    • -
    • You'll no longer hit an air alarm with your ID when unlocking it.
    • -
    • Admin modify bodyparts panel will now only show parts that are valid for modification.
    • -
    -

    SpironoZeppeli updated:

    -
      -
    • Ethereals no longer die to their own charge levels
    • -
    -

    Tlaltecuhtli updated:

    -
      -
    • the medkits in the beach dome, city of clog and russian shuttle are no longer empty
    • -
    -

    actioninja updated:

    -
      -
    • admin pms display in the proper colors
    • -
    • some uis are no longer unreadable.
    • -
    • Updated the colors of the dark mode ui.
    • -
    • darkmode is no longer the default
    • -
    - -

    20 March 2019

    -

    Basilman updated:

    -
      -
    • Chaplain's holy whip now deals more damage to vampires.
    • -
    • Fixed adminheal not curing various status effects
    • -
    • Fixed certain alien organs (eyes, tongue, liver) not registering for organ bounty.
    • -
    -

    Kmc2000 updated:

    -
      -
    • Added darkmode! You can opt-in to this by clicking the settings icon on goonchat, and looking for the toggle darkmode button.
    • -
    -

    Militaires updated:

    -
      -
    • Fixed cursed hearts maintaining red filter even when removed
    • -
    -

    MrStonedOne updated:

    -
      -
    • afk kicker no longer exempts ghosts
    • -
    • afk kicker now exempts people in the lobby join queue
    • -
    • afk kicker now exempts admins
    • -
    • afk kicker now includes a link you can use rejoin quickly.
    • -
    • (Note: these all apply to the default disabled idle time kicker, not the end of round lobby kicker)
    • -
    -

    PKPenguin321 updated:

    -
      -
    • Spasms should no longer cause you to step out of closed chambers, like cryo or DNA scanners.
    • -
    -

    Pandolphina updated:

    -
      -
    • Miniature energy guns can fit in the holster
    • -
    -

    ShizCalev updated:

    -
      -
    • Added DRAGnet crates to cargonia.
    • -
    • Fixed runtime when shooting podpeople with a alpha somatoray
    • -
    • Floorbots can now be constructed with normal toolboxes.
    • -
    -

    SpaceManiac updated:

    -
      -
    • Random docking ports (escape pod Lavaland destinations) print a more informative warning and delete themselves if Lavaland does not exist.
    • -
    -

    Time-Green updated:

    -
      -
    • Snails can't wear glasses
    • -
    • Snails don't lube the floor when buckled anymore
    • -
    -

    Tlaltecuhtli updated:

    -
      -
    • the eva suit crate now will have 1 space suit and 1 jetpack
    • -
    • the miner starter kit will be the same as the ones miners can buy grammar: changed the description of the medical refill crate to represent whats inside
    • -
    -

    YPOQ updated:

    -
      -
    • Fixed a bug that caused limbs to take incorrect damage amounts when damage exceeded the limb's damage cap
    • -
    -

    kevinz000 updated:

    -
      -
    • Panic bunker block message is now a config.
    • -
    -

    nichlas0010 updated:

    -
      -
    • The malf AI's APC-hacking is now no longer audible to people outside of the AI's location.
    • -
    - -

    19 March 2019

    -

    81Denton updated:

    -
      -
    • Curators no longer lose access to the aux base and mining station EVA during skeleton shifts.
    • -
    -

    Farquaar updated:

    -
      -
    • Added several new religions to the Nanotrasen-approved faith list, including Judaism, Rastafarianism, and Honkism
    • -
    -

    MrDoomBringer updated:

    -
      -
    • Gondolapods work again
    • -
    • the see-through pod effect for centcom podlaunchers works again
    • -
    • the Stealth effect for centcom podlaunchers works again
    • -
    • sparks will not generate if the quietLanding effect is on, for the centcom podlauncher
    • -
    • makes input text clearer for the centcom podlauncher
    • -
    -

    ShizCalev updated:

    -
      -
    • Added DRAGnet's to the armory on Delta & Pubby.
    • -
    • Added logging to cloning machinery.
    • -
    • Fixed a runtime with wabbajack / bolt of change causing the person that was hit to go invisible and be unable to do anything.
    • -
    • Fixed carbons with no eyes having a flash overlay applied when they're flashed.
    • -
    • Fixed species with no eyes getting flashed.
    • -
    -

    Time-Green updated:

    -
      -
    • Adds tools to make mutations transfer through cloning
    • -
    -

    Vile Beggar updated:

    -
      -
    • Mechs can now be equipped with disablers.
    • -
    - -

    18 March 2019

    -

    4dplanner updated:

    -
      -
    • chemical scans actually display to 3 dp, sorry
    • -
    - -

    17 March 2019

    -

    4dplanner updated:

    -
      -
    • Buckle objects can now properly specify lying angle
    • -
    • Wheelchairs and other such vehicles let you use UIs even if your legs don't work
    • -
    • You can now pull objects while in a wheelchair even if your legs don't work
    • -
    • You no longer have a chance of sleeping upside down in a bed
    • -
    • No longer randomises lying direction a second time on fall
    • -
    -

    Nervere updated:

    -
      -
    • Fixed stunbatons being invisible.
    • -
    -

    ShizCalev updated:

    -
      -
    • Blind people will no longer be able to see pills being slipped into their drinks...........
    • -
    • Fixed an issue causing slippery oil to be noninteractive.
    • -
    • Motor oil can now catch on fire. Better do your job, janitor!
    • -
    • Cleaned up some crayon and spraycan code for futureproofing.
    • -
    -

    WJohnston, Antur, and Arcane updated:

    -
      -
    • THE GOOSE IS LOOSE
    • -
    - -

    15 March 2019

    -

    4dplanner updated:

    -
      -
    • liver purging is more consistent
    • -
    • chemical recipes are more consistent
    • -
    • chemical scans only show to 2 d.p
    • -
    -

    Dennok updated:

    -
      -
    • Turbines work again.
    • -
    -

    Denton updated:

    -
      -
    • Clarified Syndicate ghost role flavor text to mention that agents are not supposed to abandon their bases.
    • -
    • Rolling a 1 with the d20 of fate prevents you from being revived by any means.
    • -
    -

    Lett1 updated:

    -
      -
    • firebots now shop up on robotics pda's
    • -
    -

    ShizCalev updated:

    -
      -
    • Pacifists can now use wormhole projectors.
    • -
    -

    SpaceManiac updated:

    -
      -
    • pAIs are no longer immune to stamina damage.
    • -
    • Fixed a runtime when an AI core witnesses someone exit a cardboard box.
    • -
    • Fixed a runtime when attempting to blind a True Devil with a flashlight.
    • -
    • The implant chair no longer runtimes when implanting non-implant organs.
    • -
    -

    cacogen updated:

    -
      -
    • Makes stun baton two words
    • -
    -

    plapatin updated:

    -
      -
    • Added a big heap of fancy new clown names! Be slightly less generic!
    • -
    - -

    14 March 2019

    -

    4dplanner updated:

    -
      -
    • sepia slime extract has a delay before activating
    • -
    • the user of a sepia slime extract is no longer immune to the time field
    • -
    • chilling sepia is now the support extract - it always freezes the user, but not other marked people
    • -
    • give one to your golem!
    • -
    • burning sepia spawns the rewind camera. Take a selfie with someone and give it to them to make sure they remember the moment forever!
    • -
    • you don't actually need to give them the photo, they'll remember anyway. Keep it as a reminder.
    • -
    • rewinding resets your location to the turf you were on after 10 seconds, and heals simple animals and objects. remove: timefreeze camera is admin spawn only.
    • -
    • recurring sepia recalls to the hand of the last person to touch it after activating. Reusable timestop grenades!
    • -
    • some special cameras don't prompt for customisation
    • -
    • timefreeze camera actually makes a photo
    • -
    • timestop stops pathing
    • -
    • timestop stops mechs
    • -
    • adds a check to make sure simple_animals don't get their AI toggled while sentient
    • -
    • Adds the timestop overlay to frozen projectiles
    • -
    • Timestopped things have INFINITY move_resist as opposed to being anchored
    • -
    • Timestop will now unfreeze things that somehow leave it
    • -
    • mobs in the middle of a walk_to will have their walk stopped by timestop
    • -
    • mobs that are stunned will be stopped mid walk as well
    • -
    • Slimes respect mobility_flags & MOBILITY_MOVE
    • -
    • Slimes no longer automatically regain MOBILITY_MOVE whenever not cold
    • -
    • pulling respects changes in move_force
    • -
    • swapping places respects move_force if the participant is not willing
    • -
    -

    BuffEngineering updated:

    -
      -
    • You may no longer summon plasteel from the door dimension.
    • -
    • High security airlocks are now 33% more materially efficient!
    • -
    • Boomers may now sip in peace knowing their cloning based longevity is not at risk.
    • -
    -

    Caiggas updated:

    -
      -
    • Fixed jump-boots breaking after colliding with things at close range.
    • -
    -

    Carbonhell updated:

    -
      -
    • youtube-dl works again for linux based servers
    • -
    -

    Ghommie updated:

    -
      -
    • Adds two cartons of space milks to the skellies pirate cutter's fridge.
    • -
    -

    JJRcop updated:

    -
      -
    • Play Internet Sound now respects start (like &t=xxx or &start=xxx) and end times (like &end=xxx). This allows admins to choose a snippet of media to play, like for example pick a song out of an hour long album compilation.
    • -
    -

    Kierany9 updated:

    -
      -
    • Fixed Hivemind Hosts retaining powers on death and while dead
    • -
    -

    Menshin updated:

    -
      -
    • engineering APCs shouldn't be reset on Grid Check event anymore.
    • -
    -

    ShizCalev updated:

    -
      -
    • Corrected a minor issue where the regenerative core would trigger at -1 HP instead of at 0HP.
    • -
    • Sentient firebots can now use their fire extinguishers.
    • -
    • Fixed hacked firebots not resetting after being reset....
    • -
    • Revolvers will no longer immediately click when trying to suicide while on an empty chamber.
    • -
    • Cult magic inhands now work again... for real this time.
    • -
    -

    SpaceManiac updated:

    -
      -
    • The wizard hardsuit now correctly grants magic resistance.
    • -
    • Cow tipping now properly stuns the cow.
    • -
    • Suiciding with the infernal contract now properly causes the victim to yell out.
    • -
    • Accessing the notes panel within the first few seconds of connecting no longer risks broken styling.
    • -
    -

    TerraGS updated:

    -
      -
    • Curing advanced voice change virus symptoms no longer leaves you unable to speak
    • -
    -

    Unit2E updated:

    -
      -
    • people in fire resistant now get properly hot in fires they shouldn't resist (temps of 35000K and over)
    • -
    -

    actioninja updated:

    -
      -
    • Fixed a few mapping issues with the Supermatter on Pubbystation
    • -
    • The ID console in the HoP's office on Meta has been rotated to face toward the HoP when they're at their desk
    • -
    -

    dvanbale updated:

    -
      -
    • Removes dizziness when adminhealing
    • -
    -

    imsxz updated:

    -
      -
    • epinephrine no longer hard caps oxygen damage at ~30
    • -
    • epinephrine now gives the no crit damage trait, which makes creatures not take passive oxygen(or brute if you cant breathe) damage while in critical
    • -
    • epinephrine now heals minor oxygen damage at the same health threshold that it currently heals other damage types at.
    • -
    • atropine and epinephrine now check if your health is under your mobs crit threshold instead of using the number 0 before healing
    • -
    -

    monster860 updated:

    -
      -
    • fixes advanced proccall
    • -
    -

    spookydonut updated:

    -
      -
    • Adds the ability to give shuttles a cooldown timer
    • -
    -

    tralezab updated:

    -
      -
    • The wizard has many more staves to play with!
    • -
    • Along with the new effects, the chaos bolt has a couple more bolts not available my normal means
    • -
GoonStation 13 Development Team diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 860b21b48f4..21578f6d1a1 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -24158,6 +24158,8 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - rscadd: An extra tile to the Box chapel's width - rscdel: One barely noticeable tile of width from escape(one escape brig chair dead [*] ) + RaveRadbury: + - refactor: mood_event timeouts are now in MINUTES and SECONDS Skoglol: - bugfix: You no longer get shocked by shock touching someone you are pulling. WJohnston: @@ -24167,3 +24169,202 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. anconfuzedrock: - rscadd: Cargo can now order a ridiculously large canister containing only saline to give medbay a more than plentiful supply of the stuff. +2019-05-17: + 4dplanner: + - bugfix: health hud will no longer show full health at 0 hp + - bugfix: glass golems properly redirect projectiles + - bugfix: glass golem reflected projectiles can damage the original firer + ExcessiveUseOfCobblestone: + - balance: borgs can now unbuckle people from stasis beds + Garen7: + - bugfix: fixes lings being able to infinitely use their strained muscles + Naksu: + - balance: The crabphone will no longer deafen everyone who didn't have the foreknowledge + that it was coming. + - balance: The crabphone has 80% less HP, as befits something that costs 7 TC and + is not two bubblegums stacked on top of eachother. + - balance: Nuclear operative TC now comes pre-distributed, the telecrystal assignment + stations have been removed. + - bugfix: mindshield nanites no longer give mindshields to revheads and one mind + awoken hiveminds. + - bugfix: Fixed several issues with venus human traps and their vines going through + walls + - code_imp: Made atmos update_visuals() proc a bit faster + jegub: + - bugfix: Lets the grass grow under your feet. + nemvar: + - bugfix: Explosive holoparasite bombs now explode if you bump into them, instead + of the other way around. + pireamaineach: + - rscadd: Added a 3rd atmos tech locker and rad locker to the incinerators on Meta + and Box, and an atmos tech locker to the incinerator on Pubby since it already + had a rad-suit. + - rscdel: Reverts https://github.com/tgstation/tgstation/pull/43557 + - tweak: Makes the doors to the incinerator on meta require atmos access. + - bugfix: Axes some hairstyles that didn't make the final cut but never got fully + removed, removes an unused sprite. + - bugfix: Also fixes the cornrows because they were bRoek + zeroisthebiggay: + - tweak: Gives Sentient Diseases a medical hud to observe their victims further + with. +2019-05-19: + CrazyClown12: + - tweak: The chloral hydrate inside of the sleepy pen is no longer slower acting + than chloral hydrate made in chemistry. + - tweak: The chloral hydrate inside of cookies synthesised by emagged borgs is no + longer slower acting than chloral hydrate made in chemistry. + - rscdel: Delayed chloral hydrate + Erwgd: + - rscadd: Swapped out an epinephrine bottle for potassium iodide in NanoMed Plus + vending machines. + Naksu: + - bugfix: Items using atom colors for coloring now show up properly colored in vending + machines, rather than snow-white + Partheo: + - imageadd: Scrubbers have updated design and animation + Rave Radbury, Art by Navi.OS: + - rscadd: pAI's have a bunch of HUD stuff now + - rscadd: pAI's now have an AI style PDA + - rscadd: pAI cameras can now download a zoom feature! Bigger and smaller pictures! + - tweak: Split the pAI medhud module into seperate medhud and health analyzer modules + - tweak: Journalism modules now have RAM costs + - balance: RAM prices have changed on a number of modules + - imageadd: added more pAI HUD icons + Zxaber: + - balance: AI power backup is now separate from the health, and is tied to their + core. Carding an AI on battery backup will leave the core at partial charge. + AIs no longer slowly lose integrity while on backups (but will instantly die + as before once the backup runs out). As such, whacking an AI with a wrench will + no longer magically lower their backup battery capacity. + - balance: AIs on backup battery can now unbolt at the cost of a quarter of their + battery's max charge. This cannot be done while at under 25% power. + imsxz: + - balance: cakehat has been nerfed + - tweak: cakehat sounds cooler +2019-05-22: + Incoming5643: + - rscadd: After a very long period of being broken, the training bomb in security + finally works properly again. + - tweak: Syndicate bomb cores have become a little more robust in their operation. + Defused but still cored bombs are no longer inert and can be set again. Would + be heroes are advised to cut out and dispose of bomb cores, and dismantle unneeded + bomb shells to be absolutely sure. + MrFluffster: + - rscadd: CLOTH foodtype + Naksu: + - rscadd: Added a new blob strain that grows inside the station and eats garbage + - code_imp: Several fixes for stuff harddeling + - bugfix: Cryotubes no longer display a double of a person that was once in but + teleported out by having ingested bluespace or other such nonsense + - code_imp: pda.detonatable and uplink component checks removed in favor of a signal + in detomatix cart handling + - balance: nukeop uplinks now have 5 unlimited discounts and 10 limited discounts + shared between the team, rather than 3 individual discounts like traitor uplinks + - bugfix: corpses no longer feel, light-headed or otherwise + - code_imp: removed /datum/mutation/human/proc/on_move in favor of having the chameleon + mutation register for a signal + RaveRadbury: + - tweak: '"Religiously Comforted" from Spiritual Quirk occurs on examine and lasts + for 5 minutes' + kriskog: + - bugfix: Added a bunch of previously missing adjacency checks to ui window actions + and alt clicks. + loserXD: + - tweak: Hangar Bay Shutters need only general CentCom access to open now + nemvar: + - bugfix: Podcloning now lets you keep your quirks. + vuonojenmustaturska: + - rscdel: Removed the ability of fat people to vore monkeys, and the ability of + aliens to vore humans. + - code_imp: Removed stubbed out would-be functionality related to stomach contents + - rscadd: Nuclear Operative reinforcements now get uplinks with 0 TC and a real + name. +2019-05-23: + 4dplanner: + - bugfix: between the sheets heals carbons + - tweak: colossus chest is intangible to colossus bolts + Naksu: + - code_imp: removed some unnecessary wrappers in Life() code. + - code_imp: get_area() is now a define rather than a proc. + TheSilverNuke: + - rscadd: edaggers have a special suicide! + nemvar: + - bugfix: You can now reuse chemical grenade casings if they fail to react. + ninjanomnom: + - rscadd: Some rpg affixes now have special effects + weeweesoda: + - balance: The CRAB protocol traitor item now has a maximum stock of 1 each round +2019-05-27: + 4dplanner: + - rscadd: The deja vu effect (previously only used by rewind camera) now resets + all your limbs and damage to the point it was added after 10 seconds (as well + as the original position reset) + - rscadd: The deja vu effect cannot resurrect the dead, but will heal their corpse + - rscadd: New limbs fall off, old ones re-attach + - rscadd: Regenerative sepia cores add a deja vu effect before healing instead of + a timestop + - rscadd: The rewind camera rewinds 2 times to distinguish it from the regenerative + core + - bugfix: colossus and drake can no longer attack from the afterlife + - bugfix: timestop is properly defeated by antimagic. + - bugfix: timestop only checks antimagic once + Akrilla: + - rscadd: Traitors now recognize codewords automatically in spoken conversation. + Phrases in blue, responses in red. + - tweak: Changed traitor greet text slightly. + ExcessiveUseOfVending: + - tweak: Wardrobe Vendors will now accept clothing types they sell. Now you can + clean up after getting that cool alternate uniform! + - code_imp: 'see PR #43964 on how to easily setup a vending machine to accept items!' + Farquaar: + - bugfix: The monk's frock has been sanctified and will no longer reveal your naked + body when the hood is pulled up. + Fire Chance: + - bugfix: Fixed the drink sprites overlapping when you are mixing beer with other + drinks. + Garen7: + - tweak: Lesser form lings can now toggle augmented vision + - bugfix: You can no longer turn back into human form as a lesser form ling while + ventcrawling + - bugfix: Stuns and Reagents are now passed when transforming into a monkey or human + Irafas: + - bugfix: Connected the incinerator/janitor's/botany backroom/service rooms to the + scrubber network + JJRcop: + - rscadd: You can now build a new PDA messaging server if you lose it. + - tweak: Requests console messages no longer work if the messaging server is offline. + Emergency alerts will still function in that case as long as the rest of telecomms + is online. + Naksu: + - code_imp: pipeline gas reconciliation is now faster + OnlineGirlfriend: + - rscadd: Lemonade + - tweak: Arnold Palmer recipe + - imageadd: lemonade sprite + Putnam3145: + - tweak: All departments can now print basic power cells from their respective techfab. + RaveRadbury: + - rscadd: Quirks have flavor text in medical records + - rscadd: All quirks have medical record entries + - spellcheck: All quirk medical records refer to "Patient", removing a few instances + of "Subject" + Tlaltecuhtli: + - bugfix: fixes message spam from riding a vehicle without enough legs/arms + XDTM: + - rscadd: Added a new device, the nanite communication remote, which can be used + to send custom messages to message-based nanite programs. + - rscadd: 'Comm remotes use separate Comm Codes: for a message to be received, the + signal''s comm code must be the same as the program''s.' + actioninja: + - bugfix: Shuttle sounds should no longer ass blast your ears as they no longer + play PER DOOR and instead from the nearest engine, or door if none are available. + - soundadd: Distant shuttle sounds. + bgobandit: + - admin: TP now shows the names of blood brothers' brothers. + hey there uwu: + - bugfix: You can no longer choose the zombie race from the magic mirror, as intended. + nemvar: + - rscadd: Colored lights now shine in different colours. + - rscadd: Mops can now be printed at the autolathe and protolathe. + tralezab: + - rscadd: Gravitokinetic stands are now available! diff --git a/html/changelogs/AutoChangeLog-pr-43908.yml b/html/changelogs/AutoChangeLog-pr-43908.yml deleted file mode 100644 index b4eff653828..00000000000 --- a/html/changelogs/AutoChangeLog-pr-43908.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "RaveRadbury" -delete-after: True -changes: - - refactor: "mood_event timeouts are now in MINUTES and SECONDS" diff --git a/icons/emoji.dmi b/icons/emoji.dmi index 9dfd9ed91c1..7467561bafc 100644 Binary files a/icons/emoji.dmi and b/icons/emoji.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index 6c42fdd68cc..0fab5cea28c 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/mob/screen_pai.dmi b/icons/mob/screen_pai.dmi index b00bc979e24..4868d26cc08 100644 Binary files a/icons/mob/screen_pai.dmi and b/icons/mob/screen_pai.dmi differ diff --git a/icons/obj/atmospherics/components/unary_devices.dmi b/icons/obj/atmospherics/components/unary_devices.dmi index badd4cba673..2875e958c96 100644 Binary files a/icons/obj/atmospherics/components/unary_devices.dmi and b/icons/obj/atmospherics/components/unary_devices.dmi differ diff --git a/icons/obj/atmospherics/pipes/pipe_item.dmi b/icons/obj/atmospherics/pipes/pipe_item.dmi index e9ab3813eab..8489294ae58 100644 Binary files a/icons/obj/atmospherics/pipes/pipe_item.dmi and b/icons/obj/atmospherics/pipes/pipe_item.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index a3b2dad750d..71fceba8b4d 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi index 2bc3997125c..984cac44712 100644 Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ diff --git a/icons/obj/machines/telecomms.dmi b/icons/obj/machines/telecomms.dmi index 4a6988f88e4..93bb9c477aa 100644 Binary files a/icons/obj/machines/telecomms.dmi and b/icons/obj/machines/telecomms.dmi differ diff --git a/sound/effects/gravhit.ogg b/sound/effects/gravhit.ogg new file mode 100644 index 00000000000..524ddf733f5 Binary files /dev/null and b/sound/effects/gravhit.ogg differ diff --git a/sound/effects/hyperspace_begin_distance.ogg b/sound/effects/hyperspace_begin_distance.ogg new file mode 100644 index 00000000000..e79363743b4 Binary files /dev/null and b/sound/effects/hyperspace_begin_distance.ogg differ diff --git a/sound/effects/hyperspace_end_distance.ogg b/sound/effects/hyperspace_end_distance.ogg new file mode 100644 index 00000000000..591abb0ad25 Binary files /dev/null and b/sound/effects/hyperspace_end_distance.ogg differ diff --git a/sound/effects/hyperspace_progress_distance.ogg b/sound/effects/hyperspace_progress_distance.ogg new file mode 100644 index 00000000000..2ba8533a845 Binary files /dev/null and b/sound/effects/hyperspace_progress_distance.ogg differ diff --git a/strings/tips.txt b/strings/tips.txt index a9017173a13..b34ea826916 100644 --- a/strings/tips.txt +++ b/strings/tips.txt @@ -79,6 +79,7 @@ As a Roboticist, you can augment people with cyborg limbs. Augmented limbs can e As the AI, you can click on people's names to look at them. This only works if there are cameras that can see them, they aren't wearing agent IDs and aren't using digital camouflage as changelings. As the AI, you can quickly open and close doors by holding shift while clicking them, bolt them when holding ctrl, and even shock them while holding alt. As the AI, you can take pictures with your camera and upload them to newscasters. +As the AI, you can use CTRL + 1-9 to set a location hotkey for your camera, allowing you to save the location and jump to it at will. Tilde and zero will return you to the last spot you jumped from, and the numpad numbers act as aliases to the regular number keys. As a Cyborg, choose your module carefully, as only cutting and mending your reset wire will let you repick it. If possible, refrain from choosing a module until a situation that requires one occurs. As a Cyborg, you are immune to most forms of stunning, and excel at almost everything far better than humans. However, flashes can easily stunlock you and you cannot do any precision work as you lack hands. As a Cyborg, you are impervious to fires and heat. If you are rogue, you can release plasma fires everywhere and walk through them without a care in the world! diff --git a/tgstation.dme b/tgstation.dme index f32f294e0bd..e7a8c51fd01 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -43,6 +43,7 @@ #include "code\__DEFINES\economy.dm" #include "code\__DEFINES\events.dm" #include "code\__DEFINES\exports.dm" +#include "code\__DEFINES\fantasy_affixes.dm" #include "code\__DEFINES\flags.dm" #include "code\__DEFINES\food.dm" #include "code\__DEFINES\footsteps.dm" @@ -337,6 +338,7 @@ #include "code\datums\components\_component.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\armor_plate.dm" +#include "code\datums\components\bane.dm" #include "code\datums\components\beetlejuice.dm" #include "code\datums\components\butchering.dm" #include "code\datums\components\caltrop.dm" @@ -354,6 +356,7 @@ #include "code\datums\components\heirloom.dm" #include "code\datums\components\infective.dm" #include "code\datums\components\jousting.dm" +#include "code\datums\components\knockback.dm" #include "code\datums\components\knockoff.dm" #include "code\datums\components\lockon_aiming.dm" #include "code\datums\components\magnetic_catch.dm" @@ -379,12 +382,18 @@ #include "code\datums\components\squeak.dm" #include "code\datums\components\stationloving.dm" #include "code\datums\components\swarming.dm" +#include "code\datums\components\tactical.dm" +#include "code\datums\components\tether.dm" #include "code\datums\components\thermite.dm" #include "code\datums\components\uplink.dm" #include "code\datums\components\waddling.dm" #include "code\datums\components\wearertargeting.dm" #include "code\datums\components\wet_floor.dm" #include "code\datums\components\decals\blood.dm" +#include "code\datums\components\fantasy\_fantasy.dm" +#include "code\datums\components\fantasy\affix.dm" +#include "code\datums\components\fantasy\prefixes.dm" +#include "code\datums\components\fantasy\suffixes.dm" #include "code\datums\components\storage\storage.dm" #include "code\datums\components\storage\concrete\_concrete.dm" #include "code\datums\components\storage\concrete\bag_of_holding.dm" @@ -453,7 +462,6 @@ #include "code\datums\helper_datums\getrev.dm" #include "code\datums\helper_datums\icon_snapshot.dm" #include "code\datums\helper_datums\teleport.dm" -#include "code\datums\helper_datums\topic_input.dm" #include "code\datums\looping_sounds\_looping_sound.dm" #include "code\datums\looping_sounds\item_sounds.dm" #include "code\datums\looping_sounds\machinery_sounds.dm" @@ -658,7 +666,6 @@ #include "code\game\machinery\computer\robot.dm" #include "code\game\machinery\computer\security.dm" #include "code\game\machinery\computer\station_alert.dm" -#include "code\game\machinery\computer\telecrystalconsoles.dm" #include "code\game\machinery\computer\teleporter.dm" #include "code\game\machinery\doors\airlock.dm" #include "code\game\machinery\doors\airlock_electronics.dm" @@ -1192,6 +1199,7 @@ #include "code\modules\antagonists\blob\blobstrains\_reagent.dm" #include "code\modules\antagonists\blob\blobstrains\blazing_oil.dm" #include "code\modules\antagonists\blob\blobstrains\cryogenic_poison.dm" +#include "code\modules\antagonists\blob\blobstrains\debris_devourer.dm" #include "code\modules\antagonists\blob\blobstrains\electromagnetic_web.dm" #include "code\modules\antagonists\blob\blobstrains\energized_jelly.dm" #include "code\modules\antagonists\blob\blobstrains\explosive_lattice.dm" @@ -2149,6 +2157,7 @@ #include "code\modules\mob\living\simple_animal\guardian\types\dextrous.dm" #include "code\modules\mob\living\simple_animal\guardian\types\explosive.dm" #include "code\modules\mob\living\simple_animal\guardian\types\fire.dm" +#include "code\modules\mob\living\simple_animal\guardian\types\gravitokinetic.dm" #include "code\modules\mob\living\simple_animal\guardian\types\lightning.dm" #include "code\modules\mob\living\simple_animal\guardian\types\protector.dm" #include "code\modules\mob\living\simple_animal\guardian\types\ranged.dm" diff --git a/tgui/assets/tgui.js b/tgui/assets/tgui.js index 9eb9091d48b..642df3307c9 100644 --- a/tgui/assets/tgui.js +++ b/tgui/assets/tgui.js @@ -1,21 +1,21 @@ -require=function(){function t(e,n,a){function r(o,s){if(!n[o]){if(!e[o]){var p="function"==typeof require&&require;if(!s&&p)return p(o,!0);if(i)return i(o,!0);var u=Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var c=n[o]={exports:{}};e[o][0].call(c.exports,function(t){var n=e[o][1][t];return r(n||t)},c,c.exports,t,e,n,a)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o=0;--a){var r=this.tryEntries[a],i=r.completion;if("root"===r.tryLoc)return e("end");if(r.tryLoc<=this.prev){var o=b.call(r,"catchLoc"),s=b.call(r,"finallyLoc");if(o&&s){if(this.prev=0;--n){var a=this.tryEntries[n];if(a.tryLoc<=this.prev&&b.call(a,"finallyLoc")&&this.prev=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),d(n),O}},"catch":function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var a=n.completion;if("throw"===a.type){var r=a.arg;d(n)}return r}}throw Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:h(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=g),O}}}("object"==typeof t?t:"object"==typeof window?window:"object"==typeof self?self:this)}).call(this,void 0!==t?t:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],3:[function(t,e,n){t(129),e.exports=t(24).RegExp.escape},{129:129,24:24}],4:[function(t,e,n){e.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},{}],5:[function(t,e,n){var a=t(19);e.exports=function(t,e){if("number"!=typeof t&&"Number"!=a(t))throw TypeError(e);return+t}},{19:19}],6:[function(t,e,n){var a=t(127)("unscopables"),r=Array.prototype;void 0==r[a]&&t(43)(r,a,{}),e.exports=function(t){r[a][t]=!0}},{127:127,43:43}],7:[function(t,e,n){e.exports=function(t,e,n,a){if(!(t instanceof e)||void 0!==a&&a in t)throw TypeError(n+": incorrect invocation!");return t}},{}],8:[function(t,e,n){var a=t(52);e.exports=function(t){if(!a(t))throw TypeError(t+" is not an object!");return t}},{52:52}],9:[function(t,e,n){"use strict";var a=t(117),r=t(112),i=t(116);e.exports=[].copyWithin||function(t,e){var n=a(this),o=i(n.length),s=r(t,o),p=r(e,o),u=arguments.length>2?arguments[2]:void 0,c=Math.min((void 0===u?o:r(u,o))-p,o-s),l=1;for(s>p&&p+c>s&&(l=-1,p+=c-1,s+=c-1);c-- >0;)p in n?n[s]=n[p]:delete n[s],s+=l,p+=l;return n}},{112:112,116:116,117:117}],10:[function(t,e,n){"use strict";var a=t(117),r=t(112),i=t(116);e.exports=function(t){for(var e=a(this),n=i(e.length),o=arguments.length,s=r(o>1?arguments[1]:void 0,n),p=o>2?arguments[2]:void 0,u=void 0===p?n:r(p,n);u>s;)e[s++]=t;return e}},{112:112,116:116,117:117}],11:[function(t,e,n){var a=t(40);e.exports=function(t,e){var n=[];return a(t,!1,n.push,n,e),n}},{40:40}],12:[function(t,e,n){var a=t(115),r=t(116),i=t(112);e.exports=function(t){return function(e,n,o){var s,p=a(e),u=r(p.length),c=i(o,u);if(t&&n!=n){for(;u>c;)if(s=p[c++],s!=s)return!0}else for(;u>c;c++)if((t||c in p)&&p[c]===n)return t||c||0;return!t&&-1}}},{112:112,115:115,116:116}],13:[function(t,e,n){var a=t(26),r=t(48),i=t(117),o=t(116),s=t(16);e.exports=function(t,e){var n=1==t,p=2==t,u=3==t,c=4==t,l=6==t,d=5==t||l,f=e||s;return function(e,s,h){for(var m,g,v=i(e),b=r(v),y=a(s,h,3),_=o(b.length),x=0,w=n?f(e,_):p?f(e,0):void 0;_>x;x++)if((d||x in b)&&(m=b[x],g=y(m,x,v),t))if(n)w[x]=g;else if(g)switch(t){case 3:return!0;case 5:return m;case 6:return x;case 2:w.push(m)}else if(c)return!1;return l?-1:u||c?c:w}}},{116:116,117:117,16:16,26:26,48:48}],14:[function(t,e,n){var a=t(4),r=t(117),i=t(48),o=t(116);e.exports=function(t,e,n,s,p){a(e);var u=r(t),c=i(u),l=o(u.length),d=p?l-1:0,f=p?-1:1;if(2>n)for(;;){if(d in c){s=c[d],d+=f;break}if(d+=f,p?0>d:d>=l)throw TypeError("Reduce of empty array with no initial value")}for(;p?d>=0:l>d;d+=f)d in c&&(s=e(s,c[d],d,u));return s}},{116:116,117:117,4:4,48:48}],15:[function(t,e,n){var a=t(52),r=t(50),i=t(127)("species");e.exports=function(t){var e;return r(t)&&(e=t.constructor,"function"!=typeof e||e!==Array&&!r(e.prototype)||(e=void 0),a(e)&&(e=e[i],null===e&&(e=void 0))),void 0===e?Array:e}},{127:127,50:50,52:52}],16:[function(t,e,n){var a=t(15);e.exports=function(t,e){return new(a(t))(e)}},{15:15}],17:[function(t,e,n){"use strict";var a=t(4),r=t(52),i=t(47),o=[].slice,s={},p=function(t,e,n){if(!(e in s)){for(var a=[],r=0;e>r;r++)a[r]="a["+r+"]";s[e]=Function("F,a","return new F("+a.join(",")+")")}return s[e](t,n)};e.exports=Function.bind||function(t){var e=a(this),n=o.call(arguments,1),s=function(){var a=n.concat(o.call(arguments));return this instanceof s?p(e,a.length,a):i(e,a,t)};return r(e.prototype)&&(s.prototype=e.prototype),s}},{4:4,47:47,52:52}],18:[function(t,e,n){var a=t(19),r=t(127)("toStringTag"),i="Arguments"==a(function(){return arguments}()),o=function(t,e){try{return t[e]}catch(n){}};e.exports=function(t){var e,n,s;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=o(e=Object(t),r))?n:i?a(e):"Object"==(s=a(e))&&"function"==typeof e.callee?"Arguments":s}},{127:127,19:19}],19:[function(t,e,n){var a={}.toString;e.exports=function(t){return a.call(t).slice(8,-1)}},{}],20:[function(t,e,n){"use strict";var a=t(72).f,r=t(71),i=t(91),o=t(26),s=t(7),p=t(40),u=t(56),c=t(58),l=t(98),d=t(30),f=t(66).fastKey,h=t(124),m=d?"_s":"size",g=function(t,e){var n,a=f(e);if("F"!==a)return t._i[a];for(n=t._f;n;n=n.n)if(n.k==e)return n};e.exports={getConstructor:function(t,e,n,u){var c=t(function(t,a){s(t,c,e,"_i"),t._t=e,t._i=r(null),t._f=void 0,t._l=void 0,t[m]=0,void 0!=a&&p(a,n,t[u],t)});return i(c.prototype,{clear:function(){for(var t=h(this,e),n=t._i,a=t._f;a;a=a.n)a.r=!0,a.p&&(a.p=a.p.n=void 0),delete n[a.i];t._f=t._l=void 0,t[m]=0},"delete":function(t){var n=h(this,e),a=g(n,t);if(a){var r=a.n,i=a.p;delete n._i[a.i],a.r=!0,i&&(i.n=r),r&&(r.p=i),n._f==a&&(n._f=r),n._l==a&&(n._l=i),n[m]--}return!!a},forEach:function(t){h(this,e);for(var n,a=o(t,arguments.length>1?arguments[1]:void 0,3);n=n?n.n:this._f;)for(a(n.v,n.k,this);n&&n.r;)n=n.p},has:function(t){return!!g(h(this,e),t)}}),d&&a(c.prototype,"size",{get:function(){return h(this,e)[m]}}),c},def:function(t,e,n){var a,r,i=g(t,e);return i?i.v=n:(t._l=i={i:r=f(e,!0),k:e,v:n,p:a=t._l,n:void 0,r:!1},t._f||(t._f=i),a&&(a.n=i),t[m]++,"F"!==r&&(t._i[r]=i)),t},getEntry:g,setStrong:function(t,e,n){u(t,e,function(t,n){this._t=h(t,e),this._k=n,this._l=void 0},function(){for(var t=this,e=t._k,n=t._l;n&&n.r;)n=n.p;return t._t&&(t._l=n=n?n.n:t._t._f)?"keys"==e?c(0,n.k):"values"==e?c(0,n.v):c(0,[n.k,n.v]):(t._t=void 0,c(1))},n?"entries":"values",!n,!0),l(e)}}},{124:124,26:26,30:30,40:40,56:56,58:58,66:66,7:7,71:71,72:72,91:91,98:98}],21:[function(t,e,n){var a=t(18),r=t(11);e.exports=function(t){return function(){if(a(this)!=t)throw TypeError(t+"#toJSON isn't generic");return r(this)}}},{11:11,18:18}],22:[function(t,e,n){"use strict";var a=t(91),r=t(66).getWeak,i=t(8),o=t(52),s=t(7),p=t(40),u=t(13),c=t(42),l=t(124),d=u(5),f=u(6),h=0,m=function(t){return t._l||(t._l=new g)},g=function(){this.a=[]},v=function(t,e){return d(t.a,function(t){return t[0]===e})};g.prototype={get:function(t){var e=v(this,t);return e?e[1]:void 0},has:function(t){return!!v(this,t)},set:function(t,e){var n=v(this,t);n?n[1]=e:this.a.push([t,e])},"delete":function(t){var e=f(this.a,function(e){return e[0]===t});return~e&&this.a.splice(e,1),!!~e}},e.exports={getConstructor:function(t,e,n,i){var u=t(function(t,a){s(t,u,e,"_i"),t._t=e,t._i=h++,t._l=void 0,void 0!=a&&p(a,n,t[i],t)});return a(u.prototype,{"delete":function(t){if(!o(t))return!1;var n=r(t);return n===!0?m(l(this,e))["delete"](t):n&&c(n,this._i)&&delete n[this._i]},has:function(t){if(!o(t))return!1;var n=r(t);return n===!0?m(l(this,e)).has(t):n&&c(n,this._i)}}),u},def:function(t,e,n){var a=r(i(e),!0);return a===!0?m(t).set(e,n):a[t._i]=n,t},ufstore:m}},{124:124,13:13,40:40,42:42,52:52,66:66,7:7,8:8,91:91}],23:[function(t,e,n){"use strict";var a=t(41),r=t(34),i=t(92),o=t(91),s=t(66),p=t(40),u=t(7),c=t(52),l=t(36),d=t(57),f=t(99),h=t(46);e.exports=function(t,e,n,m,g,v){var b=a[t],y=b,_=g?"set":"add",x=y&&y.prototype,w={},k=function(t){var e=x[t];i(x,t,"delete"==t?function(t){return v&&!c(t)?!1:e.call(this,0===t?0:t)}:"has"==t?function(t){return v&&!c(t)?!1:e.call(this,0===t?0:t)}:"get"==t?function(t){return v&&!c(t)?void 0:e.call(this,0===t?0:t)}:"add"==t?function(t){return e.call(this,0===t?0:t),this}:function(t,n){return e.call(this,0===t?0:t,n),this})};if("function"==typeof y&&(v||x.forEach&&!l(function(){(new y).entries().next()}))){var S=new y,E=S[_](v?{}:-0,1)!=S,C=l(function(){S.has(1)}),P=d(function(t){new y(t)}),A=!v&&l(function(){for(var t=new y,e=5;e--;)t[_](e,e);return!t.has(-0)});P||(y=e(function(e,n){u(e,y,t);var a=h(new b,e,y);return void 0!=n&&p(n,g,a[_],a),a}),y.prototype=x,x.constructor=y),(C||A)&&(k("delete"),k("has"),g&&k("get")),(A||E)&&k(_),v&&x.clear&&delete x.clear}else y=m.getConstructor(e,t,g,_),o(y.prototype,n),s.NEED=!0;return f(y,t),w[t]=y,r(r.G+r.W+r.F*(y!=b),w),v||m.setStrong(y,t,g),y}},{34:34,36:36,40:40,41:41,46:46,52:52,57:57,66:66,7:7,91:91,92:92,99:99}],24:[function(t,e,n){var a=e.exports={version:"2.5.6"};"number"==typeof __e&&(__e=a)},{}],25:[function(t,e,n){"use strict";var a=t(72),r=t(90);e.exports=function(t,e,n){e in t?a.f(t,e,r(0,n)):t[e]=n}},{72:72,90:90}],26:[function(t,e,n){var a=t(4);e.exports=function(t,e,n){if(a(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,a){return t.call(e,n,a)};case 3:return function(n,a,r){return t.call(e,n,a,r)}}return function(){return t.apply(e,arguments)}}},{4:4}],27:[function(t,e,n){"use strict";var a=t(36),r=Date.prototype.getTime,i=Date.prototype.toISOString,o=function(t){return t>9?t:"0"+t};e.exports=a(function(){return"0385-07-25T07:06:39.999Z"!=i.call(new Date(-5e13-1))})||!a(function(){i.call(new Date(NaN))})?function(){if(!isFinite(r.call(this)))throw RangeError("Invalid time value");var t=this,e=t.getUTCFullYear(),n=t.getUTCMilliseconds(),a=0>e?"-":e>9999?"+":"";return a+("00000"+Math.abs(e)).slice(a?-6:-4)+"-"+o(t.getUTCMonth()+1)+"-"+o(t.getUTCDate())+"T"+o(t.getUTCHours())+":"+o(t.getUTCMinutes())+":"+o(t.getUTCSeconds())+"."+(n>99?n:"0"+o(n))+"Z"}:i},{36:36}],28:[function(t,e,n){"use strict";var a=t(8),r=t(118),i="number";e.exports=function(t){if("string"!==t&&t!==i&&"default"!==t)throw TypeError("Incorrect hint");return r(a(this),t!=i)}},{118:118,8:8}],29:[function(t,e,n){e.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},{}],30:[function(t,e,n){e.exports=!t(36)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},{36:36}],31:[function(t,e,n){var a=t(52),r=t(41).document,i=a(r)&&a(r.createElement);e.exports=function(t){return i?r.createElement(t):{}}},{41:41,52:52}],32:[function(t,e,n){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},{}],33:[function(t,e,n){var a=t(81),r=t(78),i=t(82);e.exports=function(t){var e=a(t),n=r.f;if(n)for(var o,s=n(t),p=i.f,u=0;s.length>u;)p.call(t,o=s[u++])&&e.push(o);return e}},{78:78,81:81,82:82}],34:[function(t,e,n){var a=t(41),r=t(24),i=t(43),o=t(92),s=t(26),p="prototype",u=function(t,e,n){var c,l,d,f,h=t&u.F,m=t&u.G,g=t&u.S,v=t&u.P,b=t&u.B,y=m?a:g?a[e]||(a[e]={}):(a[e]||{})[p],_=m?r:r[e]||(r[e]={}),x=_[p]||(_[p]={});m&&(n=e);for(c in n)l=!h&&y&&void 0!==y[c],d=(l?y:n)[c],f=b&&l?s(d,a):v&&"function"==typeof d?s(Function.call,d):d,y&&o(y,c,d,t&u.U),_[c]!=d&&i(_,c,f),v&&x[c]!=d&&(x[c]=d)};a.core=r,u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,e.exports=u},{24:24,26:26,41:41,43:43,92:92}],35:[function(t,e,n){var a=t(127)("match");e.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[a]=!1,!"/./"[t](e)}catch(r){}}return!0}},{127:127}],36:[function(t,e,n){e.exports=function(t){try{return!!t()}catch(e){return!0}}},{}],37:[function(t,e,n){"use strict";var a=t(43),r=t(92),i=t(36),o=t(29),s=t(127);e.exports=function(t,e,n){var p=s(t),u=n(o,p,""[t]),c=u[0],l=u[1];i(function(){var e={};return e[p]=function(){return 7},7!=""[t](e)})&&(r(String.prototype,t,c),a(RegExp.prototype,p,2==e?function(t,e){return l.call(t,this,e)}:function(t){return l.call(t,this)}))}},{127:127,29:29,36:36,43:43,92:92}],38:[function(t,e,n){"use strict";var a=t(8);e.exports=function(){var t=a(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},{8:8}],39:[function(t,e,n){"use strict";function a(t,e,n,u,c,l,d,f){for(var h,m,g=c,v=0,b=d?s(d,f,3):!1;u>v;){if(v in n){if(h=b?b(n[v],v,e):n[v],m=!1,i(h)&&(m=h[p],m=void 0!==m?!!m:r(h)),m&&l>0)g=a(t,e,h,o(h.length),g,l-1)-1;else{if(g>=9007199254740991)throw TypeError();t[g]=h}g++}v++}return g}var r=t(50),i=t(52),o=t(116),s=t(26),p=t(127)("isConcatSpreadable");e.exports=a},{116:116,127:127,26:26,50:50,52:52}],40:[function(t,e,n){var a=t(26),r=t(54),i=t(49),o=t(8),s=t(116),p=t(128),u={},c={},n=e.exports=function(t,e,n,l,d){var f,h,m,g,v=d?function(){return t}:p(t),b=a(n,l,e?2:1),y=0;if("function"!=typeof v)throw TypeError(t+" is not iterable!");if(i(v)){for(f=s(t.length);f>y;y++)if(g=e?b(o(h=t[y])[0],h[1]):b(t[y]),g===u||g===c)return g}else for(m=v.call(t);!(h=m.next()).done;)if(g=r(m,b,h.value,e),g===u||g===c)return g};n.BREAK=u,n.RETURN=c},{116:116,128:128,26:26,49:49,54:54,8:8}],41:[function(t,e,n){var a=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=a)},{}],42:[function(t,e,n){var a={}.hasOwnProperty;e.exports=function(t,e){return a.call(t,e)}},{}],43:[function(t,e,n){var a=t(72),r=t(90);e.exports=t(30)?function(t,e,n){return a.f(t,e,r(1,n))}:function(t,e,n){return t[e]=n,t}},{30:30,72:72,90:90}],44:[function(t,e,n){var a=t(41).document;e.exports=a&&a.documentElement},{41:41}],45:[function(t,e,n){e.exports=!t(30)&&!t(36)(function(){return 7!=Object.defineProperty(t(31)("div"),"a",{get:function(){return 7}}).a})},{30:30,31:31,36:36}],46:[function(t,e,n){var a=t(52),r=t(97).set;e.exports=function(t,e,n){var i,o=e.constructor;return o!==n&&"function"==typeof o&&(i=o.prototype)!==n.prototype&&a(i)&&r&&r(t,i),t}},{52:52,97:97}],47:[function(t,e,n){e.exports=function(t,e,n){var a=void 0===n;switch(e.length){case 0:return a?t():t.call(n);case 1:return a?t(e[0]):t.call(n,e[0]);case 2:return a?t(e[0],e[1]):t.call(n,e[0],e[1]);case 3:return a?t(e[0],e[1],e[2]):t.call(n,e[0],e[1],e[2]);case 4:return a?t(e[0],e[1],e[2],e[3]):t.call(n,e[0],e[1],e[2],e[3])}return t.apply(n,e)}},{}],48:[function(t,e,n){var a=t(19);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==a(t)?t.split(""):Object(t)}},{19:19}],49:[function(t,e,n){var a=t(59),r=t(127)("iterator"),i=Array.prototype;e.exports=function(t){return void 0!==t&&(a.Array===t||i[r]===t)}},{127:127,59:59}],50:[function(t,e,n){var a=t(19);e.exports=Array.isArray||function(t){return"Array"==a(t)}},{19:19}],51:[function(t,e,n){var a=t(52),r=Math.floor;e.exports=function(t){return!a(t)&&isFinite(t)&&r(t)===t}},{52:52}],52:[function(t,e,n){e.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},{}],53:[function(t,e,n){var a=t(52),r=t(19),i=t(127)("match");e.exports=function(t){var e;return a(t)&&(void 0!==(e=t[i])?!!e:"RegExp"==r(t))}},{127:127,19:19,52:52}],54:[function(t,e,n){var a=t(8);e.exports=function(t,e,n,r){try{return r?e(a(n)[0],n[1]):e(n)}catch(i){var o=t["return"];throw void 0!==o&&a(o.call(t)),i}}},{8:8}],55:[function(t,e,n){"use strict";var a=t(71),r=t(90),i=t(99),o={};t(43)(o,t(127)("iterator"),function(){return this}),e.exports=function(t,e,n){t.prototype=a(o,{next:r(1,n)}),i(t,e+" Iterator")}},{127:127,43:43,71:71,90:90,99:99}],56:[function(t,e,n){"use strict";var a=t(60),r=t(34),i=t(92),o=t(43),s=t(59),p=t(55),u=t(99),c=t(79),l=t(127)("iterator"),d=!([].keys&&"next"in[].keys()),f="@@iterator",h="keys",m="values",g=function(){return this};e.exports=function(t,e,n,v,b,y,_){p(n,e,v);var x,w,k,S=function(t){if(!d&&t in A)return A[t];switch(t){case h:return function(){return new n(this,t)};case m:return function(){return new n(this,t)}}return function(){return new n(this,t)}},E=e+" Iterator",C=b==m,P=!1,A=t.prototype,O=A[l]||A[f]||b&&A[b],T=O||S(b),R=b?C?S("entries"):T:void 0,M="Array"==e?A.entries||O:O;if(M&&(k=c(M.call(new t)),k!==Object.prototype&&k.next&&(u(k,E,!0),a||"function"==typeof k[l]||o(k,l,g))),C&&O&&O.name!==m&&(P=!0,T=function(){return O.call(this)}),a&&!_||!d&&!P&&A[l]||o(A,l,T),s[e]=T,s[E]=g,b)if(x={values:C?T:S(m),keys:y?T:S(h),entries:R},_)for(w in x)w in A||i(A,w,x[w]);else r(r.P+r.F*(d||P),e,x);return x}},{127:127,34:34,43:43,55:55,59:59,60:60,79:79,92:92,99:99}],57:[function(t,e,n){var a=t(127)("iterator"),r=!1;try{var i=[7][a]();i["return"]=function(){r=!0},Array.from(i,function(){throw 2})}catch(o){}e.exports=function(t,e){if(!e&&!r)return!1;var n=!1;try{var i=[7],o=i[a]();o.next=function(){return{done:n=!0}},i[a]=function(){return o},t(i)}catch(s){}return n}},{127:127}],58:[function(t,e,n){e.exports=function(t,e){return{value:e,done:!!t}}},{}],59:[function(t,e,n){e.exports={}},{}],60:[function(t,e,n){e.exports=!1},{}],61:[function(t,e,n){var a=Math.expm1;e.exports=!a||a(10)>22025.465794806718||a(10)<22025.465794806718||-2e-17!=a(-2e-17)?function(t){return 0==(t=+t)?t:t>-1e-6&&1e-6>t?t+t*t/2:Math.exp(t)-1}:a},{}],62:[function(t,e,n){var a=t(65),r=Math.pow,i=r(2,-52),o=r(2,-23),s=r(2,127)*(2-o),p=r(2,-126),u=function(t){return t+1/i-1/i};e.exports=Math.fround||function(t){var e,n,r=Math.abs(t),c=a(t);return p>r?c*u(r/p/o)*p*o:(e=(1+o/i)*r,n=e-(e-r),n>s||n!=n?c*(1/0):c*n)}},{65:65}],63:[function(t,e,n){e.exports=Math.log1p||function(t){return(t=+t)>-1e-8&&1e-8>t?t-t*t/2:Math.log(1+t)}},{}],64:[function(t,e,n){e.exports=Math.scale||function(t,e,n,a,r){return 0===arguments.length||t!=t||e!=e||n!=n||a!=a||r!=r?NaN:t===1/0||t===-(1/0)?t:(t-e)*(r-a)/(n-e)+a}},{}],65:[function(t,e,n){e.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:0>t?-1:1}},{}],66:[function(t,e,n){var a=t(122)("meta"),r=t(52),i=t(42),o=t(72).f,s=0,p=Object.isExtensible||function(){return!0},u=!t(36)(function(){return p(Object.preventExtensions({}))}),c=function(t){o(t,a,{value:{i:"O"+ ++s,w:{}}})},l=function(t,e){if(!r(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!i(t,a)){if(!p(t))return"F";if(!e)return"E";c(t)}return t[a].i},d=function(t,e){if(!i(t,a)){if(!p(t))return!0;if(!e)return!1;c(t)}return t[a].w},f=function(t){return u&&h.NEED&&p(t)&&!i(t,a)&&c(t),t},h=e.exports={KEY:a,NEED:!1,fastKey:l,getWeak:d,onFreeze:f}},{122:122,36:36,42:42,52:52,72:72}],67:[function(t,e,n){var a=t(159),r=t(34),i=t(101)("metadata"),o=i.store||(i.store=new(t(265))),s=function(t,e,n){var r=o.get(t);if(!r){if(!n)return;o.set(t,r=new a)}var i=r.get(e);if(!i){if(!n)return;r.set(e,i=new a)}return i},p=function(t,e,n){var a=s(e,n,!1);return void 0===a?!1:a.has(t)},u=function(t,e,n){var a=s(e,n,!1);return void 0===a?void 0:a.get(t)},c=function(t,e,n,a){s(n,a,!0).set(t,e)},l=function(t,e){var n=s(t,e,!1),a=[];return n&&n.forEach(function(t,e){a.push(e)}),a},d=function(t){return void 0===t||"symbol"==typeof t?t:t+""},f=function(t){r(r.S,"Reflect",t)};e.exports={store:o,map:s,has:p,get:u,set:c,keys:l,key:d,exp:f}},{101:101,159:159,265:265,34:34}],68:[function(t,e,n){var a=t(41),r=t(111).set,i=a.MutationObserver||a.WebKitMutationObserver,o=a.process,s=a.Promise,p="process"==t(19)(o);e.exports=function(){var t,e,n,u=function(){var a,r;for(p&&(a=o.domain)&&a.exit();t;){r=t.fn,t=t.next;try{r()}catch(i){throw t?n():e=void 0,i}}e=void 0,a&&a.enter()};if(p)n=function(){o.nextTick(u)};else if(!i||a.navigator&&a.navigator.standalone)if(s&&s.resolve){var c=s.resolve(void 0);n=function(){c.then(u)}}else n=function(){r.call(a,u)};else{var l=!0,d=document.createTextNode("");new i(u).observe(d,{characterData:!0}),n=function(){d.data=l=!l}}return function(a){var r={fn:a,next:void 0};e&&(e.next=r),t||(t=r,n()),e=r}}},{111:111,19:19,41:41}],69:[function(t,e,n){"use strict";function a(t){var e,n;this.promise=new t(function(t,a){if(void 0!==e||void 0!==n)throw TypeError("Bad Promise constructor");e=t,n=a}),this.resolve=r(e),this.reject=r(n)}var r=t(4);e.exports.f=function(t){return new a(t)}},{4:4}],70:[function(t,e,n){"use strict";var a=t(81),r=t(78),i=t(82),o=t(117),s=t(48),p=Object.assign;e.exports=!p||t(36)(function(){var t={},e={},n=Symbol(),a="abcdefghijklmnopqrst";return t[n]=7,a.split("").forEach(function(t){e[t]=t}),7!=p({},t)[n]||Object.keys(p({},e)).join("")!=a})?function(t,e){for(var n=o(t),p=arguments.length,u=1,c=r.f,l=i.f;p>u;)for(var d,f=s(arguments[u++]),h=c?a(f).concat(c(f)):a(f),m=h.length,g=0;m>g;)l.call(f,d=h[g++])&&(n[d]=f[d]);return n}:p},{117:117,36:36,48:48,78:78,81:81,82:82}],71:[function(t,e,n){var a=t(8),r=t(73),i=t(32),o=t(100)("IE_PROTO"),s=function(){},p="prototype",u=function(){var e,n=t(31)("iframe"),a=i.length,r="<",o=">";for(n.style.display="none",t(44).appendChild(n),n.src="javascript:",e=n.contentWindow.document,e.open(),e.write(r+"script"+o+"document.F=Object"+r+"/script"+o),e.close(),u=e.F;a--;)delete u[p][i[a]];return u()};e.exports=Object.create||function(t,e){var n;return null!==t?(s[p]=a(t),n=new s,s[p]=null,n[o]=t):n=u(),void 0===e?n:r(n,e)}},{100:100,31:31,32:32,44:44,73:73,8:8}],72:[function(t,e,n){var a=t(8),r=t(45),i=t(118),o=Object.defineProperty;n.f=t(30)?Object.defineProperty:function(t,e,n){if(a(t),e=i(e,!0),a(n),r)try{return o(t,e,n)}catch(s){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},{118:118,30:30,45:45,8:8}],73:[function(t,e,n){var a=t(72),r=t(8),i=t(81);e.exports=t(30)?Object.defineProperties:function(t,e){r(t);for(var n,o=i(e),s=o.length,p=0;s>p;)a.f(t,n=o[p++],e[n]);return t}},{30:30,72:72,8:8,81:81}],74:[function(t,e,n){"use strict";e.exports=t(60)||!t(36)(function(){var e=Math.random();__defineSetter__.call(null,e,function(){}),delete t(41)[e]})},{36:36,41:41,60:60}],75:[function(t,e,n){var a=t(82),r=t(90),i=t(115),o=t(118),s=t(42),p=t(45),u=Object.getOwnPropertyDescriptor;n.f=t(30)?u:function(t,e){if(t=i(t),e=o(e,!0),p)try{return u(t,e)}catch(n){}return s(t,e)?r(!a.f.call(t,e),t[e]):void 0}},{115:115,118:118,30:30,42:42,45:45,82:82,90:90}],76:[function(t,e,n){var a=t(115),r=t(77).f,i={}.toString,o="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],s=function(t){try{return r(t)}catch(e){return o.slice()}};e.exports.f=function(t){return o&&"[object Window]"==i.call(t)?s(t):r(a(t))}},{115:115,77:77}],77:[function(t,e,n){var a=t(80),r=t(32).concat("length","prototype");n.f=Object.getOwnPropertyNames||function(t){return a(t,r)}},{32:32,80:80}],78:[function(t,e,n){n.f=Object.getOwnPropertySymbols},{}],79:[function(t,e,n){var a=t(42),r=t(117),i=t(100)("IE_PROTO"),o=Object.prototype;e.exports=Object.getPrototypeOf||function(t){return t=r(t),a(t,i)?t[i]:"function"==typeof t.constructor&&t instanceof t.constructor?t.constructor.prototype:t instanceof Object?o:null}},{100:100,117:117,42:42}],80:[function(t,e,n){var a=t(42),r=t(115),i=t(12)(!1),o=t(100)("IE_PROTO");e.exports=function(t,e){var n,s=r(t),p=0,u=[];for(n in s)n!=o&&a(s,n)&&u.push(n);for(;e.length>p;)a(s,n=e[p++])&&(~i(u,n)||u.push(n));return u}},{100:100,115:115,12:12,42:42}],81:[function(t,e,n){var a=t(80),r=t(32);e.exports=Object.keys||function(t){return a(t,r)}},{32:32,80:80}],82:[function(t,e,n){n.f={}.propertyIsEnumerable},{}],83:[function(t,e,n){var a=t(34),r=t(24),i=t(36);e.exports=function(t,e){var n=(r.Object||{})[t]||Object[t],o={};o[t]=e(n),a(a.S+a.F*i(function(){n(1)}),"Object",o)}},{24:24,34:34,36:36}],84:[function(t,e,n){var a=t(81),r=t(115),i=t(82).f;e.exports=function(t){return function(e){for(var n,o=r(e),s=a(o),p=s.length,u=0,c=[];p>u;)i.call(o,n=s[u++])&&c.push(t?[n,o[n]]:o[n]);return c}}},{115:115,81:81,82:82}],85:[function(t,e,n){var a=t(77),r=t(78),i=t(8),o=t(41).Reflect;e.exports=o&&o.ownKeys||function(t){var e=a.f(i(t)),n=r.f;return n?e.concat(n(t)):e}},{41:41,77:77,78:78,8:8}],86:[function(t,e,n){var a=t(41).parseFloat,r=t(109).trim;e.exports=1/a(t(110)+"-0")!==-(1/0)?function(t){var e=r(t+"",3),n=a(e);return 0===n&&"-"==e.charAt(0)?-0:n}:a},{109:109,110:110,41:41}],87:[function(t,e,n){var a=t(41).parseInt,r=t(109).trim,i=t(110),o=/^[-+]?0[xX]/;e.exports=8!==a(i+"08")||22!==a(i+"0x16")?function(t,e){var n=r(t+"",3);return a(n,e>>>0||(o.test(n)?16:10))}:a},{109:109,110:110,41:41}],88:[function(t,e,n){e.exports=function(t){try{return{e:!1,v:t()}}catch(e){return{e:!0,v:e}}}},{}],89:[function(t,e,n){var a=t(8),r=t(52),i=t(69);e.exports=function(t,e){if(a(t),r(e)&&e.constructor===t)return e;var n=i.f(t),o=n.resolve;return o(e),n.promise}},{52:52,69:69,8:8}],90:[function(t,e,n){e.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},{}],91:[function(t,e,n){var a=t(92);e.exports=function(t,e,n){for(var r in e)a(t,r,e[r],n);return t}},{92:92}],92:[function(t,e,n){var a=t(41),r=t(43),i=t(42),o=t(122)("src"),s="toString",p=Function[s],u=(""+p).split(s);t(24).inspectSource=function(t){return p.call(t)},(e.exports=function(t,e,n,s){var p="function"==typeof n;p&&(i(n,"name")||r(n,"name",e)),t[e]!==n&&(p&&(i(n,o)||r(n,o,t[e]?""+t[e]:u.join(e+""))),t===a?t[e]=n:s?t[e]?t[e]=n:r(t,e,n):(delete t[e],r(t,e,n)))})(Function.prototype,s,function(){ -return"function"==typeof this&&this[o]||p.call(this)})},{122:122,24:24,41:41,42:42,43:43}],93:[function(t,e,n){e.exports=function(t,e){var n=e===Object(e)?function(t){return e[t]}:e;return function(e){return(e+"").replace(t,n)}}},{}],94:[function(t,e,n){e.exports=Object.is||function(t,e){return t===e?0!==t||1/t===1/e:t!=t&&e!=e}},{}],95:[function(t,e,n){"use strict";var a=t(34),r=t(4),i=t(26),o=t(40);e.exports=function(t){a(a.S,t,{from:function(t){var e,n,a,s,p=arguments[1];return r(this),e=void 0!==p,e&&r(p),void 0==t?new this:(n=[],e?(a=0,s=i(p,arguments[2],2),o(t,!1,function(t){n.push(s(t,a++))})):o(t,!1,n.push,n),new this(n))}})}},{26:26,34:34,4:4,40:40}],96:[function(t,e,n){"use strict";var a=t(34);e.exports=function(t){a(a.S,t,{of:function(){for(var t=arguments.length,e=Array(t);t--;)e[t]=arguments[t];return new this(e)}})}},{34:34}],97:[function(t,e,n){var a=t(52),r=t(8),i=function(t,e){if(r(t),!a(e)&&null!==e)throw TypeError(e+": can't set as prototype!")};e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,n,a){try{a=t(26)(Function.call,t(75).f(Object.prototype,"__proto__").set,2),a(e,[]),n=!(e instanceof Array)}catch(r){n=!0}return function(t,e){return i(t,e),n?t.__proto__=e:a(t,e),t}}({},!1):void 0),check:i}},{26:26,52:52,75:75,8:8}],98:[function(t,e,n){"use strict";var a=t(41),r=t(72),i=t(30),o=t(127)("species");e.exports=function(t){var e=a[t];i&&e&&!e[o]&&r.f(e,o,{configurable:!0,get:function(){return this}})}},{127:127,30:30,41:41,72:72}],99:[function(t,e,n){var a=t(72).f,r=t(42),i=t(127)("toStringTag");e.exports=function(t,e,n){t&&!r(t=n?t:t.prototype,i)&&a(t,i,{configurable:!0,value:e})}},{127:127,42:42,72:72}],100:[function(t,e,n){var a=t(101)("keys"),r=t(122);e.exports=function(t){return a[t]||(a[t]=r(t))}},{101:101,122:122}],101:[function(t,e,n){var a=t(24),r=t(41),i="__core-js_shared__",o=r[i]||(r[i]={});(e.exports=function(t,e){return o[t]||(o[t]=void 0!==e?e:{})})("versions",[]).push({version:a.version,mode:t(60)?"pure":"global",copyright:"© 2018 Denis Pushkarev (zloirock.ru)"})},{24:24,41:41,60:60}],102:[function(t,e,n){var a=t(8),r=t(4),i=t(127)("species");e.exports=function(t,e){var n,o=a(t).constructor;return void 0===o||void 0==(n=a(o)[i])?e:r(n)}},{127:127,4:4,8:8}],103:[function(t,e,n){"use strict";var a=t(36);e.exports=function(t,e){return!!t&&a(function(){e?t.call(null,function(){},1):t.call(null)})}},{36:36}],104:[function(t,e,n){var a=t(114),r=t(29);e.exports=function(t){return function(e,n){var i,o,s=r(e)+"",p=a(n),u=s.length;return 0>p||p>=u?t?"":void 0:(i=s.charCodeAt(p),55296>i||i>56319||p+1===u||(o=s.charCodeAt(p+1))<56320||o>57343?t?s.charAt(p):i:t?s.slice(p,p+2):(i-55296<<10)+(o-56320)+65536)}}},{114:114,29:29}],105:[function(t,e,n){var a=t(53),r=t(29);e.exports=function(t,e,n){if(a(e))throw TypeError("String#"+n+" doesn't accept regex!");return r(t)+""}},{29:29,53:53}],106:[function(t,e,n){var a=t(34),r=t(36),i=t(29),o=/"/g,s=function(t,e,n,a){var r=i(t)+"",s="<"+e;return""!==n&&(s+=" "+n+'="'+(a+"").replace(o,""")+'"'),s+">"+r+""};e.exports=function(t,e){var n={};n[t]=e(s),a(a.P+a.F*r(function(){var e=""[t]('"');return e!==e.toLowerCase()||e.split('"').length>3}),"String",n)}},{29:29,34:34,36:36}],107:[function(t,e,n){var a=t(116),r=t(108),i=t(29);e.exports=function(t,e,n,o){var s=i(t)+"",p=s.length,u=void 0===n?" ":n+"",c=a(e);if(p>=c||""==u)return s;var l=c-p,d=r.call(u,Math.ceil(l/u.length));return d.length>l&&(d=d.slice(0,l)),o?d+s:s+d}},{108:108,116:116,29:29}],108:[function(t,e,n){"use strict";var a=t(114),r=t(29);e.exports=function(t){var e=r(this)+"",n="",i=a(t);if(0>i||i==1/0)throw RangeError("Count can't be negative");for(;i>0;(i>>>=1)&&(e+=e))1&i&&(n+=e);return n}},{114:114,29:29}],109:[function(t,e,n){var a=t(34),r=t(29),i=t(36),o=t(110),s="["+o+"]",p="​…",u=RegExp("^"+s+s+"*"),c=RegExp(s+s+"*$"),l=function(t,e,n){var r={},s=i(function(){return!!o[t]()||p[t]()!=p}),u=r[t]=s?e(d):o[t];n&&(r[n]=u),a(a.P+a.F*s,"String",r)},d=l.trim=function(t,e){return t=r(t)+"",1&e&&(t=t.replace(u,"")),2&e&&(t=t.replace(c,"")),t};e.exports=l},{110:110,29:29,34:34,36:36}],110:[function(t,e,n){e.exports=" \n\x0B\f\r   ᠎              \u2028\u2029\ufeff"},{}],111:[function(t,e,n){var a,r,i,o=t(26),s=t(47),p=t(44),u=t(31),c=t(41),l=c.process,d=c.setImmediate,f=c.clearImmediate,h=c.MessageChannel,m=c.Dispatch,g=0,v={},b="onreadystatechange",y=function(){var t=+this;if(v.hasOwnProperty(t)){var e=v[t];delete v[t],e()}},_=function(t){y.call(t.data)};d&&f||(d=function(t){for(var e=[],n=1;arguments.length>n;)e.push(arguments[n++]);return v[++g]=function(){s("function"==typeof t?t:Function(t),e)},a(g),g},f=function(t){delete v[t]},"process"==t(19)(l)?a=function(t){l.nextTick(o(y,t,1))}:m&&m.now?a=function(t){m.now(o(y,t,1))}:h?(r=new h,i=r.port2,r.port1.onmessage=_,a=o(i.postMessage,i,1)):c.addEventListener&&"function"==typeof postMessage&&!c.importScripts?(a=function(t){c.postMessage(t+"","*")},c.addEventListener("message",_,!1)):a=b in u("script")?function(t){p.appendChild(u("script"))[b]=function(){p.removeChild(this),y.call(t)}}:function(t){setTimeout(o(y,t,1),0)}),e.exports={set:d,clear:f}},{19:19,26:26,31:31,41:41,44:44,47:47}],112:[function(t,e,n){var a=t(114),r=Math.max,i=Math.min;e.exports=function(t,e){return t=a(t),0>t?r(t+e,0):i(t,e)}},{114:114}],113:[function(t,e,n){var a=t(114),r=t(116);e.exports=function(t){if(void 0===t)return 0;var e=a(t),n=r(e);if(e!==n)throw RangeError("Wrong length!");return n}},{114:114,116:116}],114:[function(t,e,n){var a=Math.ceil,r=Math.floor;e.exports=function(t){return isNaN(t=+t)?0:(t>0?r:a)(t)}},{}],115:[function(t,e,n){var a=t(48),r=t(29);e.exports=function(t){return a(r(t))}},{29:29,48:48}],116:[function(t,e,n){var a=t(114),r=Math.min;e.exports=function(t){return t>0?r(a(t),9007199254740991):0}},{114:114}],117:[function(t,e,n){var a=t(29);e.exports=function(t){return Object(a(t))}},{29:29}],118:[function(t,e,n){var a=t(52);e.exports=function(t,e){if(!a(t))return t;var n,r;if(e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;if("function"==typeof(n=t.valueOf)&&!a(r=n.call(t)))return r;if(!e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;throw TypeError("Can't convert object to primitive value")}},{52:52}],119:[function(t,e,n){"use strict";if(t(30)){var a=t(60),r=t(41),i=t(36),o=t(34),s=t(121),p=t(120),u=t(26),c=t(7),l=t(90),d=t(43),f=t(91),h=t(114),m=t(116),g=t(113),v=t(112),b=t(118),y=t(42),_=t(18),x=t(52),w=t(117),k=t(49),S=t(71),E=t(79),C=t(77).f,P=t(128),A=t(122),O=t(127),T=t(13),R=t(12),M=t(102),L=t(140),D=t(59),j=t(57),N=t(98),F=t(10),I=t(9),B=t(72),q=t(75),U=B.f,V=q.f,G=r.RangeError,z=r.TypeError,W=r.Uint8Array,H="ArrayBuffer",K="Shared"+H,Q="BYTES_PER_ELEMENT",Y="prototype",$=Array[Y],J=p.ArrayBuffer,X=p.DataView,Z=T(0),tt=T(2),et=T(3),nt=T(4),at=T(5),rt=T(6),it=R(!0),ot=R(!1),st=L.values,pt=L.keys,ut=L.entries,ct=$.lastIndexOf,lt=$.reduce,dt=$.reduceRight,ft=$.join,ht=$.sort,mt=$.slice,gt=$.toString,vt=$.toLocaleString,bt=O("iterator"),yt=O("toStringTag"),_t=A("typed_constructor"),xt=A("def_constructor"),wt=s.CONSTR,kt=s.TYPED,St=s.VIEW,Et="Wrong length!",Ct=T(1,function(t,e){return Rt(M(t,t[xt]),e)}),Pt=i(function(){return 1===new W(new Uint16Array([1]).buffer)[0]}),At=!!W&&!!W[Y].set&&i(function(){new W(1).set({})}),Ot=function(t,e){var n=h(t);if(0>n||n%e)throw G("Wrong offset!");return n},Tt=function(t){if(x(t)&&kt in t)return t;throw z(t+" is not a typed array!")},Rt=function(t,e){if(!(x(t)&&_t in t))throw z("It is not a typed array constructor!");return new t(e)},Mt=function(t,e){return Lt(M(t,t[xt]),e)},Lt=function(t,e){for(var n=0,a=e.length,r=Rt(t,a);a>n;)r[n]=e[n++];return r},Dt=function(t,e,n){U(t,e,{get:function(){return this._d[n]}})},jt=function(t){var e,n,a,r,i,o,s=w(t),p=arguments.length,c=p>1?arguments[1]:void 0,l=void 0!==c,d=P(s);if(void 0!=d&&!k(d)){for(o=d.call(s),a=[],e=0;!(i=o.next()).done;e++)a.push(i.value);s=a}for(l&&p>2&&(c=u(c,arguments[2],2)),e=0,n=m(s.length),r=Rt(this,n);n>e;e++)r[e]=l?c(s[e],e):s[e];return r},Nt=function(){for(var t=0,e=arguments.length,n=Rt(this,e);e>t;)n[t]=arguments[t++];return n},Ft=!!W&&i(function(){vt.call(new W(1))}),It=function(){return vt.apply(Ft?mt.call(Tt(this)):Tt(this),arguments)},Bt={copyWithin:function(t,e){return I.call(Tt(this),t,e,arguments.length>2?arguments[2]:void 0)},every:function(t){return nt(Tt(this),t,arguments.length>1?arguments[1]:void 0)},fill:function(t){return F.apply(Tt(this),arguments)},filter:function(t){return Mt(this,tt(Tt(this),t,arguments.length>1?arguments[1]:void 0))},find:function(t){return at(Tt(this),t,arguments.length>1?arguments[1]:void 0)},findIndex:function(t){return rt(Tt(this),t,arguments.length>1?arguments[1]:void 0)},forEach:function(t){Z(Tt(this),t,arguments.length>1?arguments[1]:void 0)},indexOf:function(t){return ot(Tt(this),t,arguments.length>1?arguments[1]:void 0)},includes:function(t){return it(Tt(this),t,arguments.length>1?arguments[1]:void 0)},join:function(t){return ft.apply(Tt(this),arguments)},lastIndexOf:function(t){return ct.apply(Tt(this),arguments)},map:function(t){return Ct(Tt(this),t,arguments.length>1?arguments[1]:void 0)},reduce:function(t){return lt.apply(Tt(this),arguments)},reduceRight:function(t){return dt.apply(Tt(this),arguments)},reverse:function(){for(var t,e=this,n=Tt(e).length,a=Math.floor(n/2),r=0;a>r;)t=e[r],e[r++]=e[--n],e[n]=t;return e},some:function(t){return et(Tt(this),t,arguments.length>1?arguments[1]:void 0)},sort:function(t){return ht.call(Tt(this),t)},subarray:function(t,e){var n=Tt(this),a=n.length,r=v(t,a);return new(M(n,n[xt]))(n.buffer,n.byteOffset+r*n.BYTES_PER_ELEMENT,m((void 0===e?a:v(e,a))-r))}},qt=function(t,e){return Mt(this,mt.call(Tt(this),t,e))},Ut=function(t){Tt(this);var e=Ot(arguments[1],1),n=this.length,a=w(t),r=m(a.length),i=0;if(r+e>n)throw G(Et);for(;r>i;)this[e+i]=a[i++]},Vt={entries:function(){return ut.call(Tt(this))},keys:function(){return pt.call(Tt(this))},values:function(){return st.call(Tt(this))}},Gt=function(t,e){return x(t)&&t[kt]&&"symbol"!=typeof e&&e in t&&+e+""==e+""},zt=function(t,e){return Gt(t,e=b(e,!0))?l(2,t[e]):V(t,e)},Wt=function(t,e,n){return!(Gt(t,e=b(e,!0))&&x(n)&&y(n,"value"))||y(n,"get")||y(n,"set")||n.configurable||y(n,"writable")&&!n.writable||y(n,"enumerable")&&!n.enumerable?U(t,e,n):(t[e]=n.value,t)};wt||(q.f=zt,B.f=Wt),o(o.S+o.F*!wt,"Object",{getOwnPropertyDescriptor:zt,defineProperty:Wt}),i(function(){gt.call({})})&&(gt=vt=function(){return ft.call(this)});var Ht=f({},Bt);f(Ht,Vt),d(Ht,bt,Vt.values),f(Ht,{slice:qt,set:Ut,constructor:function(){},toString:gt,toLocaleString:It}),Dt(Ht,"buffer","b"),Dt(Ht,"byteOffset","o"),Dt(Ht,"byteLength","l"),Dt(Ht,"length","e"),U(Ht,yt,{get:function(){return this[kt]}}),e.exports=function(t,e,n,p){p=!!p;var u=t+(p?"Clamped":"")+"Array",l="get"+t,f="set"+t,h=r[u],v=h||{},b=h&&E(h),y=!h||!s.ABV,w={},k=h&&h[Y],P=function(t,n){var a=t._d;return a.v[l](n*e+a.o,Pt)},A=function(t,n,a){var r=t._d;p&&(a=(a=Math.round(a))<0?0:a>255?255:255&a),r.v[f](n*e+r.o,a,Pt)},O=function(t,e){U(t,e,{get:function(){return P(this,e)},set:function(t){return A(this,e,t)},enumerable:!0})};y?(h=n(function(t,n,a,r){c(t,h,u,"_d");var i,o,s,p,l=0,f=0;if(x(n)){if(!(n instanceof J||(p=_(n))==H||p==K))return kt in n?Lt(h,n):jt.call(h,n);i=n,f=Ot(a,e);var v=n.byteLength;if(void 0===r){if(v%e)throw G(Et);if(o=v-f,0>o)throw G(Et)}else if(o=m(r)*e,o+f>v)throw G(Et);s=o/e}else s=g(n),o=s*e,i=new J(o);for(d(t,"_d",{b:i,o:f,l:o,e:s,v:new X(i)});s>l;)O(t,l++)}),k=h[Y]=S(Ht),d(k,"constructor",h)):i(function(){h(1)})&&i(function(){new h(-1)})&&j(function(t){new h,new h(null),new h(1.5),new h(t)},!0)||(h=n(function(t,n,a,r){c(t,h,u);var i;return x(n)?n instanceof J||(i=_(n))==H||i==K?void 0!==r?new v(n,Ot(a,e),r):void 0!==a?new v(n,Ot(a,e)):new v(n):kt in n?Lt(h,n):jt.call(h,n):new v(g(n))}),Z(b!==Function.prototype?C(v).concat(C(b)):C(v),function(t){t in h||d(h,t,v[t])}),h[Y]=k,a||(k.constructor=h));var T=k[bt],R=!!T&&("values"==T.name||void 0==T.name),M=Vt.values;d(h,_t,!0),d(k,kt,u),d(k,St,!0),d(k,xt,h),(p?new h(1)[yt]==u:yt in k)||U(k,yt,{get:function(){return u}}),w[u]=h,o(o.G+o.W+o.F*(h!=v),w),o(o.S,u,{BYTES_PER_ELEMENT:e}),o(o.S+o.F*i(function(){v.of.call(h,1)}),u,{from:jt,of:Nt}),Q in k||d(k,Q,e),o(o.P,u,Bt),N(u),o(o.P+o.F*At,u,{set:Ut}),o(o.P+o.F*!R,u,Vt),a||k.toString==gt||(k.toString=gt),o(o.P+o.F*i(function(){new h(1).slice()}),u,{slice:qt}),o(o.P+o.F*(i(function(){return[1,2].toLocaleString()!=new h([1,2]).toLocaleString()})||!i(function(){k.toLocaleString.call([1,2])})),u,{toLocaleString:It}),D[u]=R?T:M,a||R||d(k,bt,M)}}else e.exports=function(){}},{10:10,102:102,112:112,113:113,114:114,116:116,117:117,118:118,12:12,120:120,121:121,122:122,127:127,128:128,13:13,140:140,18:18,26:26,30:30,34:34,36:36,41:41,42:42,43:43,49:49,52:52,57:57,59:59,60:60,7:7,71:71,72:72,75:75,77:77,79:79,9:9,90:90,91:91,98:98}],120:[function(t,e,n){"use strict";function a(t,e,n){var a,r,i,o=Array(n),s=8*n-e-1,p=(1<>1,c=23===e?U(2,-24)-U(2,-77):0,l=0,d=0>t||0===t&&0>1/t?1:0;for(t=q(t),t!=t||t===I?(r=t!=t?1:0,a=p):(a=V(G(t)/z),t*(i=U(2,-a))<1&&(a--,i*=2),t+=a+u>=1?c/i:c*U(2,1-u),t*i>=2&&(a++,i/=2),a+u>=p?(r=0,a=p):a+u>=1?(r=(t*i-1)*U(2,e),a+=u):(r=t*U(2,u-1)*U(2,e),a=0));e>=8;o[l++]=255&r,r/=256,e-=8);for(a=a<0;o[l++]=255&a,a/=256,s-=8);return o[--l]|=128*d,o}function r(t,e,n){var a,r=8*n-e-1,i=(1<>1,s=r-7,p=n-1,u=t[p--],c=127&u;for(u>>=7;s>0;c=256*c+t[p],p--,s-=8);for(a=c&(1<<-s)-1,c>>=-s,s+=e;s>0;a=256*a+t[p],p--,s-=8);if(0===c)c=1-o;else{if(c===i)return a?NaN:u?-I:I;a+=U(2,e),c-=o}return(u?-1:1)*a*U(2,c-e)}function i(t){return t[3]<<24|t[2]<<16|t[1]<<8|t[0]}function o(t){return[255&t]}function s(t){return[255&t,t>>8&255]}function p(t){return[255&t,t>>8&255,t>>16&255,t>>24&255]}function u(t){return a(t,52,8)}function c(t){return a(t,23,4)}function l(t,e,n){C(t[R],e,{get:function(){return this[n]}})}function d(t,e,n,a){var r=+n,i=S(r);if(i+e>t[Y])throw F(L);var o=t[Q]._b,s=i+t[$],p=o.slice(s,s+e);return a?p:p.reverse()}function f(t,e,n,a,r,i){var o=+n,s=S(o);if(s+e>t[Y])throw F(L);for(var p=t[Q]._b,u=s+t[$],c=a(+r),l=0;e>l;l++)p[u+l]=c[i?l:e-l-1]}var h=t(41),m=t(30),g=t(60),v=t(121),b=t(43),y=t(91),_=t(36),x=t(7),w=t(114),k=t(116),S=t(113),E=t(77).f,C=t(72).f,P=t(10),A=t(99),O="ArrayBuffer",T="DataView",R="prototype",M="Wrong length!",L="Wrong index!",D=h[O],j=h[T],N=h.Math,F=h.RangeError,I=h.Infinity,B=D,q=N.abs,U=N.pow,V=N.floor,G=N.log,z=N.LN2,W="buffer",H="byteLength",K="byteOffset",Q=m?"_b":W,Y=m?"_l":H,$=m?"_o":K;if(v.ABV){if(!_(function(){D(1)})||!_(function(){new D(-1)})||_(function(){return new D,new D(1.5),new D(NaN),D.name!=O})){D=function(t){return x(this,D),new B(S(t))};for(var J,X=D[R]=B[R],Z=E(B),tt=0;Z.length>tt;)(J=Z[tt++])in D||b(D,J,B[J]);g||(X.constructor=D)}var et=new j(new D(2)),nt=j[R].setInt8;et.setInt8(0,2147483648),et.setInt8(1,2147483649),(et.getInt8(0)||!et.getInt8(1))&&y(j[R],{setInt8:function(t,e){nt.call(this,t,e<<24>>24)},setUint8:function(t,e){nt.call(this,t,e<<24>>24)}},!0)}else D=function(t){x(this,D,O);var e=S(t);this._b=P.call(Array(e),0),this[Y]=e},j=function(t,e,n){x(this,j,T),x(t,D,T);var a=t[Y],r=w(e);if(0>r||r>a)throw F("Wrong offset!");if(n=void 0===n?a-r:k(n),r+n>a)throw F(M);this[Q]=t,this[$]=r,this[Y]=n},m&&(l(D,H,"_l"),l(j,W,"_b"),l(j,H,"_l"),l(j,K,"_o")),y(j[R],{getInt8:function(t){return d(this,1,t)[0]<<24>>24},getUint8:function(t){return d(this,1,t)[0]},getInt16:function(t){var e=d(this,2,t,arguments[1]);return(e[1]<<8|e[0])<<16>>16},getUint16:function(t){var e=d(this,2,t,arguments[1]);return e[1]<<8|e[0]},getInt32:function(t){return i(d(this,4,t,arguments[1]))},getUint32:function(t){return i(d(this,4,t,arguments[1]))>>>0},getFloat32:function(t){return r(d(this,4,t,arguments[1]),23,4)},getFloat64:function(t){return r(d(this,8,t,arguments[1]),52,8)},setInt8:function(t,e){f(this,1,t,o,e)},setUint8:function(t,e){f(this,1,t,o,e)},setInt16:function(t,e){f(this,2,t,s,e,arguments[2])},setUint16:function(t,e){f(this,2,t,s,e,arguments[2])},setInt32:function(t,e){f(this,4,t,p,e,arguments[2])},setUint32:function(t,e){f(this,4,t,p,e,arguments[2])},setFloat32:function(t,e){f(this,4,t,c,e,arguments[2])},setFloat64:function(t,e){f(this,8,t,u,e,arguments[2])}});A(D,O),A(j,T),b(j[R],v.VIEW,!0),n[O]=D,n[T]=j},{10:10,113:113,114:114,116:116,121:121,30:30,36:36,41:41,43:43,60:60,7:7,72:72,77:77,91:91,99:99}],121:[function(t,e,n){for(var a,r=t(41),i=t(43),o=t(122),s=o("typed_array"),p=o("view"),u=!(!r.ArrayBuffer||!r.DataView),c=u,l=0,d=9,f="Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array".split(",");d>l;)(a=r[f[l++]])?(i(a.prototype,s,!0),i(a.prototype,p,!0)):c=!1;e.exports={ABV:u,CONSTR:c,TYPED:s,VIEW:p}},{122:122,41:41,43:43}],122:[function(t,e,n){var a=0,r=Math.random();e.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++a+r).toString(36))}},{}],123:[function(t,e,n){var a=t(41),r=a.navigator;e.exports=r&&r.userAgent||""},{41:41}],124:[function(t,e,n){var a=t(52);e.exports=function(t,e){if(!a(t)||t._t!==e)throw TypeError("Incompatible receiver, "+e+" required!");return t}},{52:52}],125:[function(t,e,n){var a=t(41),r=t(24),i=t(60),o=t(126),s=t(72).f;e.exports=function(t){var e=r.Symbol||(r.Symbol=i?{}:a.Symbol||{});"_"==t.charAt(0)||t in e||s(e,t,{value:o.f(t)})}},{126:126,24:24,41:41,60:60,72:72}],126:[function(t,e,n){n.f=t(127)},{127:127}],127:[function(t,e,n){var a=t(101)("wks"),r=t(122),i=t(41).Symbol,o="function"==typeof i,s=e.exports=function(t){return a[t]||(a[t]=o&&i[t]||(o?i:r)("Symbol."+t))};s.store=a},{101:101,122:122,41:41}],128:[function(t,e,n){var a=t(18),r=t(127)("iterator"),i=t(59);e.exports=t(24).getIteratorMethod=function(t){return void 0!=t?t[r]||t["@@iterator"]||i[a(t)]:void 0}},{127:127,18:18,24:24,59:59}],129:[function(t,e,n){var a=t(34),r=t(93)(/[\\^$*+?.()|[\]{}]/g,"\\$&");a(a.S,"RegExp",{escape:function(t){return r(t)}})},{34:34,93:93}],130:[function(t,e,n){var a=t(34);a(a.P,"Array",{copyWithin:t(9)}),t(6)("copyWithin")},{34:34,6:6,9:9}],131:[function(t,e,n){"use strict";var a=t(34),r=t(13)(4);a(a.P+a.F*!t(103)([].every,!0),"Array",{every:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],132:[function(t,e,n){var a=t(34);a(a.P,"Array",{fill:t(10)}),t(6)("fill")},{10:10,34:34,6:6}],133:[function(t,e,n){"use strict";var a=t(34),r=t(13)(2);a(a.P+a.F*!t(103)([].filter,!0),"Array",{filter:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],134:[function(t,e,n){"use strict";var a=t(34),r=t(13)(6),i="findIndex",o=!0;i in[]&&Array(1)[i](function(){o=!1}),a(a.P+a.F*o,"Array",{findIndex:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),t(6)(i)},{13:13,34:34,6:6}],135:[function(t,e,n){"use strict";var a=t(34),r=t(13)(5),i="find",o=!0;i in[]&&Array(1)[i](function(){o=!1}),a(a.P+a.F*o,"Array",{find:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),t(6)(i)},{13:13,34:34,6:6}],136:[function(t,e,n){"use strict";var a=t(34),r=t(13)(0),i=t(103)([].forEach,!0);a(a.P+a.F*!i,"Array",{forEach:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],137:[function(t,e,n){"use strict";var a=t(26),r=t(34),i=t(117),o=t(54),s=t(49),p=t(116),u=t(25),c=t(128);r(r.S+r.F*!t(57)(function(t){Array.from(t)}),"Array",{from:function(t){var e,n,r,l,d=i(t),f="function"==typeof this?this:Array,h=arguments.length,m=h>1?arguments[1]:void 0,g=void 0!==m,v=0,b=c(d);if(g&&(m=a(m,h>2?arguments[2]:void 0,2)),void 0==b||f==Array&&s(b))for(e=p(d.length),n=new f(e);e>v;v++)u(n,v,g?m(d[v],v):d[v]);else for(l=b.call(d),n=new f;!(r=l.next()).done;v++)u(n,v,g?o(l,m,[r.value,v],!0):r.value);return n.length=v,n}})},{116:116,117:117,128:128,25:25,26:26,34:34,49:49,54:54,57:57}],138:[function(t,e,n){"use strict";var a=t(34),r=t(12)(!1),i=[].indexOf,o=!!i&&1/[1].indexOf(1,-0)<0;a(a.P+a.F*(o||!t(103)(i)),"Array",{indexOf:function(t){return o?i.apply(this,arguments)||0:r(this,t,arguments[1])}})},{103:103,12:12,34:34}],139:[function(t,e,n){var a=t(34);a(a.S,"Array",{isArray:t(50)})},{34:34,50:50}],140:[function(t,e,n){"use strict";var a=t(6),r=t(58),i=t(59),o=t(115);e.exports=t(56)(Array,"Array",function(t,e){this._t=o(t),this._i=0,this._k=e},function(){var t=this._t,e=this._k,n=this._i++;return!t||n>=t.length?(this._t=void 0,r(1)):"keys"==e?r(0,n):"values"==e?r(0,t[n]):r(0,[n,t[n]])},"values"),i.Arguments=i.Array,a("keys"),a("values"),a("entries")},{115:115,56:56,58:58,59:59,6:6}],141:[function(t,e,n){"use strict";var a=t(34),r=t(115),i=[].join;a(a.P+a.F*(t(48)!=Object||!t(103)(i)),"Array",{join:function(t){return i.call(r(this),void 0===t?",":t)}})},{103:103,115:115,34:34,48:48}],142:[function(t,e,n){"use strict";var a=t(34),r=t(115),i=t(114),o=t(116),s=[].lastIndexOf,p=!!s&&1/[1].lastIndexOf(1,-0)<0;a(a.P+a.F*(p||!t(103)(s)),"Array",{lastIndexOf:function(t){if(p)return s.apply(this,arguments)||0;var e=r(this),n=o(e.length),a=n-1;for(arguments.length>1&&(a=Math.min(a,i(arguments[1]))),0>a&&(a=n+a);a>=0;a--)if(a in e&&e[a]===t)return a||0;return-1}})},{103:103,114:114,115:115,116:116,34:34}],143:[function(t,e,n){"use strict";var a=t(34),r=t(13)(1);a(a.P+a.F*!t(103)([].map,!0),"Array",{map:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],144:[function(t,e,n){"use strict";var a=t(34),r=t(25);a(a.S+a.F*t(36)(function(){function t(){}return!(Array.of.call(t)instanceof t)}),"Array",{of:function(){for(var t=0,e=arguments.length,n=new("function"==typeof this?this:Array)(e);e>t;)r(n,t,arguments[t++]);return n.length=e,n}})},{25:25,34:34,36:36}],145:[function(t,e,n){"use strict";var a=t(34),r=t(14);a(a.P+a.F*!t(103)([].reduceRight,!0),"Array",{reduceRight:function(t){return r(this,t,arguments.length,arguments[1],!0)}})},{103:103,14:14,34:34}],146:[function(t,e,n){"use strict";var a=t(34),r=t(14);a(a.P+a.F*!t(103)([].reduce,!0),"Array",{reduce:function(t){return r(this,t,arguments.length,arguments[1],!1)}})},{103:103,14:14,34:34}],147:[function(t,e,n){"use strict";var a=t(34),r=t(44),i=t(19),o=t(112),s=t(116),p=[].slice;a(a.P+a.F*t(36)(function(){r&&p.call(r)}),"Array",{slice:function(t,e){var n=s(this.length),a=i(this);if(e=void 0===e?n:e,"Array"==a)return p.call(this,t,e);for(var r=o(t,n),u=o(e,n),c=s(u-r),l=Array(c),d=0;c>d;d++)l[d]="String"==a?this.charAt(r+d):this[r+d];return l}})},{112:112,116:116,19:19,34:34,36:36,44:44}],148:[function(t,e,n){"use strict";var a=t(34),r=t(13)(3);a(a.P+a.F*!t(103)([].some,!0),"Array",{some:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],149:[function(t,e,n){"use strict";var a=t(34),r=t(4),i=t(117),o=t(36),s=[].sort,p=[1,2,3];a(a.P+a.F*(o(function(){p.sort(void 0)})||!o(function(){p.sort(null)})||!t(103)(s)),"Array",{sort:function(t){return void 0===t?s.call(i(this)):s.call(i(this),r(t))}})},{103:103,117:117,34:34,36:36,4:4}],150:[function(t,e,n){t(98)("Array")},{98:98}],151:[function(t,e,n){var a=t(34);a(a.S,"Date",{now:function(){return(new Date).getTime()}})},{34:34}],152:[function(t,e,n){var a=t(34),r=t(27);a(a.P+a.F*(Date.prototype.toISOString!==r),"Date",{toISOString:r})},{27:27,34:34}],153:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(118);a(a.P+a.F*t(36)(function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})}),"Date",{toJSON:function(t){var e=r(this),n=i(e);return"number"!=typeof n||isFinite(n)?e.toISOString():null}})},{117:117,118:118,34:34,36:36}],154:[function(t,e,n){var a=t(127)("toPrimitive"),r=Date.prototype;a in r||t(43)(r,a,t(28))},{127:127,28:28,43:43}],155:[function(t,e,n){var a=Date.prototype,r="Invalid Date",i="toString",o=a[i],s=a.getTime;new Date(NaN)+""!=r&&t(92)(a,i,function(){var t=s.call(this);return t===t?o.call(this):r})},{92:92}],156:[function(t,e,n){var a=t(34);a(a.P,"Function",{bind:t(17)})},{17:17,34:34}],157:[function(t,e,n){"use strict";var a=t(52),r=t(79),i=t(127)("hasInstance"),o=Function.prototype;i in o||t(72).f(o,i,{value:function(t){if("function"!=typeof this||!a(t))return!1;if(!a(this.prototype))return t instanceof this;for(;t=r(t);)if(this.prototype===t)return!0;return!1}})},{127:127,52:52,72:72,79:79}],158:[function(t,e,n){var a=t(72).f,r=Function.prototype,i=/^\s*function ([^ (]*)/,o="name";o in r||t(30)&&a(r,o,{configurable:!0,get:function(){try{return(""+this).match(i)[1]}catch(t){return""}}})},{30:30,72:72}],159:[function(t,e,n){"use strict";var a=t(20),r=t(124),i="Map";e.exports=t(23)(i,function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{get:function(t){var e=a.getEntry(r(this,i),t);return e&&e.v},set:function(t,e){return a.def(r(this,i),0===t?0:t,e)}},a,!0)},{124:124,20:20,23:23}],160:[function(t,e,n){var a=t(34),r=t(63),i=Math.sqrt,o=Math.acosh;a(a.S+a.F*!(o&&710==Math.floor(o(Number.MAX_VALUE))&&o(1/0)==1/0),"Math",{acosh:function(t){return(t=+t)<1?NaN:t>94906265.62425156?Math.log(t)+Math.LN2:r(t-1+i(t-1)*i(t+1))}})},{34:34,63:63}],161:[function(t,e,n){function a(t){return isFinite(t=+t)&&0!=t?0>t?-a(-t):Math.log(t+Math.sqrt(t*t+1)):t}var r=t(34),i=Math.asinh;r(r.S+r.F*!(i&&1/i(0)>0),"Math",{asinh:a})},{34:34}],162:[function(t,e,n){var a=t(34),r=Math.atanh;a(a.S+a.F*!(r&&1/r(-0)<0),"Math",{atanh:function(t){return 0==(t=+t)?t:Math.log((1+t)/(1-t))/2}})},{34:34}],163:[function(t,e,n){var a=t(34),r=t(65);a(a.S,"Math",{cbrt:function(t){return r(t=+t)*Math.pow(Math.abs(t),1/3)}})},{34:34,65:65}],164:[function(t,e,n){var a=t(34);a(a.S,"Math",{clz32:function(t){return(t>>>=0)?31-Math.floor(Math.log(t+.5)*Math.LOG2E):32}})},{34:34}],165:[function(t,e,n){var a=t(34),r=Math.exp;a(a.S,"Math",{cosh:function(t){return(r(t=+t)+r(-t))/2}})},{34:34}],166:[function(t,e,n){var a=t(34),r=t(61);a(a.S+a.F*(r!=Math.expm1),"Math",{expm1:r})},{34:34,61:61}],167:[function(t,e,n){var a=t(34);a(a.S,"Math",{fround:t(62)})},{34:34,62:62}],168:[function(t,e,n){var a=t(34),r=Math.abs;a(a.S,"Math",{hypot:function(t,e){for(var n,a,i=0,o=0,s=arguments.length,p=0;s>o;)n=r(arguments[o++]),n>p?(a=p/n,i=i*a*a+1,p=n):n>0?(a=n/p,i+=a*a):i+=n;return p===1/0?1/0:p*Math.sqrt(i)}})},{34:34}],169:[function(t,e,n){var a=t(34),r=Math.imul;a(a.S+a.F*t(36)(function(){return-5!=r(4294967295,5)||2!=r.length}),"Math",{imul:function(t,e){var n=65535,a=+t,r=+e,i=n&a,o=n&r;return 0|i*o+((n&a>>>16)*o+i*(n&r>>>16)<<16>>>0)}})},{34:34,36:36}],170:[function(t,e,n){var a=t(34);a(a.S,"Math",{log10:function(t){return Math.log(t)*Math.LOG10E}})},{34:34}],171:[function(t,e,n){var a=t(34);a(a.S,"Math",{log1p:t(63)})},{34:34,63:63}],172:[function(t,e,n){var a=t(34);a(a.S,"Math",{log2:function(t){return Math.log(t)/Math.LN2}})},{34:34}],173:[function(t,e,n){var a=t(34);a(a.S,"Math",{sign:t(65)})},{34:34,65:65}],174:[function(t,e,n){var a=t(34),r=t(61),i=Math.exp;a(a.S+a.F*t(36)(function(){return-2e-17!=!Math.sinh(-2e-17)}),"Math",{sinh:function(t){return Math.abs(t=+t)<1?(r(t)-r(-t))/2:(i(t-1)-i(-t-1))*(Math.E/2)}})},{34:34,36:36,61:61}],175:[function(t,e,n){var a=t(34),r=t(61),i=Math.exp;a(a.S,"Math",{tanh:function(t){var e=r(t=+t),n=r(-t);return e==1/0?1:n==1/0?-1:(e-n)/(i(t)+i(-t))}})},{34:34,61:61}],176:[function(t,e,n){var a=t(34);a(a.S,"Math",{trunc:function(t){return(t>0?Math.floor:Math.ceil)(t)}})},{34:34}],177:[function(t,e,n){"use strict";var a=t(41),r=t(42),i=t(19),o=t(46),s=t(118),p=t(36),u=t(77).f,c=t(75).f,l=t(72).f,d=t(109).trim,f="Number",h=a[f],m=h,g=h.prototype,v=i(t(71)(g))==f,b="trim"in String.prototype,y=function(t){var e=s(t,!1);if("string"==typeof e&&e.length>2){e=b?e.trim():d(e,3);var n,a,r,i=e.charCodeAt(0);if(43===i||45===i){if(n=e.charCodeAt(2),88===n||120===n)return NaN}else if(48===i){switch(e.charCodeAt(1)){case 66:case 98:a=2,r=49;break;case 79:case 111:a=8,r=55;break;default:return+e}for(var o,p=e.slice(2),u=0,c=p.length;c>u;u++)if(o=p.charCodeAt(u),48>o||o>r)return NaN;return parseInt(p,a)}}return+e};if(!h(" 0o1")||!h("0b1")||h("+0x1")){h=function(t){var e=arguments.length<1?0:t,n=this;return n instanceof h&&(v?p(function(){g.valueOf.call(n)}):i(n)!=f)?o(new m(y(e)),n,h):y(e)};for(var _,x=t(30)?u(m):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),w=0;x.length>w;w++)r(m,_=x[w])&&!r(h,_)&&l(h,_,c(m,_));h.prototype=g,g.constructor=h,t(92)(a,f,h)}},{109:109,118:118,19:19,30:30,36:36,41:41,42:42,46:46,71:71,72:72,75:75,77:77,92:92}],178:[function(t,e,n){var a=t(34);a(a.S,"Number",{EPSILON:Math.pow(2,-52)})},{34:34}],179:[function(t,e,n){var a=t(34),r=t(41).isFinite;a(a.S,"Number",{isFinite:function(t){return"number"==typeof t&&r(t)}})},{34:34,41:41}],180:[function(t,e,n){var a=t(34);a(a.S,"Number",{isInteger:t(51)})},{34:34,51:51}],181:[function(t,e,n){var a=t(34);a(a.S,"Number",{isNaN:function(t){return t!=t}})},{34:34}],182:[function(t,e,n){var a=t(34),r=t(51),i=Math.abs;a(a.S,"Number",{isSafeInteger:function(t){return r(t)&&i(t)<=9007199254740991}})},{34:34,51:51}],183:[function(t,e,n){var a=t(34);a(a.S,"Number",{MAX_SAFE_INTEGER:9007199254740991})},{34:34}],184:[function(t,e,n){var a=t(34);a(a.S,"Number",{MIN_SAFE_INTEGER:-9007199254740991})},{34:34}],185:[function(t,e,n){var a=t(34),r=t(86);a(a.S+a.F*(Number.parseFloat!=r),"Number",{parseFloat:r})},{34:34,86:86}],186:[function(t,e,n){var a=t(34),r=t(87);a(a.S+a.F*(Number.parseInt!=r),"Number",{parseInt:r})},{34:34,87:87}],187:[function(t,e,n){"use strict";var a=t(34),r=t(114),i=t(5),o=t(108),s=1..toFixed,p=Math.floor,u=[0,0,0,0,0,0],c="Number.toFixed: incorrect invocation!",l="0",d=function(t,e){for(var n=-1,a=e;++n<6;)a+=t*u[n],u[n]=a%1e7,a=p(a/1e7)},f=function(t){for(var e=6,n=0;--e>=0;)n+=u[e],u[e]=p(n/t),n=n%t*1e7},h=function(){for(var t=6,e="";--t>=0;)if(""!==e||0===t||0!==u[t]){var n=u[t]+"";e=""===e?n:e+o.call(l,7-n.length)+n}return e},m=function(t,e,n){return 0===e?n:e%2===1?m(t,e-1,n*t):m(t*t,e/2,n)},g=function(t){for(var e=0,n=t;n>=4096;)e+=12,n/=4096;for(;n>=2;)e+=1,n/=2;return e};a(a.P+a.F*(!!s&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==0xde0b6b3a7640080.toFixed(0))||!t(36)(function(){s.call({})})),"Number",{toFixed:function(t){var e,n,a,s,p=i(this,c),u=r(t),v="",b=l;if(0>u||u>20)throw RangeError(c);if(p!=p)return"NaN";if(-1e21>=p||p>=1e21)return p+"";if(0>p&&(v="-",p=-p),p>1e-21)if(e=g(p*m(2,69,1))-69,n=0>e?p*m(2,-e,1):p/m(2,e,1),n*=4503599627370496,e=52-e,e>0){for(d(0,n),a=u;a>=7;)d(1e7,0),a-=7;for(d(m(10,a,1),0),a=e-1;a>=23;)f(1<<23),a-=23;f(1<0?(s=b.length,b=v+(u>=s?"0."+o.call(l,u-s)+b:b.slice(0,s-u)+"."+b.slice(s-u))):b=v+b,b}})},{108:108,114:114,34:34,36:36,5:5}],188:[function(t,e,n){"use strict";var a=t(34),r=t(36),i=t(5),o=1..toPrecision;a(a.P+a.F*(r(function(){return"1"!==o.call(1,void 0)})||!r(function(){o.call({})})),"Number",{toPrecision:function(t){var e=i(this,"Number#toPrecision: incorrect invocation!");return void 0===t?o.call(e):o.call(e,t)}})},{34:34,36:36,5:5}],189:[function(t,e,n){var a=t(34);a(a.S+a.F,"Object",{assign:t(70)})},{34:34,70:70}],190:[function(t,e,n){var a=t(34);a(a.S,"Object",{create:t(71)})},{34:34,71:71}],191:[function(t,e,n){var a=t(34);a(a.S+a.F*!t(30),"Object",{defineProperties:t(73)})},{30:30,34:34,73:73}],192:[function(t,e,n){var a=t(34);a(a.S+a.F*!t(30),"Object",{defineProperty:t(72).f})},{30:30,34:34,72:72}],193:[function(t,e,n){var a=t(52),r=t(66).onFreeze;t(83)("freeze",function(t){return function(e){return t&&a(e)?t(r(e)):e}})},{52:52,66:66,83:83}],194:[function(t,e,n){var a=t(115),r=t(75).f;t(83)("getOwnPropertyDescriptor",function(){return function(t,e){return r(a(t),e)}})},{115:115,75:75,83:83}],195:[function(t,e,n){t(83)("getOwnPropertyNames",function(){return t(76).f})},{76:76,83:83}],196:[function(t,e,n){var a=t(117),r=t(79);t(83)("getPrototypeOf",function(){return function(t){return r(a(t))}})},{117:117,79:79,83:83}],197:[function(t,e,n){var a=t(52);t(83)("isExtensible",function(t){return function(e){return a(e)?t?t(e):!0:!1}}); -},{52:52,83:83}],198:[function(t,e,n){var a=t(52);t(83)("isFrozen",function(t){return function(e){return a(e)?t?t(e):!1:!0}})},{52:52,83:83}],199:[function(t,e,n){var a=t(52);t(83)("isSealed",function(t){return function(e){return a(e)?t?t(e):!1:!0}})},{52:52,83:83}],200:[function(t,e,n){var a=t(34);a(a.S,"Object",{is:t(94)})},{34:34,94:94}],201:[function(t,e,n){var a=t(117),r=t(81);t(83)("keys",function(){return function(t){return r(a(t))}})},{117:117,81:81,83:83}],202:[function(t,e,n){var a=t(52),r=t(66).onFreeze;t(83)("preventExtensions",function(t){return function(e){return t&&a(e)?t(r(e)):e}})},{52:52,66:66,83:83}],203:[function(t,e,n){var a=t(52),r=t(66).onFreeze;t(83)("seal",function(t){return function(e){return t&&a(e)?t(r(e)):e}})},{52:52,66:66,83:83}],204:[function(t,e,n){var a=t(34);a(a.S,"Object",{setPrototypeOf:t(97).set})},{34:34,97:97}],205:[function(t,e,n){"use strict";var a=t(18),r={};r[t(127)("toStringTag")]="z",r+""!="[object z]"&&t(92)(Object.prototype,"toString",function(){return"[object "+a(this)+"]"},!0)},{127:127,18:18,92:92}],206:[function(t,e,n){var a=t(34),r=t(86);a(a.G+a.F*(parseFloat!=r),{parseFloat:r})},{34:34,86:86}],207:[function(t,e,n){var a=t(34),r=t(87);a(a.G+a.F*(parseInt!=r),{parseInt:r})},{34:34,87:87}],208:[function(t,e,n){"use strict";var a,r,i,o,s=t(60),p=t(41),u=t(26),c=t(18),l=t(34),d=t(52),f=t(4),h=t(7),m=t(40),g=t(102),v=t(111).set,b=t(68)(),y=t(69),_=t(88),x=t(123),w=t(89),k="Promise",S=p.TypeError,E=p.process,C=E&&E.versions,P=C&&C.v8||"",A=p[k],O="process"==c(E),T=function(){},R=r=y.f,M=!!function(){try{var e=A.resolve(1),n=(e.constructor={})[t(127)("species")]=function(t){t(T,T)};return(O||"function"==typeof PromiseRejectionEvent)&&e.then(T)instanceof n&&0!==P.indexOf("6.6")&&-1===x.indexOf("Chrome/66")}catch(a){}}(),L=function(t){var e;return d(t)&&"function"==typeof(e=t.then)?e:!1},D=function(t,e){if(!t._n){t._n=!0;var n=t._c;b(function(){for(var a=t._v,r=1==t._s,i=0,o=function(e){var n,i,o,s=r?e.ok:e.fail,p=e.resolve,u=e.reject,c=e.domain;try{s?(r||(2==t._h&&F(t),t._h=1),s===!0?n=a:(c&&c.enter(),n=s(a),c&&(c.exit(),o=!0)),n===e.promise?u(S("Promise-chain cycle")):(i=L(n))?i.call(n,p,u):p(n)):u(a)}catch(l){c&&!o&&c.exit(),u(l)}};n.length>i;)o(n[i++]);t._c=[],t._n=!1,e&&!t._h&&j(t)})}},j=function(t){v.call(p,function(){var e,n,a,r=t._v,i=N(t);if(i&&(e=_(function(){O?E.emit("unhandledRejection",r,t):(n=p.onunhandledrejection)?n({promise:t,reason:r}):(a=p.console)&&a.error&&a.error("Unhandled promise rejection",r)}),t._h=O||N(t)?2:1),t._a=void 0,i&&e.e)throw e.v})},N=function(t){return 1!==t._h&&0===(t._a||t._c).length},F=function(t){v.call(p,function(){var e;O?E.emit("rejectionHandled",t):(e=p.onrejectionhandled)&&e({promise:t,reason:t._v})})},I=function(t){var e=this;e._d||(e._d=!0,e=e._w||e,e._v=t,e._s=2,e._a||(e._a=e._c.slice()),D(e,!0))},B=function(t){var e,n=this;if(!n._d){n._d=!0,n=n._w||n;try{if(n===t)throw S("Promise can't be resolved itself");(e=L(t))?b(function(){var a={_w:n,_d:!1};try{e.call(t,u(B,a,1),u(I,a,1))}catch(r){I.call(a,r)}}):(n._v=t,n._s=1,D(n,!1))}catch(a){I.call({_w:n,_d:!1},a)}}};M||(A=function(t){h(this,A,k,"_h"),f(t),a.call(this);try{t(u(B,this,1),u(I,this,1))}catch(e){I.call(this,e)}},a=function(t){this._c=[],this._a=void 0,this._s=0,this._d=!1,this._v=void 0,this._h=0,this._n=!1},a.prototype=t(91)(A.prototype,{then:function(t,e){var n=R(g(this,A));return n.ok="function"==typeof t?t:!0,n.fail="function"==typeof e&&e,n.domain=O?E.domain:void 0,this._c.push(n),this._a&&this._a.push(n),this._s&&D(this,!1),n.promise},"catch":function(t){return this.then(void 0,t)}}),i=function(){var t=new a;this.promise=t,this.resolve=u(B,t,1),this.reject=u(I,t,1)},y.f=R=function(t){return t===A||t===o?new i(t):r(t)}),l(l.G+l.W+l.F*!M,{Promise:A}),t(99)(A,k),t(98)(k),o=t(24)[k],l(l.S+l.F*!M,k,{reject:function(t){var e=R(this),n=e.reject;return n(t),e.promise}}),l(l.S+l.F*(s||!M),k,{resolve:function(t){return w(s&&this===o?A:this,t)}}),l(l.S+l.F*!(M&&t(57)(function(t){A.all(t)["catch"](T)})),k,{all:function(t){var e=this,n=R(e),a=n.resolve,r=n.reject,i=_(function(){var n=[],i=0,o=1;m(t,!1,function(t){var s=i++,p=!1;n.push(void 0),o++,e.resolve(t).then(function(t){p||(p=!0,n[s]=t,--o||a(n))},r)}),--o||a(n)});return i.e&&r(i.v),n.promise},race:function(t){var e=this,n=R(e),a=n.reject,r=_(function(){m(t,!1,function(t){e.resolve(t).then(n.resolve,a)})});return r.e&&a(r.v),n.promise}})},{102:102,111:111,123:123,127:127,18:18,24:24,26:26,34:34,4:4,40:40,41:41,52:52,57:57,60:60,68:68,69:69,7:7,88:88,89:89,91:91,98:98,99:99}],209:[function(t,e,n){var a=t(34),r=t(4),i=t(8),o=(t(41).Reflect||{}).apply,s=Function.apply;a(a.S+a.F*!t(36)(function(){o(function(){})}),"Reflect",{apply:function(t,e,n){var a=r(t),p=i(n);return o?o(a,e,p):s.call(a,e,p)}})},{34:34,36:36,4:4,41:41,8:8}],210:[function(t,e,n){var a=t(34),r=t(71),i=t(4),o=t(8),s=t(52),p=t(36),u=t(17),c=(t(41).Reflect||{}).construct,l=p(function(){function t(){}return!(c(function(){},[],t)instanceof t)}),d=!p(function(){c(function(){})});a(a.S+a.F*(l||d),"Reflect",{construct:function(t,e){i(t),o(e);var n=arguments.length<3?t:i(arguments[2]);if(d&&!l)return c(t,e,n);if(t==n){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var a=[null];return a.push.apply(a,e),new(u.apply(t,a))}var p=n.prototype,f=r(s(p)?p:Object.prototype),h=Function.apply.call(t,f,e);return s(h)?h:f}})},{17:17,34:34,36:36,4:4,41:41,52:52,71:71,8:8}],211:[function(t,e,n){var a=t(72),r=t(34),i=t(8),o=t(118);r(r.S+r.F*t(36)(function(){Reflect.defineProperty(a.f({},1,{value:1}),1,{value:2})}),"Reflect",{defineProperty:function(t,e,n){i(t),e=o(e,!0),i(n);try{return a.f(t,e,n),!0}catch(r){return!1}}})},{118:118,34:34,36:36,72:72,8:8}],212:[function(t,e,n){var a=t(34),r=t(75).f,i=t(8);a(a.S,"Reflect",{deleteProperty:function(t,e){var n=r(i(t),e);return n&&!n.configurable?!1:delete t[e]}})},{34:34,75:75,8:8}],213:[function(t,e,n){"use strict";var a=t(34),r=t(8),i=function(t){this._t=r(t),this._i=0;var e,n=this._k=[];for(e in t)n.push(e)};t(55)(i,"Object",function(){var t,e=this,n=e._k;do if(e._i>=n.length)return{value:void 0,done:!0};while(!((t=n[e._i++])in e._t));return{value:t,done:!1}}),a(a.S,"Reflect",{enumerate:function(t){return new i(t)}})},{34:34,55:55,8:8}],214:[function(t,e,n){var a=t(75),r=t(34),i=t(8);r(r.S,"Reflect",{getOwnPropertyDescriptor:function(t,e){return a.f(i(t),e)}})},{34:34,75:75,8:8}],215:[function(t,e,n){var a=t(34),r=t(79),i=t(8);a(a.S,"Reflect",{getPrototypeOf:function(t){return r(i(t))}})},{34:34,79:79,8:8}],216:[function(t,e,n){function a(t,e){var n,s,c=arguments.length<3?t:arguments[2];return u(t)===c?t[e]:(n=r.f(t,e))?o(n,"value")?n.value:void 0!==n.get?n.get.call(c):void 0:p(s=i(t))?a(s,e,c):void 0}var r=t(75),i=t(79),o=t(42),s=t(34),p=t(52),u=t(8);s(s.S,"Reflect",{get:a})},{34:34,42:42,52:52,75:75,79:79,8:8}],217:[function(t,e,n){var a=t(34);a(a.S,"Reflect",{has:function(t,e){return e in t}})},{34:34}],218:[function(t,e,n){var a=t(34),r=t(8),i=Object.isExtensible;a(a.S,"Reflect",{isExtensible:function(t){return r(t),i?i(t):!0}})},{34:34,8:8}],219:[function(t,e,n){var a=t(34);a(a.S,"Reflect",{ownKeys:t(85)})},{34:34,85:85}],220:[function(t,e,n){var a=t(34),r=t(8),i=Object.preventExtensions;a(a.S,"Reflect",{preventExtensions:function(t){r(t);try{return i&&i(t),!0}catch(e){return!1}}})},{34:34,8:8}],221:[function(t,e,n){var a=t(34),r=t(97);r&&a(a.S,"Reflect",{setPrototypeOf:function(t,e){r.check(t,e);try{return r.set(t,e),!0}catch(n){return!1}}})},{34:34,97:97}],222:[function(t,e,n){function a(t,e,n){var p,d,f=arguments.length<4?t:arguments[3],h=i.f(c(t),e);if(!h){if(l(d=o(t)))return a(d,e,n,f);h=u(0)}if(s(h,"value")){if(h.writable===!1||!l(f))return!1;if(p=i.f(f,e)){if(p.get||p.set||p.writable===!1)return!1;p.value=n,r.f(f,e,p)}else r.f(f,e,u(0,n));return!0}return void 0===h.set?!1:(h.set.call(f,n),!0)}var r=t(72),i=t(75),o=t(79),s=t(42),p=t(34),u=t(90),c=t(8),l=t(52);p(p.S,"Reflect",{set:a})},{34:34,42:42,52:52,72:72,75:75,79:79,8:8,90:90}],223:[function(t,e,n){var a=t(41),r=t(46),i=t(72).f,o=t(77).f,s=t(53),p=t(38),u=a.RegExp,c=u,l=u.prototype,d=/a/g,f=/a/g,h=new u(d)!==d;if(t(30)&&(!h||t(36)(function(){return f[t(127)("match")]=!1,u(d)!=d||u(f)==f||"/a/i"!=u(d,"i")}))){u=function(t,e){var n=this instanceof u,a=s(t),i=void 0===e;return!n&&a&&t.constructor===u&&i?t:r(h?new c(a&&!i?t.source:t,e):c((a=t instanceof u)?t.source:t,a&&i?p.call(t):e),n?this:l,u)};for(var m=(function(t){t in u||i(u,t,{configurable:!0,get:function(){return c[t]},set:function(e){c[t]=e}})}),g=o(c),v=0;g.length>v;)m(g[v++]);l.constructor=u,u.prototype=l,t(92)(a,"RegExp",u)}t(98)("RegExp")},{127:127,30:30,36:36,38:38,41:41,46:46,53:53,72:72,77:77,92:92,98:98}],224:[function(t,e,n){t(30)&&"g"!=/./g.flags&&t(72).f(RegExp.prototype,"flags",{configurable:!0,get:t(38)})},{30:30,38:38,72:72}],225:[function(t,e,n){t(37)("match",1,function(t,e,n){return[function(n){"use strict";var a=t(this),r=void 0==n?void 0:n[e];return void 0!==r?r.call(n,a):RegExp(n)[e](a+"")},n]})},{37:37}],226:[function(t,e,n){t(37)("replace",2,function(t,e,n){return[function(a,r){"use strict";var i=t(this),o=void 0==a?void 0:a[e];return void 0!==o?o.call(a,i,r):n.call(i+"",a,r)},n]})},{37:37}],227:[function(t,e,n){t(37)("search",1,function(t,e,n){return[function(n){"use strict";var a=t(this),r=void 0==n?void 0:n[e];return void 0!==r?r.call(n,a):RegExp(n)[e](a+"")},n]})},{37:37}],228:[function(t,e,n){t(37)("split",2,function(e,n,a){"use strict";var r=t(53),i=a,o=[].push,s="split",p="length",u="lastIndex";if("c"=="abbc"[s](/(b)*/)[1]||4!="test"[s](/(?:)/,-1)[p]||2!="ab"[s](/(?:ab)*/)[p]||4!="."[s](/(.?)(.?)/)[p]||"."[s](/()()/)[p]>1||""[s](/.?/)[p]){var c=void 0===/()??/.exec("")[1];a=function(t,e){var n=this+"";if(void 0===t&&0===e)return[];if(!r(t))return i.call(n,t,e);var a,s,l,d,f,h=[],m=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),g=0,v=void 0===e?4294967295:e>>>0,b=RegExp(t.source,m+"g");for(c||(a=RegExp("^"+b.source+"$(?!\\s)",m));(s=b.exec(n))&&(l=s.index+s[0][p],!(l>g&&(h.push(n.slice(g,s.index)),!c&&s[p]>1&&s[0].replace(a,function(){for(f=1;f1&&s.index=v)));)b[u]===s.index&&b[u]++;return g===n[p]?(d||!b.test(""))&&h.push(""):h.push(n.slice(g)),h[p]>v?h.slice(0,v):h}}else"0"[s](void 0,0)[p]&&(a=function(t,e){return void 0===t&&0===e?[]:i.call(this,t,e)});return[function(t,r){var i=e(this),o=void 0==t?void 0:t[n];return void 0!==o?o.call(t,i,r):a.call(i+"",t,r)},a]})},{37:37,53:53}],229:[function(t,e,n){"use strict";t(224);var a=t(8),r=t(38),i=t(30),o="toString",s=/./[o],p=function(e){t(92)(RegExp.prototype,o,e,!0)};t(36)(function(){return"/a/b"!=s.call({source:"a",flags:"b"})})?p(function(){var t=a(this);return"/".concat(t.source,"/","flags"in t?t.flags:!i&&t instanceof RegExp?r.call(t):void 0)}):s.name!=o&&p(function(){return s.call(this)})},{224:224,30:30,36:36,38:38,8:8,92:92}],230:[function(t,e,n){"use strict";var a=t(20),r=t(124),i="Set";e.exports=t(23)(i,function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{add:function(t){return a.def(r(this,i),t=0===t?0:t,t)}},a)},{124:124,20:20,23:23}],231:[function(t,e,n){"use strict";t(106)("anchor",function(t){return function(e){return t(this,"a","name",e)}})},{106:106}],232:[function(t,e,n){"use strict";t(106)("big",function(t){return function(){return t(this,"big","","")}})},{106:106}],233:[function(t,e,n){"use strict";t(106)("blink",function(t){return function(){return t(this,"blink","","")}})},{106:106}],234:[function(t,e,n){"use strict";t(106)("bold",function(t){return function(){return t(this,"b","","")}})},{106:106}],235:[function(t,e,n){"use strict";var a=t(34),r=t(104)(!1);a(a.P,"String",{codePointAt:function(t){return r(this,t)}})},{104:104,34:34}],236:[function(t,e,n){"use strict";var a=t(34),r=t(116),i=t(105),o="endsWith",s=""[o];a(a.P+a.F*t(35)(o),"String",{endsWith:function(t){var e=i(this,t,o),n=arguments.length>1?arguments[1]:void 0,a=r(e.length),p=void 0===n?a:Math.min(r(n),a),u=t+"";return s?s.call(e,u,p):e.slice(p-u.length,p)===u}})},{105:105,116:116,34:34,35:35}],237:[function(t,e,n){"use strict";t(106)("fixed",function(t){return function(){return t(this,"tt","","")}})},{106:106}],238:[function(t,e,n){"use strict";t(106)("fontcolor",function(t){return function(e){return t(this,"font","color",e)}})},{106:106}],239:[function(t,e,n){"use strict";t(106)("fontsize",function(t){return function(e){return t(this,"font","size",e)}})},{106:106}],240:[function(t,e,n){var a=t(34),r=t(112),i=String.fromCharCode,o=String.fromCodePoint;a(a.S+a.F*(!!o&&1!=o.length),"String",{fromCodePoint:function(t){for(var e,n=[],a=arguments.length,o=0;a>o;){if(e=+arguments[o++],r(e,1114111)!==e)throw RangeError(e+" is not a valid code point");n.push(65536>e?i(e):i(((e-=65536)>>10)+55296,e%1024+56320))}return n.join("")}})},{112:112,34:34}],241:[function(t,e,n){"use strict";var a=t(34),r=t(105),i="includes";a(a.P+a.F*t(35)(i),"String",{includes:function(t){return!!~r(this,t,i).indexOf(t,arguments.length>1?arguments[1]:void 0)}})},{105:105,34:34,35:35}],242:[function(t,e,n){"use strict";t(106)("italics",function(t){return function(){return t(this,"i","","")}})},{106:106}],243:[function(t,e,n){"use strict";var a=t(104)(!0);t(56)(String,"String",function(t){this._t=t+"",this._i=0},function(){var t,e=this._t,n=this._i;return n>=e.length?{value:void 0,done:!0}:(t=a(e,n),this._i+=t.length,{value:t,done:!1})})},{104:104,56:56}],244:[function(t,e,n){"use strict";t(106)("link",function(t){return function(e){return t(this,"a","href",e)}})},{106:106}],245:[function(t,e,n){var a=t(34),r=t(115),i=t(116);a(a.S,"String",{raw:function(t){for(var e=r(t.raw),n=i(e.length),a=arguments.length,o=[],s=0;n>s;)o.push(e[s++]+""),a>s&&o.push(arguments[s]+"");return o.join("")}})},{115:115,116:116,34:34}],246:[function(t,e,n){var a=t(34);a(a.P,"String",{repeat:t(108)})},{108:108,34:34}],247:[function(t,e,n){"use strict";t(106)("small",function(t){return function(){return t(this,"small","","")}})},{106:106}],248:[function(t,e,n){"use strict";var a=t(34),r=t(116),i=t(105),o="startsWith",s=""[o];a(a.P+a.F*t(35)(o),"String",{startsWith:function(t){var e=i(this,t,o),n=r(Math.min(arguments.length>1?arguments[1]:void 0,e.length)),a=t+"";return s?s.call(e,a,n):e.slice(n,n+a.length)===a}})},{105:105,116:116,34:34,35:35}],249:[function(t,e,n){"use strict";t(106)("strike",function(t){return function(){return t(this,"strike","","")}})},{106:106}],250:[function(t,e,n){"use strict";t(106)("sub",function(t){return function(){return t(this,"sub","","")}})},{106:106}],251:[function(t,e,n){"use strict";t(106)("sup",function(t){return function(){return t(this,"sup","","")}})},{106:106}],252:[function(t,e,n){"use strict";t(109)("trim",function(t){return function(){return t(this,3)}})},{109:109}],253:[function(t,e,n){"use strict";var a=t(41),r=t(42),i=t(30),o=t(34),s=t(92),p=t(66).KEY,u=t(36),c=t(101),l=t(99),d=t(122),f=t(127),h=t(126),m=t(125),g=t(33),v=t(50),b=t(8),y=t(52),_=t(115),x=t(118),w=t(90),k=t(71),S=t(76),E=t(75),C=t(72),P=t(81),A=E.f,O=C.f,T=S.f,R=a.Symbol,M=a.JSON,L=M&&M.stringify,D="prototype",j=f("_hidden"),N=f("toPrimitive"),F={}.propertyIsEnumerable,I=c("symbol-registry"),B=c("symbols"),q=c("op-symbols"),U=Object[D],V="function"==typeof R,G=a.QObject,z=!G||!G[D]||!G[D].findChild,W=i&&u(function(){return 7!=k(O({},"a",{get:function(){return O(this,"a",{value:7}).a}})).a})?function(t,e,n){var a=A(U,e);a&&delete U[e],O(t,e,n),a&&t!==U&&O(U,e,a)}:O,H=function(t){var e=B[t]=k(R[D]);return e._k=t,e},K=V&&"symbol"==typeof R.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof R},Q=function(t,e,n){return t===U&&Q(q,e,n),b(t),e=x(e,!0),b(n),r(B,e)?(n.enumerable?(r(t,j)&&t[j][e]&&(t[j][e]=!1),n=k(n,{enumerable:w(0,!1)})):(r(t,j)||O(t,j,w(1,{})),t[j][e]=!0),W(t,e,n)):O(t,e,n)},Y=function(t,e){b(t);for(var n,a=g(e=_(e)),r=0,i=a.length;i>r;)Q(t,n=a[r++],e[n]);return t},$=function(t,e){return void 0===e?k(t):Y(k(t),e)},J=function(t){var e=F.call(this,t=x(t,!0));return this===U&&r(B,t)&&!r(q,t)?!1:e||!r(this,t)||!r(B,t)||r(this,j)&&this[j][t]?e:!0},X=function(t,e){if(t=_(t),e=x(e,!0),t!==U||!r(B,e)||r(q,e)){var n=A(t,e);return!n||!r(B,e)||r(t,j)&&t[j][e]||(n.enumerable=!0),n}},Z=function(t){for(var e,n=T(_(t)),a=[],i=0;n.length>i;)r(B,e=n[i++])||e==j||e==p||a.push(e);return a},tt=function(t){for(var e,n=t===U,a=T(n?q:_(t)),i=[],o=0;a.length>o;)r(B,e=a[o++])&&(n?r(U,e):!0)&&i.push(B[e]);return i};V||(R=function(){if(this instanceof R)throw TypeError("Symbol is not a constructor!");var t=d(arguments.length>0?arguments[0]:void 0),e=function(n){this===U&&e.call(q,n),r(this,j)&&r(this[j],t)&&(this[j][t]=!1),W(this,t,w(1,n))};return i&&z&&W(U,t,{configurable:!0,set:e}),H(t)},s(R[D],"toString",function(){return this._k}),E.f=X,C.f=Q,t(77).f=S.f=Z,t(82).f=J,t(78).f=tt,i&&!t(60)&&s(U,"propertyIsEnumerable",J,!0),h.f=function(t){return H(f(t))}),o(o.G+o.W+o.F*!V,{Symbol:R});for(var et="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),nt=0;et.length>nt;)f(et[nt++]);for(var at=P(f.store),rt=0;at.length>rt;)m(at[rt++]);o(o.S+o.F*!V,"Symbol",{"for":function(t){return r(I,t+="")?I[t]:I[t]=R(t)},keyFor:function(t){if(!K(t))throw TypeError(t+" is not a symbol!");for(var e in I)if(I[e]===t)return e},useSetter:function(){z=!0},useSimple:function(){z=!1}}),o(o.S+o.F*!V,"Object",{create:$,defineProperty:Q,defineProperties:Y,getOwnPropertyDescriptor:X,getOwnPropertyNames:Z,getOwnPropertySymbols:tt}),M&&o(o.S+o.F*(!V||u(function(){var t=R();return"[null]"!=L([t])||"{}"!=L({a:t})||"{}"!=L(Object(t))})),"JSON",{stringify:function(t){for(var e,n,a=[t],r=1;arguments.length>r;)a.push(arguments[r++]);return n=e=a[1],!y(e)&&void 0===t||K(t)?void 0:(v(e)||(e=function(t,e){return"function"==typeof n&&(e=n.call(this,t,e)),K(e)?void 0:e}),a[1]=e,L.apply(M,a))}}),R[D][N]||t(43)(R[D],N,R[D].valueOf),l(R,"Symbol"),l(Math,"Math",!0),l(a.JSON,"JSON",!0)},{101:101,115:115,118:118,122:122,125:125,126:126,127:127,30:30,33:33,34:34,36:36,41:41,42:42,43:43,50:50,52:52,60:60,66:66,71:71,72:72,75:75,76:76,77:77,78:78,8:8,81:81,82:82,90:90,92:92,99:99}],254:[function(t,e,n){"use strict";var a=t(34),r=t(121),i=t(120),o=t(8),s=t(112),p=t(116),u=t(52),c=t(41).ArrayBuffer,l=t(102),d=i.ArrayBuffer,f=i.DataView,h=r.ABV&&c.isView,m=d.prototype.slice,g=r.VIEW,v="ArrayBuffer";a(a.G+a.W+a.F*(c!==d),{ArrayBuffer:d}),a(a.S+a.F*!r.CONSTR,v,{isView:function(t){return h&&h(t)||u(t)&&g in t}}),a(a.P+a.U+a.F*t(36)(function(){return!new d(2).slice(1,void 0).byteLength}),v,{slice:function(t,e){if(void 0!==m&&void 0===e)return m.call(o(this),t);for(var n=o(this).byteLength,a=s(t,n),r=s(void 0===e?n:e,n),i=new(l(this,d))(p(r-a)),u=new f(this),c=new f(i),h=0;r>a;)c.setUint8(h++,u.getUint8(a++));return i}}),t(98)(v)},{102:102,112:112,116:116,120:120,121:121,34:34,36:36,41:41,52:52,8:8,98:98}],255:[function(t,e,n){var a=t(34);a(a.G+a.W+a.F*!t(121).ABV,{DataView:t(120).DataView})},{120:120,121:121,34:34}],256:[function(t,e,n){t(119)("Float32",4,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],257:[function(t,e,n){t(119)("Float64",8,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],258:[function(t,e,n){t(119)("Int16",2,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],259:[function(t,e,n){t(119)("Int32",4,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],260:[function(t,e,n){t(119)("Int8",1,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],261:[function(t,e,n){t(119)("Uint16",2,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],262:[function(t,e,n){t(119)("Uint32",4,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],263:[function(t,e,n){t(119)("Uint8",1,function(t){return function(e,n,a){return t(this,e,n,a)}})},{119:119}],264:[function(t,e,n){t(119)("Uint8",1,function(t){return function(e,n,a){return t(this,e,n,a)}},!0)},{119:119}],265:[function(t,e,n){"use strict";var a,r=t(13)(0),i=t(92),o=t(66),s=t(70),p=t(22),u=t(52),c=t(36),l=t(124),d="WeakMap",f=o.getWeak,h=Object.isExtensible,m=p.ufstore,g={},v=function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},b={get:function(t){if(u(t)){var e=f(t);return e===!0?m(l(this,d)).get(t):e?e[this._i]:void 0}},set:function(t,e){return p.def(l(this,d),t,e)}},y=e.exports=t(23)(d,v,b,p,!0,!0);c(function(){return 7!=(new y).set((Object.freeze||Object)(g),7).get(g)})&&(a=p.getConstructor(v,d),s(a.prototype,b),o.NEED=!0,r(["delete","has","get","set"],function(t){var e=y.prototype,n=e[t];i(e,t,function(e,r){if(u(e)&&!h(e)){this._f||(this._f=new a);var i=this._f[t](e,r);return"set"==t?this:i}return n.call(this,e,r)})}))},{124:124,13:13,22:22,23:23,36:36,52:52,66:66,70:70,92:92}],266:[function(t,e,n){"use strict";var a=t(22),r=t(124),i="WeakSet";t(23)(i,function(t){return function(){return t(this,arguments.length>0?arguments[0]:void 0)}},{add:function(t){return a.def(r(this,i),t,!0)}},a,!1,!0)},{124:124,22:22,23:23}],267:[function(t,e,n){"use strict";var a=t(34),r=t(39),i=t(117),o=t(116),s=t(4),p=t(16);a(a.P,"Array",{flatMap:function(t){var e,n,a=i(this);return s(t),e=o(a.length),n=p(a,0),r(n,a,a,e,0,1,t,arguments[1]),n}}),t(6)("flatMap")},{116:116,117:117,16:16,34:34,39:39,4:4,6:6}],268:[function(t,e,n){"use strict";var a=t(34),r=t(39),i=t(117),o=t(116),s=t(114),p=t(16);a(a.P,"Array",{flatten:function(){var t=arguments[0],e=i(this),n=o(e.length),a=p(e,0);return r(a,e,e,n,0,void 0===t?1:s(t)),a}}),t(6)("flatten")},{114:114,116:116,117:117,16:16,34:34,39:39,6:6}],269:[function(t,e,n){"use strict";var a=t(34),r=t(12)(!0);a(a.P,"Array",{includes:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0)}}),t(6)("includes")},{12:12,34:34,6:6}],270:[function(t,e,n){var a=t(34),r=t(68)(),i=t(41).process,o="process"==t(19)(i);a(a.G,{asap:function(t){var e=o&&i.domain;r(e?e.bind(t):t)}})},{19:19,34:34,41:41,68:68}],271:[function(t,e,n){var a=t(34),r=t(19);a(a.S,"Error",{isError:function(t){return"Error"===r(t)}})},{19:19,34:34}],272:[function(t,e,n){var a=t(34);a(a.G,{global:t(41)})},{34:34,41:41}],273:[function(t,e,n){t(95)("Map")},{95:95}],274:[function(t,e,n){t(96)("Map")},{96:96}],275:[function(t,e,n){var a=t(34);a(a.P+a.R,"Map",{toJSON:t(21)("Map")})},{21:21,34:34}],276:[function(t,e,n){var a=t(34);a(a.S,"Math",{clamp:function(t,e,n){return Math.min(n,Math.max(e,t))}})},{34:34}],277:[function(t,e,n){var a=t(34);a(a.S,"Math",{DEG_PER_RAD:Math.PI/180})},{34:34}],278:[function(t,e,n){var a=t(34),r=180/Math.PI;a(a.S,"Math",{degrees:function(t){return t*r}})},{34:34}],279:[function(t,e,n){var a=t(34),r=t(64),i=t(62);a(a.S,"Math",{fscale:function(t,e,n,a,o){return i(r(t,e,n,a,o))}})},{34:34,62:62,64:64}],280:[function(t,e,n){var a=t(34);a(a.S,"Math",{iaddh:function(t,e,n,a){var r=t>>>0,i=e>>>0,o=n>>>0;return i+(a>>>0)+((r&o|(r|o)&~(r+o>>>0))>>>31)|0}})},{34:34}],281:[function(t,e,n){var a=t(34);a(a.S,"Math",{imulh:function(t,e){var n=65535,a=+t,r=+e,i=a&n,o=r&n,s=a>>16,p=r>>16,u=(s*o>>>0)+(i*o>>>16);return s*p+(u>>16)+((i*p>>>0)+(u&n)>>16)}})},{34:34}],282:[function(t,e,n){var a=t(34);a(a.S,"Math",{isubh:function(t,e,n,a){var r=t>>>0,i=e>>>0,o=n>>>0;return i-(a>>>0)-((~r&o|~(r^o)&r-o>>>0)>>>31)|0}})},{34:34}],283:[function(t,e,n){var a=t(34);a(a.S,"Math",{RAD_PER_DEG:180/Math.PI})},{34:34}],284:[function(t,e,n){var a=t(34),r=Math.PI/180;a(a.S,"Math",{radians:function(t){return t*r}})},{34:34}],285:[function(t,e,n){var a=t(34);a(a.S,"Math",{scale:t(64)})},{34:34,64:64}],286:[function(t,e,n){var a=t(34);a(a.S,"Math",{signbit:function(t){return(t=+t)!=t?t:0==t?1/t==1/0:t>0}})},{34:34}],287:[function(t,e,n){var a=t(34);a(a.S,"Math",{umulh:function(t,e){var n=65535,a=+t,r=+e,i=a&n,o=r&n,s=a>>>16,p=r>>>16,u=(s*o>>>0)+(i*o>>>16);return s*p+(u>>>16)+((i*p>>>0)+(u&n)>>>16)}})},{34:34}],288:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(4),o=t(72);t(30)&&a(a.P+t(74),"Object",{__defineGetter__:function(t,e){o.f(r(this),t,{get:i(e),enumerable:!0,configurable:!0})}})},{117:117,30:30,34:34,4:4,72:72,74:74}],289:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(4),o=t(72);t(30)&&a(a.P+t(74),"Object",{__defineSetter__:function(t,e){o.f(r(this),t,{set:i(e),enumerable:!0,configurable:!0})}})},{117:117,30:30,34:34,4:4,72:72,74:74}],290:[function(t,e,n){var a=t(34),r=t(84)(!0);a(a.S,"Object",{entries:function(t){return r(t)}})},{34:34,84:84}],291:[function(t,e,n){var a=t(34),r=t(85),i=t(115),o=t(75),s=t(25);a(a.S,"Object",{getOwnPropertyDescriptors:function(t){for(var e,n,a=i(t),p=o.f,u=r(a),c={},l=0;u.length>l;)n=p(a,e=u[l++]),void 0!==n&&s(c,e,n);return c}})},{115:115,25:25,34:34,75:75,85:85}],292:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(118),o=t(79),s=t(75).f;t(30)&&a(a.P+t(74),"Object",{__lookupGetter__:function(t){var e,n=r(this),a=i(t,!0);do if(e=s(n,a))return e.get;while(n=o(n))}})},{117:117,118:118,30:30,34:34,74:74,75:75,79:79}],293:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(118),o=t(79),s=t(75).f;t(30)&&a(a.P+t(74),"Object",{__lookupSetter__:function(t){var e,n=r(this),a=i(t,!0);do if(e=s(n,a))return e.set;while(n=o(n))}})},{117:117,118:118,30:30,34:34,74:74,75:75,79:79}],294:[function(t,e,n){var a=t(34),r=t(84)(!1);a(a.S,"Object",{values:function(t){return r(t)}})},{34:34,84:84}],295:[function(t,e,n){"use strict";var a=t(34),r=t(41),i=t(24),o=t(68)(),s=t(127)("observable"),p=t(4),u=t(8),c=t(7),l=t(91),d=t(43),f=t(40),h=f.RETURN,m=function(t){return null==t?void 0:p(t)},g=function(t){var e=t._c;e&&(t._c=void 0,e())},v=function(t){return void 0===t._o},b=function(t){v(t)||(t._o=void 0,g(t))},y=function(t,e){u(t),this._c=void 0,this._o=t,t=new _(this);try{var n=e(t),a=n;null!=n&&("function"==typeof n.unsubscribe?n=function(){a.unsubscribe()}:p(n),this._c=n)}catch(r){return void t.error(r)}v(this)&&g(this)};y.prototype=l({},{unsubscribe:function(){b(this)}});var _=function(t){this._s=t};_.prototype=l({},{next:function(t){var e=this._s;if(!v(e)){var n=e._o;try{var a=m(n.next);if(a)return a.call(n,t)}catch(r){try{b(e)}finally{throw r}}}},error:function(t){var e=this._s;if(v(e))throw t;var n=e._o;e._o=void 0;try{var a=m(n.error);if(!a)throw t;t=a.call(n,t)}catch(r){try{g(e)}finally{throw r}}return g(e),t},complete:function(t){var e=this._s;if(!v(e)){var n=e._o;e._o=void 0;try{var a=m(n.complete);t=a?a.call(n,t):void 0}catch(r){try{g(e)}finally{throw r}}return g(e),t}}});var x=function(t){c(this,x,"Observable","_f")._f=p(t)};l(x.prototype,{subscribe:function(t){return new y(t,this._f)},forEach:function(t){var e=this;return new(i.Promise||r.Promise)(function(n,a){p(t);var r=e.subscribe({next:function(e){try{return t(e)}catch(n){a(n),r.unsubscribe()}},error:a,complete:n})})}}),l(x,{from:function(t){var e="function"==typeof this?this:x,n=m(u(t)[s]);if(n){var a=u(n.call(t));return a.constructor===e?a:new e(function(t){return a.subscribe(t)})}return new e(function(e){var n=!1;return o(function(){if(!n){try{if(f(t,!1,function(t){return e.next(t),n?h:void 0})===h)return}catch(a){if(n)throw a;return void e.error(a)}e.complete()}}),function(){n=!0}})},of:function(){for(var t=0,e=arguments.length,n=Array(e);e>t;)n[t]=arguments[t++];return new("function"==typeof this?this:x)(function(t){var e=!1;return o(function(){if(!e){for(var a=0;a1?arguments[1]:void 0,!1)}})},{107:107,123:123,34:34}],313:[function(t,e,n){"use strict";var a=t(34),r=t(107),i=t(123);a(a.P+a.F*/Version\/10\.\d+(\.\d+)? Safari\//.test(i),"String",{padStart:function(t){return r(this,t,arguments.length>1?arguments[1]:void 0,!0)}})},{107:107,123:123,34:34}],314:[function(t,e,n){"use strict";t(109)("trimLeft",function(t){return function(){return t(this,1)}},"trimStart")},{109:109}],315:[function(t,e,n){"use strict";t(109)("trimRight",function(t){return function(){return t(this,2)}},"trimEnd")},{109:109}],316:[function(t,e,n){t(125)("asyncIterator")},{125:125}],317:[function(t,e,n){t(125)("observable")},{125:125}],318:[function(t,e,n){var a=t(34);a(a.S,"System",{global:t(41) -})},{34:34,41:41}],319:[function(t,e,n){t(95)("WeakMap")},{95:95}],320:[function(t,e,n){t(96)("WeakMap")},{96:96}],321:[function(t,e,n){t(95)("WeakSet")},{95:95}],322:[function(t,e,n){t(96)("WeakSet")},{96:96}],323:[function(t,e,n){for(var a=t(140),r=t(81),i=t(92),o=t(41),s=t(43),p=t(59),u=t(127),c=u("iterator"),l=u("toStringTag"),d=p.Array,f={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},h=r(f),m=0;m2,r=a?o.call(arguments,2):!1;return t(a?function(){("function"==typeof e?e:Function(e)).apply(this,r)}:e,n)}};r(r.G+r.B+r.F*s,{setTimeout:p(a.setTimeout),setInterval:p(a.setInterval)})},{123:123,34:34,41:41}],326:[function(t,e,n){t(253),t(190),t(192),t(191),t(194),t(196),t(201),t(195),t(193),t(203),t(202),t(198),t(199),t(197),t(189),t(200),t(204),t(205),t(156),t(158),t(157),t(207),t(206),t(177),t(187),t(188),t(178),t(179),t(180),t(181),t(182),t(183),t(184),t(185),t(186),t(160),t(161),t(162),t(163),t(164),t(165),t(166),t(167),t(168),t(169),t(170),t(171),t(172),t(173),t(174),t(175),t(176),t(240),t(245),t(252),t(243),t(235),t(236),t(241),t(246),t(248),t(231),t(232),t(233),t(234),t(237),t(238),t(239),t(242),t(244),t(247),t(249),t(250),t(251),t(151),t(153),t(152),t(155),t(154),t(139),t(137),t(144),t(141),t(147),t(149),t(136),t(143),t(133),t(148),t(131),t(146),t(145),t(138),t(142),t(130),t(132),t(135),t(134),t(150),t(140),t(223),t(229),t(224),t(225),t(226),t(227),t(228),t(208),t(159),t(230),t(265),t(266),t(254),t(255),t(260),t(263),t(264),t(258),t(261),t(259),t(262),t(256),t(257),t(209),t(210),t(211),t(212),t(213),t(216),t(214),t(215),t(217),t(218),t(219),t(220),t(222),t(221),t(269),t(267),t(268),t(310),t(313),t(312),t(314),t(315),t(311),t(316),t(317),t(291),t(294),t(290),t(288),t(289),t(292),t(293),t(275),t(309),t(274),t(308),t(320),t(322),t(273),t(307),t(319),t(321),t(272),t(318),t(271),t(276),t(277),t(278),t(279),t(280),t(282),t(281),t(283),t(284),t(285),t(287),t(286),t(296),t(297),t(298),t(299),t(301),t(300),t(303),t(302),t(304),t(305),t(306),t(270),t(295),t(325),t(324),t(323),e.exports=t(24)},{130:130,131:131,132:132,133:133,134:134,135:135,136:136,137:137,138:138,139:139,140:140,141:141,142:142,143:143,144:144,145:145,146:146,147:147,148:148,149:149,150:150,151:151,152:152,153:153,154:154,155:155,156:156,157:157,158:158,159:159,160:160,161:161,162:162,163:163,164:164,165:165,166:166,167:167,168:168,169:169,170:170,171:171,172:172,173:173,174:174,175:175,176:176,177:177,178:178,179:179,180:180,181:181,182:182,183:183,184:184,185:185,186:186,187:187,188:188,189:189,190:190,191:191,192:192,193:193,194:194,195:195,196:196,197:197,198:198,199:199,200:200,201:201,202:202,203:203,204:204,205:205,206:206,207:207,208:208,209:209,210:210,211:211,212:212,213:213,214:214,215:215,216:216,217:217,218:218,219:219,220:220,221:221,222:222,223:223,224:224,225:225,226:226,227:227,228:228,229:229,230:230,231:231,232:232,233:233,234:234,235:235,236:236,237:237,238:238,239:239,24:24,240:240,241:241,242:242,243:243,244:244,245:245,246:246,247:247,248:248,249:249,250:250,251:251,252:252,253:253,254:254,255:255,256:256,257:257,258:258,259:259,260:260,261:261,262:262,263:263,264:264,265:265,266:266,267:267,268:268,269:269,270:270,271:271,272:272,273:273,274:274,275:275,276:276,277:277,278:278,279:279,280:280,281:281,282:282,283:283,284:284,285:285,286:286,287:287,288:288,289:289,290:290,291:291,292:292,293:293,294:294,295:295,296:296,297:297,298:298,299:299,300:300,301:301,302:302,303:303,304:304,305:305,306:306,307:307,308:308,309:309,310:310,311:311,312:312,313:313,314:314,315:315,316:316,317:317,318:318,319:319,320:320,321:321,322:322,323:323,324:324,325:325}],327:[function(t,e,n){!function(t){"use strict";function e(){return c.createDocumentFragment()}function n(t){return c.createElement(t)}function a(t){if(1===t.length)return r(t[0]);for(var n=e(),a=B.call(t),i=0;i-1}}([].indexOf||function(t){for(q=this.length;q--&&this[q]!==t;);return q}),item:function(t){return this[t]||null},remove:function(){for(var t,e=0;e=p?e(i):document.fonts.load(u(i,i.family),s).then(function(e){1<=e.length?t(i):setTimeout(d,25)},function(){e(i)})};d()}else n(function(){function n(){var e;(e=-1!=g&&-1!=v||-1!=g&&-1!=b||-1!=v&&-1!=b)&&((e=g!=v&&g!=b&&v!=b)||(null===l&&(e=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent),l=!!e&&(536>parseInt(e[1],10)||536===parseInt(e[1],10)&&11>=parseInt(e[2],10))),e=l&&(g==y&&v==y&&b==y||g==_&&v==_&&b==_||g==x&&v==x&&b==x)),e=!e),e&&(null!==w.parentNode&&w.parentNode.removeChild(w),clearTimeout(k),t(i))}function d(){if((new Date).getTime()-c>=p)null!==w.parentNode&&w.parentNode.removeChild(w),e(i);else{var t=document.hidden;(!0===t||void 0===t)&&(g=f.a.offsetWidth,v=h.a.offsetWidth,b=m.a.offsetWidth,n()),k=setTimeout(d,50)}}var f=new a(s),h=new a(s),m=new a(s),g=-1,v=-1,b=-1,y=-1,_=-1,x=-1,w=document.createElement("div"),k=0;w.dir="ltr",r(f,u(i,"sans-serif")),r(h,u(i,"serif")),r(m,u(i,"monospace")),w.appendChild(f.a),w.appendChild(h.a),w.appendChild(m.a),document.body.appendChild(w),y=f.a.offsetWidth,_=h.a.offsetWidth,x=m.a.offsetWidth,d(),o(f,function(t){g=t,n()}),r(f,u(i,'"'+i.family+'",sans-serif')),o(h,function(t){v=t,n()}),r(h,u(i,'"'+i.family+'",serif')),o(m,function(t){b=t,n()}),r(m,u(i,'"'+i.family+'",monospace'))})})},window.FontFaceObserver=s,window.FontFaceObserver.prototype.check=s.prototype.a,void 0!==e&&(e.exports=window.FontFaceObserver)}()},{}],330:[function(t,e,n){!function(t,n){function a(t,e){var n=t.createElement("p"),a=t.getElementsByTagName("head")[0]||t.documentElement;return n.innerHTML="x",a.insertBefore(n.lastChild,a.firstChild)}function r(){var t=_.elements;return"string"==typeof t?t.split(" "):t}function i(t,e){var n=_.elements;"string"!=typeof n&&(n=n.join(" ")),"string"!=typeof t&&(t=t.join(" ")),_.elements=n+" "+t,c(e)}function o(t){var e=y[t[v]];return e||(e={},b++,t[v]=b,y[b]=e),e}function s(t,e,a){if(e||(e=n),d)return e.createElement(t);a||(a=o(e));var r;return r=a.cache[t]?a.cache[t].cloneNode():g.test(t)?(a.cache[t]=a.createElem(t)).cloneNode():a.createElem(t),!r.canHaveChildren||m.test(t)||r.tagUrn?r:a.frag.appendChild(r)}function p(t,e){if(t||(t=n),d)return t.createDocumentFragment();e=e||o(t);for(var a=e.frag.cloneNode(),i=0,s=r(),p=s.length;p>i;i++)a.createElement(s[i]);return a}function u(t,e){e.cache||(e.cache={},e.createElem=t.createElement,e.createFrag=t.createDocumentFragment,e.frag=e.createFrag()),t.createElement=function(n){return _.shivMethods?s(n,t,e):e.createElem(n)},t.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+r().join().replace(/[\w\-:]+/g,function(t){return e.createElem(t),e.frag.createElement(t),'c("'+t+'")'})+");return n}")(_,e.frag)}function c(t){t||(t=n);var e=o(t);return!_.shivCSS||l||e.hasCSS||(e.hasCSS=!!a(t,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),d||u(t,e),t}var l,d,f="3.7.3-pre",h=t.html5||{},m=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,g=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",b=0,y={};!function(){try{var t=n.createElement("a");t.innerHTML="",l="hidden"in t,d=1==t.childNodes.length||function(){n.createElement("a");var t=n.createDocumentFragment();return void 0===t.cloneNode||void 0===t.createDocumentFragment||void 0===t.createElement}()}catch(e){l=!0,d=!0}}();var _={elements:h.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:f,shivCSS:h.shivCSS!==!1,supportsUnknownElements:d,shivMethods:h.shivMethods!==!1,type:"default",shivDocument:c,createElement:s,createDocumentFragment:p,addElements:i};t.html5=_,c(n),"object"==typeof e&&e.exports&&(e.exports=_)}("undefined"!=typeof window?window:this,document)},{}],331:[function(t,e,n){(function(t){(function(t){!function(t){function e(t,e,n,a){for(var i,o,s=n.slice(),p=r(e,t),u=0,c=s.length;c>u&&(i=s[u],"object"==typeof i?"function"==typeof i.handleEvent&&i.handleEvent(p):i.call(t,p),!p.stoppedImmediatePropagation);u++);return o=!p.stoppedPropagation,a&&o&&t.parentNode?t.parentNode.dispatchEvent(p):!p.defaultPrevented}function n(t,e){return{configurable:!0,get:t,set:e}}function a(t,e,a){var r=y(e||t,a);v(t,"textContent",n(function(){return r.get.call(this)},function(t){r.set.call(this,t)}))}function r(t,e){return t.currentTarget=e,t.eventPhase=t.target===t.currentTarget?2:3,t}function i(t,e){for(var n=t.length;n--&&t[n]!==e;);return n}function o(){if("BR"===this.tagName)return"\n";for(var t=this.firstChild,e=[];t;)8!==t.nodeType&&7!==t.nodeType&&e.push(t.textContent),t=t.nextSibling;return e.join("")}function s(t){var e=document.createEvent("Event");e.initEvent("input",!0,!0),(t.srcElement||t.fromElement||document).dispatchEvent(e)}function p(t){!f&&S.test(document.readyState)&&(f=!f,document.detachEvent(h,p),t=document.createEvent("Event"),t.initEvent(m,!0,!0),document.dispatchEvent(t))}function u(t){return function(){return P[t]||document.body&&document.body[t]||0}}function c(t){for(var e;e=this.lastChild;)this.removeChild(e);null!=t&&this.appendChild(document.createTextNode(t))}function l(e,n){return n||(n=t.event),n.target||(n.target=n.srcElement||n.fromElement||document),n.timeStamp||(n.timeStamp=(new Date).getTime()),n}if(!document.createEvent){var d=!0,f=!1,h="onreadystatechange",m="DOMContentLoaded",g="__IE8__"+Math.random(),v=Object.defineProperty||function(t,e,n){t[e]=n.value},b=Object.defineProperties||function(e,n){for(var a in n)if(_.call(n,a))try{v(e,a,n[a])}catch(r){t.console&&console.log(a+" failed on object:",e,r.message)}},y=Object.getOwnPropertyDescriptor,_=Object.prototype.hasOwnProperty,x=t.Element.prototype,w=t.Text.prototype,k=/^[a-z]+$/,S=/loaded|complete/,E={},C=document.createElement("div"),P=document.documentElement,A=P.removeAttribute,O=P.setAttribute,T=function(t){return{enumerable:!0,writable:!0,configurable:!0,value:t}};a(t.HTMLCommentElement.prototype,x,"nodeValue"),a(t.HTMLScriptElement.prototype,null,"text"),a(w,null,"nodeValue"),a(t.HTMLTitleElement.prototype,null,"text"),v(t.HTMLStyleElement.prototype,"textContent",function(t){return n(function(){return t.get.call(this.styleSheet)},function(e){t.set.call(this.styleSheet,e)})}(y(t.CSSStyleSheet.prototype,"cssText")));var R=/\b\s*alpha\s*\(\s*opacity\s*=\s*(\d+)\s*\)/;v(t.CSSStyleDeclaration.prototype,"opacity",{get:function(){var t=this.filter.match(R);return t?""+t[1]/100:""},set:function(t){this.zoom=1;var e=!1;t=1>t?" alpha(opacity="+Math.round(100*t)+")":"",this.filter=this.filter.replace(R,function(){return e=!0,t}),!e&&t&&(this.filter+=t)}}),b(x,{textContent:{get:o,set:c},firstElementChild:{get:function(){for(var t=this.childNodes||[],e=0,n=t.length;n>e;e++)if(1==t[e].nodeType)return t[e]}},lastElementChild:{get:function(){for(var t=this.childNodes||[],e=t.length;e--;)if(1==t[e].nodeType)return t[e]}},oninput:{get:function(){return this._oninput||null},set:function(t){this._oninput&&(this.removeEventListener("input",this._oninput),this._oninput=t,t&&this.addEventListener("input",t))}},previousElementSibling:{get:function(){for(var t=this.previousSibling;t&&1!=t.nodeType;)t=t.previousSibling;return t}},nextElementSibling:{get:function(){for(var t=this.nextSibling;t&&1!=t.nodeType;)t=t.nextSibling;return t}},childElementCount:{get:function(){for(var t=0,e=this.childNodes||[],n=e.length;n--;t+=1==e[n].nodeType);return t}},addEventListener:T(function(t,n,a){if("function"==typeof n||"object"==typeof n){var r,o,p=this,u="on"+t,c=p[g]||v(p,g,{value:{}})[g],d=c[u]||(c[u]={}),f=d.h||(d.h=[]);if(!_.call(d,"w")){if(d.w=function(t){return t[g]||e(p,l(p,t),f,!1)},!_.call(E,u))if(k.test(t)){try{r=document.createEventObject(),r[g]=!0,9!=p.nodeType&&(null==p.parentNode&&C.appendChild(p),(o=p.getAttribute(u))&&A.call(p,u)),p.fireEvent(u,r),E[u]=!0}catch(h){for(E[u]=!1;C.hasChildNodes();)C.removeChild(C.firstChild)}null!=o&&O.call(p,u,o)}else E[u]=!1;(d.n=E[u])&&p.attachEvent(u,d.w)}i(f,n)<0&&f[a?"unshift":"push"](n),"input"===t&&p.attachEvent("onkeyup",s)}}),dispatchEvent:T(function(t){var n,a=this,r="on"+t.type,i=a[g],o=i&&i[r],s=!!o;return t.target||(t.target=a),s?o.n?a.fireEvent(r,t):e(a,t,o.h,!0):(n=a.parentNode)?n.dispatchEvent(t):!0,!t.defaultPrevented}),removeEventListener:T(function(t,e,n){if("function"==typeof e||"object"==typeof e){var a=this,r="on"+t,o=a[g],s=o&&o[r],p=s&&s.h,u=p?i(p,e):-1;u>-1&&p.splice(u,1)}})}),b(w,{addEventListener:T(x.addEventListener),dispatchEvent:T(x.dispatchEvent),removeEventListener:T(x.removeEventListener)}),b(t.XMLHttpRequest.prototype,{addEventListener:T(function(t,e,n){var a=this,r="on"+t,o=a[g]||v(a,g,{value:{}})[g],s=o[r]||(o[r]={}),p=s.h||(s.h=[]);i(p,e)<0&&(a[r]||(a[r]=function(){var e=document.createEvent("Event");e.initEvent(t,!0,!0),a.dispatchEvent(e)}),p[n?"unshift":"push"](e))}),dispatchEvent:T(function(t){var n=this,a="on"+t.type,r=n[g],i=r&&r[a],o=!!i;return o&&(i.n?n.fireEvent(a,t):e(n,t,i.h,!0))}),removeEventListener:T(x.removeEventListener)});var M=y(Event.prototype,"button").get;b(t.Event.prototype,{bubbles:T(!0),cancelable:T(!0),preventDefault:T(function(){this.cancelable&&(this.returnValue=!1)}),stopPropagation:T(function(){this.stoppedPropagation=!0,this.cancelBubble=!0}),stopImmediatePropagation:T(function(){this.stoppedImmediatePropagation=!0,this.stopPropagation()}),initEvent:T(function(t,e,n){this.type=t,this.bubbles=!!e,this.cancelable=!!n,this.bubbles||this.stopPropagation()}),pageX:{get:function(){return this._pageX||(this._pageX=this.clientX+t.scrollX-(P.clientLeft||0))}},pageY:{get:function(){return this._pageY||(this._pageY=this.clientY+t.scrollY-(P.clientTop||0))}},which:{get:function(){return this.keyCode?this.keyCode:isNaN(this.button)?void 0:this.button+1}},charCode:{get:function(){return this.keyCode&&"keypress"==this.type?this.keyCode:0}},buttons:{get:function(){return M.call(this)}},button:{get:function(){var t=this.buttons;return 1&t?0:2&t?2:4&t?1:void 0}},defaultPrevented:{get:function(){var t,e=this.returnValue;return!(e===t||e)}},relatedTarget:{get:function(){var t=this.type;return"mouseover"===t?this.fromElement:"mouseout"===t?this.toElement:null}}}),b(t.HTMLDocument.prototype,{defaultView:{get:function(){return this.parentWindow}},textContent:{get:function(){return 11===this.nodeType?o.call(this):null},set:function(t){11===this.nodeType&&c.call(this,t)}},addEventListener:T(function(e,n,a){var r=this;x.addEventListener.call(r,e,n,a),d&&e===m&&!S.test(r.readyState)&&(d=!1,r.attachEvent(h,p),t==top&&!function i(t){try{r.documentElement.doScroll("left"),p()}catch(e){setTimeout(i,50)}}())}),dispatchEvent:T(x.dispatchEvent),removeEventListener:T(x.removeEventListener),createEvent:T(function(t){var e;if("Event"!==t)throw Error("unsupported "+t);return e=document.createEventObject(),e.timeStamp=(new Date).getTime(),e})}),b(t.Window.prototype,{getComputedStyle:T(function(){function t(t){this._=t}function e(){}var n=/^(?:[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|))(?!px)[a-z%]+$/,a=/^(top|right|bottom|left)$/,r=/\-([a-z])/g,i=function(t,e){return e.toUpperCase()};return t.prototype.getPropertyValue=function(t){var e,o,s,p=this._,u=p.style,c=p.currentStyle,l=p.runtimeStyle;return"opacity"==t?u.opacity||"1":(t=("float"===t?"style-float":t).replace(r,i),e=c?c[t]:u[t],n.test(e)&&!a.test(t)&&(o=u.left,s=l&&l.left,s&&(l.left=c.left),u.left="fontSize"===t?"1em":e,e=u.pixelLeft+"px",u.left=o,s&&(l.left=s)),null==e?e:e+""||"auto")},e.prototype.getPropertyValue=function(){return null},function(n,a){return a?new e(n):new t(n)}}()),addEventListener:T(function(n,a,r){var o,s=t,p="on"+n;s[p]||(s[p]=function(t){return e(s,l(s,t),o,!1)&&void 0}),o=s[p][g]||(s[p][g]=[]),i(o,a)<0&&o[r?"unshift":"push"](a)}),dispatchEvent:T(function(e){var n=t["on"+e.type];return n?n.call(t,e)!==!1&&!e.defaultPrevented:!0}),removeEventListener:T(function(e,n,a){var r="on"+e,o=(t[r]||Object)[g],s=o?i(o,n):-1;s>-1&&o.splice(s,1)}),pageXOffset:{get:u("scrollLeft")},pageYOffset:{get:u("scrollTop")},scrollX:{get:u("scrollLeft")},scrollY:{get:u("scrollTop")},innerWidth:{get:u("clientWidth")},innerHeight:{get:u("clientHeight")}}),t.HTMLElement=t.Element,function(t,e,n){for(n=0;na;a++)e.appendChild(n[a].cloneNode(!0));return e},n.cloneRange=function(){var t=new e;return t._start=this._start,t._end=this._end,t},n.deleteContents=function(){for(var e=this._start.parentNode,n=t(this._start,this._end),a=0,r=n.length;r>a;a++)e.removeChild(n[a])},n.extractContents=function(){for(var e=this._start.ownerDocument.createDocumentFragment(),n=t(this._start,this._end),a=0,r=n.length;r>a;a++)e.appendChild(n[a]);return e},n.setEndAfter=function(t){this._end=t},n.setEndBefore=function(t){this._end=t.previousSibling},n.setStartAfter=function(t){this._start=t.nextSibling},n.setStartBefore=function(t){this._start=t}}}()}}(this.window||t)}).call(this,void 0!==t?t:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],332:[function(t,e,n){"use strict";function a(t){return t&&t.__esModule?t:{"default":t}}function r(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e=s)return(0,p["default"])({points:n});for(var l=1;s-1>=l;l++)i.push((0,u.times)(a,(0,u.minus)(n[l],n[l-1])));for(var d=[(0,u.plus)(n[0],c(i[0],i[1]))],l=1;s-2>=l;l++)d.push((0,u.minus)(n[l],(0,u.average)([i[l],i[l-1]])));d.push((0,u.minus)(n[s-1],c(i[s-2],i[s-3])));var f=d[0],h=d[1],m=n[0],g=n[1],v=(e=(0,o["default"])()).moveto.apply(e,r(m)).curveto(f[0],f[1],h[0],h[1],g[0],g[1]);return{path:(0,u.range)(2,s).reduce(function(t,e){var a=d[e],r=n[e];return t.smoothcurveto(a[0],a[1],r[0],r[1])},v),centroid:(0,u.average)(n)}},e.exports=n["default"]},{335:335,336:336,337:337}],333:[function(t,e,n){"use strict";function a(t){return t&&t.__esModule?t:{"default":t}}Object.defineProperty(n,"__esModule",{value:!0});var r=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),i=t(334),o=a(i),s=t(335),p=1e-5,u=function(t,e){var n=t.map(e),a=n.sort(function(t,e){var n=r(t,2),a=n[0],i=(n[1],r(e,2)),o=i[0];i[1];return a-o}),i=a.length,o=a[0][0],u=a[i-1][0],c=(0,s.minBy)(a,function(t){return t[1]}),l=(0,s.maxBy)(a,function(t){return t[1]});return o==u&&(u+=p),c==l&&(l+=p),{points:a,xmin:o,xmax:u,ymin:c,ymax:l}};n["default"]=function(t){var e=t.data,n=t.xaccessor,a=t.yaccessor,i=t.width,p=t.height,c=t.closed,l=t.min,d=t.max;n||(n=function(t){var e=r(t,2),n=e[0];e[1];return n}),a||(a=function(t){var e=r(t,2),n=(e[0],e[1]);return n});var f=function(t){return[n(t),a(t)]},h=e.map(function(t){return u(t,f)}),m=(0,s.minBy)(h,function(t){return t.xmin}),g=(0,s.maxBy)(h,function(t){return t.xmax}),v=null==l?(0,s.minBy)(h,function(t){return t.ymin}):l,b=null==d?(0,s.maxBy)(h,function(t){return t.ymax}):d;c&&(v=Math.min(v,0),b=Math.max(b,0));var y=c?0:v,_=(0,o["default"])([m,g],[0,i]),x=(0,o["default"])([v,b],[p,0]),w=function(t){var e=r(t,2),n=e[0],a=e[1];return[_(n),x(a)]};return{arranged:h,scale:w,xscale:_,yscale:x,base:y}},e.exports=n["default"]},{334:334,335:335}],334:[function(t,e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var a=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),r=function i(t,e){var n=a(t,2),r=n[0],o=n[1],s=a(e,2),p=s[0],u=s[1],c=function(t){return p+(u-p)*(t-r)/(o-r)};return c.inverse=function(){return i([p,u],[r,o])},c};n["default"]=r,e.exports=n["default"]},{}],335:[function(t,e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var a=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),r=function(t){return t.reduce(function(t,e){return t+e},0)},i=function(t){return t.reduce(function(t,e){return Math.min(t,e)})},o=function(t){return t.reduce(function(t,e){return Math.max(t,e)})},s=function(t,e){return t.reduce(function(t,n){return t+e(n)},0)},p=function(t,e){return t.reduce(function(t,n){return Math.min(t,e(n))},1/0)},u=function(t,e){return t.reduce(function(t,n){return Math.max(t,e(n))},-(1/0))},c=function(t,e){var n=a(t,2),r=n[0],i=n[1],o=a(e,2),s=o[0],p=o[1];return[r+s,i+p]},l=function(t,e){var n=a(t,2),r=n[0],i=n[1],o=a(e,2),s=o[0],p=o[1];return[r-s,i-p]},d=function(t,e){var n=a(e,2),r=n[0],i=n[1];return[t*r,t*i]},f=function(t){var e=a(t,2),n=e[0],r=e[1];return Math.sqrt(n*n+r*r)},h=function(t){return t.reduce(c,[0,0])},m=function(t){return d(1/t.length,t.reduce(c))},g=function(t,e){return d(t,[Math.sin(e),-Math.cos(e)])},v=function(t,e){var n=t||{};for(var a in n){var r=n[a];e[a]=r(e.index,e.item,e.group)}return e},b=function(t,e,n){for(var a=[],r=t;e>r;r++)a.push(r);return n&&a.push(e),a},y=function(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=Object.keys(t)[Symbol.iterator]();!(a=(o=s.next()).done);a=!0){var p=o.value,u=t[p];n.push(e(p,u))}}catch(c){r=!0,i=c}finally{ -try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n},_=function(t){return y(t,function(t,e){return[t,e]})},x=function(t){return t};n.sum=r,n.min=i,n.max=o,n.sumBy=s,n.minBy=p,n.maxBy=u,n.plus=c,n.minus=l,n.times=d,n.id=x,n.length=f,n.sumVectors=h,n.average=m,n.onCircle=g,n.enhance=v,n.range=b,n.mapObject=y,n.pairs=_,n["default"]={sum:r,min:i,max:o,sumBy:s,minBy:p,maxBy:u,plus:c,minus:l,times:d,id:x,length:f,sumVectors:h,average:m,onCircle:g,enhance:v,range:b,mapObject:y,pairs:_}},{}],336:[function(t,e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var a=function(){function t(t,e){var n=[],a=!0,r=!1,i=void 0;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),r=function i(t){var e=t||[],n=function(t,e){var n=t.slice(0,t.length);return n.push(e),n},r=function(t,e){var n=a(t,2),r=n[0],i=n[1],o=a(e,2),s=o[0],p=o[1];return r===s&&i===p},o=function(t,e){for(var n=t.length;"0"===t.charAt(n-1);)n-=1;return"."===t.charAt(n-1)&&(n-=1),t.substr(0,n)},s=function(t,e){var n=t.toFixed(e);return o(n)},p=function(t){var e=t.command,n=t.params,a=n.map(function(t){return s(t,6)});return e+" "+a.join(" ")},u=function(t,e){var n=t.command,r=t.params,i=a(e,2),o=i[0],s=i[1];switch(n){case"M":return[r[0],r[1]];case"L":return[r[0],r[1]];case"H":return[r[0],s];case"V":return[o,r[0]];case"Z":return null;case"C":return[r[4],r[5]];case"S":return[r[2],r[3]];case"Q":return[r[2],r[3]];case"T":return[r[0],r[1]];case"A":return[r[5],r[6]]}},c=function(t,e){return function(n){var a="object"==typeof n?t.map(function(t){return n[t]}):arguments;return e.apply(null,a)}},l=function(t){return i(n(e,t))};return{moveto:c(["x","y"],function(t,e){return l({command:"M",params:[t,e]})}),lineto:c(["x","y"],function(t,e){return l({command:"L",params:[t,e]})}),hlineto:c(["x"],function(t){return l({command:"H",params:[t]})}),vlineto:c(["y"],function(t){return l({command:"V",params:[t]})}),closepath:function(){return l({command:"Z",params:[]})},curveto:c(["x1","y1","x2","y2","x","y"],function(t,e,n,a,r,i){return l({command:"C",params:[t,e,n,a,r,i]})}),smoothcurveto:c(["x2","y2","x","y"],function(t,e,n,a){return l({command:"S",params:[t,e,n,a]})}),qcurveto:c(["x1","y1","x","y"],function(t,e,n,a){return l({command:"Q",params:[t,e,n,a]})}),smoothqcurveto:c(["x","y"],function(t,e){return l({command:"T",params:[t,e]})}),arc:c(["rx","ry","xrot","largeArcFlag","sweepFlag","x","y"],function(t,e,n,a,r,i,o){return l({command:"A",params:[t,e,n,a,r,i,o]})}),print:function(){return e.map(p).join(" ")},points:function(){var t=[],n=[0,0],a=!0,r=!1,i=void 0;try{for(var o,s=e[Symbol.iterator]();!(a=(o=s.next()).done);a=!0){var p=o.value,c=u(p,n);n=c,c&&t.push(c)}}catch(l){r=!0,i=l}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return t},instructions:function(){return e.slice(0,e.length)},connect:function(t){var e=this.points(),n=e[e.length-1],a=t.points()[0],o=t.instructions().slice(1);return r(n,a)||o.unshift({command:"L",params:a}),i(this.instructions().concat(o))}}};n["default"]=function(){return r()},e.exports=n["default"]},{}],337:[function(t,e,n){"use strict";function a(t){return t&&t.__esModule?t:{"default":t}}function r(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];for(var r,i;i=n.shift();)for(r in i)Mo.call(i,r)&&(t[r]=i[r]);return t}function r(t){for(var e=arguments.length,n=Array(e>1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];return n.forEach(function(e){for(var n in e)!e.hasOwnProperty(n)||n in t||(t[n]=e[n])}),t}function i(t){return"[object Array]"===Lo.call(t)}function o(t){return Do.test(Lo.call(t))}function s(t,e){return null===t&&null===e?!0:"object"==typeof t||"object"==typeof e?!1:t===e}function p(t){return!isNaN(parseFloat(t))&&isFinite(t)}function u(t){return t&&"[object Object]"===Lo.call(t)}function c(t,e){return t.replace(/%s/g,function(){return e.shift()})}function l(t){for(var e=arguments.length,n=Array(e>1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];throw t=c(t,n),Error(t)}function d(){Mg.DEBUG&&Oo.apply(null,arguments)}function f(t){for(var e=arguments.length,n=Array(e>1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];t=c(t,n),To(t,n)}function h(t){for(var e=arguments.length,n=Array(e>1?e-1:0),a=1;e>a;a++)n[a-1]=arguments[a];t=c(t,n),jo[t]||(jo[t]=!0,To(t,n))}function m(){Mg.DEBUG&&f.apply(null,arguments)}function g(){Mg.DEBUG&&h.apply(null,arguments)}function v(t,e,n){var a=b(t,e,n);return a?a[t][n]:null}function b(t,e,n){for(;e;){if(n in e[t])return e;if(e.isolated)return null;e=e.parent}}function y(t){return function(){return t}}function _(t){var e,n,a,r,i,o;for(e=t.split("."),(n=zo[e.length])||(n=x(e.length)),i=[],a=function(t,n){return t?"*":e[n]},r=n.length;r--;)o=n[r].map(a).join("."),i.hasOwnProperty(o)||(i.push(o),i[o]=!0);return i}function x(t){var e,n,a,r,i,o,s,p,u="";if(!zo[t]){for(a=[];u.length=i;i+=1){for(n=i.toString(2);n.lengtho;o++)p.push(r(n[o]));a[i]=p}zo[t]=a}return zo[t]}function w(t,e,n,a){var r=t[e];if(!r||!r.equalsOrStartsWith(a)&&r.equalsOrStartsWith(n))return t[e]=r?r.replace(n,a):a,!0}function k(t){var e=t.slice(2);return"i"===t[1]&&p(e)?+e:e}function S(t){return null==t?t:(Ko.hasOwnProperty(t)||(Ko[t]=new Qo(t)),Ko[t])}function E(t,e){function n(e,n){var a,r,o;return n.isRoot?o=[].concat(Object.keys(t.viewmodel.data),Object.keys(t.viewmodel.mappings),Object.keys(t.viewmodel.computations)):(a=t.viewmodel.wrapped[n.str],r=a?a.get():t.viewmodel.get(n),o=r?Object.keys(r):null),o&&o.forEach(function(t){"_ractive"===t&&i(r)||e.push(n.join(t))}),e}var a,r,o;for(a=e.str.split("."),o=[$o];r=a.shift();)"*"===r?o=o.reduce(n,[]):o[0]===$o?o[0]=S(r):o=o.map(C(r));return o}function C(t){return function(e){return e.join(t)}}function P(t){return t?t.replace(Wo,".$1"):""}function A(t,e,n){if("string"!=typeof e||!p(n))throw Error("Bad arguments");var a=void 0,r=void 0;if(/\*/.test(e))return r={},E(t,S(P(e))).forEach(function(e){var a=t.viewmodel.get(e);if(!p(a))throw Error(Xo);r[e.str]=a+n}),t.set(r);if(a=t.get(e),!p(a))throw Error(Xo);return t.set(e,+a+n)}function O(t,e){return Jo(this,t,void 0===e?1:+e)}function T(t){this.event=t,this.method="on"+t,this.deprecate=as[t]}function R(t,e){var n=t.indexOf(e);-1===n&&t.push(e)}function M(t,e){for(var n=0,a=t.length;a>n;n++)if(t[n]==e)return!0;return!1}function L(t,e){var n;if(!i(t)||!i(e))return!1;if(t.length!==e.length)return!1;for(n=t.length;n--;)if(t[n]!==e[n])return!1;return!0}function D(t){return"string"==typeof t?[t]:void 0===t?[]:t}function j(t){return t[t.length-1]}function N(t,e){var n=t.indexOf(e);-1!==n&&t.splice(n,1)}function F(t){for(var e=[],n=t.length;n--;)e[n]=t[n];return e}function I(t){setTimeout(t,0)}function B(t,e){return function(){for(var n;n=t.shift();)n(e)}}function q(t,e,n,a){var r;if(e===t)throw new TypeError("A promise's fulfillment handler cannot return the same promise");if(e instanceof rs)e.then(n,a);else if(!e||"object"!=typeof e&&"function"!=typeof e)n(e);else{try{r=e.then}catch(i){return void a(i)}if("function"==typeof r){var o,s,p;s=function(e){o||(o=!0,q(t,e,n,a))},p=function(t){o||(o=!0,a(t))};try{r.call(e,s,p)}catch(i){if(!o)return a(i),void(o=!0)}}else n(e)}}function U(t,e,n){var a;return e=P(e),"~/"===e.substr(0,2)?(a=S(e.substring(2)),z(t,a.firstKey,n)):"."===e[0]?(a=V(cs(n),e),a&&z(t,a.firstKey,n)):a=G(t,S(e),n),a}function V(t,e){var n;if(void 0!=t&&"string"!=typeof t&&(t=t.str),"."===e)return S(t);if(n=t?t.split("."):[],"../"===e.substr(0,3)){for(;"../"===e.substr(0,3);){if(!n.length)throw Error('Could not resolve reference - too many "../" prefixes');n.pop(),e=e.substring(3)}return n.push(e),S(n.join("."))}return S(t?t+e.replace(/^\.\//,"."):e.replace(/^\.\/?/,""))}function G(t,e,n,a){var r,i,o,s,p;if(e.isRoot)return e;for(i=e.firstKey;n;)if(r=n.context,n=n.parent,r&&(s=!0,o=t.viewmodel.get(r),o&&("object"==typeof o||"function"==typeof o)&&i in o))return r.join(e.str);return W(t.viewmodel,i)?e:t.parent&&!t.isolated&&(s=!0,n=t.component.parentFragment,i=S(i),p=G(t.parent,i,n,!0))?(t.viewmodel.map(i,{origin:t.parent.viewmodel,keypath:p}),e):a||s?void 0:(t.viewmodel.set(e,void 0),e)}function z(t,e){var n;!t.parent||t.isolated||W(t.viewmodel,e)||(e=S(e),(n=G(t.parent,e,t.component.parentFragment,!0))&&t.viewmodel.map(e,{origin:t.parent.viewmodel,keypath:n}))}function W(t,e){return""===e||e in t.data||e in t.computations||e in t.mappings}function H(t){t.teardown()}function K(t){t.unbind()}function Q(t){t.unrender()}function Y(t){t.cancel()}function $(t){t.detach()}function J(t){t.detachNodes()}function X(t){!t.ready||t.outros.length||t.outroChildren||(t.outrosComplete||(t.parent?t.parent.decrementOutros(t):t.detachNodes(),t.outrosComplete=!0),t.intros.length||t.totalChildren||("function"==typeof t.callback&&t.callback(),t.parent&&t.parent.decrementTotal()))}function Z(){for(var t,e,n;fs.ractives.length;)e=fs.ractives.pop(),n=e.viewmodel.applyChanges(),n&&vs.fire(e,n);for(tt(),t=0;t=0;i--)r=t._subs[e[i]],r&&(s=vt(t,r,n,a)&&s);if(Gs.dequeue(t),t.parent&&s){if(o&&t.component){var p=t.component.name+"."+e[e.length-1];e=S(p).wildcardMatches(),n&&(n.component=t)}gt(t.parent,e,n,a)}}function vt(t,e,n,a){var r=null,i=!1;n&&!n._noArg&&(a=[n].concat(a)),e=e.slice();for(var o=0,s=e.length;s>o;o+=1)e[o].apply(t,a)===!1&&(i=!0);return n&&!n._noArg&&i&&(r=n.original)&&(r.preventDefault&&r.preventDefault(),r.stopPropagation&&r.stopPropagation()),!i}function bt(t){var e={args:Array.prototype.slice.call(arguments,1)};zs(this,t,e)}function yt(t){var e;return t=S(P(t)),e=this.viewmodel.get(t,Ks),void 0===e&&this.parent&&!this.isolated&&ls(this,t.str,this.component.parentFragment)&&(e=this.viewmodel.get(t)),e}function _t(e,n){if(!this.fragment.rendered)throw Error("The API has changed - you must call `ractive.render(target[, anchor])` to render your Ractive instance. Once rendered you can use `ractive.insert()`.");if(e=t(e),n=t(n)||null,!e)throw Error("You must specify a valid target to insert into");e.insertBefore(this.detach(),n),this.el=e,(e.__ractive_instances__||(e.__ractive_instances__=[])).push(this),this.detached=null,xt(this)}function xt(t){Ys.fire(t),t.findAllComponents("*").forEach(function(t){xt(t.instance)})}function wt(t,e,n){var a,r;return t=S(P(t)),a=this.viewmodel.get(t),i(a)&&i(e)?(r=bs.start(this,!0),this.viewmodel.merge(t,a,e,n),bs.end(),r):this.set(t,e,n&&n.complete)}function kt(t,e){var n,a;return n=E(t,e),a={},n.forEach(function(e){a[e.str]=t.get(e.str)}),a}function St(t,e,n,a){var r,i,o;e=S(P(e)),a=a||cp,e.isPattern?(r=new pp(t,e,n,a),t.viewmodel.patternObservers.push(r),i=!0):r=new Zs(t,e,n,a),r.init(a.init),t.viewmodel.register(e,r,i?"patternObservers":"observers"),r.ready=!0;var s={cancel:function(){var n;o||(i?(n=t.viewmodel.patternObservers.indexOf(r),t.viewmodel.patternObservers.splice(n,1),t.viewmodel.unregister(e,r,"patternObservers")):t.viewmodel.unregister(e,r,"observers"),o=!0)}};return t._observers.push(s),s}function Et(t,e,n){var a,r,i,o;if(u(t)){n=e,r=t,a=[];for(t in r)r.hasOwnProperty(t)&&(e=r[t],a.push(this.observe(t,e,n)));return{cancel:function(){for(;a.length;)a.pop().cancel()}}}if("function"==typeof t)return n=e,e=t,t="",up(this,t,e,n);if(i=t.split(" "),1===i.length)return up(this,t,e,n);for(a=[],o=i.length;o--;)t=i[o],t&&a.push(up(this,t,e,n));return{cancel:function(){for(;a.length;)a.pop().cancel()}}}function Ct(t,e,n){var a=this.observe(t,function(){e.apply(this,arguments),a.cancel()},{init:!1,defer:n&&n.defer});return a}function Pt(t,e){var n,a=this;if(t)n=t.split(" ").map(fp).filter(hp),n.forEach(function(t){var n,r;(n=a._subs[t])&&(e?(r=n.indexOf(e),-1!==r&&n.splice(r,1)):a._subs[t]=[])});else for(t in this._subs)delete this._subs[t];return this}function At(t,e){var n,a,r,i=this;if("object"==typeof t){n=[];for(a in t)t.hasOwnProperty(a)&&n.push(this.on(a,t[a]));return{cancel:function(){for(var t;t=n.pop();)t.cancel()}}}return r=t.split(" ").map(fp).filter(hp),r.forEach(function(t){(i._subs[t]||(i._subs[t]=[])).push(e)}),{cancel:function(){return i.off(t,e)}}}function Ot(t,e){var n=this.on(t,function(){e.apply(this,arguments),n.cancel()});return n}function Tt(t,e,n){var a,r,i,o,s,p,u=[];if(a=Rt(t,e,n),!a)return null;for(r=t.length,s=a.length-2-a[1],i=Math.min(r,a[0]),o=i+a[1],p=0;i>p;p+=1)u.push(p);for(;o>p;p+=1)u.push(-1);for(;r>p;p+=1)u.push(p+s);return 0!==s?u.touchedFrom=a[0]:u.touchedFrom=t.length,u}function Rt(t,e,n){switch(e){case"splice":for(void 0!==n[0]&&n[0]<0&&(n[0]=t.length+Math.max(n[0],-t.length));n.length<2;)n.push(0);return n[1]=Math.min(n[1],t.length-n[0]),n;case"sort":case"reverse":return null;case"pop":return t.length?[t.length-1,1]:[0,0];case"push":return[t.length,0].concat(n);case"shift":return[0,t.length?1:0];case"unshift":return[0,0].concat(n)}}function Mt(e,n){var a,r,i,o=this;if(i=this.transitionsEnabled,this.noIntro&&(this.transitionsEnabled=!1),a=bs.start(this,!0),bs.scheduleTask(function(){return Rp.fire(o)},!0),this.fragment.rendered)throw Error("You cannot call ractive.render() on an already rendered instance! Call ractive.unrender() first");if(e=t(e)||this.el,n=t(n)||this.anchor,this.el=e,this.anchor=n,!this.append&&e){var s=e.__ractive_instances__;s&&s.length&&Lt(s),e.innerHTML=""}return this.cssId&&Op.apply(),e&&((r=e.__ractive_instances__)?r.push(this):e.__ractive_instances__=[this],n?e.insertBefore(this.fragment.render(),n):e.appendChild(this.fragment.render())),bs.end(),this.transitionsEnabled=i,a.then(function(){return Mp.fire(o)})}function Lt(t){t.splice(0,t.length).forEach(H)}function Dt(t,e){for(var n=t.slice(),a=e.length;a--;)~n.indexOf(e[a])||n.push(e[a]);return n}function jt(t,e){var n,a,r;return a='[data-ractive-css~="{'+e+'}"]',r=function(t){var e,n,r,i,o,s,p,u=[];for(e=[];n=Ip.exec(t);)e.push({str:n[0],base:n[1],modifiers:n[2]});for(i=e.map(Ft),p=e.length;p--;)s=i.slice(),r=e[p],s[p]=r.base+a+r.modifiers||"",o=i.slice(),o[p]=a+" "+o[p],u.push(s.join(" "),o.join(" "));return u.join(", ")},n=qp.test(t)?t.replace(qp,a):t.replace(Fp,"").replace(Np,function(t,e){var n,a;return Bp.test(e)?t:(n=e.split(",").map(Nt),a=n.map(r).join(", ")+" ",t.replace(e,a))})}function Nt(t){return t.trim?t.trim():t.replace(/^\s+/,"").replace(/\s+$/,"")}function Ft(t){return t.str}function It(t){t&&t.constructor!==Object&&("function"==typeof t||("object"!=typeof t?l("data option must be an object or a function, `"+t+"` is not valid"):m("If supplied, options.data should be a plain JavaScript object - using a non-POJO as the root object may work, but is discouraged")))}function Bt(t,e){It(e);var n="function"==typeof t,a="function"==typeof e;return e||n||(e={}),n||a?function(){var r=a?qt(e,this):e,i=n?qt(t,this):t;return Ut(r,i)}:Ut(e,t)}function qt(t,e){var n=t.call(e);if(n)return"object"!=typeof n&&l("Data function must return an object"),n.constructor!==Object&&g("Data function returned something other than a plain JavaScript object. This might work, but is strongly discouraged"),n}function Ut(t,e){if(t&&e){for(var n in e)n in t||(t[n]=e[n]);return t}return t||e}function Vt(t){var e=So(Qp);return e.parse=function(e,n){return Gt(e,n||t)},e}function Gt(t,e){if(!Hp)throw Error("Missing Ractive.parse - cannot parse template. Either preparse or use the version that includes the parser");return Hp(t,e||this.options)}function zt(t,e){var n;if(!Xi){if(e&&e.noThrow)return;throw Error("Cannot retrieve template #"+t+" as Ractive is not running in a browser.")}if(Wt(t)&&(t=t.substring(1)),!(n=document.getElementById(t))){if(e&&e.noThrow)return;throw Error("Could not find template element with id #"+t)}if("SCRIPT"!==n.tagName.toUpperCase()){if(e&&e.noThrow)return;throw Error("Template element with id #"+t+", must be a